/src/Raven.Server/Smuggler/Documents/DatabaseSource.cs

https://github.com/fitzchak/ravendb · C# · 247 lines · 205 code · 42 blank · 0 comment · 12 complexity · f81ed7ba03a02dfae8f9fa00f85c3259 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using Raven.Client;
  6. using Raven.Client.Documents.Indexes;
  7. using Raven.Client.Documents.Smuggler;
  8. using Raven.Client.ServerWide;
  9. using Raven.Client.Util;
  10. using Raven.Server.Documents;
  11. using Raven.Server.ServerWide;
  12. using Raven.Server.ServerWide.Context;
  13. using Raven.Server.Smuggler.Documents.Data;
  14. using Raven.Server.Utils;
  15. using Sparrow.Json;
  16. using Voron;
  17. namespace Raven.Server.Smuggler.Documents
  18. {
  19. public class DatabaseSource : ISmugglerSource
  20. {
  21. private readonly DocumentDatabase _database;
  22. private DocumentsOperationContext _context;
  23. private readonly long _startDocumentEtag;
  24. private IDisposable _returnContext;
  25. private IDisposable _disposeTransaction;
  26. private int _currentTypeIndex;
  27. private readonly DatabaseItemType[] _types =
  28. {
  29. DatabaseItemType.DatabaseRecord,
  30. DatabaseItemType.Documents,
  31. DatabaseItemType.RevisionDocuments,
  32. DatabaseItemType.Tombstones,
  33. DatabaseItemType.Conflicts,
  34. DatabaseItemType.Indexes,
  35. DatabaseItemType.Identities,
  36. DatabaseItemType.CompareExchange,
  37. DatabaseItemType.None
  38. };
  39. public DatabaseSource(DocumentDatabase database, long startDocumentEtag)
  40. {
  41. _database = database;
  42. _startDocumentEtag = startDocumentEtag;
  43. }
  44. public IDisposable Initialize(DatabaseSmugglerOptions options, SmugglerResult result, out long buildVersion)
  45. {
  46. _currentTypeIndex = 0;
  47. _returnContext = _database.DocumentsStorage.ContextPool.AllocateOperationContext(out _context);
  48. _disposeTransaction = _context.OpenReadTransaction();
  49. buildVersion = ServerVersion.Build;
  50. return new DisposableAction(() =>
  51. {
  52. _disposeTransaction.Dispose();
  53. _returnContext.Dispose();
  54. });
  55. }
  56. public DatabaseItemType GetNextType()
  57. {
  58. return _types[_currentTypeIndex++];
  59. }
  60. public DatabaseRecord GetDatabaseRecord()
  61. {
  62. return _database.ReadDatabaseRecord();
  63. }
  64. public IEnumerable<DocumentItem> GetDocuments(List<string> collectionsToExport, INewDocumentActions actions)
  65. {
  66. var documents = collectionsToExport.Count != 0
  67. ? _database.DocumentsStorage.GetDocumentsFrom(_context, collectionsToExport, _startDocumentEtag, int.MaxValue)
  68. : _database.DocumentsStorage.GetDocumentsFrom(_context, _startDocumentEtag, 0, int.MaxValue);
  69. foreach (var document in documents)
  70. {
  71. yield return new DocumentItem
  72. {
  73. Document = document
  74. };
  75. }
  76. }
  77. public IEnumerable<DocumentItem> GetRevisionDocuments(List<string> collectionsToExport, INewDocumentActions actions)
  78. {
  79. var revisionsStorage = _database.DocumentsStorage.RevisionsStorage;
  80. if (revisionsStorage.Configuration == null)
  81. yield break;
  82. var documents = revisionsStorage.GetRevisionsFrom(_context, _startDocumentEtag, int.MaxValue);
  83. foreach (var document in documents)
  84. {
  85. yield return new DocumentItem
  86. {
  87. Document = document
  88. };
  89. }
  90. }
  91. public IEnumerable<DocumentItem> GetLegacyAttachments(INewDocumentActions actions)
  92. {
  93. return Enumerable.Empty<DocumentItem>();
  94. }
  95. public IEnumerable<string> GetLegacyAttachmentDeletions()
  96. {
  97. return Enumerable.Empty<string>();
  98. }
  99. public IEnumerable<string> GetLegacyDocumentDeletions()
  100. {
  101. return Enumerable.Empty<string>();
  102. }
  103. public Stream GetAttachmentStream(LazyStringValue hash, out string tag)
  104. {
  105. using (Slice.External(_context.Allocator, hash, out Slice hashSlice))
  106. {
  107. return _database.DocumentsStorage.AttachmentsStorage.GetAttachmentStream(_context, hashSlice, out tag);
  108. }
  109. }
  110. public IEnumerable<DocumentTombstone> GetTombstones(List<string> collectionsToExport, INewDocumentActions actions)
  111. {
  112. var tombstones = collectionsToExport.Count > 0
  113. ? _database.DocumentsStorage.GetTombstonesFrom(_context, collectionsToExport, _startDocumentEtag, int.MaxValue)
  114. : _database.DocumentsStorage.GetTombstonesFrom(_context, _startDocumentEtag, 0, int.MaxValue);
  115. foreach (var tombstone in tombstones)
  116. {
  117. yield return tombstone;
  118. }
  119. }
  120. public IEnumerable<DocumentConflict> GetConflicts(List<string> collectionsToExport, INewDocumentActions actions)
  121. {
  122. var conflicts = _database.DocumentsStorage.ConflictsStorage.GetConflictsFrom(_context, _startDocumentEtag);
  123. if (collectionsToExport.Count > 0)
  124. {
  125. foreach (var conflict in conflicts)
  126. {
  127. if (collectionsToExport.Contains(conflict.Collection) == false)
  128. continue;
  129. yield return conflict;
  130. }
  131. yield break;
  132. }
  133. foreach (var conflict in conflicts)
  134. {
  135. yield return conflict;
  136. }
  137. }
  138. public IEnumerable<IndexDefinitionAndType> GetIndexes()
  139. {
  140. var allIndexes = _database.IndexStore.GetIndexes().ToList();
  141. var sideBySideIndexes = allIndexes.Where(x => x.Name.StartsWith(Constants.Documents.Indexing.SideBySideIndexNamePrefix)).ToList();
  142. var originalSideBySideIndexNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
  143. foreach (var index in sideBySideIndexes)
  144. {
  145. allIndexes.Remove(index);
  146. if (index.Type == IndexType.Faulty)
  147. continue;
  148. var indexName = index.Name.Remove(0, Constants.Documents.Indexing.SideBySideIndexNamePrefix.Length);
  149. originalSideBySideIndexNames.Add(indexName);
  150. var indexDefinition = index.GetIndexDefinition();
  151. indexDefinition.Name = indexName;
  152. yield return new IndexDefinitionAndType
  153. {
  154. IndexDefinition = indexDefinition,
  155. Type = index.Type
  156. };
  157. }
  158. foreach (var index in allIndexes)
  159. {
  160. if (originalSideBySideIndexNames.Contains(index.Name))
  161. continue;
  162. if (index.Type == IndexType.Faulty)
  163. continue;
  164. if (index.Type.IsStatic())
  165. {
  166. yield return new IndexDefinitionAndType
  167. {
  168. IndexDefinition = index.GetIndexDefinition(),
  169. Type = index.Type
  170. };
  171. continue;
  172. }
  173. yield return new IndexDefinitionAndType
  174. {
  175. IndexDefinition = index.Definition,
  176. Type = index.Type
  177. };
  178. }
  179. }
  180. public IDisposable GetIdentities(out IEnumerable<(string Prefix, long Value)> identities)
  181. {
  182. using (var scope = new DisposableScope())
  183. {
  184. scope.EnsureDispose(_database.ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context));
  185. scope.EnsureDispose(context.OpenReadTransaction());
  186. identities = _database.ServerStore.Cluster.ReadIdentities(context, _database.Name, 0, long.MaxValue);
  187. return scope.Delay();
  188. }
  189. }
  190. public IDisposable GetCompareExchangeValues(out IEnumerable<(string key, long index, BlittableJsonReaderObject value)> compareExchange)
  191. {
  192. using (var scope = new DisposableScope())
  193. {
  194. scope.EnsureDispose(_database.ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context));
  195. scope.EnsureDispose(context.OpenReadTransaction());
  196. compareExchange = _database.ServerStore.Cluster.GetCompareExchangeValuesStartsWith(context, _database.Name, _database.Name, 0, int.MaxValue);
  197. return scope.Delay();
  198. }
  199. }
  200. public long SkipType(DatabaseItemType type, Action<long> onSkipped)
  201. {
  202. return 0; // no-op
  203. }
  204. }
  205. }