public Etag PutStatic(string name, Etag etag, Stream data, RavenJObject metadata) { if (name == null) { throw new ArgumentNullException("name"); } name = name.Trim(); if (Encoding.Unicode.GetByteCount(name) >= 2048) { throw new ArgumentException("The key must be a maximum of 2,048 bytes in Unicode, 1,024 characters", "name"); } var locker = putAttachmentSerialLock.GetOrAdd(name, s => new object()); Monitor.Enter(locker); try { Etag newEtag = Etag.Empty; TransactionalStorage.Batch(actions => { AssertAttachmentPutOperationNotVetoed(name, metadata, data); Database.AttachmentPutTriggers.Apply(trigger => trigger.OnPut(name, data, metadata)); newEtag = actions.Attachments.AddAttachment(name, etag, data, metadata); Database.AttachmentPutTriggers.Apply(trigger => trigger.AfterPut(name, data, metadata, newEtag)); WorkContext.ShouldNotifyAboutWork(() => "PUT ATTACHMENT " + name); }); TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.AttachmentPutTriggers.Apply(trigger => trigger.AfterCommit(name, data, metadata, newEtag)); var newAttachmentNotification = new AttachmentChangeNotification() { Id = name, Type = AttachmentChangeTypes.Put, Etag = newEtag }; Database.Notifications.RaiseNotifications(newAttachmentNotification, metadata); }); return(newEtag); } finally { Monitor.Exit(locker); putAttachmentSerialLock.TryRemove(name, out locker); } }
public bool DeleteTransform(string name, int?deletedTransformerVersion) { var transformer = GetTransformerDefinition(name); if (transformer == null) { return(false); } var currentTransformerVersion = transformer.TransformerVersion; if (deletedTransformerVersion != null && currentTransformerVersion != null && currentTransformerVersion > deletedTransformerVersion) { // the transformer version is larger than the deleted one // got an old delete from an outdated node return(false); } if (IndexDefinitionStorage.RemoveTransformer(name) == false) { return(false); } var version = currentTransformerVersion ?? 0; if (deletedTransformerVersion != null) { version = Math.Max(version, deletedTransformerVersion.Value); } TransactionalStorage.Batch(actions => { var metadata = new RavenJObject { { IndexDefinitionStorage.TransformerVersionKey, version } }; actions.Lists.Set(Constants.RavenDeletedTransformersVersions, name, metadata, UuidType.Transformers); }); //raise notification only if the transformer was actually removed TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification { Name = name, Type = TransformerChangeTypes.TransformerRemoved, Version = version })); return(true); }
public static List <string> ReportOn(TransactionalStorage transactionalStorage) { var list = new List <string>(); transactionalStorage.Batch(accessor => { var session = ((StorageActionsAccessor)accessor).Inner.Session; var jetDbid = ((StorageActionsAccessor)accessor).Inner.Dbid; var dictionary = GetSizes(session, jetDbid); list.AddRange(dictionary.OrderByDescending(x => x.Item2).Select(l => l.Item1)); }); return(list); }
public Attachment GetStatic(string name) { Attachment attachment = null; TransactionalStorage.Batch(actions => { attachment = actions.Attachments.GetAttachment(name); attachment = ProcessAttachmentReadVetoes(name, attachment); ExecuteAttachmentReadTriggers(name, attachment); }); return(attachment); }
public Etag GetLastEtagForCollection(string collectionName) { Etag value = Etag.Empty; TransactionalStorage.Batch(accessor => { var dbvalue = accessor.Lists.Read("Raven/Collection/Etag", collectionName); if (dbvalue != null) { value = Etag.Parse(dbvalue.Data.Value <Byte[]>("Etag")); } }); return(value); }
public void UpdateClientActivityDate(long id) { using (LockSubscription(id)) { TransactionalStorage.Batch(accessor => { var config = GetSubscriptionConfig(id); config.TimeOfLastClientActivity = SystemTime.UtcNow; SaveSubscriptionConfig(id, config); }); } }
internal void DeleteIndex(IndexDefinition instance, bool removeByNameMapping = true, bool clearErrors = true, bool removeIndexReplaceDocument = true, bool isSideBySideReplacement = false) { using (IndexDefinitionStorage.TryRemoveIndexContext()) { if (instance == null) { return; } // Set up a flag to signal that this is something we're doing TransactionalStorage.Batch(actions => actions.Lists.Set("Raven/Indexes/PendingDeletion", instance.IndexId.ToString(CultureInfo.InvariantCulture), (RavenJObject.FromObject(new { TimeOfOriginalDeletion = SystemTime.UtcNow, instance.IndexId, IndexName = instance.Name, instance.IndexVersion })), UuidType.Tasks)); // Delete the main record synchronously IndexDefinitionStorage.RemoveIndex(instance.IndexId, removeByNameMapping); Database.IndexStorage.DeleteIndex(instance.IndexId); if (clearErrors) { WorkContext.ClearErrorsFor(instance.Name); } if (removeIndexReplaceDocument && instance.IsSideBySideIndex) { Database.Documents.Delete(Constants.IndexReplacePrefix + instance.Name, null, null); } // And delete the data in the background StartDeletingIndexDataAsync(instance.IndexId, instance.Name); var indexChangeType = isSideBySideReplacement ? IndexChangeTypes.SideBySideReplace : IndexChangeTypes.IndexRemoved; // We raise the notification now because as far as we're concerned it is done *now* TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = instance.Name, Type = indexChangeType, Version = instance.IndexVersion }) ); } }
public List <SubscriptionConfig> GetSubscriptions(int start, int take) { var subscriptions = new List <SubscriptionConfig>(); TransactionalStorage.Batch(accessor => { foreach (var listItem in accessor.Lists.Read(Constants.RavenSubscriptionsPrefix, start, take)) { var config = listItem.Data.JsonDeserialization <SubscriptionConfig>(); subscriptions.Add(config); } }); return(subscriptions); }
private static void ReportOn(TransactionalStorage transactionalStorage, string tableName, string path) { var list = new List <string>(); transactionalStorage.Batch(accessor => { var session = ((StorageActionsAccessor)accessor).Inner.Session; var jetDbid = ((StorageActionsAccessor)accessor).Inner.Dbid; using (var stream = new FileStream(Path.Combine(path, tableName + "Dump.csv"), FileMode.Create)) using (var table = new Table(session, jetDbid, tableName, OpenTableGrbit.None)) { DumpTable(session, table, stream); } }); }
internal Task StartDeletingIndexDataAsync(int id, string indexName) { var sp = Stopwatch.StartNew(); //remove the header information in a sync process TransactionalStorage.Batch(actions => actions.Indexing.PrepareIndexForDeletion(id)); var deleteIndexTask = Task.Run(() => { Debug.Assert(Database.IndexStorage != null); Log.Info("Starting async deletion of index {0}", indexName); Database.IndexStorage.DeleteIndexData(id); // Data can take a while TransactionalStorage.Batch(actions => { // And Esent data can take a while too actions.Indexing.DeleteIndex(id, WorkContext.CancellationToken); if (WorkContext.CancellationToken.IsCancellationRequested) { return; } actions.Lists.Remove("Raven/Indexes/PendingDeletion", id.ToString(CultureInfo.InvariantCulture)); }); }); long taskId; Database.Tasks.AddTask(deleteIndexTask, null, new TaskActions.PendingTaskDescription { StartTime = SystemTime.UtcNow, TaskType = TaskActions.PendingTaskType.IndexDeleteOperation, Payload = indexName }, out taskId); deleteIndexTask.ContinueWith(t => { if (t.IsFaulted || t.IsCanceled) { Log.WarnException("Failure when deleting index " + indexName, t.Exception); } else { Log.Info("The async deletion of index {0} was completed in {1}", indexName, sp.Elapsed); } }); return(deleteIndexTask); }
public static List <string> ReportOn(TransactionalStorage transactionalStorage, Action <string> progress, CancellationToken token) { var list = new List <string>(); transactionalStorage.Batch(accessor => { var session = ((StorageActionsAccessor)accessor).Inner.Session; var jetDbid = ((StorageActionsAccessor)accessor).Inner.Dbid; token.ThrowIfCancellationRequested(); var dictionary = GetSizes(session, jetDbid, progress, token); list.AddRange(dictionary.OrderByDescending(x => x.Item2).Select(l => l.Item1)); }); return(list); }
protected override void Dispose(bool disposing) { if (!disposed) { if (disposing) { Flush(); if (StorageStreamAccess == StorageStreamAccess.CreateAndWrite) { TransactionalStorage.Batch(accessor => accessor.CompleteFileUpload(Name)); } } disposed = true; } }
public override void Flush() { if (InnerBuffer != null && InnerBufferOffset > 0) { ConcurrencyAwareExecutor.Execute(() => TransactionalStorage.Batch( accessor => { var hashKey = accessor.InsertPage(InnerBuffer, InnerBufferOffset); accessor.AssociatePage(Name, hashKey, writtingPagePosition, InnerBufferOffset); writtingPagePosition++; })); InnerBuffer = null; InnerBufferOffset = 0; } }
public void ResetIndex(string index) { var indexDefinition = IndexDefinitionStorage.GetIndexDefinition(index); if (indexDefinition == null) { throw new InvalidOperationException("There is no index named: " + index); } IndexStorage.DeleteIndex(index); IndexStorage.CreateIndexImplementation(index, indexDefinition); TransactionalStorage.Batch(actions => { actions.Indexing.DeleteIndex(index); AddIndexAndEnqueueIndexingTasks(actions, index); }); }
public void PurgeOutdatedTombstones() { var tomstoneLists = new[] { Constants.RavenPeriodicExportsDocsTombstones, Constants.RavenReplicationDocsTombstones }; var olderThan = SystemTime.UtcNow.Subtract(Database.Configuration.Core.TombstoneRetentionTime.AsTimeSpan); foreach (var listName in tomstoneLists) { string name = listName; TransactionalStorage.Batch(accessor => accessor.Lists.RemoveAllOlderThan(name, olderThan)); } }
public void ReplaceIndexingErrors(string indexToReplaceName, int?indexToReplaceId, string indexName, int newIndexId) { TransactionalStorage.Batch(accessor => { ClearErrorsFor(indexToReplaceName); if (indexToReplaceId.HasValue) { object _; indexingErrorLocks.TryRemove(indexToReplaceId.Value, out _); } HandleIndexRename(indexName, indexToReplaceName, newIndexId, accessor); }); }
public PutResult Put(string key, Guid?etag, JObject document, JObject metadata, TransactionInformation transactionInformation) { if (string.IsNullOrEmpty(key)) { // we no longer sort by the key, so it doesn't matter // that the key is no longer sequential key = Guid.NewGuid().ToString(); } RemoveReservedProperties(document); RemoveReservedProperties(metadata); Guid newEtag = Guid.Empty; lock (this) { TransactionalStorage.Batch(actions => { if (key.EndsWith("/")) { key += actions.General.GetNextIdentityValue(key); } if (transactionInformation == null) { AssertPutOperationNotVetoed(key, metadata, document, transactionInformation); PutTriggers.Apply(trigger => trigger.OnPut(key, document, metadata, transactionInformation)); newEtag = actions.Documents.AddDocument(key, etag, document, metadata); // We detect this by using the etags // AddIndexingTask(actions, metadata, () => new IndexDocumentsTask { Keys = new[] { key } }); PutTriggers.Apply(trigger => trigger.AfterPut(key, document, metadata, newEtag, transactionInformation)); } else { newEtag = actions.Transactions.AddDocumentInTransaction(key, etag, document, metadata, transactionInformation); } workContext.ShouldNotifyAboutWork(); }); } TransactionalStorage .ExecuteImmediatelyOrRegisterForSyncronization(() => PutTriggers.Apply(trigger => trigger.AfterCommit(key, document, metadata, newEtag))); return(new PutResult { Key = key, ETag = newEtag }); }
public AttachmentInformation[] GetAttachments(int start, int pageSize, Guid?etag) { AttachmentInformation[] documents = null; TransactionalStorage.Batch(actions => { if (etag == null) { documents = actions.Attachments.GetAttachmentsByReverseUpdateOrder(start).Take(pageSize).ToArray(); } else { documents = actions.Attachments.GetAttachmentsAfter(etag.Value).Take(pageSize).ToArray(); } }); return(documents); }
public PutResult Put(string key, Guid?etag, JObject document, JObject metadata, TransactionInformation transactionInformation) { if (string.IsNullOrEmpty(key)) { Guid value; UuidCreateSequential(out value); key = value.ToString(); } RemoveReservedProperties(document); RemoveReservedProperties(metadata); TransactionalStorage.Batch(actions => { metadata["Last-Modified"] = JToken.FromObject(DateTime.UtcNow.ToString("r")); if (key.EndsWith("/")) { key += actions.General.GetNextIdentityValue(key); } metadata.Add("@id", new JValue(key)); if (transactionInformation == null) { AssertPutOperationNotVetoed(key, metadata, document, transactionInformation); PutTriggers.Apply(trigger => trigger.OnPut(key, document, metadata, transactionInformation)); etag = actions.Documents.AddDocument(key, etag, document, metadata); AddIndexingTask(actions, metadata, () => new IndexDocumentsTask { Keys = new[] { key } }); PutTriggers.Apply(trigger => trigger.AfterPut(key, document, metadata, etag.Value, transactionInformation)); } else { etag = actions.Transactions.AddDocumentInTransaction(key, etag, document, metadata, transactionInformation); } workContext.ShouldNotifyAboutWork(); }); TransactionalStorage .ExecuteImmediatelyOrRegisterForSyncronization(() => PutTriggers.Apply(trigger => trigger.AfterCommit(key, document, metadata, etag.Value))); return(new PutResult { Key = key, ETag = etag.Value }); }
public JsonDocument Get(string key, TransactionInformation transactionInformation) { if (key == null) { throw new ArgumentNullException(nameof(key)); } key = key.Trim(); JsonDocument document = null; if (transactionInformation == null || Database.InFlightTransactionalState.TryGet(key, transactionInformation, out document) == false) { TransactionalStorage.Batch(actions => { var nonAuthoritativeInformationBehavior = actions.InFlightStateSnapshot.GetNonAuthoritativeInformationBehavior <JsonDocument>(transactionInformation, key); document = actions.Documents.DocumentByKey(key); if (nonAuthoritativeInformationBehavior != null) { document = nonAuthoritativeInformationBehavior(document); } if (document != null) { if (document.Metadata.ContainsKey(Constants.RavenReplicationConflict) && !document.Metadata.ContainsKey(Constants.RavenReplicationConflictDocument)) { JsonDocument newDocument; Database.ResolveConflict(document, actions, out newDocument); if (newDocument != null) { document = newDocument; } } } }); } JsonDocument.EnsureIdInMetadata(document); return(new DocumentRetriever(null, null, Database.ReadTriggers) .ExecuteReadTriggers(document, transactionInformation, ReadOperation.Load)); }
public void ClearErrorsFor(string indexName) { var list = new List <IndexingError>(); var removed = new List <IndexingError>(); IndexingError error; while (indexingErrors.TryDequeue(out error)) { if (StringComparer.OrdinalIgnoreCase.Equals(error.IndexName, indexName) == false) { list.Add(error); } else { removed.Add(error); } } foreach (var indexingError in list) { indexingErrors.Enqueue(indexingError); } var removedIndexIds = removed .Select(x => x.Index) .Distinct(); foreach (var removedIndexId in removedIndexIds) { object _; indexingErrorLocks.TryRemove(removedIndexId, out _); } TransactionalStorage.Batch(accessor => { foreach (var removedError in removed) { accessor.Lists.Remove("Raven/Indexing/Errors/" + indexName, removedError.Id.ToString(CultureInfo.InvariantCulture)); } using (TransactionalStorage.DisableBatchNesting()) accessor.Lists.RemoveAllOlderThan("Raven/Indexing/Errors/" + indexName, DateTime.MaxValue); }); }
public List <object> GetDebugInfo() { var subscriptions = new List <object>(); TransactionalStorage.Batch(accessor => { foreach (var listItem in accessor.Lists.Read(Constants.RavenSubscriptionsPrefix, 0, int.MaxValue)) { var config = listItem.Data.JsonDeserialization <SubscriptionConfig>(); SubscriptionConnectionOptions options = null; openSubscriptions.TryGetValue(config.SubscriptionId, out options); var debugInfo = new { config.SubscriptionId, config.AckEtag, TimeOfLastClientActivity = config.TimeOfLastClientActivity != default(DateTime) ? config.TimeOfLastClientActivity : (DateTime?)null, TimeOfSendingLastBatch = config.TimeOfSendingLastBatch != default(DateTime) ? config.TimeOfSendingLastBatch : (DateTime?)null, Criteria = new { config.Criteria.KeyStartsWith, config.Criteria.BelongsToAnyCollection, PropertiesMatch = config.Criteria.PropertiesMatch == null ? null : config.Criteria.PropertiesMatch.Select(x => new { x.Key, x.Value }).ToList(), PropertiesNotMatch = config.Criteria.PropertiesNotMatch == null ? null : config.Criteria.PropertiesNotMatch.Select(x => new { x.Key, x.Value }).ToList(), config.Criteria.StartEtag }, IsOpen = options != null, ConnectionOptions = options }; subscriptions.Add(debugInfo); } }); return(subscriptions); }
public void ResetIndex(string index) { index = IndexDefinitionStorage.FixupIndexName(index); var indexDefinition = IndexDefinitionStorage.GetIndexDefinition(index); if (indexDefinition == null) { throw new InvalidOperationException("There is no index named: " + index); } IndexStorage.DeleteIndex(index); IndexStorage.CreateIndexImplementation(indexDefinition); TransactionalStorage.Batch(actions => { actions.Indexing.DeleteIndex(index); actions.Indexing.AddIndex(index, indexDefinition.IsMapReduce); workContext.ShouldNotifyAboutWork(); }); }
private int GetDeletedTransformerVersion(string listName, string transformerName) { var version = 0; TransactionalStorage.Batch(action => { var li = action.Lists.Read(listName, transformerName); if (li == null) { return; } var versionStr = li.Data.Value <string>("TransformerVersion"); int.TryParse(versionStr, out version); }); return(version); }
private int GetDeletedTransformerId(string transformerName) { var version = 0; TransactionalStorage.Batch(action => { var li = action.Lists.Read(Constants.RavenReplicationTransformerTombstones, transformerName); if (li == null) { return; } var versionStr = li.Data.Value <string>("TransformerVersion"); int.TryParse(versionStr, out version); }); return(version); }
public SubscriptionConfig GetSubscriptionConfig(long id) { SubscriptionConfig config = null; TransactionalStorage.Batch(accessor => { var listItem = accessor.Lists.Read(Constants.RavenSubscriptionsPrefix, id.ToString("D19")); if (listItem == null) { throw new SubscriptionDoesNotExistException("There is no subscription configuration for specified identifier (id: " + id + ")"); } config = listItem.Data.JsonDeserialization <SubscriptionConfig>(); }); return(config); }
public string PutIndex(string name, IndexDefinition definition) { switch (IndexDefinitionStorage.FindIndexCreationOptionsOptions(name, definition)) { case IndexCreationOptions.Noop: return(name); case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(name, definition, Extensions).GenerateInstance(); DeleteIndex(name); break; } IndexDefinitionStorage.AddIndex(name, definition); IndexStorage.CreateIndexImplementation(name, definition); TransactionalStorage.Batch(actions => AddIndexAndEnqueueIndexingTasks(actions, name)); return(name); }
public Etag GetDocumentsWithIdStartingWith(string idPrefix, int pageSize, Etag etag, CancellationToken token, Action <JsonDocument> addDocument) { TransactionalStorage.Batch(actions => { bool returnedDocs = false; while (true) { var documents = actions.Documents.GetDocumentsAfterWithIdStartingWith(etag, idPrefix, pageSize, token, timeout: TimeSpan.FromSeconds(2)); var documentRetriever = new DocumentRetriever(Database.Configuration, actions, Database.ReadTriggers, Database.InFlightTransactionalState); int docCount = 0; foreach (var doc in documents) { docCount++; token.ThrowIfCancellationRequested(); etag = doc.Etag; JsonDocument.EnsureIdInMetadata(doc); var nonAuthoritativeInformationBehavior = Database.InFlightTransactionalState.GetNonAuthoritativeInformationBehavior <JsonDocument>(null, doc.Key); var document = nonAuthoritativeInformationBehavior == null ? doc : nonAuthoritativeInformationBehavior(doc); document = documentRetriever.ExecuteReadTriggers(document, null, ReadOperation.Load); if (document == null) { continue; } addDocument(document); returnedDocs = true; Database.WorkContext.UpdateFoundWork(); } if (returnedDocs || docCount == 0) { break; } } }); return(etag); }
public void DeleteStatic(string name, Guid?etag) { TransactionalStorage.Batch(actions => { AssertAttachmentDeleteOperationNotVetoed(name); AttachmentDeleteTriggers.Apply(x => x.OnDelete(name)); actions.Attachments.DeleteAttachment(name, etag); AttachmentDeleteTriggers.Apply(x => x.AfterDelete(name)); workContext.ShouldNotifyAboutWork(); }); TransactionalStorage .ExecuteImmediatelyOrRegisterForSyncronization( () => AttachmentDeleteTriggers.Apply(trigger => trigger.AfterCommit(name))); }
public void AcknowledgeBatchProcessed(long id, Etag lastEtag) { TransactionalStorage.Batch(accessor => { var config = GetSubscriptionConfig(id); var options = GetBatchOptions(id); var timeSinceBatchSent = SystemTime.UtcNow - config.TimeOfSendingLastBatch; if (timeSinceBatchSent > options.AcknowledgmentTimeout) { throw new TimeoutException("The subscription cannot be acknowledged because the timeout has been reached."); } config.AckEtag = lastEtag; config.TimeOfLastClientActivity = SystemTime.UtcNow; SaveSubscriptionConfig(id, config); }); }