private async Task <Errorable <Ref> > persistRef(Ref rf) { FileInfo tmpFile = system.getTemporaryFile(); // Write the ref's contents to the temporary file: using (var fs = new FileStream(tmpFile.FullName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 16384, true)) await fs.WriteRawAsync(rf.WriteTo(new StringBuilder()).ToString()); lock (FileSystem.SystemLock) { // TODO: would love to see FileInfo.DeleteAsync, DirectoryInfo.CreateAsync, etc. FileInfo fi = system.getRefPathByRefName(rf.Name); if (fi.Exists) { fi.Delete(); } else // Create directory if it doesn't exist: if (!fi.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", fi.Directory.FullName)); fi.Directory.Create(); } // Move the temp file to the real file: Debug.WriteLine(String.Format("New REF '{0}'", fi.FullName)); File.Move(tmpFile.FullName, fi.FullName); } return(rf); }
private async Task <Errorable <Commit> > persistCommit(Commit cm) { FileInfo tmpFile = system.getTemporaryFile(); // Write the commit contents to the file: using (var fs = new FileStream(tmpFile.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 16834, useAsync: true)) { await fs.WriteRawAsync(cm.WriteTo(new StringBuilder()).ToString()); } lock (FileSystem.SystemLock) { FileInfo fi = system.getPathByID(cm.ID); // NOTE: if the record already exists we can either error out or overwrite the existing file with contents known to be good in the case the existing file got corrupt. // Let's stick with the self-repair scenario since erroring out doesn't help anyone. if (fi.Exists) { Debug.WriteLine(String.Format("Self-repair scenario: overwriting old CommitID {0} with new contents", cm.ID)); fi.Delete(); } // Create directory if it doesn't exist: if (!fi.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", fi.Directory.FullName)); fi.Directory.Create(); } Debug.WriteLine(String.Format("New COMMIT '{0}'", fi.FullName)); File.Move(tmpFile.FullName, fi.FullName); } return(cm); }
private async Task <Errorable <Stage> > persistStage(Stage stg) { FileInfo tmpFile = system.getTemporaryFile(); using (var fs = new FileStream(tmpFile.FullName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, bufferSize: 16386, useAsync: true)) { await fs.WriteRawAsync(stg.WriteTo(new StringBuilder()).ToString()); } lock (FileSystem.SystemLock) { FileInfo fi = system.getStagePathByStageName(stg.Name); if (fi.Exists) { fi.Delete(); } // Create directory if it doesn't exist: if (!fi.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", fi.Directory.FullName)); fi.Directory.Create(); } // Write the contents to the file: Debug.WriteLine(String.Format("New STAGE '{0}'", fi.FullName)); File.Move(tmpFile.FullName, fi.FullName); } return(stg); }
private async Task <Errorable <TreeNode> > persistTree(TreeNode tr) { Debug.Assert(tr != null); // Check that all referenced blobs are already persisted: foreach (var trbl in tr.Blobs) { if (!system.getPathByID(trbl.BlobID).Exists) { return(new BlobIDRecordDoesNotExistError(trbl.BlobID)); } } // Check that all referenced blobs are already persisted: foreach (var trtr in tr.Trees) { if (!system.getPathByID(trtr.TreeID).Exists) { return(new TreeIDRecordDoesNotExistError(trtr.TreeID)); } } // Write the tree contents to the file: FileInfo tmpFile = system.getTemporaryFile(); using (var fs = new FileStream(tmpFile.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 16384, useAsync: true)) { await fs.WriteRawAsync(tr.WriteTo(new StringBuilder()).ToString()); } lock (FileSystem.SystemLock) { FileInfo fi = system.getPathByID(tr.ID); // NOTE: if the record already exists we can either error out or overwrite the existing file with contents known to be good in the case the existing file got corrupt. // Let's stick with the self-repair scenario since erroring out doesn't help anyone. if (fi.Exists) { Debug.WriteLine(String.Format("Self-repair scenario: overwriting old TreeID {0} with new contents", tr.ID)); fi.Delete(); File.Move(tmpFile.FullName, fi.FullName); return(tr); } // Create directory if it doesn't exist: if (!fi.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", fi.Directory.FullName)); fi.Directory.Create(); } Debug.WriteLine(String.Format("New TREE '{0}'", fi.FullName)); File.Move(tmpFile.FullName, fi.FullName); } return(tr); }
private async Task <Errorable <IStreamedBlob> > persistBlob(PersistingBlob blob) { Debug.WriteLine(String.Format("Starting persistence of blob")); // Find a temporary filename: FileInfo tmpPath = system.getTemporaryFile(); long length = -1; BlobID blid; // Open a new stream to the source blob contents: using (var sr = blob.Stream) { length = sr.Length; // Create a new file and set its length so we can asynchronously write to it: using (var tmpFi = File.Open(tmpPath.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { Debug.WriteLine(String.Format("New BLOB temp '{0}' length {1}", tmpPath.FullName, length)); tmpFi.SetLength(length); tmpFi.Close(); } // Determine the best buffer size to use for writing contents: int bufSize = Math.Min(Math.Max((int)length, 8), largeBufferSize); // Open a new FileStream to asynchronously write the blob contents: using (var fs = new FileStream(tmpPath.FullName, FileMode.Open, FileAccess.Write, FileShare.Read, bufSize, useAsync: true)) using (var sha1 = new SHA1StreamWriter(fs)) { // Copy the contents asynchronously (expected copy in order): await sr.CopyToAsync(sha1, bufSize).ConfigureAwait(continueOnCapturedContext: false); // Create the BlobID from the SHA1 hash calculated during copy: blid = new BlobID(sha1.GetHash()); } } // Serialize access to the official blob file: lock (FileSystem.SystemLock) { // Create the blob's subdirectory under 'objects': FileInfo path = system.getPathByID(blid); path.Refresh(); if (!path.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", path.Directory.FullName)); path.Directory.Create(); } // Don't recreate an existing blob: if (path.Exists) { Debug.WriteLine(String.Format("Blob already exists at path '{0}', deleting temporary...", path.FullName)); tmpPath.Delete(); return(new Errorable <IStreamedBlob>((IStreamedBlob) new StreamedBlob(this, blid, length))); } // Move the temp file to the final blob filename: File.Move(tmpPath.FullName, path.FullName); } return(new Errorable <IStreamedBlob>((IStreamedBlob) new StreamedBlob(this, blid, length))); }
private async Task <Errorable <Tag> > persistTag(Tag tg) { // Write the commit contents to the file: FileInfo tmpFile = system.getTemporaryFile(); using (var fs = new FileStream(tmpFile.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { await fs.WriteRawAsync(tg.WriteTo(new StringBuilder()).ToString()); } lock (FileSystem.SystemLock) { FileInfo fi = system.getPathByID(tg.ID); // NOTE: if the record already exists we can either error out or overwrite the existing file with contents known to be good in the case the existing file got corrupt. // Let's stick with the self-repair scenario since erroring out doesn't help anyone. if (fi.Exists) { Debug.WriteLine(String.Format("Self-repair scenario: overwriting old TagID {0} with new contents", tg.ID)); fi.Delete(); } // Create directory if it doesn't exist: if (!fi.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", fi.Directory.FullName)); fi.Directory.Create(); } Debug.WriteLine(String.Format("New TAG '{0}'", fi.FullName)); File.Move(tmpFile.FullName, fi.FullName); } // Now keep track of the tag by its name: tmpFile = system.getTemporaryFile(); using (var fs = new FileStream(tmpFile.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { await fs.WriteRawAsync(tg.ID.ToString()); } lock (FileSystem.SystemLock) { FileInfo fiTracker = system.getTagPathByTagName(tg.Name); // Does this tag name exist already? if (fiTracker.Exists) { tmpFile.Delete(); return(new TagNameAlreadyExistsError(tg.Name)); } // Create directory if it doesn't exist: if (!fiTracker.Directory.Exists) { Debug.WriteLine(String.Format("New DIR '{0}'", fiTracker.Directory.FullName)); fiTracker.Directory.Create(); } Debug.WriteLine(String.Format("New TAG '{0}'", fiTracker.FullName)); File.Move(tmpFile.FullName, fiTracker.FullName); } return(tg); }