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 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); }