public void DeleteStatic(string name, Etag etag) { if (name == null) { throw new ArgumentNullException("name"); } name = name.Trim(); TransactionalStorage.Batch(actions => { AssertAttachmentDeleteOperationNotVetoed(name); Database.AttachmentDeleteTriggers.Apply(x => x.OnDelete(name)); actions.Attachments.DeleteAttachment(name, etag); Database.AttachmentDeleteTriggers.Apply(x => x.AfterDelete(name)); WorkContext.ShouldNotifyAboutWork(() => "DELETE ATTACHMENT " + name); }); TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization( () => { Database.AttachmentDeleteTriggers.Apply(trigger => trigger.AfterCommit(name)); var newAttachmentNotification = new AttachmentChangeNotification() { Id = name, Type = AttachmentChangeTypes.Delete, Etag = etag }; Database.Notifications.RaiseNotifications(newAttachmentNotification, null); }); }
public void DeleteIndex(string name) { using (IndexDefinitionStorage.TryRemoveIndexContext()) { var instance = IndexDefinitionStorage.GetIndexDefinition(name); 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 })), UuidType.Tasks)); // Delete the main record synchronously IndexDefinitionStorage.RemoveIndex(name); Database.IndexStorage.DeleteIndex(instance.IndexId); WorkContext.ClearErrorsFor(name); // And delete the data in the background StartDeletingIndexDataAsync(instance.IndexId, name); // We raise the notification now because as far as we're concerned it is done *now* TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexRemoved, })); } }
public string PutTransform(string name, TransformerDefinition definition) { if (name == null) { throw new ArgumentNullException("name"); } if (definition == null) { throw new ArgumentNullException("definition"); } name = name.Trim(); var existingDefinition = IndexDefinitionStorage.GetTransformerDefinition(name); if (existingDefinition != null) { switch (existingDefinition.LockMode) { case TransformerLockMode.Unlock: if (existingDefinition.Equals(definition)) { return(name); // no op for the same transformer } break; case TransformerLockMode.LockedIgnore: Log.Info("Transformer {0} not saved because it was lock (with ignore)", name); return(name); default: throw new ArgumentOutOfRangeException(); } } var generator = IndexDefinitionStorage.CompileTransform(definition); if (existingDefinition != null) { IndexDefinitionStorage.RemoveTransformer(existingDefinition.TransfomerId); } TransactionalStorage.Batch(accessor => { definition.TransfomerId = (int)Database.Documents.GetNextIdentityValueWithoutOverwritingOnExistingDocuments("TransformerId", accessor); }); IndexDefinitionStorage.CreateAndPersistTransform(definition, generator); IndexDefinitionStorage.AddTransform(definition.TransfomerId, definition); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification() { Name = name, Type = TransformerChangeTypes.TransformerAdded, })); return(name); }
public void DeleteTransform(string name) { IndexDefinitionStorage.RemoveTransformer(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification { Name = name, Type = TransformerChangeTypes.TransformerRemoved })); }
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); } var isSideBySide = instance.IsSideBySideIndex || instance.Name.StartsWith(Constants.SideBySideIndexNamePrefix, StringComparison.OrdinalIgnoreCase); if (removeIndexReplaceDocument && isSideBySide) { Database.Documents.Delete(Constants.IndexReplacePrefix + instance.Name, null, null); } Database.IndexStorage.DeleteSuggestionsData(instance.Name); //remove the header information in a sync process TransactionalStorage.Batch(actions => actions.Indexing.PrepareIndexForDeletion(instance.IndexId)); //and delete the data in the background Database.Maintenance.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 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 bool DeleteTransform(string name) { if (!IndexDefinitionStorage.RemoveTransformer(name)) { return(false); } //raise notification only if the transformer was actually removed TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification { Name = name, Type = TransformerChangeTypes.TransformerRemoved })); return(true); }
public string PutTransform(string name, TransformerDefinition definition) { if (name == null) { throw new ArgumentNullException("name"); } if (definition == null) { throw new ArgumentNullException("definition"); } name = name.Trim(); var existingDefinition = IndexDefinitionStorage.GetTransformerDefinition(name); if (existingDefinition != null && existingDefinition.Equals(definition)) { return(name); // no op for the same transformer } var generator = IndexDefinitionStorage.CompileTransform(definition); if (existingDefinition != null) { IndexDefinitionStorage.RemoveTransformer(existingDefinition.TransfomerId); } TransactionalStorage.Batch(accessor => { definition.TransfomerId = (int)Database.Documents.GetNextIdentityValueWithoutOverwritingOnExistingDocuments("TransformerId", accessor); }); IndexDefinitionStorage.CreateAndPersistTransform(definition, generator); IndexDefinitionStorage.AddTransform(definition.TransfomerId, definition); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification() { Name = name, Type = TransformerChangeTypes.TransformerAdded, })); return(name); }
public string[] PutIndexes(string[] names, IndexDefinition[] definitions, IndexingPriority[] priorities) { var createdIndexes = new List <string>(); var prioritiesList = new List <IndexingPriority>(); try { for (int i = 0; i < names.Length; i++) { var name = names[i]; var definition = definitions[i]; var priority = priorities[i]; if (name == null) { throw new ArgumentNullException("names", "Names cannot contain null values"); } IsIndexNameValid(name); var existingIndex = IndexDefinitionStorage.GetIndexDefinition(name); if (existingIndex != null) { switch (existingIndex.LockMode) { case IndexLockMode.SideBySide: Log.Info("Index {0} not saved because it might be only updated by side-by-side index"); throw new InvalidOperationException("Can not overwrite locked index: " + name + ". This index can be only updated by side-by-side index."); case IndexLockMode.LockedIgnore: Log.Info("Index {0} not saved because it was lock (with ignore)", name); continue; case IndexLockMode.LockedError: throw new InvalidOperationException("Can not overwrite locked index: " + name); } } name = name.Trim(); if (name.Equals("dynamic", StringComparison.OrdinalIgnoreCase) || name.StartsWith("dynamic/", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Cannot use index name " + name + " because it clashes with reserved dynamic index names", "name"); } if (name.Contains("//")) { throw new ArgumentException("Cannot use an index with // in the name, but got: " + name, "name"); } AssertAnalyzersValid(definition); switch (FindIndexCreationOptions(definition, ref name)) { case IndexCreationOptions.Noop: continue; case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); IndexDefinitionStorage.UpdateIndexDefinitionWithoutUpdatingCompiledIndex(definition); break; case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); DeleteIndex(name); break; } PutNewIndexIntoStorage(name, definition, true); WorkContext.ClearErrorsFor(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexAdded, })); createdIndexes.Add(name); prioritiesList.Add(priority); } var indexesIds = createdIndexes.Select(x => Database.IndexStorage.GetIndexInstance(x).indexId).ToArray(); Database.TransactionalStorage.Batch(accessor => accessor.Indexing.SetIndexesPriority(indexesIds, prioritiesList.ToArray())); return(createdIndexes.ToArray()); } catch (Exception e) { Log.WarnException("Could not create index batch", e); foreach (var index in createdIndexes) { DeleteIndex(index); } throw; } }
public string PutIndex(string name, IndexDefinition definition) { if (name == null) { throw new ArgumentNullException("name"); } IsIndexNameValid(name); var existingIndex = IndexDefinitionStorage.GetIndexDefinition(name); if (existingIndex != null) { switch (existingIndex.LockMode) { case IndexLockMode.SideBySide: Log.Info("Index {0} not saved because it might be only updated by side-by-side index"); throw new InvalidOperationException("Can not overwrite locked index: " + name + ". This index can be only updated by side-by-side index."); case IndexLockMode.LockedIgnore: Log.Info("Index {0} not saved because it was lock (with ignore)", name); return(name); case IndexLockMode.LockedError: throw new InvalidOperationException("Can not overwrite locked index: " + name); } } name = name.Trim(); if (name.Equals("dynamic", StringComparison.OrdinalIgnoreCase) || name.StartsWith("dynamic/", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException("Cannot use index name " + name + " because it clashes with reserved dynamic index names", "name"); } if (name.Contains("//")) { throw new ArgumentException("Cannot use an index with // in the name, but got: " + name, "name"); } AssertAnalyzersValid(definition); switch (FindIndexCreationOptions(definition, ref name)) { case IndexCreationOptions.Noop: return(name); case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); IndexDefinitionStorage.UpdateIndexDefinitionWithoutUpdatingCompiledIndex(definition); return(name); case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); DeleteIndex(name); break; } PutNewIndexIntoStorage(name, definition); WorkContext.ClearErrorsFor(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexAdded, })); return(name); }
private string PutIndexInternal(string name, IndexDefinition definition, bool disableIndexBeforePut = false, bool isUpdateBySideSide = false, IndexCreationOptions?creationOptions = null, bool isReplication = false) { if (name == null) { throw new ArgumentNullException(nameof(name)); } name = name.Trim(); IsIndexNameValid(name); var existingIndex = IndexDefinitionStorage.GetIndexDefinition(name); if (existingIndex != null) { var newIndexVersion = definition.IndexVersion; var currentIndexVersion = existingIndex.IndexVersion; // whether we update the index definition or not, // we need to update the index version existingIndex.IndexVersion = definition.IndexVersion = Math.Max(currentIndexVersion ?? 0, newIndexVersion ?? 0); switch (isReplication) { case true: if (newIndexVersion != null && currentIndexVersion != null && newIndexVersion <= currentIndexVersion) { //this new index is an older version of the current one return(null); } // we need to update the lock mode only if it was updated by another server existingIndex.LockMode = definition.LockMode; break; default: if (CanUpdateIndex(name, definition, isUpdateBySideSide, existingIndex) == false) { return(null); } break; } } AssertAnalyzersValid(definition); switch (creationOptions ?? FindIndexCreationOptions(definition, ref name)) { case IndexCreationOptions.Noop: return(null); case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); IndexDefinitionStorage.UpdateIndexDefinitionWithoutUpdatingCompiledIndex(definition); if (isReplication == false) { definition.IndexVersion = (definition.IndexVersion ?? 0) + 1; } return(null); case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); DeleteIndex(name); if (isReplication == false) { definition.IndexVersion = (definition.IndexVersion ?? 0) + 1; } break; case IndexCreationOptions.Create: if (isReplication == false) { // we create a new index, // we need to restore its previous IndexVersion (if it was deleted before) var deletedIndexVersion = IndexDefinitionStorage.GetDeletedIndexVersion(definition); var replacingIndexVersion = GetOriginalIndexVersion(definition.Name); definition.IndexVersion = Math.Max(deletedIndexVersion, replacingIndexVersion); definition.IndexVersion++; } break; } PutNewIndexIntoStorage(name, definition, disableIndexBeforePut); WorkContext.ClearErrorsFor(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexAdded, Version = definition.IndexVersion })); return(name); }
public bool Delete(string key, Etag etag, TransactionInformation transactionInformation, out RavenJObject metadata) { if (key == null) { throw new ArgumentNullException("key"); } key = key.Trim(); var deleted = false; Log.Debug("Delete a document with key: {0} and etag {1}", key, etag); RavenJObject metadataVar = null; using (Database.DocumentLock.Lock()) { TransactionalStorage.Batch(actions => { AssertDeleteOperationNotVetoed(key, transactionInformation); if (transactionInformation == null) { Database.DeleteTriggers.Apply(trigger => trigger.OnDelete(key, null)); Etag deletedETag; if (actions.Documents.DeleteDocument(key, etag, out metadataVar, out deletedETag)) { deleted = true; actions.Indexing.RemoveAllDocumentReferencesFrom(key); WorkContext.MarkDeleted(key); Database.Indexes.CheckReferenceBecauseOfDocumentUpdate(key, actions); foreach (var indexName in IndexDefinitionStorage.IndexNames) { AbstractViewGenerator abstractViewGenerator = IndexDefinitionStorage.GetViewGenerator(indexName); if (abstractViewGenerator == null) { continue; } var token = metadataVar.Value <string>(Constants.RavenEntityName); if (token != null && // the document has a entity name abstractViewGenerator.ForEntityNames.Count > 0) // the index operations on specific entities { if (abstractViewGenerator.ForEntityNames.Contains(token) == false) { continue; } } var instance = IndexDefinitionStorage.GetIndexDefinition(indexName); var task = actions.GetTask(x => x.Index == instance.IndexId, new RemoveFromIndexTask { Index = instance.IndexId }); task.Keys.Add(key); } if (deletedETag != null) { Database.Prefetcher.AfterDelete(key, deletedETag); } Database.DeleteTriggers.Apply(trigger => trigger.AfterDelete(key, null)); } TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.DeleteTriggers.Apply(trigger => trigger.AfterCommit(key)); Database.Notifications.RaiseNotifications(new DocumentChangeNotification { Id = key, Type = DocumentChangeTypes.Delete, TypeName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenClrType) : null, CollectionName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenEntityName) : null }, metadataVar); }); } else { var doc = actions.Documents.DocumentMetadataByKey(key, null); Database.InFlightTransactionalState.DeleteDocumentInTransaction(transactionInformation, key, etag, doc == null ? Etag.Empty : doc.Etag, UuidGenerator); deleted = doc != null; } WorkContext.ShouldNotifyAboutWork(() => "DEL " + key); }); metadata = metadataVar; return(deleted); } }
public bool Delete(string key, Etag etag, out RavenJObject metadata, string[] participatingIds = null) { if (key == null) { throw new ArgumentNullException("key"); } key = key.Trim(); var deleted = false; if (Log.IsDebugEnabled) { Log.Debug("Delete a document with key: {0} and etag {1}", key, etag); } RavenJObject metadataVar = null; using (Database.DocumentLock.Lock()) { TransactionalStorage.Batch(actions => { AssertDeleteOperationNotVetoed(key); Database.DeleteTriggers.Apply(trigger => trigger.OnDelete(key)); string collection = null; Etag deletedETag; if (actions.Documents.DeleteDocument(key, etag, out metadataVar, out deletedETag)) { deleted = true; actions.Indexing.RemoveAllDocumentReferencesFrom(key); WorkContext.MarkDeleted(key); Database.Indexes.CheckReferenceBecauseOfDocumentUpdate(key, actions, participatingIds); collection = metadataVar.Value <string>(Constants.RavenEntityName); DeleteDocumentFromIndexesForCollection(key, collection, actions); if (deletedETag != null) { Database.Prefetcher.AfterDelete(key, deletedETag); } Database.DeleteTriggers.Apply(trigger => trigger.AfterDelete(key)); } TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.DeleteTriggers.Apply(trigger => trigger.AfterCommit(key)); if (string.IsNullOrEmpty(collection) == false) { Database.LastCollectionEtags.Update(collection); } Database.Notifications.RaiseNotifications(new DocumentChangeNotification { Id = key, Type = DocumentChangeTypes.Delete, TypeName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenClrType) : null, CollectionName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenEntityName) : null }, metadataVar); }); WorkContext.ShouldNotifyAboutWork(() => "DEL " + key); }); metadata = metadataVar; return(deleted); } }
public string PutTransform(string name, TransformerDefinition definition, bool isReplication = false) { if (name == null) { throw new ArgumentNullException("name"); } if (definition == null) { throw new ArgumentNullException("definition"); } name = name.Trim(); var existingDefinition = IndexDefinitionStorage.GetTransformerDefinition(name); if (existingDefinition != null) { var newTransformerVersion = definition.TransformerVersion; var currentTransformerVersion = existingDefinition.TransformerVersion; // whether we update the transformer definition or not, // we need to update the transformer version existingDefinition.TransformerVersion = definition.TransformerVersion = Math.Max(currentTransformerVersion ?? 0, newTransformerVersion ?? 0); switch (isReplication) { case true: if (newTransformerVersion != null && currentTransformerVersion != null && newTransformerVersion <= currentTransformerVersion) { //this new transformer is an older version of the current one return(null); } // we need to update the lock mode only if it was updated by another server existingDefinition.LockMode = definition.LockMode; break; default: switch (existingDefinition.LockMode) { case TransformerLockMode.Unlock: if (existingDefinition.Equals(definition)) { return(name); // no op for the same transformer } definition.TransformerVersion++; break; case TransformerLockMode.LockedIgnore: Log.Info("Transformer {0} not saved because it was lock (with ignore)", name); return(name); default: throw new ArgumentOutOfRangeException(); } break; } } else if (isReplication == false) { // we're creating a new transformer, // we need to take the transformer version of the deleted transformer (if exists) definition.TransformerVersion = GetDeletedTransformerId(definition.Name); definition.TransformerVersion = (definition.TransformerVersion ?? 0) + 1; } if (definition.TransformerVersion == null) { definition.TransformerVersion = 0; } var generator = IndexDefinitionStorage.CompileTransform(definition); if (existingDefinition != null) { IndexDefinitionStorage.RemoveTransformer(existingDefinition.TransfomerId); } var temporary = definition.Temporary; if (temporary) { definition.TransfomerId = Database.Transformers.GetNextTemporaryTransformerIndex(); IndexDefinitionStorage.CreateTransform(definition, generator); IndexDefinitionStorage.AddTransform(definition.TransfomerId, definition); } else { TransactionalStorage.Batch(accessor => { definition.TransfomerId = (int)Database.Documents.GetNextIdentityValueWithoutOverwritingOnExistingDocuments("TransformerId", accessor); }); IndexDefinitionStorage.CreateTransform(definition, generator); IndexDefinitionStorage.PersistTransform(definition); IndexDefinitionStorage.AddTransform(definition.TransfomerId, definition); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification() { Name = name, Type = TransformerChangeTypes.TransformerAdded, Version = definition.TransformerVersion })); } return(name); }
public PutResult Put(string key, Etag etag, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation) { WorkContext.MetricsCounters.DocsPerSecond.Mark(); key = string.IsNullOrWhiteSpace(key) ? Guid.NewGuid().ToString() : key.Trim(); RemoveReservedProperties(document); RemoveMetadataReservedProperties(metadata); Etag newEtag = Etag.Empty; using (Database.DocumentLock.Lock()) { TransactionalStorage.Batch(actions => { if (key.EndsWith("/")) { key += GetNextIdentityValueWithoutOverwritingOnExistingDocuments(key, actions); } AssertPutOperationNotVetoed(key, metadata, document, transactionInformation); if (transactionInformation == null) { if (Database.InFlightTransactionalState.IsModified(key)) { throw new ConcurrencyException("PUT attempted on : " + key + " while it is being locked by another transaction"); } Database.PutTriggers.Apply(trigger => trigger.OnPut(key, document, metadata, null)); var addDocumentResult = actions.Documents.AddDocument(key, etag, document, metadata); newEtag = addDocumentResult.Etag; Database.Indexes.CheckReferenceBecauseOfDocumentUpdate(key, actions); metadata[Constants.LastModified] = addDocumentResult.SavedAt; metadata.EnsureSnapshot( "Metadata was written to the database, cannot modify the document after it was written (changes won't show up in the db). Did you forget to call CreateSnapshot() to get a clean copy?"); document.EnsureSnapshot( "Document was written to the database, cannot modify the document after it was written (changes won't show up in the db). Did you forget to call CreateSnapshot() to get a clean copy?"); actions.AfterStorageCommitBeforeWorkNotifications(new JsonDocument { Metadata = metadata, Key = key, DataAsJson = document, Etag = newEtag, LastModified = addDocumentResult.SavedAt, SkipDeleteFromIndex = addDocumentResult.Updated == false }, documents => Database.Prefetcher.AfterStorageCommitBeforeWorkNotifications(PrefetchingUser.Indexer, documents)); if (addDocumentResult.Updated) { Database.Prefetcher.AfterUpdate(key, addDocumentResult.PrevEtag); } Database.PutTriggers.Apply(trigger => trigger.AfterPut(key, document, metadata, newEtag, null)); TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.PutTriggers.Apply(trigger => trigger.AfterCommit(key, document, metadata, newEtag)); var newDocumentChangeNotification = new DocumentChangeNotification { Id = key, Type = DocumentChangeTypes.Put, TypeName = metadata.Value <string>(Constants.RavenClrType), CollectionName = metadata.Value <string>(Constants.RavenEntityName), Etag = newEtag }; Database.Notifications.RaiseNotifications(newDocumentChangeNotification, metadata); }); WorkContext.ShouldNotifyAboutWork(() => "PUT " + key); } else { var doc = actions.Documents.DocumentMetadataByKey(key); newEtag = Database.InFlightTransactionalState.AddDocumentInTransaction(key, etag, document, metadata, transactionInformation, doc == null ? Etag.Empty : doc.Etag, UuidGenerator); } }); Log.Debug("Put document {0} with etag {1}", key, newEtag); return(new PutResult { Key = key, ETag = newEtag }); } }
public bool Delete(string key, Etag etag, TransactionInformation transactionInformation, out RavenJObject metadata) { if (key == null) { throw new ArgumentNullException("key"); } key = key.Trim(); var deleted = false; Log.Debug("Delete a document with key: {0} and etag {1}", key, etag); RavenJObject metadataVar = null; using (Database.DocumentLock.Lock()) { TransactionalStorage.Batch(actions => { AssertDeleteOperationNotVetoed(key, transactionInformation); if (transactionInformation == null) { Database.DeleteTriggers.Apply(trigger => trigger.OnDelete(key, null)); Etag deletedETag; if (actions.Documents.DeleteDocument(key, etag, out metadataVar, out deletedETag)) { deleted = true; actions.Indexing.RemoveAllDocumentReferencesFrom(key); WorkContext.MarkDeleted(key); Database.Indexes.CheckReferenceBecauseOfDocumentUpdate(key, actions); var collection = metadataVar.Value <string>(Constants.RavenEntityName); DeleteDocumentFromIndexesForCollection(key, collection, actions); if (deletedETag != null) { Database.Prefetcher.AfterDelete(key, deletedETag); } Database.DeleteTriggers.Apply(trigger => trigger.AfterDelete(key, null)); } TransactionalStorage .ExecuteImmediatelyOrRegisterForSynchronization(() => { Database.DeleteTriggers.Apply(trigger => trigger.AfterCommit(key)); Database.Notifications.RaiseNotifications(new DocumentChangeNotification { Id = key, Type = DocumentChangeTypes.Delete, TypeName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenClrType) : null, CollectionName = (metadataVar != null) ? metadataVar.Value <string>(Constants.RavenEntityName) : null }, metadataVar); }); } else { var doc = actions.Documents.DocumentMetadataByKey(key); Database.InFlightTransactionalState.DeleteDocumentInTransaction(transactionInformation, key, etag, doc == null ? Etag.Empty : doc.Etag, UuidGenerator); deleted = doc != null; } WorkContext.ShouldNotifyAboutWork(() => "DEL " + key); }); metadata = metadataVar; return(deleted); } }
private string PutIndexInternal(string name, IndexDefinition definition, bool disableIndexBeforePut = false, bool isUpdateBySideSide = false, IndexCreationOptions?creationOptions = null) { if (name == null) { throw new ArgumentNullException("name"); } name = name.Trim(); IsIndexNameValid(name); var existingIndex = IndexDefinitionStorage.GetIndexDefinition(name); if (existingIndex != null) { switch (existingIndex.LockMode) { case IndexLockMode.SideBySide: if (isUpdateBySideSide == false) { Log.Info("Index {0} not saved because it might be only updated by side-by-side index"); throw new InvalidOperationException("Can not overwrite locked index: " + name + ". This index can be only updated by side-by-side index."); } break; case IndexLockMode.LockedIgnore: Log.Info("Index {0} not saved because it was lock (with ignore)", name); return(null); case IndexLockMode.LockedError: throw new InvalidOperationException("Can not overwrite locked index: " + name); } } AssertAnalyzersValid(definition); switch (creationOptions ?? FindIndexCreationOptions(definition, ref name)) { case IndexCreationOptions.Noop: return(null); case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); IndexDefinitionStorage.UpdateIndexDefinitionWithoutUpdatingCompiledIndex(definition); return(null); case IndexCreationOptions.Update: // ensure that the code can compile new DynamicViewCompiler(definition.Name, definition, Database.Extensions, IndexDefinitionStorage.IndexDefinitionsPath, Database.Configuration).GenerateInstance(); DeleteIndex(name); break; } PutNewIndexIntoStorage(name, definition, disableIndexBeforePut); WorkContext.ClearErrorsFor(name); TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new IndexChangeNotification { Name = name, Type = IndexChangeTypes.IndexAdded, })); return(name); }