public void TestTransactBlock() { SharedMemoryStream shared = new SharedMemoryStream(); FragmentedFile.CreateNew(shared, 512, 100, 2).Dispose(); using (FragmentedFile ff = new FragmentedFile(shared, 512, 100, 2)) { long id; byte[] orig = MakeBytes(255); using (Stream write = ff.Create(out id)) write.Write(orig, 0, orig.Length); Assert.AreEqual(orig, IOStream.ReadAllBytes(ff.Open(id, FileAccess.Read))); byte[] change = MakeBytes(800); using (Stream write = ff.Open(id, FileAccess.Write)) using (ITransactable trans = (ITransactable)write) //the Fragmented File Streams are ITransactable { write.Write(change, 0, change.Length); Assert.AreEqual(orig, IOStream.ReadAllBytes(ff.Open(id, FileAccess.Read))); trans.Commit(); //commit changes so that readers can read Assert.AreEqual(change, IOStream.ReadAllBytes(ff.Open(id, FileAccess.Read))); trans.Rollback(); //rollback even after commit to 'undo' the changes Assert.AreEqual(orig, IOStream.ReadAllBytes(ff.Open(id, FileAccess.Read))); } //once disposed you can no longer rollback, if rollback has not been called commit is implied. Assert.AreEqual(orig, IOStream.ReadAllBytes(ff.Open(id, FileAccess.Read))); } }
public void SetContents(string path, HttpStatusCode status, string contentType, string etag, DateTime?modified, byte[] contents) { if (contents.Length == 0) { Console.Error.WriteLine("{0} - {1} (Content is empty)", (int)status, path); } ContentRecord rec = _data[path]; ITransactable pendingUpdate = null; try { ContentRecord.Builder builder = rec.ToBuilder() .SetContentUri(path) .SetLastCrawled(CrawlTime) .SetLastValid(CrawlTime) .SetHttpStatus((uint)status) ; builder.ClearContentRedirect(); builder.SetContentType(contentType); builder.SetContentLength((uint)contents.Length); if (!String.IsNullOrEmpty(etag)) { builder.SetETag(etag); } string hash = Hash.SHA256(contents).ToString(); if (hash != builder.HashOriginal) { Modified = true; builder.SetHashOriginal(hash); builder.SetDateModified(CrawlTime); pendingUpdate = _data.WriteContent(builder, contents); } if (_data.AddOrUpdate(path, rec = builder.Build())) { if (pendingUpdate != null) { pendingUpdate.Commit(); pendingUpdate.Dispose(); pendingUpdate = null; } } } finally { if (pendingUpdate != null) { pendingUpdate.Rollback(); pendingUpdate.Dispose(); } } ProcessFileContent(rec, contents); }
public void Commit() { Flush(); ITransactable tstore = _store as ITransactable; if (tstore != null) { tstore.Commit(); } }
public void Commit() { lock (_flushSync) // disallow concurrent async flush { Flush(); ITransactable tstore = _store as ITransactable; if (tstore != null) { tstore.Commit(); } } }
public void Commit() { lock (_writeBehindFunc) { CompleteAsync(); Flush(); ITransactable tstore = _store as ITransactable; if (tstore != null) { tstore.Commit(); } } }
public void TestTransactWriteAfterCommit() { SharedMemoryStream shared = new SharedMemoryStream(); FragmentedFile.CreateNew(shared, 512, 100, 2).Dispose(); using (FragmentedFile ff = new FragmentedFile(shared, 512, 100, 2)) { long id; byte[] bytes = MakeBytes(255); using (Stream write = ff.Create(out id)) using (ITransactable trans = (ITransactable)write) { write.Write(bytes, 0, bytes.Length); trans.Commit(); write.Write(bytes, 0, bytes.Length); } } }
public void WriteContent(ContentRecord rec, byte[] bytes) { bool[] modified = new bool[1]; modified[0] = false; bool success = Update(rec.ContentUri, r => { ContentRecord.Builder b = r.ToBuilder(); using (ITransactable t = WriteContent(b, bytes)) t.Commit(); ContentRecord newRec = b.Build(); modified[0] = !newRec.Equals(r); return(newRec); } ); if (!success && modified[0]) { throw new ApplicationException("Record not found."); } }
public void TestRollbackCreate() { SharedMemoryStream shared = new SharedMemoryStream(); FragmentedFile.CreateNew(shared, 512, 100, 2).Dispose(); using (FragmentedFile ff = new FragmentedFile(shared, 512, 100, 2)) { long id; byte[] bytes = MakeBytes(255); using (Stream write = ff.Create(out id)) using (ITransactable trans = (ITransactable)write) { write.Write(bytes, 0, bytes.Length); trans.Commit(); Assert.AreEqual(bytes, IOStream.ReadAllBytes(ff.Open(id, FileAccess.Read))); trans.Rollback(); } AssertThrows <InvalidDataException>(delegate() { ff.Open(id, FileAccess.Read); }); } }
public void CopyTo(ContentStorage writer, Func <ContentRecord, byte[], byte[]> fnprocess) { bool success; foreach (KeyValuePair <string, ContentRecord> item in _content) { ContentRecord.Builder builder = item.Value.ToBuilder(); if (item.Value.HasContentStoreId) { byte[] data = _content.ReadContent(item.Value, true); if (fnprocess != null) { data = fnprocess(item.Value, data); } using (ITransactable trans = writer.WriteContent(builder, data)) { success = Overwrite ? writer.AddOrUpdate(item.Key, builder.Build()) : writer.Add(item.Key, builder.Build()); if (success) { trans.Commit(); } } } else { success = Overwrite ? writer.AddOrUpdate(item.Key, builder.Build()) : writer.Add(item.Key, builder.Build()); } if (!success) { Console.Error.WriteLine("Path already exists " + item.Key); } } }
private void UpdateTemplate(bool forced) { string tempPath = new Uri(_baseUri, _config.Searching.TemplateUri).NormalizedPathAndQuery(); ContentRecord record; ContentRecord.Builder update; if (_data.TryGetValue(TemplatePath, out record)) { update = record.ToBuilder(); } else { update = _data.New(TemplatePath, DateTime.Now); } ContentRecord template; if (_data.TryGetValue(tempPath, out template)) { if (template.HasContentStoreId && (forced || template.HashOriginal != update.HashOriginal)) { update.SetContentType(template.ContentType); update.SetHashOriginal(template.HashOriginal); update.SetLastCrawled(template.LastCrawled); update.SetLastValid(template.LastValid); update.SetDateModified(DateTime.Now); update.SetHttpStatus(template.HttpStatus); update.ClearContentRedirect(); if (template.HasContentRedirect) { update.SetContentRedirect(update.ContentRedirect); } ContentParser parser = new ContentParser(_data, _baseUri); parser.RelativeUri = true; parser.RewriteUri += uri => new Uri(uri.OriginalString); Uri templateUri = new Uri(_baseUri, SearchTemplate.SearchPath); parser.MakeRelativeUri = (s, d) => templateUri.MakeRelativeUri(d); byte[] mapped = parser.ProcessFile(template, _data.ReadContent(template, true)); string templateHtml = CreateTemplate(Encoding.UTF8.GetString(mapped)); using (ITransactable trans = _data.WriteContent(update, Encoding.UTF8.GetBytes(templateHtml))) { _data.AddOrUpdate(TemplatePath, update.Build()); trans.Commit(); } } } if (!_data.TryGetValue(SearchCssPath, out record)) { ContentRecord cssRecord = _data.New(SearchCssPath, DateTime.Now) .SetContentType("text/css") .SetHttpStatus(200) .Build(); _data.Add(cssRecord.ContentUri, cssRecord); _data.WriteContent(cssRecord, Encoding.UTF8.GetBytes(Properties.Resources.search_css)); } }