Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / FileState.cs @ ab2f6f79

History | View | Annotate | Download (12.8 kB)

1
// -----------------------------------------------------------------------
2
// <copyright file="FileState.cs" company="Microsoft">
3
// TODO: Update copyright text.
4
// </copyright>
5
// -----------------------------------------------------------------------
6

    
7
using System.Diagnostics.Contracts;
8
using System.IO;
9
using System.Threading.Tasks;
10
using Castle.ActiveRecord;
11
using Castle.ActiveRecord.Framework;
12
using Castle.ActiveRecord.Queries;
13
using NHibernate.Engine;
14
using Pithos.Core.Agents;
15
using Pithos.Interfaces;
16
using Pithos.Network;
17

    
18
namespace Pithos.Core
19
{
20
    using System;
21
    using System.Collections.Generic;
22
    using System.Linq;
23
    using System.Text;
24

    
25
    /// <summary>
26
    /// TODO: Update summary.
27
    /// </summary>
28
    [ActiveRecord]
29
    public class FileState:ActiveRecordLinqBase<FileState>
30
    {
31
        private string _filePath;
32
        private IList<FileTag> _tags=new List<FileTag>();
33

    
34
        [PrimaryKey(PrimaryKeyType.Guid)]
35
        public Guid Id { get; set; }
36

    
37
        [Property(Unique=true,UniqueKey="IX_FileState_FilePath")]
38
        public string FilePath
39
        {
40
            get { return _filePath; }
41
            set { _filePath = value.ToLower(); }
42
        }
43

    
44
        [Property]
45
        public FileOverlayStatus OverlayStatus { get; set; }
46

    
47
        [Property]
48
        public FileStatus FileStatus { get; set; }
49

    
50
        [Property]
51
        public string Checksum { get; set; }
52

    
53
/*
54
        [Property]
55
        public string TopHash { get; set; }
56
*/
57

    
58
        [Property]
59
        public long? Version { get; set; }
60

    
61
        [Property]
62
        public DateTime? VersionTimeStamp { get; set; }
63

    
64

    
65
        [Property]
66
        public bool IsShared { get; set; }
67

    
68
        [Property]
69
        public string SharedBy { get; set; }
70

    
71
        [Property]
72
        public bool ShareWrite { get; set; }
73

    
74

    
75
       [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true,Inverse=true)]
76
        public IList<FileTag> Tags
77
        {
78
            get { return _tags; }   
79
            set { _tags=value;}
80
        }
81

    
82
//        [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true)]
83
//        public IList<FileHash> Hashes { get; set; }
84

    
85
//        [Property]
86
//        public byte[] HashmapHash { get; set; }
87
       
88
        public static FileState FindByFilePath(string absolutePath)
89
        {
90
            if (string.IsNullOrWhiteSpace(absolutePath))
91
                throw new ArgumentNullException("absolutePath");
92
            Contract.EndContractBlock();
93
            return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower());
94
        }
95

    
96
        public static void DeleteByFilePath(string absolutePath)
97
        {
98
            if(string.IsNullOrWhiteSpace(absolutePath))
99
                throw new ArgumentNullException("absolutePath");
100
            Contract.EndContractBlock();
101
            
102
            FileState.Execute((session, instance) =>
103
                             {
104
                                 const string hqlDelete = "delete FileState where FilePath = :path";                                 
105
                                 var deletedEntities = session.CreateQuery(hqlDelete)
106
                                         .SetString("path", absolutePath.ToLower())
107
                                         .ExecuteUpdate();
108
                                 return null;
109
                             },null);
110
            
111
        }
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

    
247
        public static void ChangeRootPath(string oldPath,string newPath)
248
        {
249
            if (String.IsNullOrWhiteSpace(oldPath))
250
                throw new ArgumentNullException("oldPath");
251
            if (!Path.IsPathRooted(oldPath))
252
                throw new ArgumentException("oldPath must be an absolute path", "oldPath");
253
            if (string.IsNullOrWhiteSpace(newPath))
254
                throw new ArgumentNullException("newPath");
255
            if (!Path.IsPathRooted(newPath))
256
                throw new ArgumentException("newPath must be an absolute path", "newPath");
257
            Contract.EndContractBlock();
258

    
259
            //Ensure the paths end with the same character
260
            if (!oldPath.EndsWith("\\"))
261
                oldPath = oldPath + "\\";
262
            if (!newPath.EndsWith("\\"))
263
                newPath = newPath + "\\";
264

    
265
            using (new TransactionScope())
266
            {
267
                Execute((session, instance) =>
268
                            {
269
                                const string hqlUpdate =
270
                                    "update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' ";
271
                                var result=session.CreateQuery(hqlUpdate)
272
                                    .SetString("oldPath", oldPath.ToLower())
273
                                    .SetString("newPath", newPath.ToLower())
274
                                    .ExecuteUpdate();
275
                                return null;
276
                            }, null);
277
            }
278
        }
279

    
280
        public static Task<FileState> CreateForAsync(string filePath,int blockSize,string algorithm)
281
        {
282
            if (blockSize <= 0)
283
                throw new ArgumentOutOfRangeException("blockSize");
284
            if (String.IsNullOrWhiteSpace(algorithm))
285
                throw new ArgumentNullException("algorithm");
286
            Contract.EndContractBlock();
287

    
288

    
289
            var fileState = new FileState
290
                                {
291
                                    FilePath = filePath, 
292
                                    OverlayStatus = FileOverlayStatus.Unversioned, 
293
                                    FileStatus = FileStatus.Created,
294
                                    Id=Guid.NewGuid()
295
                                };
296

    
297

    
298
            return fileState.UpdateHashesAsync(blockSize,algorithm);            
299
        }
300

    
301
        public Task<FileState> UpdateHashesAsync(int blockSize,string algorithm)
302
        {
303
            if (blockSize<=0)
304
                throw new ArgumentOutOfRangeException("blockSize");
305
            if (String.IsNullOrWhiteSpace(algorithm))
306
                throw new ArgumentNullException("algorithm");
307
            Contract.EndContractBlock();
308
            
309
            //Skip updating the hash for folders
310
            if (Directory.Exists(FilePath))
311
                return Task.Factory.FromResult(this);
312

    
313
            var results = Task.Factory.StartNew(() =>
314
            {
315
                var info = new FileInfo(FilePath);
316
                return info.CalculateHash(blockSize, algorithm);
317
            });
318

    
319
            var state=results.Then(hash =>
320
            {
321
                Checksum = hash;
322
                return Task.Factory.FromResult(this);
323
            });
324
            
325
            return state;
326
        }
327
    }
328

    
329
    [ActiveRecord("Tags")]
330
    public class FileTag : ActiveRecordLinqBase<FileTag>
331
    {
332
        [PrimaryKey]
333
        public int Id { get; set; }
334

    
335
        [Property]
336
        public string Name { get; set; }
337

    
338
        [Property]
339
        public string Value { get; set; }
340

    
341
        [BelongsTo("FileStateId")]
342
        public FileState FileState { get; set; }
343

    
344
    }
345
    
346
  /*  [ActiveRecord("hashes")]
347
    public class FileHash : ActiveRecordLinqBase<FileHash>
348
    {
349
        [PrimaryKey]
350
        public int Id { get; set; }
351

    
352
        [Property]
353
        public int Order { get; set; }
354

    
355
        [Property]
356
        public byte[] Value { get; set; }        
357

    
358
        [BelongsTo("FileStateID")]
359
        public FileState FileState { get; set; }
360

    
361
    }*/
362

    
363

    
364
}