public static List <string> GetDatabases(UpdateStep step) { var dbs = new List <string>(); using (var items = step.ReadTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items)) using (Slice.From(step.ReadTx.Allocator, DbKey, out var loweredPrefix)) { foreach (var result in items.SeekByPrimaryKeyPrefix(loweredPrefix, Slices.Empty, 0)) { dbs.Add(ClusterStateMachine.GetCurrentItemKey(result.Value).Substring(DbKey.Length)); } } return(dbs); }
public bool Update(UpdateStep step) { var dbs = new List <string>(); const string dbKey = "db/"; var identities = step.ReadTx.ReadTree(ClusterStateMachine.Identities); step.WriteTx.DeleteTree(ClusterStateMachine.Identities); using (var items = step.ReadTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items)) using (Slice.From(step.ReadTx.Allocator, dbKey, out Slice loweredPrefix)) { foreach (var result in items.SeekByPrimaryKeyPrefix(loweredPrefix, Slices.Empty, 0)) { dbs.Add(ClusterStateMachine.GetCurrentItemKey(result.Value).Substring(dbKey.Length)); } } step.WriteTx.CreateTree(ClusterStateMachine.CompareExchangeIndex); foreach (var db in dbs) { if (identities != null) { Slice.From(step.WriteTx.Allocator, "Identities", out var identitySlice); ClusterStateMachine.IdentitiesSchema.Create(step.WriteTx, identitySlice, 32); var writeTable = step.WriteTx.OpenTable(ClusterStateMachine.IdentitiesSchema, identitySlice); using (Slice.From(step.ReadTx.Allocator, $"{dbKey}{db.ToLowerInvariant()}/identities/", out var identityPrefix)) { using (var it = identities.Iterate(prefetch: false)) { it.SetRequiredPrefix(identityPrefix); if (it.Seek(identityPrefix)) { do { var key = it.CurrentKey; var keyAsString = key.ToString(); // old identity key var value = it.CreateReaderForCurrent().ReadLittleEndianInt64(); var newKey = keyAsString.Substring(identityPrefix.ToString().Length); // write to new identities schema GetKeyAndPrefixIndexSlices(step.ReadTx.Allocator, db, $"{newKey}", 0L, out var keyTuple, out var indexTuple); using (keyTuple.Scope) using (indexTuple.Scope) using (Slice.External(step.ReadTx.Allocator, keyTuple.Buffer.Ptr, keyTuple.Buffer.Length, out var keySlice)) using (Slice.External(step.ReadTx.Allocator, indexTuple.Buffer.Ptr, indexTuple.Buffer.Length, out var prefixIndexSlice)) { using (writeTable.Allocate(out var write)) { write.Add(keySlice); write.Add(value); write.Add(0L); write.Add(prefixIndexSlice); writeTable.Set(write); } } } while (it.MoveNext()); } } } } // update db backup status var dbLower = db.ToLowerInvariant(); using (var items = step.WriteTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items)) using (Slice.From(step.ReadTx.Allocator, $"{dbKey}{dbLower}", out Slice lowerKey)) using (var ctx = JsonOperationContext.ShortTermSingleUse()) { var(databaseRecordJson, _) = GetBjroAndIndex(ctx, items, lowerKey); var databaseRecord = JsonDeserializationCluster.DatabaseRecord(databaseRecordJson); if (databaseRecord == null) { continue; } foreach (var pb in databaseRecord.PeriodicBackups) { var pbItemName = PeriodicBackupStatus.GenerateItemName(db, pb.TaskId); using (Slice.From(step.WriteTx.Allocator, pbItemName, out Slice pbsSlice)) using (Slice.From(step.WriteTx.Allocator, pbItemName.ToLowerInvariant(), out Slice pbsSliceLower)) { var(singleBackupStatus, index) = GetBjroAndIndex(ctx, items, pbsSlice); if (singleBackupStatus == null) { continue; } if (singleBackupStatus.TryGet(nameof(PeriodicBackupStatus.LocalBackup), out BlittableJsonReaderObject localBackup) == false || singleBackupStatus.TryGet(nameof(PeriodicBackupStatus.LastRaftIndex), out BlittableJsonReaderObject lastRaftIndexBlittable) == false) { continue; } if (localBackup.TryGet(nameof(PeriodicBackupStatus.LastIncrementalBackup), out DateTime? lastIncrementalBackupDate) == false || lastRaftIndexBlittable.TryGet(nameof(PeriodicBackupStatus.LastEtag), out long?lastRaftIndex) == false) { continue; } if (lastIncrementalBackupDate == null || lastRaftIndex == null) { continue; } var myLastRaftIndex = new LastRaftIndex { LastEtag = 0L }; singleBackupStatus.Modifications = new DynamicJsonValue { [nameof(PeriodicBackupStatus.LastRaftIndex)] = myLastRaftIndex.ToJson() }; using (var old = singleBackupStatus) { singleBackupStatus = ctx.ReadObject(singleBackupStatus, pbItemName); } using (items.Allocate(out var builder)) { builder.Add(pbsSliceLower); builder.Add(pbsSlice); builder.Add(singleBackupStatus.BasePointer, singleBackupStatus.Size); builder.Add(index); items.Set(builder); } } } } } return(true); }
public bool Update(UpdateStep step) { var ids = new HashSet <long>(); var minimal = long.MaxValue; const string dbKey = "db/"; var continueAfterCommit = true; var skip = 0; while (continueAfterCommit) { continueAfterCommit = false; var fixedItems = 0; var items = step.WriteTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items); using (Slice.From(step.WriteTx.Allocator, dbKey, out Slice loweredPrefix)) { foreach (var result in items.SeekByPrimaryKeyPrefix(loweredPrefix, Slices.Empty, 0)) { var databaseName = ClusterStateMachine.GetCurrentItemKey(result.Value).Substring(3); using (Slice.From(step.WriteTx.Allocator, dbKey + databaseName.ToLowerInvariant(), out var key)) { if (items.VerifyKeyExists(key) == false) { continue; } } using (Slice.From(step.WriteTx.Allocator, SubscriptionState.SubscriptionPrefix(databaseName), out var startWith)) using (var ctx = JsonOperationContext.ShortTermSingleUse()) { foreach (var holder in items.SeekByPrimaryKeyPrefix(startWith, Slices.Empty, skip)) { skip++; var reader = holder.Value.Reader; var ptr = reader.Read(2, out int size); using (var doc = new BlittableJsonReaderObject(ptr, size, ctx)) { if (doc.TryGet(nameof(SubscriptionState.SubscriptionId), out long id) == false) { continue; } if (minimal > id) { minimal = id; } if (ids.Add(id)) { continue; } minimal--; ids.Add(minimal); var subscriptionState = JsonDeserializationClient.SubscriptionState(doc); subscriptionState.SubscriptionId = minimal; var subscriptionItemName = SubscriptionState.GenerateSubscriptionItemKeyName(databaseName, subscriptionState.SubscriptionName); using (Slice.From(step.WriteTx.Allocator, subscriptionItemName, out Slice valueName)) using (Slice.From(step.WriteTx.Allocator, subscriptionItemName.ToLowerInvariant(), out Slice valueNameLowered)) using (var receivedSubscriptionState = ctx.ReadObject(subscriptionState.ToJson(), subscriptionState.SubscriptionName)) { ClusterStateMachine.UpdateValue(0, items, valueNameLowered, valueName, receivedSubscriptionState); } } fixedItems++; if (fixedItems < 1024) { continue; } continueAfterCommit = true; break; } } if (continueAfterCommit) { break; } } } if (continueAfterCommit) { step.Commit(null); step.RenewTransactions(); } } return(true); }
public bool Update(UpdateStep step) { var dbs = new List <string>(); const string dbKey = "db/"; var newIdentitiesSchema = new TableSchema() .DefineKey(new TableSchema.SchemaIndexDef { StartIndex = (int)ClusterStateMachine.IdentitiesTable.Key, Count = 1 }).DefineIndex(new TableSchema.SchemaIndexDef { StartIndex = (int)ClusterStateMachine.IdentitiesTable.KeyIndex, Count = 1, IsGlobal = true, Name = ClusterStateMachine.IdentitiesIndex }); using (var items = step.ReadTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items)) using (Slice.From(step.ReadTx.Allocator, dbKey, out Slice loweredPrefix)) { foreach (var result in items.SeekByPrimaryKeyPrefix(loweredPrefix, Slices.Empty, 0)) { dbs.Add(ClusterStateMachine.GetCurrentItemKey(result.Value).Substring(dbKey.Length)); } } foreach (var db in dbs) { var dbPrefixLowered = $"{db.ToLowerInvariant()}/"; // update IdentitiesSchema var readIdentitiesTable = step.ReadTx.OpenTable(ClusterStateMachine.IdentitiesSchema, ClusterStateMachine.Identities); if (readIdentitiesTable != null) { using (Slice.From(step.ReadTx.Allocator, dbPrefixLowered, out var keyPrefix)) { var writeIdentitiesTable = step.WriteTx.OpenTable(newIdentitiesSchema, ClusterStateMachine.Identities); foreach (var item in readIdentitiesTable.SeekByPrimaryKeyPrefix(keyPrefix, Slices.Empty, 0)) { var value = TableValueToLong((int)ClusterStateMachine.IdentitiesTable.Value, ref item.Value.Reader); var index = TableValueToLong((int)ClusterStateMachine.IdentitiesTable.Index, ref item.Value.Reader); // if value is not 0 than we come from v4.2 and could have wrong index value if (index != 0) { using (GetPrefixIndexSlices(step.ReadTx.Allocator, db, 0L, out var buffer)) using (Slice.External(step.WriteTx.Allocator, buffer.Ptr, buffer.Length, out var prefixIndexSlice)) using (writeIdentitiesTable.Allocate(out TableValueBuilder write)) { write.Add(item.Key); write.Add(value); write.Add(0L); write.Add(prefixIndexSlice); writeIdentitiesTable.Set(write); } } } } } // update db backup status var dbLower = db.ToLowerInvariant(); using (var items = step.WriteTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items)) using (Slice.From(step.ReadTx.Allocator, $"{dbKey}{dbLower}", out Slice lowerKey)) using (var ctx = JsonOperationContext.ShortTermSingleUse()) { var(databaseRecordJson, _) = GetBjroAndIndex(ctx, items, lowerKey); var databaseRecord = JsonDeserializationCluster.DatabaseRecord(databaseRecordJson); if (databaseRecord == null) { continue; } foreach (var pb in databaseRecord.PeriodicBackups) { var pbItemName = PeriodicBackupStatus.GenerateItemName(db, pb.TaskId); using (Slice.From(step.WriteTx.Allocator, pbItemName, out Slice pbsSlice)) using (Slice.From(step.WriteTx.Allocator, pbItemName.ToLowerInvariant(), out Slice pbsSliceLower)) { var(singleBackupStatus, index) = GetBjroAndIndex(ctx, items, pbsSlice); if (singleBackupStatus == null) { continue; } if (singleBackupStatus.TryGet(nameof(PeriodicBackupStatus.LocalBackup), out BlittableJsonReaderObject localBackup) == false || singleBackupStatus.TryGet(nameof(PeriodicBackupStatus.LastRaftIndex), out BlittableJsonReaderObject lastRaftIndexBlittable) == false) { continue; } if (localBackup.TryGet(nameof(PeriodicBackupStatus.LastIncrementalBackup), out DateTime? lastIncrementalBackupDate) == false || lastRaftIndexBlittable.TryGet(nameof(PeriodicBackupStatus.LastEtag), out long?lastRaftIndex) == false) { continue; } if (lastIncrementalBackupDate == null || lastRaftIndex == null) { continue; } // already set in from12 before if (lastRaftIndex == 0) { continue; } var myLastRaftIndex = new LastRaftIndex { LastEtag = 0L }; singleBackupStatus.Modifications = new DynamicJsonValue { [nameof(PeriodicBackupStatus.LastRaftIndex)] = myLastRaftIndex.ToJson() }; using (var old = singleBackupStatus) { singleBackupStatus = ctx.ReadObject(singleBackupStatus, pbItemName); } using (items.Allocate(out var builder)) { builder.Add(pbsSliceLower); builder.Add(pbsSlice); builder.Add(singleBackupStatus.BasePointer, singleBackupStatus.Size); builder.Add(index); items.Set(builder); } } } } } return(true); }
public bool Update(UpdateStep step) { var dbs = new List <string>(); const string dbKey = "db/"; var newIdentitiesSchema = new TableSchema() .DefineKey(new TableSchema.SchemaIndexDef { StartIndex = (int)ClusterStateMachine.IdentitiesTable.Key, Count = 1 }).DefineIndex(new TableSchema.SchemaIndexDef { StartIndex = (int)ClusterStateMachine.IdentitiesTable.KeyIndex, Count = 1, IsGlobal = true, Name = ClusterStateMachine.IdentitiesIndex }); using (var items = step.ReadTx.OpenTable(ClusterStateMachine.ItemsSchema, ClusterStateMachine.Items)) using (Slice.From(step.ReadTx.Allocator, dbKey, out Slice loweredPrefix)) { foreach (var result in items.SeekByPrimaryKeyPrefix(loweredPrefix, Slices.Empty, 0)) { dbs.Add(ClusterStateMachine.GetCurrentItemKey(result.Value).Substring(dbKey.Length)); } } foreach (var db in dbs) { var dbPrefixLowered = $"{db.ToLowerInvariant()}/"; // update IdentitiesSchema var readIdentitiesTable = step.ReadTx.OpenTable(ClusterStateMachine.IdentitiesSchema, ClusterStateMachine.Identities); if (readIdentitiesTable != null) { using (Slice.From(step.ReadTx.Allocator, dbPrefixLowered, out var keyPrefix)) { var writeIdentitiesTable = step.WriteTx.OpenTable(newIdentitiesSchema, ClusterStateMachine.Identities); foreach (var item in readIdentitiesTable.SeekByPrimaryKeyPrefix(keyPrefix, Slices.Empty, 0)) { var indexPtr = item.Value.Reader.Read((int)ClusterStateMachine.IdentitiesTable.Index, out var size); // we come from v4.2 RC1 if (size == sizeof(int)) { var indexIntValue = *(int *)indexPtr; long index = (long)indexIntValue; var value = TableValueToLong((int)ClusterStateMachine.IdentitiesTable.Value, ref item.Value.Reader); using (GetPrefixIndexSlices(step.ReadTx.Allocator, db, index, out var buffer)) using (Slice.External(step.WriteTx.Allocator, buffer.Ptr, buffer.Length, out var prefixIndexSlice)) using (writeIdentitiesTable.Allocate(out TableValueBuilder write)) { write.Add(item.Key); write.Add(value); write.Add(index); write.Add(prefixIndexSlice); writeIdentitiesTable.Set(write); } } } } } } return(true); }