Revision e81dd1f6

b/trunk/Pithos.Core/Agents/CloudTransferAction.cs
108 108
    public class CloudDeleteAction:CloudAction
109 109
    {
110 110
        public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState)
111
            : this(accountInfo,new ObjectInfo(accountInfo.AccountPath,accountInfo.UserName,fileInfo),fileState)
112
        {
111
            : this(accountInfo,fileInfo,new ObjectInfo(accountInfo.AccountPath,accountInfo.UserName,fileInfo),fileState)
112
        {            
113 113
        }
114 114

  
115
        public CloudDeleteAction(AccountInfo accountInfo, ObjectInfo cloudFile, FileState fileState) 
115
        public CloudDeleteAction(AccountInfo accountInfo, FileSystemInfo fileInfo,ObjectInfo cloudFile, FileState fileState) 
116 116
            : base(accountInfo,CloudActionType.DeleteCloud)
117 117
        {
118 118
            CloudFile = cloudFile;
119
            LocalFile = fileInfo;
119 120
            FileState = fileState;
120 121
        }
121 122

  
122 123
        public CloudDeleteAction(CloudAction action)
123
            : this(action.AccountInfo,action.CloudFile,action.FileState)
124
            : this(action.AccountInfo,action.LocalFile,action.CloudFile,action.FileState)
124 125
        {}
125 126

  
126 127
        [ContractInvariantMethod]
b/trunk/Pithos.Core/Agents/NetworkAgent.cs
45 45
using System.Linq;
46 46
using System.Net;
47 47
using System.Threading.Tasks;
48
using Castle.ActiveRecord;
48 49
using Pithos.Interfaces;
49 50
using Pithos.Network;
50 51
using log4net;
......
61 62
        private Agent<CloudDeleteAction> _deleteAgent;
62 63

  
63 64

  
64
        [Import]
65
        [System.ComponentModel.Composition.Import]
65 66
        public IStatusKeeper StatusKeeper { get; set; }
66 67
        
67 68
        public IStatusNotification StatusNotification { get; set; }
......
352 353
            Contract.EndContractBlock();
353 354

  
354 355
            //If the action targets a local file, add a treehash calculation
355
            if (cloudAction.LocalFile as FileInfo != null)
356
            if (!(cloudAction is CloudDeleteAction) && cloudAction.LocalFile as FileInfo != null)
356 357
            {
357 358
                var accountInfo = cloudAction.AccountInfo;
358 359
                var localFile = (FileInfo) cloudAction.LocalFile;
......
548 549
                    var localFile = fileAgent.GetFileSystemInfo(relativePath);
549 550
                    if (objectInfo.Content_Type == @"application/directory" && localFile is DirectoryInfo)
550 551
                        continue;
551
                    var state = FileState.FindByFilePath(localFile.FullName);
552
                    //Common files should be checked on a per-case basis to detect differences, which is newer
552
                    using (new SessionScope(FlushAction.Never))
553
                    {
554
                        var state = FileState.FindByFilePath(localFile.FullName);
555
                        //Common files should be checked on a per-case basis to detect differences, which is newer
553 556

  
554
                    yield return new CloudAction(accountInfo,CloudActionType.MustSynch,
555
                                                   localFile, objectInfo, state, accountInfo.BlockSize,
556
                                                   accountInfo.BlockHash);
557
                        yield return new CloudAction(accountInfo, CloudActionType.MustSynch,
558
                                                     localFile, objectInfo, state, accountInfo.BlockSize,
559
                                                     accountInfo.BlockHash);
560
                    }
557 561
                }
558 562
                else
559 563
                {
b/trunk/Pithos.Core/Agents/StatusAgent.cs
61 61
                                         },
62 62
                                 };
63 63

  
64
            var connectionString = String.Format(@"Data Source={0}\pithos.db;Version=3", pithosDbPath);
64
            var connectionString = String.Format(@"Data Source={0}\pithos.db;Version=3;Enlist=N", pithosDbPath);
65 65
            properties.Add("connection.connection_string", connectionString);
66 66

  
67 67
            var source = new InPlaceConfigurationSource();                        
......
140 140

  
141 141
            var pairs = currentFiles.Union(deletedFiles);
142 142

  
143
            Parallel.ForEach(pairs, pair =>
143
            foreach(var pair in pairs)
144 144
            {
145 145
                var fileState = pair.State;
146 146
                var file = pair.File;
......
156 156
                    //This file was deleted while we were down. We should mark it as deleted
157 157
                    //We have to go through UpdateStatus here because the state object we are using
158 158
                    //was created by a different ORM session.
159
                    FileState.UpdateStatus(fileState.Id,FileStatus.Deleted);                    
159
                    _persistenceAgent.Post(()=> UpdateStatusDirect(fileState.Id, FileStatus.Deleted));                    
160 160
                }
161 161
                else
162 162
                {
......
165 165
                    //If the hashes don't match the file was changed
166 166
                    if (fileState.Checksum != hashString)
167 167
                    {
168
                        FileState.UpdateStatus(fileState.Id, FileStatus.Modified);
168
                        _persistenceAgent.Post(() => UpdateStatusDirect(fileState.Id, FileStatus.Modified));
169 169
                    }                    
170 170
                }
171
            });            
171
            };            
172 172
         
173 173
        }
174 174

  
175
       
175
        private int UpdateStatusDirect(Guid id, FileStatus status)
176
        {
177
            try
178
            {
179

  
180
                var connectionString = GetConnectionString();
181
                using (var connection = new SQLiteConnection(connectionString))
182
                {
183
                    var command = new SQLiteCommand("update FileState set FileStatus= :fileStatus where Id = :id  ",
184
                                                    connection);
185

  
186
                    command.Parameters.AddWithValue("fileStatus", status);
187

  
188
                    command.Parameters.AddWithValue("id", id);
189
                    connection.Open();
190
                    var affected = command.ExecuteNonQuery();
191
                    return affected;
192
                }
193
            }
194
            catch (Exception exc)
195
            {
196
                Log.Error(exc.ToString());
197
                throw;
198
            }
199

  
200
        }
201
        
202
        private int UpdateStatusDirect(string path, FileStatus status)
203
        {
204
            try
205
            {
206

  
207
                var connectionString = GetConnectionString();
208
                using (var connection = new SQLiteConnection(connectionString))
209
                {
210
                    var command = new SQLiteCommand("update FileState set FileStatus= :fileStatus where FilePath = :path ",
211
                                                    connection);
212

  
213
                    command.Parameters.AddWithValue("fileStatus", status);
214

  
215
                    command.Parameters.AddWithValue("path", path.ToLower());
216
                    connection.Open();
217
                    var affected = command.ExecuteNonQuery();
218
                    return affected;
219
                }
220
            }
221
            catch (Exception exc)
222
            {
223
                Log.Error(exc.ToString());
224
                throw;
225
            }
226

  
227
        }
228

  
229
        private int UpdateStatusDirect(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus)
230
        {
231
            try
232
            {
233

  
234
                var connectionString = GetConnectionString();
235
                using (var connection = new SQLiteConnection(connectionString))
236
                {
237
                    var command = new SQLiteCommand("update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ",
238
                                                    connection);
239
                    command.Parameters.AddWithValue("path", absolutePath.ToLower());
240
                    command.Parameters.AddWithValue("fileStatus", fileStatus);
241
                    command.Parameters.AddWithValue("overlayStatus", overlayStatus);
242
                    connection.Open();
243
                    var affected = command.ExecuteNonQuery();
244
                    return affected;
245
                }
246
            }
247
            catch (Exception exc)
248
            {
249
                Log.Error(exc.ToString());
250
                throw;
251
            }
252

  
253
        }
254
        
176 255

  
177 256

  
178 257
        public string BlockHash { get; set; }
......
220 299

  
221 300
            try
222 301
            {
223

  
302
                var connectionString = GetConnectionString();
303
                using (var connection = new SQLiteConnection(connectionString))
304
                {
305
                    var command = new SQLiteCommand("select OverlayStatus from FileState where FilePath=:path", connection);
306
                    command.Parameters.AddWithValue("path", path.ToLower());
307
                    connection.Open();
308
                    var s = command.ExecuteScalar();
309
                    return (FileOverlayStatus) Convert.ToInt32(s);
310
                }
224 311
                var status = from state in  FileState.Queryable 
225 312
                                 where state.FilePath ==path.ToLower()
226 313
                                 select state.OverlayStatus;
......
233 320
            }
234 321
        }
235 322

  
323
        private string GetConnectionString()
324
        {
325
            var connectionString = String.Format(@"Data Source={0}\pithos.db;Version=3;Enlist=N;Pooling=True;Default Isolation Level=ReadCommited", _pithosDataPath);
326
            return connectionString;
327
        }
328

  
236 329
        public void SetFileOverlayStatus(string path, FileOverlayStatus overlayStatus)
237 330
        {
238 331
            if (String.IsNullOrWhiteSpace(path))
......
270 363
            Debug.Assert(!path.Contains(FolderConstants.CacheFolder));
271 364
            Debug.Assert(!path.EndsWith(".ignore"));
272 365

  
273
            _persistenceAgent.Post(() => FileState.UpdateStatus(path.ToLower(), fileStatus, overlayStatus));
366
            _persistenceAgent.Post(() => UpdateStatusDirect(path.ToLower(), fileStatus, overlayStatus));
274 367
        }
275 368

  
276 369
        public void StoreInfo(string path,ObjectInfo objectInfo)
......
320 413
            if (!Path.IsPathRooted(path))
321 414
                throw new ArgumentException("The path must be rooted", "path");
322 415
            Contract.EndContractBlock();
323

  
324
            _persistenceAgent.Post(() => FileState.UpdateStatus(path.ToLower(), status));
416
            
417
            _persistenceAgent.Post(() => UpdateStatusDirect(path.ToLower(), status));
325 418
        }
326 419

  
327 420
        public FileStatus GetFileStatus(string path)
......
332 425
                throw new ArgumentException("The path must be rooted", "path");
333 426
            Contract.EndContractBlock();
334 427

  
428
            var connectionString = GetConnectionString();
429
            using (var connection = new SQLiteConnection(connectionString))
430
            {
431
                var command = new SQLiteCommand("select FileStatus from FileState where FilePath=:path", connection);
432
                command.Parameters.AddWithValue("path", path.ToLower());
433
                connection.Open();
434
                var s = command.ExecuteScalar();
435
                return (FileStatus)Convert.ToInt32(s);
436
            }
437

  
335 438
            var status = from r in FileState.Queryable
336 439
                     where r.FilePath == path.ToLower()
337 440
                     select r.FileStatus;                        
......
345 448
            if (!Path.IsPathRooted(path))
346 449
                throw new ArgumentException("The path must be rooted", "path");
347 450
            Contract.EndContractBlock();
348
            
349
            _persistenceAgent.Post(() => FileState.DeleteByFilePath(path));   
451

  
452
            _persistenceAgent.Post(() => DeleteDirect(path));   
453
        }
454

  
455
        private int DeleteDirect(string filePath)
456
        {
457
            try
458
            {
459

  
460
                var connectionString = GetConnectionString();
461
                using (var connection = new SQLiteConnection(connectionString))
462
                {
463
                    var command = new SQLiteCommand("delete FileState where FilePath = :path",
464
                                                    connection);
465

  
466
                    command.Parameters.AddWithValue("path", filePath.ToLower());
467
                    connection.Open();
468
                    var affected = command.ExecuteNonQuery();
469
                    return affected;
470
                }
471
            }
472
            catch (Exception exc)
473
            {
474
                Log.Error(exc.ToString());
475
                throw;
476
            }
477

  
350 478
        }
351 479

  
352 480
        public void UpdateFileChecksum(string path, string checksum)
b/trunk/Pithos.Core/Agents/WorkflowAgent.cs
44 44
using System.Linq;
45 45
using System.Text;
46 46
using System.Threading.Tasks;
47
using Castle.ActiveRecord;
47 48
using Pithos.Interfaces;
48 49
using Pithos.Network;
49 50
using log4net;
......
56 57
        Agent<WorkflowState> _agent;
57 58
                
58 59
        public IStatusNotification StatusNotification { get; set; }
59
        [Import]
60
        [System.ComponentModel.Composition.Import]
60 61
        public IStatusKeeper StatusKeeper { get; set; }
61 62

  
62
        [Import]
63
        [System.ComponentModel.Composition.Import]
63 64
        public NetworkAgent NetworkAgent { get; set; }
64 65

  
65 66
        private static readonly ILog Log = LogManager.GetLogger("WorkflowAgent");
......
114 115
                        return CompletedTask<object>.Default;
115 116
                    }
116 117

  
117
                    var fileState = FileState.FindByFilePath(path);
118

  
119

  
120
                    switch (state.Status)
118
                    using (new SessionScope(FlushAction.Never))
121 119
                    {
122
                        case FileStatus.Created:
123
                        case FileStatus.Modified:
124
                            NetworkAgent.Post(new CloudUploadAction(accountInfo, info, fileState, accountInfo.BlockSize,
125
                                                                    accountInfo.BlockHash));
126
                            break;
127
                        case FileStatus.Deleted:
128
                            NetworkAgent.Post(new CloudDeleteAction(accountInfo, info, fileState));
129
                            break;
130
                        case FileStatus.Renamed:
131
                            FileSystemInfo oldInfo = Directory.Exists(state.OldPath) ? (FileSystemInfo)new DirectoryInfo(state.OldPath) : new FileInfo(state.OldPath);
132
                            FileSystemInfo newInfo = Directory.Exists(state.Path) ? (FileSystemInfo)new DirectoryInfo(state.Path) : new FileInfo(state.Path);
133
                            NetworkAgent.Post(new CloudMoveAction(accountInfo, CloudActionType.RenameCloud,
134
                                                                  oldInfo,
135
                                                                  newInfo));
136
                            break;
120

  
121
                        var fileState = FileState.FindByFilePath(path);
122

  
123

  
124
                        switch (state.Status)
125
                        {
126
                            case FileStatus.Created:
127
                            case FileStatus.Modified:
128
                                NetworkAgent.Post(new CloudUploadAction(accountInfo, info, fileState,
129
                                                                        accountInfo.BlockSize,
130
                                                                        accountInfo.BlockHash));
131
                                break;
132
                            case FileStatus.Deleted:
133
                                NetworkAgent.Post(new CloudDeleteAction(accountInfo, info, fileState));
134
                                break;
135
                            case FileStatus.Renamed:
136
                                FileSystemInfo oldInfo = Directory.Exists(state.OldPath)
137
                                                             ? (FileSystemInfo) new DirectoryInfo(state.OldPath)
138
                                                             : new FileInfo(state.OldPath);
139
                                FileSystemInfo newInfo = Directory.Exists(state.Path)
140
                                                             ? (FileSystemInfo) new DirectoryInfo(state.Path)
141
                                                             : new FileInfo(state.Path);
142
                                NetworkAgent.Post(new CloudMoveAction(accountInfo, CloudActionType.RenameCloud,
143
                                                                      oldInfo,
144
                                                                      newInfo));
145
                                break;
146
                        }
137 147
                    }
138 148

  
139 149
                    return CompletedTask<object>.Default;
b/trunk/Pithos.Core/DbConfig.xml
4 4
    <add key="connection.driver_class"  value="NHibernate.Driver.SQLite20Driver" />
5 5
    <add key="dialect"                  value="NHibernate.Dialect.SQLiteDialect" />
6 6
    <add key="connection.provider"      value="NHibernate.Connection.DriverConnectionProvider" />
7
    <add key="connection.connection_string"        value="Data Source=pithos.db;Version=3" />
7
    <add key="connection.connection_string"        value="Data Source=pithos.db;Version=3;Enlist=N" />
8 8
    <add key="proxyfactory.factory_class" value="NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle" />
9 9
  </config>
10 10

  
b/trunk/Pithos.Core/FileState.cs
35 35
// </copyright>
36 36
// -----------------------------------------------------------------------
37 37

  
38
using System.Data.SQLite;
38 39
using System.Diagnostics.Contracts;
39 40
using System.IO;
40 41
using System.Threading.Tasks;
......
54 55
    /// TODO: Update summary.
55 56
    /// </summary>
56 57
    [ActiveRecord]
57
    public class FileState:ActiveRecordLinqBase<FileState>
58
    public class FileState : ActiveRecordLinqBase<FileState>
58 59
    {
59 60
        private static readonly ILog Log = LogManager.GetLogger("FileState");
60
        
61

  
61 62
        private string _filePath;
62
        private IList<FileTag> _tags=new List<FileTag>();
63
        private IList<FileTag> _tags = new List<FileTag>();
63 64

  
64 65
        [PrimaryKey(PrimaryKeyType.Guid)]
65 66
        public Guid Id { get; set; }
66 67

  
67
        [Property(Unique=true,UniqueKey="IX_FileState_FilePath")]
68
        [Property(Unique = true, UniqueKey = "IX_FileState_FilePath")]
68 69
        public string FilePath
69 70
        {
70 71
            get { return _filePath; }
......
98 99
        public bool ShareWrite { get; set; }
99 100

  
100 101

  
101
       [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true,Inverse=true)]
102
        [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true, Inverse = true)]
102 103
        public IList<FileTag> Tags
103 104
        {
104
            get { return _tags; }   
105
            set { _tags=value;}
105
            get { return _tags; }
106
            set { _tags = value; }
106 107
        }
107 108

  
108
   
109

  
109 110
        public static FileState FindByFilePath(string absolutePath)
110 111
        {
111 112
            if (string.IsNullOrWhiteSpace(absolutePath))
......
113 114
            Contract.EndContractBlock();
114 115
            try
115 116
            {
117

  
118
                
119

  
116 120
                return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower());
117 121
            }
118 122
            catch (Exception ex)
......
120 124
                Log.Error(ex.ToString());
121 125
                throw;
122 126
            }
123
                
127

  
124 128

  
125 129
        }
126 130

  
127
        public static void DeleteByFilePath(string absolutePath)
131
       /* public static void DeleteByFilePath(string absolutePath)
128 132
        {
129
            if(string.IsNullOrWhiteSpace(absolutePath))
133
            if (string.IsNullOrWhiteSpace(absolutePath))
130 134
                throw new ArgumentNullException("absolutePath");
131 135
            Contract.EndContractBlock();
132
            
133
            Execute((session, instance) =>
134
                             {
135
                                 const string hqlDelete = "delete FileState where FilePath = :path";                                 
136
                                 var deletedEntities = session.CreateQuery(hqlDelete)
137
                                         .SetString("path", absolutePath.ToLower())
138
                                         .ExecuteUpdate();
139
                                 return deletedEntities;
140
                             },null);
141
            
142
        }
136

  
137
            ExecuteWithRetry((session, instance) =>
138
                        {
139
                            const string hqlDelete = "delete FileState where FilePath = :path";
140
                            var deletedEntities = session.CreateQuery(hqlDelete)
141
                                .SetString("path", absolutePath.ToLower())
142
                                .ExecuteUpdate();
143
                            return deletedEntities;
144
                        }, null);
145

  
146
        }*/
143 147

  
144 148
        public static void StoreFileStatus(string absolutePath, FileStatus newStatus)
145 149
        {
......
147 151
                throw new ArgumentNullException("absolutePath");
148 152
            Contract.EndContractBlock();
149 153

  
150
            Execute((session, instance) =>
151
            {
152
                const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path  ";
153
                var updatedEntities = session.CreateQuery(hqlUpdate)
154
                        .SetString("path", absolutePath.ToLower())
155
                        .SetEnum("status", newStatus)
156
                        .ExecuteUpdate();
157
                if (updatedEntities == 0)
158
                {
159
                    var newState = new FileState { FilePath = absolutePath.ToLower(), Id = Guid.NewGuid(), FileStatus = newStatus };
160
                    newState.CreateAndFlush();
161
                }
162
                return null;
163
            }, null);
154
            ExecuteWithRetry((session, instance) =>
155
                        {
156
                            const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path  ";
157
                            var updatedEntities = session.CreateQuery(hqlUpdate)
158
                                .SetString("path", absolutePath.ToLower())
159
                                .SetEnum("status", newStatus)
160
                                .ExecuteUpdate();
161
                            if (updatedEntities == 0)
162
                            {
163
                                var newState = new FileState
164
                                                   {
165
                                                       FilePath = absolutePath.ToLower(),
166
                                                       Id = Guid.NewGuid(),
167
                                                       FileStatus = newStatus
168
                                                   };
169
                                newState.CreateAndFlush();
170
                            }
171
                            return null;
172
                        }, null);
164 173

  
165 174
        }
166 175

  
......
170 179
                throw new ArgumentNullException("absolutePath");
171 180
            Contract.EndContractBlock();
172 181

  
173
            Execute((session, instance) =>
174
            {
175
                const string hqlUpdate = "update FileState set OverlayStatus= :status where FilePath = :path  ";
176
                var updatedEntities = session.CreateQuery(hqlUpdate)
177
                        .SetString("path", absolutePath.ToLower())
178
                        .SetEnum("status", newStatus)
179
                        .ExecuteUpdate();
180
                if (updatedEntities == 0)
181
                {
182
                    var newState = new FileState { FilePath = absolutePath, Id = Guid.NewGuid(), OverlayStatus = newStatus };
183
                    newState.CreateAndFlush();
184
                }
185
                return null;
186
            }, null);
182
            ExecuteWithRetry((session, instance) =>
183
                        {
184
                            const string hqlUpdate =
185
                                "update FileState set OverlayStatus= :status where FilePath = :path  ";
186
                            var updatedEntities = session.CreateQuery(hqlUpdate)
187
                                .SetString("path", absolutePath.ToLower())
188
                                .SetEnum("status", newStatus)
189
                                .ExecuteUpdate();
190
                            if (updatedEntities == 0)
191
                            {
192
                                var newState = new FileState
193
                                                   {
194
                                                       FilePath = absolutePath,
195
                                                       Id = Guid.NewGuid(),
196
                                                       OverlayStatus = newStatus
197
                                                   };
198
                                newState.CreateAndFlush();
199
                            }
200
                            return null;
201
                        }, null);
187 202

  
188 203
        }
189 204

  
205
/*
190 206
        public static void UpdateStatus(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus)
191 207
        {
192 208
            if (string.IsNullOrWhiteSpace(absolutePath))
193 209
                throw new ArgumentNullException("absolutePath");
194 210
            Contract.EndContractBlock();
195 211

  
196
            Execute((session, instance) =>
197
            {
198
                const string hqlUpdate = "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ";
199
                var updatedEntities = session.CreateQuery(hqlUpdate)
200
                        .SetString("path", absolutePath.ToLower())
201
                        .SetEnum("fileStatus", fileStatus)
202
                        .SetEnum("overlayStatus", overlayStatus)
203
                        .ExecuteUpdate();
204
                return updatedEntities;
205
            }, null);
212
            ExecuteWithRetry((session, instance) =>
213
                        {
214
                            const string hqlUpdate =
215
                                "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ";
216
                            var updatedEntities = session.CreateQuery(hqlUpdate)
217
                                .SetString("path", absolutePath.ToLower())
218
                                .SetEnum("fileStatus", fileStatus)
219
                                .SetEnum("overlayStatus", overlayStatus)
220
                                .ExecuteUpdate();
221
                            return updatedEntities;
222
                        }, null);
206 223

  
207 224
        }
225
*/
226

  
227
/*
208 228
        public static void UpdateStatus(string absolutePath, FileStatus fileStatus)
209 229
        {
210 230
            if (string.IsNullOrWhiteSpace(absolutePath))
211 231
                throw new ArgumentNullException("absolutePath");
212 232
            Contract.EndContractBlock();
213 233

  
214
            Execute((session, instance) =>
215
            {
216
                const string hqlUpdate = "update FileState set FileStatus= :fileStatus where FilePath = :path  ";
217
                var updatedEntities = session.CreateQuery(hqlUpdate)
218
                        .SetString("path", absolutePath.ToLower())
219
                        .SetEnum("fileStatus", fileStatus)                        
220
                        .ExecuteUpdate();
221
                return updatedEntities;
222
            }, null);
234
            ExecuteWithRetry((session, instance) =>
235
                        {
236
                            const string hqlUpdate =
237
                                "update FileState set FileStatus= :fileStatus where FilePath = :path  ";
238
                            var updatedEntities = session.CreateQuery(hqlUpdate)
239
                                .SetString("path", absolutePath.ToLower())
240
                                .SetEnum("fileStatus", fileStatus)
241
                                .ExecuteUpdate();
242
                            return updatedEntities;
243
                        }, null);
223 244

  
224 245
        }
225 246

  
247
*/
226 248
        public static void RenameState(string oldPath, string newPath)
227 249
        {
228 250
            if (string.IsNullOrWhiteSpace(oldPath))
229 251
                throw new ArgumentNullException("oldPath");
230 252
            Contract.EndContractBlock();
231 253

  
232
            Execute((session, instance) =>
233
            {
234
                const string hqlUpdate = "update FileState set FilePath= :newPath where FilePath = :oldPath  ";
235
                var updatedEntities = session.CreateQuery(hqlUpdate)
236
                        .SetString("oldPath", oldPath.ToLower())
237
                        .SetString("newPath", newPath.ToLower())                                          
238
                        .ExecuteUpdate();
239
                return updatedEntities;
240
            }, null);
254
            ExecuteWithRetry((session, instance) =>
255
                        {
256
                            const string hqlUpdate =
257
                                "update FileState set FilePath= :newPath where FilePath = :oldPath  ";
258
                            var updatedEntities = session.CreateQuery(hqlUpdate)
259
                                .SetString("oldPath", oldPath.ToLower())
260
                                .SetString("newPath", newPath.ToLower())
261
                                .ExecuteUpdate();
262
                            return updatedEntities;
263
                        }, null);
241 264

  
242 265
        }
243 266

  
244
        public static void UpdateStatus(Guid id, FileStatus fileStatus)
267
     /*   public static void UpdateStatus(Guid id, FileStatus fileStatus)
245 268
        {
246
            Contract.EndContractBlock();
247 269

  
248
            Execute((session, instance) =>
270
            ExecuteWithRetry((session, instance) =>
249 271
            {
250
                const string hqlUpdate = "update FileState set FileStatus= :fileStatus where Id = :id  ";
272
                const string hqlUpdate =
273
                    "update FileState set FileStatus= :fileStatus where Id = :id  ";
251 274
                var updatedEntities = session.CreateQuery(hqlUpdate)
252
                        .SetGuid("id", id)
253
                        .SetEnum("fileStatus", fileStatus)                        
254
                        .ExecuteUpdate();
275
                    .SetGuid("id", id)
276
                    .SetEnum("fileStatus", fileStatus)
277
                    .ExecuteUpdate();
255 278
                return updatedEntities;
256 279
            }, null);
257

  
258
        }
280
        }*/
259 281

  
260 282
        public static void UpdateChecksum(string absolutePath, string checksum)
261 283
        {
......
263 285
                throw new ArgumentNullException("absolutePath");
264 286
            Contract.EndContractBlock();
265 287

  
266
            Execute((session, instance) =>
267
            {
268
                const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path  ";
269
                var updatedEntities = session.CreateQuery(hqlUpdate)
270
                        .SetString("path", absolutePath.ToLower())
271
                        .SetString("checksum", checksum)                        
272
                        .ExecuteUpdate();
273
                return updatedEntities;
274
            }, null);
288
            ExecuteWithRetry((session, instance) =>
289
                        {
290
                            const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path  ";
291
                            var updatedEntities = session.CreateQuery(hqlUpdate)
292
                                .SetString("path", absolutePath.ToLower())
293
                                .SetString("checksum", checksum)
294
                                .ExecuteUpdate();
295
                            return updatedEntities;
296
                        }, null);
275 297

  
276 298
        }
277 299

  
278
        public static void ChangeRootPath(string oldPath,string newPath)
300
        public static void ChangeRootPath(string oldPath, string newPath)
279 301
        {
280 302
            if (String.IsNullOrWhiteSpace(oldPath))
281 303
                throw new ArgumentNullException("oldPath");
......
293 315
            if (!newPath.EndsWith("\\"))
294 316
                newPath = newPath + "\\";
295 317

  
296
            using (new TransactionScope())
297
            {
298
                Execute((session, instance) =>
318
                ExecuteWithRetry((session, instance) =>
299 319
                            {
300 320
                                const string hqlUpdate =
301 321
                                    "update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' ";
302
                                var renames=session.CreateQuery(hqlUpdate)
322
                                var renames = session.CreateQuery(hqlUpdate)
303 323
                                    .SetString("oldPath", oldPath.ToLower())
304 324
                                    .SetString("newPath", newPath.ToLower())
305 325
                                    .ExecuteUpdate();
306 326
                                return renames;
307 327
                            }, null);
308
            }
309 328
        }
310 329

  
311
        public static Task<FileState> CreateForAsync(string filePath,int blockSize,string algorithm)
330
        public static Task<FileState> CreateForAsync(string filePath, int blockSize, string algorithm)
312 331
        {
313 332
            if (blockSize <= 0)
314 333
                throw new ArgumentOutOfRangeException("blockSize");
......
319 338

  
320 339
            var fileState = new FileState
321 340
                                {
322
                                    FilePath = filePath.ToLower(), 
323
                                    OverlayStatus = FileOverlayStatus.Unversioned, 
341
                                    FilePath = filePath.ToLower(),
342
                                    OverlayStatus = FileOverlayStatus.Unversioned,
324 343
                                    FileStatus = FileStatus.Created,
325
                                    Id=Guid.NewGuid()
344
                                    Id = Guid.NewGuid()
326 345
                                };
327 346

  
328 347

  
329
            return fileState.UpdateHashesAsync(blockSize,algorithm);            
348
            return fileState.UpdateHashesAsync(blockSize, algorithm);
330 349
        }
331 350

  
332
        public async Task<FileState> UpdateHashesAsync(int blockSize,string algorithm)
351
        public async Task<FileState> UpdateHashesAsync(int blockSize, string algorithm)
333 352
        {
334
            if (blockSize<=0)
353
            if (blockSize <= 0)
335 354
                throw new ArgumentOutOfRangeException("blockSize");
336 355
            if (String.IsNullOrWhiteSpace(algorithm))
337 356
                throw new ArgumentNullException("algorithm");
338 357
            Contract.EndContractBlock();
339
            
358

  
340 359
            //Skip updating the hash for folders
341 360
            if (Directory.Exists(FilePath))
342 361
                return this;
343 362

  
344 363
            var hash = await TaskEx.Run(() =>
345
            {
346
                var info = new FileInfo(FilePath);
347
                return info.CalculateHash(blockSize, algorithm);
348
            });
364
                                            {
365
                                                var info = new FileInfo(FilePath);
366
                                                return info.CalculateHash(blockSize, algorithm);
367
                                            });
349 368

  
350 369
            Checksum = hash;
351
            
370

  
352 371
            return this;
353 372
        }
373

  
374
        private static void ExecuteWithRetry(NHibernateDelegate call, object state)
375
        {
376
            int retries = 3;
377
            while (retries > 0)
378
                try
379
                {
380
                    using (new SessionScope())
381
                    {
382
                        Execute(call, state);
383
                    }
384
                }
385
                catch (ActiveRecordException exc)
386
                {
387
                    retries--;
388
                    if (retries <= 0)
389
                        throw;
390
                }
391
                catch (Exception exc)
392
                {
393
                    throw;
394
                }
395

  
396
        }
354 397
    }
355 398

  
356 399
    [ActiveRecord("Tags")]
b/trunk/Pithos.Interfaces/FileInfoExtensions.cs
74 74
            var parentDirInfo = dirInfo.Parent;
75 75
            if (null == parentDirInfo)
76 76
                return dirInfo.Name;
77
            return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo.FullName),
78
                                parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
77

  
78
            try
79
            {
80

  
81

  
82
                if (dirInfo.Exists)
83
                    return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo.FullName),
84
                                        parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
85
                else
86
                {
87
                    return dirInfo.FullName;
88
                }
89
            }
90
            catch (DirectoryNotFoundException)
91
            {
92
                //An exception can occur if a directory is deleted right after the Exists call
93
                return dirInfo.FullName;
94
            }
79 95
        }
80 96

  
81 97

  
......
104 120
            //Directory will not be null for an absolute path
105 121
            Contract.Assume(dirInfo != null);
106 122

  
107
            return Path.Combine(GetProperDirectoryCapitalization(dirInfo.FullName),
108
                                dirInfo.GetFiles(fileInfo.Name)[0].Name);
123
            try
124
            {
125

  
126
                if (fileInfo.Exists)
127
                    return Path.Combine(GetProperDirectoryCapitalization(dirInfo.FullName),
128
                                        dirInfo.GetFiles(fileInfo.Name)[0].Name);
129
                else
130
                {
131
                    return fileInfo.FullName;
132
                }
133
            }
134
            catch (FileNotFoundException)
135
            {
136
                //An exception can occur if a file is deleted right after the Exists call
137
                return fileInfo.FullName;
138

  
139
            }
109 140
        }
110 141

  
111 142
        public static string GetProperCapitalization(this FileSystemInfo info)

Also available in: Unified diff