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);
            });
        }
示例#2
0
        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,
                }));
            }
        }
示例#3
0
        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);
        }
示例#4
0
 public void DeleteTransform(string name)
 {
     IndexDefinitionStorage.RemoveTransformer(name);
     TransactionalStorage.ExecuteImmediatelyOrRegisterForSynchronization(() => Database.Notifications.RaiseNotifications(new TransformerChangeNotification
     {
         Name = name,
         Type = TransformerChangeTypes.TransformerRemoved
     }));
 }
示例#5
0
        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);
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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);
        }
示例#10
0
        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;
            }
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
        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);
            }
        }
示例#14
0
        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);
            }
        }
示例#15
0
        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);
        }
示例#16
0
        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
                });
            }
        }
示例#17
0
        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);
            }
        }
示例#18
0
        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);
        }