private void ReplicateSingleSideBySideIndex(ReplicationStrategy destination, IndexDefinition indexDefinition, IndexDefinition sideBySideIndexDefinition) { var url = $"{destination.ConnectionStringOptions.Url}/replication/side-by-side?{GetDebugInformation()}"; IndexReplaceDocument indexReplaceDocument; try { indexReplaceDocument = Database.Documents.Get(Constants.IndexReplacePrefix + sideBySideIndexDefinition.Name, null).DataAsJson.JsonDeserialization <IndexReplaceDocument>(); } catch (Exception e) { Log.Warn("Cannot get side-by-side index replacement document. Aborting operation. (this exception should not happen and the cause should be investigated)", e); return; } var sideBySideReplicationInfo = new SideBySideReplicationInfo { Index = indexDefinition, SideBySideIndex = sideBySideIndexDefinition, OriginDatabaseId = destination.CurrentDatabaseId, IndexReplaceDocument = indexReplaceDocument }; var replicationRequest = HttpRavenRequestFactory.Create(url, HttpMethod.Post, destination.ConnectionStringOptions, Replication.GetRequestBuffering(destination)); replicationRequest.Write(RavenJObject.FromObject(sideBySideReplicationInfo)); replicationRequest.ExecuteRequest(); }
private void PutSideBySideIndexDocument(SideBySideReplicationInfo sideBySideReplicationInfo) { using (Database.DocumentLock.Lock()) { var id = Constants.IndexReplacePrefix + sideBySideReplicationInfo.SideBySideIndex.Name; var indexReplaceDocument = sideBySideReplicationInfo.IndexReplaceDocument; if (indexReplaceDocument.MinimumEtagBeforeReplace != null) //TODO : verify that this is OK -> not sure { indexReplaceDocument.MinimumEtagBeforeReplace = EtagUtil.Increment(Database.Statistics.LastDocEtag, 1); } Database.TransactionalStorage.Batch(accessor => accessor.Documents.AddDocument(id, null, RavenJObject.FromObject(indexReplaceDocument), new RavenJObject())); } }
public HttpResponseMessage ReplicateSideBySideIndex([FromBody] SideBySideReplicationInfo sideBySideReplicationInfo) { var index = Database.Indexes.GetIndexDefinition(sideBySideReplicationInfo.Index.Name); var sideBySideIndex = Database.Indexes.GetIndexDefinition(sideBySideReplicationInfo.SideBySideIndex.Name); //handle special cases first if (index == null) { //if there is no main index we would recreate it with side-by-side index definition, //but if something happened and the old index was deleted and the side-by-side index was not deleted, //then it is not needed anymore and should be deleted if (sideBySideIndex != null) { using (Database.DisableAllTriggersForCurrentThread()) //prevent this from being replicated as this change is internal and should not be replicated using (Database.DocumentLock.Lock()) //prevent race condition -> simultaneously with replication to this node, //a client creates side-by-side index { Database.Indexes.DeleteIndex(sideBySideIndex.Name); var id = Constants.IndexReplacePrefix + sideBySideReplicationInfo.SideBySideIndex.Name; Database.Documents.Delete(id, null, null); } } return(InternalPutIndex(sideBySideReplicationInfo.Index.Name, sideBySideReplicationInfo.SideBySideIndex, string.Format("Index with the name {0} wasn't found, so we created it with side-by-side index definition. (Perhaps it was deleted?)", sideBySideReplicationInfo.Index.Name))); } if (index.Equals(sideBySideReplicationInfo.SideBySideIndex, false)) { return(GetMessageWithObject(new { Message = "It appears that side-by-side index already replaced the old index. Nothing to do..." }, HttpStatusCode.NotModified)); } //if both side-by-side index and the original index are identical, nothing to do here var areIndexesEqual = index.Equals(sideBySideReplicationInfo.Index, false); var areSideBySideIndexesEqual = (sideBySideIndex != null) && sideBySideIndex.Equals(sideBySideReplicationInfo.SideBySideIndex, false); if (areIndexesEqual && areSideBySideIndexesEqual) { return(GetMessageWithObject(new { Message = "It appears that side-by-side index and the old index are the same. Nothing to do..." }, HttpStatusCode.NotModified)); } if (areIndexesEqual == false && areSideBySideIndexesEqual) { return(InternalPutIndex(sideBySideReplicationInfo.Index, "Side-by-side indexes were equal, updated the old index.")); } // ReSharper disable once ConditionIsAlwaysTrueOrFalse -> for better readability if (areIndexesEqual && areSideBySideIndexesEqual == false) { var internalPutIndex = InternalPutIndex(sideBySideReplicationInfo.SideBySideIndex, "Indexes to be replaced were equal, updated the side-by-side index."); if (internalPutIndex.IsSuccessStatusCode) { PutSideBySideIndexDocument(sideBySideReplicationInfo); } return(internalPutIndex); } var updateIndexResult = InternalPutIndex(sideBySideReplicationInfo.Index, "Side-by-side indexes were equal, updated the old index."); var updateSideBySideIndexResult = InternalPutIndex(sideBySideReplicationInfo.SideBySideIndex, "Indexes to be replaced were equal, updated the side-by-side index."); if (updateSideBySideIndexResult.IsSuccessStatusCode) { PutSideBySideIndexDocument(sideBySideReplicationInfo); } if (updateIndexResult.IsSuccessStatusCode && updateSideBySideIndexResult.IsSuccessStatusCode) { return(GetMessageWithObject(new { Indexes = new[] { sideBySideReplicationInfo.Index.Name, sideBySideReplicationInfo.SideBySideIndex.Name }, Message = "Both index and side-by-side index were different, so we updated them both" }, HttpStatusCode.Created)); } return(updateIndexResult.IsSuccessStatusCode == false ? updateIndexResult : updateSideBySideIndexResult); }