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