public void Start() { var indexDefinitions = Database.Indexes.Definitions; var sideBySideIndexes = indexDefinitions.Where(x => x.Name.StartsWith(Constants.SideBySideIndexNamePrefix)).ToList(); foreach (var indexDefinition in sideBySideIndexes) { var indexName = indexDefinition.Name; var instance = Database.IndexStorage.GetIndexInstance(indexName); if (instance == null) { //probably deleted continue; } var indexToAdd = new IndexToAdd { Name = indexDefinition.Name, Definition = indexDefinition, Priority = instance.Priority }; SetIndexReplaceInfo(indexName, indexToAdd); StartReplicatingSideBySideIndexAsync(indexToAdd); } Database.Notifications.OnIndexChange += OnIndexChange; Database.Notifications.OnDocumentChange += OnDocumentChange; indexReplicationTimer = Database.TimerManager.NewTimer(x => Execute(), TimeSpan.Zero, replicationFrequency); lastQueriedTimer = Database.TimerManager.NewTimer(x => SendLastQueried(), TimeSpan.Zero, lastQueriedFrequency); }
public void StartReplicatingSideBySideIndexAsync(IndexToAdd indexToAdd) { if (indexToAdd.Name.StartsWith(Constants.SideBySideIndexNamePrefix)) indexToAdd.Name = indexToAdd.Name.Substring(Constants.SideBySideIndexNamePrefix.Length); sideBySideIndexesToReplicate.TryAdd(indexToAdd.Definition.IndexId, indexToAdd); ReplicateSideBySideIndexes(); }
private void SetIndexReplaceInfo(string indexName, IndexToAdd indexToAdd) { var key = Constants.IndexReplacePrefix + indexName; var replaceDoc = Database.Documents.Get(key, null); if (replaceDoc == null) return; try { var indexReplaceInformation = replaceDoc.DataAsJson.JsonDeserialization<IndexReplaceDocument>(); indexToAdd.MinimumEtagBeforeReplace = indexReplaceInformation.MinimumEtagBeforeReplace; indexToAdd.ReplaceTimeUtc = indexReplaceInformation.ReplaceTimeUtc; } catch (Exception) { //the index was already replaced or the document was deleted //anyway, we'll try to replicate this index with default settings } }
private void OnDocumentChange(DocumentDatabase db, DocumentChangeNotification notification, RavenJObject doc) { var docId = notification.Id; if (docId == null) return; if (docId.StartsWith(Constants.IndexReplacePrefix, StringComparison.OrdinalIgnoreCase) == false) return; if (notification.Type != DocumentChangeTypes.Put) return; var replaceIndexName = docId.Substring(Constants.IndexReplacePrefix.Length); var instance = Database.IndexStorage.GetIndexInstance(replaceIndexName); if (instance == null) return; var indexDefinition = Database.Indexes.GetIndexDefinition(replaceIndexName); if (indexDefinition == null) return; var indexToAdd = new IndexToAdd { Name = replaceIndexName, Definition = indexDefinition, Priority = instance.Priority, }; SetIndexReplaceInfo(replaceIndexName, indexToAdd); StartReplicatingSideBySideIndexAsync(indexToAdd); }
public string[] PutIndexes(IndexToAdd[] indexesToAdd) { var createdIndexes = new List<string>(); var prioritiesList = new List<IndexingPriority>(); try { foreach (var indexToAdd in indexesToAdd) { var name = indexToAdd.Name; var definition = indexToAdd.Definition; var priority = indexToAdd.Priority; 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 SideBySideIndexInfo[] PutSideBySideIndexes(IndexToAdd[] indexesToAdd) { var createdIndexes = new List<SideBySideIndexInfo>(); var prioritiesList = new List<IndexingPriority>(); try { foreach (var indexToAdd in indexesToAdd) { var originalIndexName = indexToAdd.Name.Trim(); var indexName = Constants.SideBySideIndexNamePrefix + originalIndexName; var isSideBySide = true; IndexCreationOptions? creationOptions = null; //if there is no existing side by side index, we might need to update the old index if (IndexDefinitionStorage.GetIndexDefinition(indexName) == null) { var originalIndexCreationOptions = FindIndexCreationOptions(indexToAdd.Definition, ref originalIndexName); switch (originalIndexCreationOptions) { case IndexCreationOptions.Noop: continue; case IndexCreationOptions.Create: case IndexCreationOptions.UpdateWithoutUpdatingCompiledIndex: //cases in which we don't need to create a side by side index: //1) index doesn't exist => need to create a new regular index //2) there is an existing index and we need to update its definition without reindexing indexName = originalIndexName; isSideBySide = false; creationOptions = originalIndexCreationOptions; break; } } var nameToAdd = PutIndexInternal(indexName, indexToAdd.Definition, disableIndexBeforePut: true, isUpdateBySideSide: true, creationOptions: creationOptions); if (nameToAdd == null) continue; createdIndexes.Add(new SideBySideIndexInfo { OriginalName = originalIndexName, Name = nameToAdd, IsSideBySide = isSideBySide }); prioritiesList.Add(indexToAdd.Priority); } var indexesIds = createdIndexes.Select(x => Database.IndexStorage.GetIndexInstance(x.Name).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.Name); } throw; } }
public string[] PutIndexes(IndexToAdd[] indexesToAdd) { var createdIndexes = new List<string>(); var prioritiesList = new List<IndexingPriority>(); try { foreach (var indexToAdd in indexesToAdd) { var nameToAdd = PutIndexInternal(indexToAdd.Name, indexToAdd.Definition, disableIndexBeforePut: true); if (nameToAdd == null) continue; createdIndexes.Add(nameToAdd); prioritiesList.Add(indexToAdd.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[] PutIndexes(IndexToAdd[] indexesToAdd, bool isReplication) { var createdIndexes = new List<string>(); var prioritiesList = new List<IndexingPriority>(); try { foreach (var indexToAdd in indexesToAdd) { var nameToAdd = PutIndexInternal(indexToAdd.Name, indexToAdd.Definition, disableIndexBeforePut: true, isReplication: isReplication); if (nameToAdd == null) continue; createdIndexes.Add(nameToAdd); prioritiesList.Add(indexToAdd.Priority); } var indexesIds = createdIndexes.Select(x => Database.IndexStorage.GetIndexInstance(x).indexId).ToArray(); Database.TransactionalStorage.Batch(accessor => accessor.Indexing.SetIndexesPriority(indexesIds, prioritiesList.ToArray())); for (var i = 0; i < createdIndexes.Count; i++) { var indexName = createdIndexes[i]; var priority = prioritiesList[i]; var instance = Database.IndexStorage.GetIndexInstance(indexName); if (instance == null) { Log.Warn("Couldn't set index priority because index named: '{0}' doesn't exist", indexName); continue; } instance.Priority = priority; } return createdIndexes.ToArray(); } catch (Exception e) { Log.WarnException("Could not create index batch", e); foreach (var index in createdIndexes) { DeleteIndex(index); } throw; } }