root / trunk / Pithos.Core / FileState.cs @ 4ec636f6
History | View | Annotate | Download (7.6 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 |
using log4net; |
18 |
|
19 |
namespace Pithos.Core |
20 |
{ |
21 |
using System; |
22 |
using System.Collections.Generic; |
23 |
using System.Linq; |
24 |
using System.Text; |
25 |
|
26 |
/// <summary> |
27 |
/// TODO: Update summary. |
28 |
/// </summary> |
29 |
[ActiveRecord] |
30 |
public class FileState:ActiveRecordLinqBase<FileState> |
31 |
{ |
32 |
private static readonly ILog Log = LogManager.GetLogger("FileState"); |
33 |
|
34 |
private string _filePath; |
35 |
private IList<FileTag> _tags=new List<FileTag>(); |
36 |
|
37 |
[PrimaryKey(PrimaryKeyType.Guid)] |
38 |
public Guid Id { get; set; } |
39 |
|
40 |
[Property(Unique=true,UniqueKey="IX_FileState_FilePath")] |
41 |
public string FilePath |
42 |
{ |
43 |
get { return _filePath; } |
44 |
set { _filePath = value.ToLower(); } |
45 |
} |
46 |
|
47 |
[Property] |
48 |
public FileOverlayStatus OverlayStatus { get; set; } |
49 |
|
50 |
[Property] |
51 |
public FileStatus FileStatus { get; set; } |
52 |
|
53 |
[Property] |
54 |
public string Checksum { get; set; } |
55 |
|
56 |
/* |
57 |
[Property] |
58 |
public string TopHash { get; set; } |
59 |
*/ |
60 |
|
61 |
[Property] |
62 |
public long? Version { get; set; } |
63 |
|
64 |
[Property] |
65 |
public DateTime? VersionTimeStamp { get; set; } |
66 |
|
67 |
|
68 |
[Property] |
69 |
public bool IsShared { get; set; } |
70 |
|
71 |
[Property] |
72 |
public string SharedBy { get; set; } |
73 |
|
74 |
[Property] |
75 |
public bool ShareWrite { get; set; } |
76 |
|
77 |
|
78 |
[HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true,Inverse=true)] |
79 |
public IList<FileTag> Tags |
80 |
{ |
81 |
get { return _tags; } |
82 |
set { _tags=value;} |
83 |
} |
84 |
|
85 |
// [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true)] |
86 |
// public IList<FileHash> Hashes { get; set; } |
87 |
|
88 |
// [Property] |
89 |
// public byte[] HashmapHash { get; set; } |
90 |
|
91 |
public static FileState FindByFilePath(string absolutePath) |
92 |
{ |
93 |
if (string.IsNullOrWhiteSpace(absolutePath)) |
94 |
throw new ArgumentNullException("absolutePath"); |
95 |
Contract.EndContractBlock(); |
96 |
try |
97 |
{ |
98 |
return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower()); |
99 |
} |
100 |
catch (Exception ex) |
101 |
{ |
102 |
Log.Error(ex.ToString()); |
103 |
throw; |
104 |
} |
105 |
|
106 |
|
107 |
} |
108 |
|
109 |
public static void DeleteByFilePath(string absolutePath) |
110 |
{ |
111 |
if(string.IsNullOrWhiteSpace(absolutePath)) |
112 |
throw new ArgumentNullException("absolutePath"); |
113 |
Contract.EndContractBlock(); |
114 |
|
115 |
FileState.Execute((session, instance) => |
116 |
{ |
117 |
const string hqlDelete = "delete FileState where FilePath = :path"; |
118 |
var deletedEntities = session.CreateQuery(hqlDelete) |
119 |
.SetString("path", absolutePath.ToLower()) |
120 |
.ExecuteUpdate(); |
121 |
return null; |
122 |
},null); |
123 |
|
124 |
} |
125 |
|
126 |
public static void ChangeRootPath(string oldPath,string newPath) |
127 |
{ |
128 |
if (String.IsNullOrWhiteSpace(oldPath)) |
129 |
throw new ArgumentNullException("oldPath"); |
130 |
if (!Path.IsPathRooted(oldPath)) |
131 |
throw new ArgumentException("oldPath must be an absolute path", "oldPath"); |
132 |
if (string.IsNullOrWhiteSpace(newPath)) |
133 |
throw new ArgumentNullException("newPath"); |
134 |
if (!Path.IsPathRooted(newPath)) |
135 |
throw new ArgumentException("newPath must be an absolute path", "newPath"); |
136 |
Contract.EndContractBlock(); |
137 |
|
138 |
//Ensure the paths end with the same character |
139 |
if (!oldPath.EndsWith("\\")) |
140 |
oldPath = oldPath + "\\"; |
141 |
if (!newPath.EndsWith("\\")) |
142 |
newPath = newPath + "\\"; |
143 |
|
144 |
using (new TransactionScope()) |
145 |
{ |
146 |
Execute((session, instance) => |
147 |
{ |
148 |
const string hqlUpdate = |
149 |
"update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' "; |
150 |
var result=session.CreateQuery(hqlUpdate) |
151 |
.SetString("oldPath", oldPath.ToLower()) |
152 |
.SetString("newPath", newPath.ToLower()) |
153 |
.ExecuteUpdate(); |
154 |
return null; |
155 |
}, null); |
156 |
} |
157 |
} |
158 |
|
159 |
public static Task<FileState> CreateForAsync(string filePath,int blockSize,string algorithm) |
160 |
{ |
161 |
if (blockSize <= 0) |
162 |
throw new ArgumentOutOfRangeException("blockSize"); |
163 |
if (String.IsNullOrWhiteSpace(algorithm)) |
164 |
throw new ArgumentNullException("algorithm"); |
165 |
Contract.EndContractBlock(); |
166 |
|
167 |
|
168 |
var fileState = new FileState |
169 |
{ |
170 |
FilePath = filePath, |
171 |
OverlayStatus = FileOverlayStatus.Unversioned, |
172 |
FileStatus = FileStatus.Created, |
173 |
Id=Guid.NewGuid() |
174 |
}; |
175 |
|
176 |
|
177 |
return fileState.UpdateHashesAsync(blockSize,algorithm); |
178 |
} |
179 |
|
180 |
public Task<FileState> UpdateHashesAsync(int blockSize,string algorithm) |
181 |
{ |
182 |
if (blockSize<=0) |
183 |
throw new ArgumentOutOfRangeException("blockSize"); |
184 |
if (String.IsNullOrWhiteSpace(algorithm)) |
185 |
throw new ArgumentNullException("algorithm"); |
186 |
Contract.EndContractBlock(); |
187 |
|
188 |
//Skip updating the hash for folders |
189 |
if (Directory.Exists(FilePath)) |
190 |
return Task.Factory.FromResult(this); |
191 |
|
192 |
var results = Task.Factory.StartNew(() => |
193 |
{ |
194 |
var info = new FileInfo(FilePath); |
195 |
return info.CalculateHash(blockSize, algorithm); |
196 |
}); |
197 |
|
198 |
var state=results.Then(hash => |
199 |
{ |
200 |
Checksum = hash; |
201 |
return Task.Factory.FromResult(this); |
202 |
}); |
203 |
|
204 |
return state; |
205 |
} |
206 |
} |
207 |
|
208 |
[ActiveRecord("Tags")] |
209 |
public class FileTag : ActiveRecordLinqBase<FileTag> |
210 |
{ |
211 |
[PrimaryKey] |
212 |
public int Id { get; set; } |
213 |
|
214 |
[Property] |
215 |
public string Name { get; set; } |
216 |
|
217 |
[Property] |
218 |
public string Value { get; set; } |
219 |
|
220 |
[BelongsTo("FileStateId")] |
221 |
public FileState FileState { get; set; } |
222 |
|
223 |
} |
224 |
|
225 |
/* [ActiveRecord("hashes")] |
226 |
public class FileHash : ActiveRecordLinqBase<FileHash> |
227 |
{ |
228 |
[PrimaryKey] |
229 |
public int Id { get; set; } |
230 |
|
231 |
[Property] |
232 |
public int Order { get; set; } |
233 |
|
234 |
[Property] |
235 |
public byte[] Value { get; set; } |
236 |
|
237 |
[BelongsTo("FileStateID")] |
238 |
public FileState FileState { get; set; } |
239 |
|
240 |
}*/ |
241 |
|
242 |
|
243 |
} |