public unsafe void GetCriteriaAndEtag(long id, DocumentsOperationContext context, out SubscriptionCriteria criteria, out long startEtag) { var transactionPersistentContext = new TransactionPersistentContext(); using (var tx = _environment.ReadTransaction(transactionPersistentContext)) { var config = GetSubscriptionConfig(id, tx); int criteriaSize; var criteriaPtr = config.Read(SubscriptionSchema.SubscriptionTable.CriteriaIndex, out criteriaSize); var criteriaBlittable = new BlittableJsonReaderObject(criteriaPtr, criteriaSize, context); criteria = JsonDeserializationServer.SubscriptionCriteria(criteriaBlittable); startEtag = *(long *)config.Read(SubscriptionSchema.SubscriptionTable.AckEtagIndex, out criteriaSize); } }
private void ValidateMulti(StorageEnvironment env, IEnumerable <string> trees) { using (var snapshot = env.ReadTransaction()) { foreach (var tree in trees) { using (var iterator = snapshot.ReadTree(tree).MultiRead("test/0/user-50")) { Assert.True(iterator.Seek(Slices.BeforeAllKeys)); var keys = new HashSet <string>(); var count = 0; do { keys.Add(iterator.CurrentKey.ToString()); Guid.Parse(iterator.CurrentKey.ToString()); count++; }while (iterator.MoveNext()); Assert.Equal(2, count); Assert.Equal(2, keys.Count); } } } }
public void ShouldWork() { using (var env = new StorageEnvironment(StorageEnvironmentOptions.CreateMemoryOnly())) { using (var tx = env.WriteTransaction()) { var s = new string('0', 500); var tree = tx.CreateTree("data"); for (int i = 0; i < 10; i++) { tree.Add("users-" + i + "-" + s, new byte[0]); } tx.Commit(); } using (var tx = env.ReadTransaction()) { var tree = tx.ReadTree("data"); using (var it = tree.Iterate(false)) { Slice key; Slice.From(tx.Allocator, "users-7", out key); Assert.True(it.Seek(key)); for (int i = 0; i < 10; i++) { Slice.From(tx.Allocator, "users-" + i, out key); Assert.True(it.Seek(key), i.ToString()); } } } } }
private void ValidateRecords(StorageEnvironment env, IEnumerable <string> trees, IList <string> ids) { using (var snapshot = env.ReadTransaction()) { foreach (var treeName in trees) { var tree = snapshot.ReadTree(treeName); using (var iterator = tree.Iterate(false)) { Assert.True(iterator.Seek(Slices.BeforeAllKeys)); var keys = new HashSet <string>(); var count = 0; do { keys.Add(iterator.CurrentKey.ToString()); Assert.True(ids.Contains(iterator.CurrentKey.ToString()), "Unknown key: " + iterator.CurrentKey); Assert.NotNull(tree.Read(iterator.CurrentKey)); count++; }while (iterator.MoveNext()); Assert.Equal(ids.Count, tree.State.NumberOfEntries); Assert.Equal(ids.Count, count); Assert.Equal(ids.Count, keys.Count); } } } }
private void ValidateMultiRecords(StorageEnvironment env, IEnumerable <string> trees, int documentCount, int i) { using (var tx = env.ReadTransaction()) { for (var j = 0; j < 10; j++) { foreach (var treeName in trees) { var tree = tx.CreateTree(treeName); using (var iterator = tree.MultiRead((j % 10).ToString())) { Assert.True(iterator.Seek(Slices.BeforeAllKeys)); var count = 0; do { count++; }while (iterator.MoveNext()); Assert.Equal((i * documentCount) / 10, count); } } } } }
public void DataIsKeptAfterRestart_OnDisk() { using (var pager = StorageEnvironmentOptions.ForPath(DataDir)) { pager.OwnsPagers = false; using (var env = new StorageEnvironment(pager)) { using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("foo"); tree.Add("test/1", new MemoryStream()); tx.Commit(); } using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("foo"); tree.Add("test/2", new MemoryStream()); tx.Commit(); } } using (var env = new StorageEnvironment(pager)) { using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("foo"); Assert.NotNull(tree.Read("test/1")); Assert.NotNull(tree.Read("test/2")); tx.Commit(); } } } }
public void IterationShouldNotFindAnyRecordsAndShouldNotThrowWhenNumberOfEntriesOnPageIs1AndKeyDoesNotMatch() { using (var env = new StorageEnvironment(StorageEnvironmentOptions.CreateMemoryOnly())) { using (var tx = env.WriteTransaction()) { tx.CreateTree("tree"); tx.Commit(); } using (var tx = env.WriteTransaction()) { var tree = tx.ReadTree("tree"); tree.Add(@"Raven\Database\1", StreamFor("123")); tx.Commit(); } using (var snapshot = env.ReadTransaction()) using (var iterator = snapshot.ReadTree("tree").Iterate(false)) { Slice v; Slice.From(snapshot.Allocator, @"Raven\Filesystem\", out v); Assert.False(iterator.Seek(v)); } } }
public void CanBackupAndRestoreSmall() { RequireFileBasedPager(); var random = new Random(); var buffer = new byte[8192]; random.NextBytes(buffer); using (var tx = Env.WriteTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 0; i < 2; i++) { tree.Add("items/" + i, new MemoryStream(buffer)); } tx.Commit(); } Env.FlushLogToDataFile(); // force writing data to the data file // add more data to journal files using (var tx = Env.WriteTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 2; i < 4; i++) { tree.Add("items/" + i, new MemoryStream(buffer)); } tx.Commit(); } Env.FlushLogToDataFile(); // force writing data to the data file - this won't sync data to disk because there was another sync within last minute BackupMethods.Full.ToFile(Env, Path.Combine(DataDir, "voron-test.backup")); BackupMethods.Full.Restore(Path.Combine(DataDir, "voron-test.backup"), Path.Combine(DataDir, "backup-test.data")); var options = StorageEnvironmentOptions.ForPath(Path.Combine(DataDir, "backup-test.data")); options.MaxLogFileSize = Env.Options.MaxLogFileSize; using (var env = new StorageEnvironment(options)) { using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 0; i < 4; i++) { var readResult = tree.Read("items/" + i); Assert.NotNull(readResult); var memoryStream = new MemoryStream(); readResult.Reader.CopyTo(memoryStream); Assert.Equal(memoryStream.ToArray(), buffer); } } } }
public void IncorrectWriteOfOverflowPagesFromJournalsToDataFile_RavenDB_2806() { RequireFileBasedPager(); const int testedOverflowSize = 20000; var overflowValue = new byte[testedOverflowSize]; new Random(1).NextBytes(overflowValue); using (var tx = Env.WriteTransaction()) { var tree = tx.CreateTree("test"); var itemBytes = new byte[16000]; new Random(2).NextBytes(itemBytes); tree.Add("items/1", itemBytes); new Random(3).NextBytes(itemBytes); tree.Add("items/2", itemBytes); tree.Delete("items/1"); tree.Delete("items/2"); tree.Add("items/3", overflowValue); tx.Commit(); } BackupMethods.Incremental.ToFile(Env, IncrementalBackupTestUtils.IncrementalBackupFile(0)); var options = StorageEnvironmentOptions.ForPath(IncrementalBackupTestUtils.RestoredStoragePath); options.MaxLogFileSize = Env.Options.MaxLogFileSize; BackupMethods.Incremental.Restore(options, new[] { IncrementalBackupTestUtils.IncrementalBackupFile(0) }); using (var env = new StorageEnvironment(options)) { using (var tx = env.ReadTransaction()) { var tree = tx.ReadTree("test"); var readResult = tree.Read("items/3"); var readBytes = new byte[testedOverflowSize]; readResult.Reader.Read(readBytes, 0, testedOverflowSize); Assert.Equal(overflowValue, readBytes); } } }
public void ShouldNotThrowChecksumMismatch() { var random = new Random(1); var buffer = new byte[100]; random.NextBytes(buffer); for (int i = 0; i < 100; i++) { buffer[i] = 13; } var options = StorageEnvironmentOptions.ForPath(DataDir); using (var env = new StorageEnvironment(options)) { using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 0; i < 50; i++) { tree.Add("items/" + i, new MemoryStream(buffer)); } tx.Commit(); } using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 50; i < 100; i++) { tree.Add("items/" + i, new MemoryStream(buffer)); } tx.Commit(); } } options = StorageEnvironmentOptions.ForPath(DataDir); using (var env = new StorageEnvironment(options)) { using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 0; i < 100; i++) { var readResult = tree.Read("items/" + i); Assert.NotNull(readResult); var memoryStream = new MemoryStream(); readResult.Reader.CopyTo(memoryStream); Assert.Equal(memoryStream.ToArray(), buffer); } } } }
public void StorageRecoveryShouldWorkWhenThereAreMultipleCommitedTransactions2() { using (var env = new StorageEnvironment(StorageEnvironmentOptions.ForPath(DataDir))) { using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("atree"); for (var i = 0; i < 1000; i++) { tree.Add("key" + i, new MemoryStream()); } tx.Commit(); } using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("btree"); for (var i = 0; i < 5; i++) { tree.Add("key" + i, new MemoryStream()); } tx.Commit(); } } using (var env = new StorageEnvironment(StorageEnvironmentOptions.ForPath(DataDir))) { using (var tx = env.WriteTransaction()) { tx.CreateTree("atree"); tx.CreateTree("btree"); tx.Commit(); } using (var tx = env.ReadTransaction()) { var aTree = tx.CreateTree("atree"); var bTree = tx.CreateTree("btree"); for (var i = 0; i < 1000; i++) { Assert.NotNull(aTree.Read("key" + i)); } for (var i = 0; i < 5; i++) { Assert.NotNull(bTree.Read("key" + i)); } } } }
public void OldestActiveTransactionShouldBeCalculatedProperly() { using (var options = StorageEnvironmentOptions.CreateMemoryOnly()) { options.ManualFlushing = true; using (var env = new StorageEnvironment(options)) { var trees = CreateTrees(env, 1, "tree"); var transactions = new List <Transaction>(); for (int a = 0; a < 100; a++) { var random = new Random(1337); var buffer = new byte[random.Next(100, 1000)]; random.NextBytes(buffer); using (var tx = env.WriteTransaction()) { for (int i = 0; i < 100; i++) { foreach (var tree in trees) { tx.CreateTree(tree).Add(string.Format("key/{0}/{1}", a, i), new MemoryStream(buffer)); } } var txr = env.ReadTransaction(); transactions.Add(txr); tx.Commit(); } env.FlushLogToDataFile(); } Assert.Equal(transactions.OrderBy(x => x.LowLevelTransaction.Id).First().LowLevelTransaction.Id, env.ActiveTransactions.OldestTransaction); foreach (var tx in transactions) { foreach (var tree in trees) { using (var iterator = tx.CreateTree(tree).Iterate(false)) { if (!iterator.Seek(Slices.BeforeAllKeys)) { continue; } do { Assert.Contains("key/", iterator.CurrentKey.ToString()); } while (iterator.MoveNext()); } } } } } }
public void ShouldBeAbleToWriteValuesGreaterThanLogAndRecoverThem() { var random = new Random(1234); var buffer = new byte[1024 * 512]; random.NextBytes(buffer); var options = StorageEnvironmentOptions.ForPath(DataDir); options.MaxLogFileSize = 10 * Constants.Storage.PageSize; using (var env = new StorageEnvironment(options)) { using (var tx = env.WriteTransaction()) { tx.CreateTree("tree"); tx.Commit(); } using (var tx = env.WriteTransaction()) { tx.CreateTree("tree").Add("key1", new MemoryStream(buffer)); tx.Commit(); } } options = StorageEnvironmentOptions.ForPath(DataDir); options.MaxLogFileSize = 10 * Constants.Storage.PageSize; using (var env = new StorageEnvironment(options)) { using (var tx = env.WriteTransaction()) { tx.CreateTree("tree"); tx.Commit(); } using (var tx = env.ReadTransaction()) { var read = tx.CreateTree("tree").Read("key1"); Assert.NotNull(read); { Assert.Equal(buffer.Length, read.Reader.Length); var bytes = read.Reader.ReadBytes(read.Reader.Length); Assert.Equal(buffer, bytes.Array.Skip(bytes.Offset).Take(bytes.Count).ToArray()); } } } }
private static void CopyTrees(StorageEnvironment existingEnv, StorageEnvironment compactedEnv, Action <CompactionProgress> progressReport = null) { var context = new TransactionPersistentContext(true); using (var txr = existingEnv.ReadTransaction(context)) using (var rootIterator = txr.LowLevelTransaction.RootObjects.Iterate(false)) { if (rootIterator.Seek(Slices.BeforeAllKeys) == false) { return; } var totalTreesCount = txr.LowLevelTransaction.RootObjects.State.NumberOfEntries; var copiedTrees = 0L; do { var treeName = rootIterator.CurrentKey.ToString(); var currentKey = rootIterator.CurrentKey.Clone(txr.Allocator); var objectType = txr.GetRootObjectType(currentKey); switch (objectType) { case RootObjectType.None: break; case RootObjectType.VariableSizeTree: copiedTrees = CopyVariableSizeTree(compactedEnv, progressReport, txr, treeName, copiedTrees, totalTreesCount, context); break; case RootObjectType.EmbeddedFixedSizeTree: case RootObjectType.FixedSizeTree: if (FreeSpaceHandling.IsFreeSpaceTreeName(treeName)) { copiedTrees++;// we don't copy the fixed size tree continue; } copiedTrees = CopyFixedSizeTrees(compactedEnv, progressReport, txr, rootIterator, treeName, copiedTrees, totalTreesCount, objectType, context); break; case RootObjectType.Table: copiedTrees = CopyTableTree(compactedEnv, progressReport, txr, treeName, copiedTrees, totalTreesCount, context); break; default: throw new ArgumentOutOfRangeException("Unknown " + objectType); } } while (rootIterator.MoveNext()); } }
public void CanBackupAndRestoreOnEmptyStorage() { RequireFileBasedPager(); var random = new Random(); var buffer = new byte[8192]; random.NextBytes(buffer); using (var tx = Env.WriteTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 0; i < 500; i++) { tree.Add("items/" + i, new MemoryStream(buffer)); } tx.Commit(); } long nextPageNumberBeforeBackup = Env.NextPageNumber; BackupMethods.Incremental.ToFile(Env, _incrementalBackupTestUtils.IncrementalBackupFile(0)); var options = StorageEnvironmentOptions.ForPath(_incrementalBackupTestUtils.RestoredStoragePath); options.MaxLogFileSize = Env.Options.MaxLogFileSize; BackupMethods.Incremental.Restore(options, new[] { _incrementalBackupTestUtils.IncrementalBackupFile(0) }); using (var env = new StorageEnvironment(options)) { Assert.Equal(nextPageNumberBeforeBackup, env.NextPageNumber); using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("foo"); for (int i = 0; i < 500; i++) { var readResult = tree.Read("items/" + i); Assert.NotNull(readResult); var memoryStream = new MemoryStream(); readResult.Reader.CopyTo(memoryStream); Assert.Equal(memoryStream.ToArray(), buffer); } } } }
public static IndexDefinition Load(StorageEnvironment environment) { using (var context = JsonOperationContext.ShortTermSingleUse()) using (var tx = environment.ReadTransaction()) { using (var stream = GetIndexDefinitionStream(environment, tx)) using (var reader = context.ReadForDisk(stream, "index/def")) { var definition = ReadIndexDefinition(reader); definition.Name = ReadName(reader); definition.LockMode = ReadLockMode(reader); definition.Priority = ReadPriority(reader); return(definition); } } }
public static string ReadDatabaseId(string name, StorageEnvironment environment) { using (var tx = environment.ReadTransaction()) { var statsTree = tx.ReadTree(IndexSchema.StatsTree); if (statsTree == null) { throw new InvalidOperationException($"Index '{name}' does not contain 'Stats' tree."); } var result = statsTree.Read(IndexSchema.DatabaseIdSlice); if (result == null) { return(null); // backward compatibility } return(result.Reader.ReadString(result.Reader.Length)); } }
public static AutoMapReduceIndexDefinition Load(StorageEnvironment environment) { using (var context = JsonOperationContext.ShortTermSingleUse()) using (var tx = environment.ReadTransaction()) { using (var stream = GetIndexDefinitionStream(environment, tx)) { if (stream == null) { return(null); } using (var reader = context.ReadForDisk(stream, string.Empty)) { return(LoadFromJson(reader)); } } } }
public static AutoMapReduceIndexDefinition Load(StorageEnvironment environment) { using (var context = JsonOperationContext.ShortTermSingleUse()) using (var tx = environment.ReadTransaction()) { var tree = tx.CreateTree("Definition"); var result = tree.Read(DefinitionSlice); if (result == null) { return(null); } using (var reader = context.ReadForDisk(result.Reader.AsStream(), string.Empty)) { return(LoadFromJson(reader)); } } }
public static IndexSourceType ReadIndexSourceType(string name, StorageEnvironment environment) { using (var tx = environment.ReadTransaction()) { var statsTree = tx.ReadTree(IndexSchema.StatsTree); if (statsTree == null) { throw new InvalidOperationException($"Index '{name}' does not contain 'Stats' tree."); } var result = statsTree.Read(IndexSchema.SourceTypeSlice); if (result == null) { return(IndexSourceType.Documents); // backward compatibility } return((IndexSourceType)result.Reader.ReadLittleEndianInt32()); } }
public static IndexType ReadIndexType(string name, StorageEnvironment environment) { using (var tx = environment.ReadTransaction()) { var statsTree = tx.ReadTree(IndexSchema.StatsTree); if (statsTree == null) { throw new InvalidOperationException($"Index '{name}' does not contain 'Stats' tree."); } var result = statsTree.Read(IndexSchema.TypeSlice); if (result == null) { throw new InvalidOperationException($"Stats tree does not contain 'Type' entry in index '{name}'."); } return((IndexType)result.Reader.ReadLittleEndianInt32()); } }
public void ReadTransactionCanReadJustCommittedValue() { var options = StorageEnvironmentOptions.CreateMemoryOnly(); options.ManualFlushing = true; using (var env = new StorageEnvironment(options)) { CreateTrees(env, 1, "tree"); using (var txw = env.WriteTransaction()) { txw.CreateTree("tree0").Add("key/1", new MemoryStream()); txw.Commit(); using (var txr = env.ReadTransaction()) { Assert.NotNull(txr.CreateTree("tree0").Read("key/1")); } } } }
public void DataIsKeptAfterRestartForSubTrees() { using (var pureMemoryPager = StorageEnvironmentOptions.CreateMemoryOnly()) { pureMemoryPager.OwnsPagers = false; using (var env = new StorageEnvironment(pureMemoryPager)) { using (var tx = env.WriteTransaction()) { tx.CreateTree("test"); tx.Commit(); } using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("test"); tree.Add("test", Stream.Null); tx.Commit(); Assert.NotNull(tree.Read("test")); } } using (var env = new StorageEnvironment(pureMemoryPager)) { using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("test"); tx.Commit(); } using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("test"); Assert.NotNull(tree.Read("test")); tx.Commit(); } } } }
public static IndexDefinition Load(StorageEnvironment environment) { using (var context = JsonOperationContext.ShortTermSingleUse()) using (var tx = environment.ReadTransaction()) { var tree = tx.CreateTree("Definition"); var result = tree.Read(DefinitionSlice); if (result == null) { return(null); } using (var reader = context.ReadForDisk(result.Reader.AsStream(), string.Empty)) { var definition = ReadIndexDefinition(reader); definition.Name = ReadName(reader); definition.LockMode = ReadLockMode(reader); return(definition); } } }
public void StorageRecoveryShouldWorkWhenThereSingleTransactionToRecoverFromLog() { using (var env = new StorageEnvironment(StorageEnvironmentOptions.ForPath(DataDir))) { using (var tx = env.WriteTransaction()) { var tree = tx.CreateTree("tree"); for (var i = 0; i < 100; i++) { tree.Add("key" + i, new MemoryStream()); } tx.Commit(); } } using (var env = new StorageEnvironment(StorageEnvironmentOptions.ForPath(DataDir))) { using (var tx = env.WriteTransaction()) { tx.CreateTree("tree"); tx.Commit(); } using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("tree"); for (var i = 0; i < 100; i++) { Assert.NotNull(tree.Read("key" + i)); } } } }
public void MultiTreeIteratorShouldBeIsolated1() { DeleteDirectory(DataDir); var options = StorageEnvironmentOptions.ForPath(DataDir); using (var env = new StorageEnvironment(options)) { CreateTrees(env, 1, "tree"); for (var i = 0; i < 10; i++) { Write(env, i); } using (var txr = env.ReadTransaction()) { var key = Write(env, 10); using (var iterator = txr.ReadTree("tree0").MultiRead("key/1")) { Assert.True(iterator.Seek(Slices.BeforeAllKeys)); var count = 0; do { Assert.True(iterator.CurrentKey.ToString() != key, string.Format("Key '{0}' should not be present in multi-iterator", key)); count++; }while (iterator.MoveNext()); Assert.Equal(10, count); } } } }
public void MultiTreeIteratorShouldBeIsolated2() { DeleteDirectory(DataDir); var options = StorageEnvironmentOptions.ForPath(DataDir); using (var env = new StorageEnvironment(options)) { CreateTrees(env, 1, "tree"); for (var i = 0; i < 11; i++) { Write(env, i); } using (var txr = env.ReadTransaction()) { var key = Delete(env, 10); using (var iterator = txr.ReadTree("tree0").MultiRead("key/1")) { Assert.True(iterator.Seek(Slices.BeforeAllKeys)); var keys = new List <string>(); do { keys.Add(iterator.CurrentKey.ToString()); }while (iterator.MoveNext()); Assert.Equal(11, keys.Count); Assert.Contains(key, keys); } } } }
public void CanAddMultiValuesUnderTheSameKeyToBatch() { using (var env = new StorageEnvironment(StorageEnvironmentOptions.CreateMemoryOnly())) { var rand = new Random(); var testBuffer = new byte[168]; rand.NextBytes(testBuffer); CreateTrees(env, 1, "multitree"); using (var tx = env.WriteTransaction()) { var batch = tx.CreateTree("multitree0"); batch.MultiAdd("key", "value1"); batch.MultiAdd("key", "value2"); tx.Commit(); } using (var tx = env.ReadTransaction()) { var tree = tx.CreateTree("multitree0"); using (var it = tree.MultiRead("key")) { Assert.True(it.Seek(Slices.BeforeAllKeys)); Assert.Equal("value1", it.CurrentKey.ToString()); Assert.True(it.MoveNext()); Assert.Equal("value2", it.CurrentKey.ToString()); } } } }
internal HashSet <string> ReadIndexTimeFields() { var fields = new HashSet <string>(); using (var tx = _environment.ReadTransaction()) { var fieldsTree = tx.ReadTree(IndexSchema.FieldsTree); if (fieldsTree != null) { using (var it = fieldsTree.MultiRead(IndexSchema.TimeSlice)) { if (it.Seek(Slices.BeforeAllKeys)) { do { fields.Add(it.CurrentKey.ToString()); } while (it.MoveNext()); } } } } return(fields); }
public void ScratchPagesShouldNotBeReleasedUntilNotUsed() { var options = StorageEnvironmentOptions.ForPath(DataDir); options.ManualFlushing = true; using (var env = new StorageEnvironment(options)) { CreateTrees(env, 2, "tree"); for (int a = 0; a < 3; a++) { using (var tx = env.WriteTransaction()) { tx.CreateTree("tree0").Add(string.Format("key/{0}/{1}/1", new string('0', 1000), a), new MemoryStream()); tx.CreateTree("tree0").Add(string.Format("key/{0}/{1}/2", new string('0', 1000), a), new MemoryStream()); tx.Commit(); } } using (var tx = env.WriteTransaction()) { tx.CreateTree("tree1").Add("yek/1", new MemoryStream()); tx.Commit(); } using (var txr = env.ReadTransaction()) { using (var iterator = txr.CreateTree("tree0").Iterate(false)) { Assert.True(iterator.Seek(Slices.BeforeAllKeys)); // all pages are from scratch (one from position 11) var currentKey = iterator.CurrentKey.ToString(); env.FlushLogToDataFile(); // frees pages from scratch (including the one at position 11) using (var txw = env.WriteTransaction()) { var tree = txw.CreateTree("tree1"); tree.Add(string.Format("yek/{0}/0/0", new string('0', 1000)), new MemoryStream()); // allocates new page from scratch (position 11) txw.Commit(); } Assert.Equal(currentKey, iterator.CurrentKey.ToString()); using (var txw = env.WriteTransaction()) { var tree = txw.CreateTree("tree1"); tree.Add("fake", new MemoryStream()); txw.Commit(); } Assert.Equal(currentKey, iterator.CurrentKey.ToString()); var count = 0; do { currentKey = iterator.CurrentKey.ToString(); count++; Assert.Contains("key/", currentKey); }while (iterator.MoveNext()); Assert.Equal(6, count); } } } }