PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/ToMigrate/Raven.Tests/Indexes/Recovery/MapIndexRecoveryTests.cs

https://github.com/georgiosd/ravendb
C# | 409 lines | 308 code | 86 blank | 15 comment | 3 complexity | ccf7e809004fd756029e9cace5ff692f MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-SA-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. // -----------------------------------------------------------------------
  2. // <copyright file="IndexRecovery.cs" company="Hibernating Rhinos LTD">
  3. // Copyright (c) Hibernating Rhinos LTD. All rights reserved.
  4. // </copyright>
  5. // -----------------------------------------------------------------------
  6. using System;
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Linq;
  10. using Raven.Client.Document;
  11. using Raven.Database.Config;
  12. using Raven.Database.Indexing;
  13. using Raven.Imports.Newtonsoft.Json;
  14. using Raven.Tests.Common;
  15. using Xunit;
  16. namespace Raven.Tests.Indexes.Recovery
  17. {
  18. using Client.Connection;
  19. using Imports.Newtonsoft.Json.Linq;
  20. using Raven.Abstractions.Data;
  21. using Raven.Abstractions.Extensions;
  22. using Raven.Json.Linq;
  23. public class MapIndexRecoveryTests : RavenTest
  24. {
  25. private void CommitPointAfterEachCommit(InMemoryRavenConfiguration configuration)
  26. {
  27. // force commit point creation after each commit
  28. configuration.MinIndexingTimeIntervalToStoreCommitPoint = TimeSpan.FromSeconds(0);
  29. configuration.MaxIndexCommitPointStoreTimeInterval = TimeSpan.FromSeconds(0);
  30. }
  31. private void CommitPointAfterFirstCommitOnly(InMemoryRavenConfiguration configuration)
  32. {
  33. // by default first commit will force creating commit point, here we don't need more
  34. configuration.MinIndexingTimeIntervalToStoreCommitPoint = TimeSpan.FromMinutes(30);
  35. configuration.MaxIndexCommitPointStoreTimeInterval = TimeSpan.MaxValue;
  36. }
  37. protected override void ModifyConfiguration(InMemoryRavenConfiguration configuration)
  38. {
  39. configuration.DefaultStorageTypeName = "esent";
  40. configuration.FlushIndexToDiskSizeInMb = 0;
  41. }
  42. [Fact]
  43. public void ShouldCreateCommitPointsForMapIndexes()
  44. {
  45. var index = new MapRecoveryTestIndex();
  46. string commitPointsDirectory;
  47. using (var server = GetNewServer(runInMemory: false))
  48. {
  49. CommitPointAfterEachCommit(server.SystemDatabase.Configuration);
  50. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  51. {
  52. index.Execute(store);
  53. using (var session = store.OpenSession())
  54. {
  55. session.Store(new Recovery
  56. {
  57. Name = "One",
  58. Number = 1
  59. });
  60. session.SaveChanges();
  61. WaitForIndexing(store);
  62. session.Store(new Recovery
  63. {
  64. Name = "Two",
  65. Number = 2
  66. });
  67. session.SaveChanges();
  68. WaitForIndexing(store);
  69. }
  70. Index indexInstance = server.SystemDatabase.IndexStorage.GetIndexInstance(index.IndexName);
  71. commitPointsDirectory = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  72. indexInstance.IndexId + "\\CommitPoints");
  73. }
  74. Assert.True(Directory.Exists(commitPointsDirectory));
  75. var commitPoints = Directory.GetDirectories(commitPointsDirectory);
  76. Assert.Equal(2, commitPoints.Length);
  77. foreach (var commitPoint in commitPoints)
  78. {
  79. var files = Directory.GetFiles(commitPoint);
  80. Assert.Equal(2, files.Length);
  81. Assert.True(files.Any(file => Path.GetFileName(file) == "index.commitPoint"));
  82. Assert.True(files.Any(file => Path.GetFileName(file).StartsWith("segments_")));
  83. }
  84. }
  85. }
  86. [Fact]
  87. public void ShouldKeepLimitedNumberOfCommitPoints()
  88. {
  89. var index = new MapRecoveryTestIndex();
  90. using (var server = GetNewServer(runInMemory: false))
  91. {
  92. CommitPointAfterEachCommit(server.SystemDatabase.Configuration);
  93. var maxNumberOfStoredCommitPoints = server.SystemDatabase.Configuration.MaxNumberOfStoredCommitPoints;
  94. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  95. {
  96. index.Execute(store);
  97. for (int i = 0; i < 2 * maxNumberOfStoredCommitPoints; i++)
  98. {
  99. using (var session = store.OpenSession())
  100. {
  101. session.Store(new Recovery
  102. {
  103. Name = i.ToString(),
  104. Number = i
  105. });
  106. session.SaveChanges();
  107. WaitForIndexing(store);
  108. }
  109. Index indexInstance = server.SystemDatabase.IndexStorage.GetIndexInstance(index.IndexName);
  110. var commitPointsDirectory = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  111. indexInstance.IndexId + "\\CommitPoints");
  112. var commitPoints = Directory.GetDirectories(commitPointsDirectory);
  113. Assert.True(commitPoints.Length <= maxNumberOfStoredCommitPoints);
  114. }
  115. }
  116. }
  117. }
  118. [Fact]
  119. public void ShouldRecoverMapIndexFromLastCommitPoint()
  120. {
  121. var dataDir = NewDataPath("RecoverMapIndex");
  122. string indexFullPath;
  123. string commitPointsDirectory;
  124. var index = new MapRecoveryTestIndex();
  125. using (var server = GetNewServer(runInMemory: false, dataDirectory: dataDir))
  126. {
  127. CommitPointAfterFirstCommitOnly(server.SystemDatabase.Configuration);
  128. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  129. {
  130. index.Execute(store);
  131. using (var session = store.OpenSession())
  132. {
  133. session.Store(new Recovery // indexing this entity will create commit point
  134. {
  135. Name = "One",
  136. Number = 1
  137. });
  138. session.SaveChanges();
  139. WaitForIndexing(store);
  140. session.Store(new Recovery // this will not be in commit point
  141. {
  142. Name = "Two",
  143. Number = 2
  144. });
  145. session.SaveChanges();
  146. WaitForIndexing(store);
  147. }
  148. }
  149. Index indexInstance = server.SystemDatabase.IndexStorage.GetIndexInstance(index.IndexName);
  150. commitPointsDirectory = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  151. indexInstance.IndexId + "\\CommitPoints");
  152. indexFullPath = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  153. indexInstance.IndexId.ToString(CultureInfo.InvariantCulture));
  154. }
  155. // make sure that there is only one commit point - which doesn't have the second entity indexed
  156. Assert.Equal(1, Directory.GetDirectories(commitPointsDirectory).Length);
  157. IndexMessing.MessSegmentsFile(indexFullPath);
  158. using (GetNewServer(runInMemory: false, dataDirectory: dataDir)) // do not delete previous directory
  159. {
  160. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  161. {
  162. using (var session = store.OpenSession())
  163. {
  164. var result = session.Query<Recovery, MapRecoveryTestIndex>().Customize(x => x.WaitForNonStaleResults()).ToList();
  165. Assert.Equal(2, result.Count);
  166. }
  167. }
  168. // here we should have another commit point because missing document after restore were indexed again
  169. Assert.Equal(2, Directory.GetDirectories(commitPointsDirectory).Length);
  170. }
  171. }
  172. [Fact]
  173. public void ShouldRecoverDeletes()
  174. {
  175. var dataDir = NewDataPath("ShouldRecoverDeletes");
  176. string indexFullPath;
  177. string commitPointsDirectory;
  178. var index = new MapRecoveryTestIndex();
  179. using (var server = GetNewServer(runInMemory: false, dataDirectory: dataDir))
  180. {
  181. CommitPointAfterFirstCommitOnly(server.SystemDatabase.Configuration);
  182. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  183. {
  184. index.Execute(store);
  185. using (var session = store.OpenSession())
  186. {
  187. session.Store(new Recovery
  188. {
  189. Name = "One",
  190. Number = 1
  191. });
  192. session.Store(new Recovery
  193. {
  194. Name = "Two",
  195. Number = 2
  196. });
  197. session.Store(new Recovery
  198. {
  199. Name = "Three",
  200. Number = 3
  201. });
  202. session.SaveChanges(); // store all items in commit point
  203. WaitForIndexing(store);
  204. var itemToDelete = session.Query<Recovery, MapRecoveryTestIndex>().First();
  205. session.Delete(itemToDelete);
  206. session.SaveChanges();
  207. WaitForIndexing(store);
  208. }
  209. }
  210. Index indexInstance = server.SystemDatabase.IndexStorage.GetIndexInstance(index.IndexName);
  211. commitPointsDirectory = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  212. indexInstance.IndexId + "\\CommitPoints");
  213. indexFullPath = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  214. indexInstance.IndexId.ToString(CultureInfo.InvariantCulture));
  215. }
  216. // make sure that there is only one commit point - which doesn't have the second entity indexed
  217. Assert.Equal(1, Directory.GetDirectories(commitPointsDirectory).Length);
  218. IndexMessing.MessSegmentsFile(indexFullPath);
  219. using (GetNewServer(runInMemory: false, dataDirectory: dataDir)) // do not delete previous directory
  220. {
  221. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  222. {
  223. using (var session = store.OpenSession())
  224. {
  225. var result = session.Query<Recovery, MapRecoveryTestIndex>().ToArray();
  226. Assert.Equal(2, result.Length);
  227. }
  228. }
  229. }
  230. }
  231. [Fact]
  232. public void ShouldDeleteCommitPointIfCouldNotRecoverFromIt()
  233. {
  234. var dataDir = NewDataPath("ShouldDeleteCommitPointIfCouldNotRecoverFromIt");
  235. string indexFullPath;
  236. string indexStoragePath;
  237. int indexId;
  238. string commitPointsDirectory;
  239. var index = new MapRecoveryTestIndex();
  240. using (var server = GetNewServer(runInMemory: false, dataDirectory: dataDir))
  241. {
  242. CommitPointAfterEachCommit(server.SystemDatabase.Configuration);
  243. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  244. {
  245. index.Execute(store);
  246. using (var session = store.OpenSession())
  247. {
  248. session.Store(new Recovery
  249. {
  250. Name = "One",
  251. Number = 1
  252. });
  253. session.SaveChanges(); // first commit point
  254. WaitForIndexing(store);
  255. server.SystemDatabase.IndexStorage.FlushMapIndexes();
  256. server.SystemDatabase.IndexStorage.FlushReduceIndexes();
  257. session.Store(new Recovery
  258. {
  259. Name = "Two",
  260. Number = 2
  261. });
  262. session.SaveChanges(); // second commit point
  263. WaitForIndexing(store);
  264. server.SystemDatabase.IndexStorage.FlushMapIndexes();
  265. server.SystemDatabase.IndexStorage.FlushReduceIndexes();
  266. session.Store(new Recovery
  267. {
  268. Name = "Three",
  269. Number = 3
  270. });
  271. session.SaveChanges(); // second commit point
  272. WaitForIndexing(store, timeout: TimeSpan.FromSeconds(60));
  273. server.SystemDatabase.IndexStorage.FlushMapIndexes();
  274. server.SystemDatabase.IndexStorage.FlushReduceIndexes();
  275. }
  276. }
  277. Index indexInstance = server.SystemDatabase.IndexStorage.GetIndexInstance(index.IndexName);
  278. commitPointsDirectory = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  279. indexInstance.IndexId + "\\CommitPoints");
  280. indexFullPath = Path.Combine(server.SystemDatabase.Configuration.IndexStoragePath,
  281. indexInstance.IndexId.ToString(CultureInfo.InvariantCulture));
  282. indexStoragePath = server.SystemDatabase.Configuration.IndexStoragePath;
  283. indexId = indexInstance.IndexId;
  284. }
  285. // make sure that there are 3 commit points
  286. var directories = Directory.GetDirectories(commitPointsDirectory);
  287. Assert.Equal(3, directories.Length);
  288. // mess "index.CommitPoint" file in the SECOND and THIRD commit points by adding additional files required to recover from it
  289. for (int i = 1; i < 3; i++)
  290. {
  291. IndexCommitPoint commitPoint;
  292. Assert.True(IndexStorage.TryGetCommitPoint(new IndexCommitPointDirectory(indexStoragePath, indexId.ToString(CultureInfo.InvariantCulture), directories[i].Split(new[] { '\\' }).Last()), out commitPoint));
  293. commitPoint.SegmentsInfo.ReferencedFiles.Add("file-that-doesnt-exist");
  294. using (var commitPointFile = File.Open(Path.Combine(directories[i], "index.CommitPoint"), FileMode.Open))
  295. {
  296. using (var sw = new StreamWriter(commitPointFile))
  297. {
  298. var textWriter = new JsonTextWriter(sw);
  299. JsonExtensions.CreateDefaultJsonSerializer().Serialize(textWriter, commitPoint);
  300. sw.Flush();
  301. }
  302. }
  303. }
  304. IndexMessing.MessSegmentsFile(indexFullPath);
  305. using (GetNewServer(runInMemory: false, dataDirectory: dataDir)) // do not delete previous directory
  306. {
  307. using (var store = new DocumentStore { Url = "http://localhost:8079" }.Initialize())
  308. {
  309. using (var session = store.OpenSession())
  310. {
  311. var result =
  312. session.Query<Recovery, MapRecoveryTestIndex>().Customize(x => x.WaitForNonStaleResults()).ToList();
  313. Assert.Equal(3, result.Count);
  314. }
  315. }
  316. }
  317. // there should be exactly 2 commit points:
  318. // the first one which we used to recover
  319. // and the second one created because of indexing after recovery
  320. Assert.Equal(2, Directory.GetDirectories(commitPointsDirectory).Length);
  321. }
  322. }
  323. }