Revision ab2f6f79

b/trunk/Pithos.Core/Agents/StatusAgent.cs
143 143
                    //This file was deleted while we were down. We should mark it as deleted
144 144
                    //We have to go through UpdateStatus here because the state object we are using
145 145
                    //was created by a different ORM session.
146
                    UpdateStatus(fileState.Id,state=> state.FileStatus = FileStatus.Deleted);                    
146
                    FileState.UpdateStatus(fileState.Id,FileStatus.Deleted);                    
147 147
                }
148 148
                else
149 149
                {
......
152 152
                    //If the hashes don't match the file was changed
153 153
                    if (fileState.Checksum != hashString)
154 154
                    {
155
                        UpdateStatus(fileState.Id, state => state.FileStatus = FileStatus.Modified);
155
                        FileState.UpdateStatus(fileState.Id, FileStatus.Modified);
156 156
                    }                    
157 157
                }
158 158
            });            
......
195 195

  
196 196

  
197 197
        private string _pithosDataPath;
198

  
199
        public T GetStatus<T>(string path,Func<FileState,T> getter,T defaultValue )
200
        {
201
            if (String.IsNullOrWhiteSpace(path))
202
                throw new ArgumentNullException("path");
203
            if (!Path.IsPathRooted(path))
204
                throw new ArgumentException("path must be a rooted path", "path");
205
            if (getter == null)
206
                throw new ArgumentNullException("getter");
207
            Contract.EndContractBlock();
208

  
209

  
210
            try
211
            {                
212
                var state = FileState.FindByFilePath(path);
213
                return state == null ? defaultValue : getter(state);
214
            }
215
            catch (Exception exc)
216
            {
217
                Log.ErrorFormat(exc.ToString());
218
                return defaultValue;
219
            }
220
        }
221

  
222
        /// <summary>
223
        /// Sets the status of a file, creating a new FileState entry if one doesn't already exist.
224
        /// </summary>
225
        /// <param name="path"></param>
226
        /// <param name="setter"></param>
227
        public void SetStatus(string path,Action<FileState> setter)
228
        {
229
            if (String.IsNullOrWhiteSpace(path))
230
                throw new ArgumentNullException("path", "path can't be empty");
231
            if (setter==null)
232
                throw new ArgumentNullException("setter", "setter can't be empty");
233
            Contract.EndContractBlock();
234

  
235
            _persistenceAgent.Post(() =>
236
            {
237
                using (new SessionScope())
238
                {
239
                    var filePath = path.ToLower();
240
                    var state = FileState.FindByFilePath(filePath);
241
                    if (state != null)
242
                    {
243
                        setter(state);
244
                        state.Save();
245
                    }
246
                    else
247
                    {
248
                        state = new FileState {FilePath = filePath};
249
                        setter(state);
250
                        state.Save();
251
                    }                    
252
                }
253
            });
254
        }
255

  
256
        /// <summary>
257
        /// Sets the status of a file only if the file already exists
258
        /// </summary>
259
        /// <param name="path"></param>
260
        /// <param name="setter"></param>
261
        private void UpdateStatus(string path, Action<FileState> setter)
262
        {
263
            if (String.IsNullOrWhiteSpace(path))
264
                throw new ArgumentNullException("path");
265
            if (!Path.IsPathRooted(path))
266
                throw new ArgumentException("The path must be rooted", "path");
267
            if (setter == null)
268
                throw new ArgumentNullException("setter");
269
            Contract.EndContractBlock();
270

  
271
            Debug.Assert(!path.Contains(FolderConstants.CacheFolder));
272
            Debug.Assert(!path.EndsWith(".ignore"));
273

  
274
            if (String.IsNullOrWhiteSpace(path))
275
                throw new ArgumentNullException("path", "path can't be empty");
276

  
277
            if (setter == null)
278
                throw new ArgumentNullException("setter", "setter can't be empty");
279

  
280
            _persistenceAgent.Post(() =>
281
            {
282
                using (new SessionScope())
283
                {
284
                    var filePath = path.ToLower();
285

  
286
                    var state = FileState.FindByFilePath(filePath);
287
                    if (state == null)
288
                    {
289
                        Log.WarnFormat("[NOFILE] Unable to set status for {0}.", filePath);
290
                        return;
291
                    }
292
                    setter(state);
293
                    state.Save();
294
                }
295
                
296
            });
297
        }
298
        
299
        /// <summary>
300
        /// Sets the status of a specific state
301
        /// </summary>
302
        /// <param name="path"></param>
303
        /// <param name="setter"></param>
304
        private void UpdateStatus(Guid stateID, Action<FileState> setter)
305
        {
306
            if (setter == null)
307
                throw new ArgumentNullException("setter");
308
            Contract.EndContractBlock();
309

  
310

  
311
            _persistenceAgent.Post(() =>
312
            {
313
                using (new SessionScope())
314
                {
315
                    var state = FileState.Find(stateID);
316
                    if (state == null)
317
                    {
318
                        Log.WarnFormat("[NOFILE] Unable to set status for {0}.", stateID);
319
                        return;
320
                    }
321
                    setter(state);
322
                    state.Save();
323
                }
324
                
325
            });
326
        }
198
       
327 199

  
328 200
        public FileOverlayStatus GetFileOverlayStatus(string path)
329 201
        {
......
335 207

  
336 208
            try
337 209
            {
338
                var state = FileState.FindByFilePath(path);
339
                return state == null ? FileOverlayStatus.Unversioned : state.OverlayStatus;
210
                var status = from state in  FileState.Queryable 
211
                                 where state.FilePath ==path.ToLower()
212
                                 select state.OverlayStatus;
213
                return status.Any()? status.First():FileOverlayStatus.Unversioned;
340 214
            }
341 215
            catch (Exception exc)
342 216
            {
......
353 227
                throw new ArgumentException("The path must be rooted","path");
354 228
            Contract.EndContractBlock();
355 229

  
356
            SetStatus(path.ToLower(),s=>s.OverlayStatus=overlayStatus);
230
            _persistenceAgent.Post(() => FileState.StoreOverlayStatus(path.ToLower(),overlayStatus));
357 231
        }
358 232

  
359 233
        /*public void RemoveFileOverlayStatus(string path)
......
391 265
                throw new ArgumentException("The newPath must be rooted", "newPath");
392 266
            Contract.EndContractBlock();
393 267

  
394
            _persistenceAgent.Post(() =>
395
                InnerRenameFileOverlayStatus(oldPath, newPath));
396
        }
397

  
398
        private static void InnerRenameFileOverlayStatus(string oldPath, string newPath)
399
        {
400
            if (String.IsNullOrWhiteSpace(oldPath))
401
                throw new ArgumentNullException("oldPath");
402
            if (!Path.IsPathRooted(oldPath))
403
                throw new ArgumentException("The oldPath must be rooted", "oldPath");
404
            if (String.IsNullOrWhiteSpace(newPath))
405
                throw new ArgumentNullException("newPath");
406
            if (!Path.IsPathRooted(newPath))
407
                throw new ArgumentException("The newPath must be rooted", "newPath");
408
            Contract.EndContractBlock();
409

  
410
            var state = FileState.FindByFilePath(oldPath);
411

  
412
            if (state == null)
413
            {
414
                Log.WarnFormat("[NOFILE] Unable to set status for {0}.", oldPath);
415
                return;
416
            }
417
            //NOTE: This will cause problems if path is used as a key in relationships
418
            state.FilePath = newPath;
419
            state.Update();
268
            _persistenceAgent.Post(() =>FileState.RenameState(oldPath, newPath));
420 269
        }
421 270

  
422 271
        public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus)
......
427 276
                throw new ArgumentException("The path must be rooted", "path");
428 277
            Contract.EndContractBlock();
429 278

  
430
            UpdateStatus(path.ToLower(),state=>
431
                                  {
432
                                      state.FileStatus = fileStatus;
433
                                      state.OverlayStatus = overlayStatus;
434
                                  });            
279
            Debug.Assert(!path.Contains(FolderConstants.CacheFolder));
280
            Debug.Assert(!path.EndsWith(".ignore"));
281

  
282
            _persistenceAgent.Post(() => FileState.UpdateStatus(path.ToLower(), fileStatus, overlayStatus));
435 283
        }
436 284

  
437 285
        public void StoreInfo(string path,ObjectInfo objectInfo)
......
453 301
                    //Forgetting to use a sessionscope results in two sessions being created, one by 
454 302
                    //FirstOrDefault and one by Save()
455 303
                    var state =FileState.FindByFilePath(filePath);
304
                    
456 305
                    //Create a new empty state object if this is a new file
457 306
                    state = state ?? new FileState();
458 307

  
......
485 334

  
486 335
        
487 336
        public void SetFileStatus(string path, FileStatus status)
488
        {            
489
            UpdateStatus(path.ToLower(), state=>state.FileStatus = status);
337
        {
338
            if (String.IsNullOrWhiteSpace(path))
339
                throw new ArgumentNullException("path");
340
            if (!Path.IsPathRooted(path))
341
                throw new ArgumentException("The path must be rooted", "path");
342
            Contract.EndContractBlock();
343

  
344
            _persistenceAgent.Post(() => FileState.UpdateStatus(path.ToLower(), status));
490 345
        }
491 346

  
492 347
        public FileStatus GetFileStatus(string path)
......
497 352
                throw new ArgumentException("The path must be rooted", "path");
498 353
            Contract.EndContractBlock();
499 354

  
500
            var state = FileState.FindByFilePath(path);
501
            return (state==null)?FileStatus.Missing:state.FileStatus ;
355
            var status = from r in FileState.Queryable
356
                     where r.FilePath == path.ToLower()
357
                     select r.FileStatus;                        
358
            return status.Any()?status.First(): FileStatus.Missing;
502 359
        }
503 360

  
504 361
        public void ClearFileStatus(string path)
......
527 384
                throw new ArgumentException("The path must be rooted", "path");            
528 385
            Contract.EndContractBlock();
529 386

  
530
            _persistenceAgent.Post(() =>
531
            {
532
                using (new SessionScope())
533
                {
534
                    var state = FileState.FindByFilePath(path);
535
                    if (state == null)
536
                    {
537
                        Log.WarnFormat("[NOFILE] Unable to set checkesum for {0}.", path);
538
                        return;
539
                    }
540
                    state.Checksum = checksum;
541
                    state.Update();
542
                }
543
            });
387
            _persistenceAgent.Post(() => FileState.UpdateChecksum(path.ToLower(), checksum));
544 388
        }
545 389

  
546 390
    }
b/trunk/Pithos.Core/FileState.cs
110 110
            
111 111
        }
112 112

  
113
        public static void StoreFileStatus(string absolutePath, FileStatus newStatus)
114
        {
115
            if (string.IsNullOrWhiteSpace(absolutePath))
116
                throw new ArgumentNullException("absolutePath");
117
            Contract.EndContractBlock();
118

  
119
            Execute((session, instance) =>
120
            {
121
                const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path  ";
122
                var updatedEntities = session.CreateQuery(hqlUpdate)
123
                        .SetString("path", absolutePath.ToLower())
124
                        .SetEnum("status", newStatus)
125
                        .ExecuteUpdate();
126
                if (updatedEntities == 0)
127
                {
128
                    var newState = new FileState { FilePath = absolutePath, Id = Guid.NewGuid(), FileStatus = newStatus };
129
                    newState.CreateAndFlush();
130
                }
131
                return null;
132
            }, null);
133

  
134
        }
135

  
136
        public static void StoreOverlayStatus(string absolutePath, FileOverlayStatus newStatus)
137
        {
138
            if (string.IsNullOrWhiteSpace(absolutePath))
139
                throw new ArgumentNullException("absolutePath");
140
            Contract.EndContractBlock();
141

  
142
            Execute((session, instance) =>
143
            {
144
                const string hqlUpdate = "update FileState set OverlayStatus= :status where FilePath = :path  ";
145
                var updatedEntities = session.CreateQuery(hqlUpdate)
146
                        .SetString("path", absolutePath.ToLower())
147
                        .SetEnum("status", newStatus)
148
                        .ExecuteUpdate();
149
                if (updatedEntities == 0)
150
                {
151
                    var newState = new FileState { FilePath = absolutePath, Id = Guid.NewGuid(), OverlayStatus = newStatus };
152
                    newState.CreateAndFlush();
153
                }
154
                return null;
155
            }, null);
156

  
157
        }
158

  
159
        public static void UpdateStatus(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus)
160
        {
161
            if (string.IsNullOrWhiteSpace(absolutePath))
162
                throw new ArgumentNullException("absolutePath");
163
            Contract.EndContractBlock();
164

  
165
            Execute((session, instance) =>
166
            {
167
                const string hqlUpdate = "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ";
168
                var updatedEntities = session.CreateQuery(hqlUpdate)
169
                        .SetString("path", absolutePath.ToLower())
170
                        .SetEnum("fileStatus", fileStatus)
171
                        .SetEnum("overlayStatus", overlayStatus)
172
                        .ExecuteUpdate();
173
                return null;
174
            }, null);
175

  
176
        }
177
        public static void UpdateStatus(string absolutePath, FileStatus fileStatus)
178
        {
179
            if (string.IsNullOrWhiteSpace(absolutePath))
180
                throw new ArgumentNullException("absolutePath");
181
            Contract.EndContractBlock();
182

  
183
            Execute((session, instance) =>
184
            {
185
                const string hqlUpdate = "update FileState set FileStatus= :fileStatus where FilePath = :path  ";
186
                var updatedEntities = session.CreateQuery(hqlUpdate)
187
                        .SetString("path", absolutePath.ToLower())
188
                        .SetEnum("fileStatus", fileStatus)                        
189
                        .ExecuteUpdate();
190
                return updatedEntities;
191
            }, null);
192

  
193
        }
194

  
195
        public static void RenameState(string oldPath, string newPath)
196
        {
197
            if (string.IsNullOrWhiteSpace(oldPath))
198
                throw new ArgumentNullException("oldPath");
199
            Contract.EndContractBlock();
200

  
201
            Execute((session, instance) =>
202
            {
203
                const string hqlUpdate = "update FileState set FilePath= :newPath where FilePath = :oldPath  ";
204
                var updatedEntities = session.CreateQuery(hqlUpdate)
205
                        .SetString("oldPath", oldPath.ToLower())
206
                        .SetString("newPath", newPath.ToLower())                                          
207
                        .ExecuteUpdate();
208
                return updatedEntities;
209
            }, null);
210

  
211
        }
212

  
213
        public static void UpdateStatus(Guid id, FileStatus fileStatus)
214
        {
215
            Contract.EndContractBlock();
216

  
217
            Execute((session, instance) =>
218
            {
219
                const string hqlUpdate = "update FileState set FileStatus= :fileStatus where Id = :id  ";
220
                var updatedEntities = session.CreateQuery(hqlUpdate)
221
                        .SetGuid("id", id)
222
                        .SetEnum("fileStatus", fileStatus)                        
223
                        .ExecuteUpdate();
224
                return null;
225
            }, null);
226

  
227
        }
228

  
229
        public static void UpdateChecksum(string absolutePath, string checksum)
230
        {
231
            if (string.IsNullOrWhiteSpace(absolutePath))
232
                throw new ArgumentNullException("absolutePath");
233
            Contract.EndContractBlock();
234

  
235
            Execute((session, instance) =>
236
            {
237
                const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path  ";
238
                var updatedEntities = session.CreateQuery(hqlUpdate)
239
                        .SetString("path", absolutePath.ToLower())
240
                        .SetString("checksum", checksum)                        
241
                        .ExecuteUpdate();
242
                return null;
243
            }, null);
244

  
245
        }
246

  
113 247
        public static void ChangeRootPath(string oldPath,string newPath)
114 248
        {
115 249
            if (String.IsNullOrWhiteSpace(oldPath))
b/trunk/Pithos.Core/IStatusKeeper.cs
22 22
        void Stop();
23 23
        void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus);
24 24
        void StoreInfo(string path, ObjectInfo objectInfo);
25
        T GetStatus<T>(string path,Func<FileState,T> getter,T defaultValue );
26
        void SetStatus(string path, Action<FileState> setter);        
25
        //T GetStatus<T>(string path,Func<FileState,T> getter,T defaultValue );
26
        //void SetStatus(string path, Action<FileState> setter);        
27 27

  
28 28
        void StartProcessing(CancellationToken token);
29 29

  
b/trunk/Pithos.sln
36 36
EndProject
37 37
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Pithos.Setup.x86", "Pithos.Setup.x86\Pithos.Setup.x86.vdproj", "{0D7E50F2-D7B4-4458-AA01-2CAC0F386737}"
38 38
EndProject
39
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetworkTests", "Tests\NetworkTests\NetworkTests.csproj", "{052D04DA-28FE-471F-96FD-BC1E92BF2A54}"
40
EndProject
41 39
Global
42 40
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
43 41
		Debug All|Any CPU = Debug All|Any CPU
......
534 532
		{0D7E50F2-D7B4-4458-AA01-2CAC0F386737}.Test|Mixed Platforms.ActiveCfg = Release
535 533
		{0D7E50F2-D7B4-4458-AA01-2CAC0F386737}.Test|x64.ActiveCfg = Release
536 534
		{0D7E50F2-D7B4-4458-AA01-2CAC0F386737}.Test|x86.ActiveCfg = Release
537
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug All|Any CPU.ActiveCfg = Debug|x86
538
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug All|Mixed Platforms.ActiveCfg = Debug|x86
539
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug All|Mixed Platforms.Build.0 = Debug|x86
540
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug All|x64.ActiveCfg = Debug|x86
541
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug All|x86.ActiveCfg = Debug|x86
542
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug All|x86.Build.0 = Debug|x86
543
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug|Any CPU.ActiveCfg = Debug|x86
544
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
545
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug|Mixed Platforms.Build.0 = Debug|x86
546
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug|x64.ActiveCfg = Debug|x86
547
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug|x86.ActiveCfg = Debug|x86
548
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Debug|x86.Build.0 = Debug|x86
549
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Premium Debug|Any CPU.ActiveCfg = Debug|x86
550
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Premium Debug|Mixed Platforms.ActiveCfg = Debug|x86
551
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Premium Debug|Mixed Platforms.Build.0 = Debug|x86
552
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Premium Debug|x64.ActiveCfg = Debug|x86
553
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Premium Debug|x86.ActiveCfg = Debug|x86
554
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Premium Debug|x86.Build.0 = Debug|x86
555
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Release|Any CPU.ActiveCfg = Release|x86
556
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Release|Mixed Platforms.ActiveCfg = Release|x86
557
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Release|Mixed Platforms.Build.0 = Release|x86
558
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Release|x64.ActiveCfg = Release|x86
559
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Release|x86.ActiveCfg = Release|x86
560
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Release|x86.Build.0 = Release|x86
561
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Test|Any CPU.ActiveCfg = Release|x86
562
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Test|Mixed Platforms.ActiveCfg = Release|x86
563
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Test|Mixed Platforms.Build.0 = Release|x86
564
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Test|x64.ActiveCfg = Release|x86
565
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Test|x86.ActiveCfg = Release|x86
566
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54}.Test|x86.Build.0 = Release|x86
567 535
	EndGlobalSection
568 536
	GlobalSection(SolutionProperties) = preSolution
569 537
		HideSolutionNode = FALSE
......
573 541
		{2CFE2DF1-20AE-47E2-B1BB-36B974600BE1} = {B5DD7C4D-D396-4C55-A8D5-DCFE865AA095}
574 542
		{E027200B-C26A-4877-BFD9-1A18CF5DF2F4} = {B5DD7C4D-D396-4C55-A8D5-DCFE865AA095}
575 543
		{F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA} = {B5DD7C4D-D396-4C55-A8D5-DCFE865AA095}
576
		{052D04DA-28FE-471F-96FD-BC1E92BF2A54} = {B5DD7C4D-D396-4C55-A8D5-DCFE865AA095}
577 544
	EndGlobalSection
578 545
EndGlobal

Also available in: Unified diff