Exemplo n.º 1
0
        private void WriteDatabaseInfo(string databaseName, BlittableJsonReaderObject dbRecordBlittable,
                                       TransactionOperationContext context, AbstractBlittableJsonTextWriter writer)
        {
            var nodesTopology = new NodesTopology();

            try
            {
                var online = ServerStore.DatabasesLandlord.DatabasesCache.TryGetValue(databaseName, out Task <DocumentDatabase> dbTask) &&
                             dbTask != null &&
                             dbTask.IsCompleted;

                var dbRecord = JsonDeserializationCluster.DatabaseRecord(dbRecordBlittable);
                var topology = dbRecord.Topology;

                var statuses = ServerStore.GetNodesStatuses();
                if (topology != null)
                {
                    nodesTopology.PriorityOrder = topology.PriorityOrder;

                    var clusterTopology = ServerStore.GetClusterTopology(context);
                    clusterTopology.ReplaceCurrentNodeUrlWithClientRequestedNodeUrlIfNecessary(ServerStore, HttpContext);

                    foreach (var member in topology.Members)
                    {
                        if (dbRecord.DeletionInProgress != null && dbRecord.DeletionInProgress.ContainsKey(member))
                        {
                            continue;
                        }

                        var url  = clusterTopology.GetUrlFromTag(member);
                        var node = new InternalReplication
                        {
                            Database = databaseName,
                            NodeTag  = member,
                            Url      = url
                        };
                        nodesTopology.Members.Add(GetNodeId(node));
                        SetNodeStatus(topology, member, nodesTopology, statuses);
                    }

                    foreach (var promotable in topology.Promotables)
                    {
                        if (dbRecord.DeletionInProgress != null && dbRecord.DeletionInProgress.ContainsKey(promotable))
                        {
                            continue;
                        }

                        topology.PredefinedMentors.TryGetValue(promotable, out var mentorCandidate);
                        var node   = GetNode(databaseName, clusterTopology, promotable, mentorCandidate, out var promotableTask);
                        var mentor = topology.WhoseTaskIsIt(ServerStore.Engine.CurrentState, promotableTask, null);
                        nodesTopology.Promotables.Add(GetNodeId(node, mentor));
                        SetNodeStatus(topology, promotable, nodesTopology, statuses);
                    }

                    foreach (var rehab in topology.Rehabs)
                    {
                        if (dbRecord.DeletionInProgress != null && dbRecord.DeletionInProgress.ContainsKey(rehab))
                        {
                            continue;
                        }

                        var node   = GetNode(databaseName, clusterTopology, rehab, null, out var promotableTask);
                        var mentor = topology.WhoseTaskIsIt(ServerStore.Engine.CurrentState, promotableTask, null);
                        nodesTopology.Rehabs.Add(GetNodeId(node, mentor));
                        SetNodeStatus(topology, rehab, nodesTopology, statuses);
                    }
                }

                // Check for exceptions
                if (dbTask != null && dbTask.IsFaulted)
                {
                    var exception = dbTask.Exception.ExtractSingleInnerException();
                    WriteFaultedDatabaseInfo(databaseName, nodesTopology, exception, context, writer);
                    return;
                }

                var db = online ? dbTask.Result : null;

                var indexingStatus = db?.IndexStore?.Status;
                if (indexingStatus == null)
                {
                    // Looking for disabled indexing flag inside the database settings for offline database status
                    if (dbRecord.Settings.TryGetValue(RavenConfiguration.GetKey(x => x.Indexing.Disabled), out var val) &&
                        bool.TryParse(val, out var indexingDisabled) && indexingDisabled)
                    {
                        indexingStatus = IndexRunningStatus.Disabled;
                    }
                }

                var disabled = dbRecord.Disabled;

                var studioEnvironment = StudioConfiguration.StudioEnvironment.None;
                if (dbRecord.Studio != null && !dbRecord.Studio.Disabled)
                {
                    studioEnvironment = dbRecord.Studio.Environment;
                }

                if (online == false)
                {
                    // if state of database is found in the cache we can continue
                    if (ServerStore.DatabaseInfoCache.TryGet(databaseName, databaseInfoJson =>
                    {
                        databaseInfoJson.Modifications = new DynamicJsonValue(databaseInfoJson)
                        {
                            [nameof(DatabaseInfo.Disabled)] = disabled,
                            [nameof(DatabaseInfo.IndexingStatus)] = indexingStatus,
                            [nameof(DatabaseInfo.NodesTopology)] = nodesTopology.ToJson(),
                            [nameof(DatabaseInfo.DeletionInProgress)] = DynamicJsonValue.Convert(dbRecord.DeletionInProgress),
                            [nameof(DatabaseInfo.Environment)] = studioEnvironment
                        };

                        context.Write(writer, databaseInfoJson);
                    }))
                    {
                        return;
                    }

                    // we won't find it if it is a new database or after a dirty shutdown,
                    // so just report empty values then
                }

                var size = db?.GetSizeOnDisk() ?? (new Size(0), new Size(0));

                var databaseInfo = new DatabaseInfo
                {
                    Name            = databaseName,
                    Disabled        = disabled,
                    TotalSize       = size.Data,
                    TempBuffersSize = size.TempBuffers,

                    IsAdmin     = true,
                    IsEncrypted = dbRecord.Encrypted,
                    UpTime      = online ? (TimeSpan?)GetUptime(db) : null,
                    BackupInfo  = GetBackupInfo(db, context),

                    Alerts           = db?.NotificationCenter.GetAlertCount() ?? 0,
                    PerformanceHints = db?.NotificationCenter.GetPerformanceHintCount() ?? 0,
                    RejectClients    = false,
                    LoadError        = null,
                    IndexingErrors   = db?.IndexStore?.GetIndexes()?.Sum(index => index.GetErrorCount()) ?? 0,

                    DocumentsCount             = db?.DocumentsStorage.GetNumberOfDocuments() ?? 0,
                    HasRevisionsConfiguration  = db?.DocumentsStorage.RevisionsStorage.Configuration != null,
                    HasExpirationConfiguration = (db?.ExpiredDocumentsCleaner?.ExpirationConfiguration?.Disabled ?? true) == false,
                    HasRefreshConfiguration    = (db?.ExpiredDocumentsCleaner?.RefreshConfiguration?.Disabled ?? true) == false,
                    IndexesCount   = db?.IndexStore?.GetIndexes()?.Count() ?? 0,
                    IndexingStatus = indexingStatus ?? IndexRunningStatus.Running,
                    Environment    = studioEnvironment,

                    NodesTopology            = nodesTopology,
                    ReplicationFactor        = topology?.ReplicationFactor ?? -1,
                    DynamicNodesDistribution = topology?.DynamicNodesDistribution ?? false,
                    DeletionInProgress       = dbRecord.DeletionInProgress
                };

                var doc = databaseInfo.ToJson();
                context.Write(writer, doc);
            }
            catch (Exception e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Failed to get database info for: {databaseName}", e);
                }

                WriteFaultedDatabaseInfo(databaseName, nodesTopology, e, context, writer);
            }
        }
Exemplo n.º 2
0
 public override object FromRemote(object remoteResult)
 {
     return(JsonDeserializationCluster.CompareExchangeResult((BlittableJsonReaderObject)remoteResult));
 }
Exemplo n.º 3
0
        private void WriteDatabaseInfo(string databaseName, BlittableJsonReaderObject dbRecordBlittable,
                                       TransactionOperationContext context, BlittableJsonTextWriter writer)
        {
            var online = ServerStore.DatabasesLandlord.DatabasesCache.TryGetValue(databaseName, out Task <DocumentDatabase> dbTask) &&
                         dbTask != null &&
                         dbTask.IsCompleted;

            // Check for exceptions
            if (dbTask != null && dbTask.IsFaulted)
            {
                WriteFaultedDatabaseInfo(context, writer, dbTask, databaseName);
                return;
            }

            var dbRecord = JsonDeserializationCluster.DatabaseRecord(dbRecordBlittable);
            var db       = online ? dbTask.Result : null;

            var indexingStatus = db?.IndexStore.Status ?? IndexRunningStatus.Running;

            // Looking for disabled indexing flag inside the database settings for offline database status
            if (dbRecord.Settings.TryGetValue(RavenConfiguration.GetKey(x => x.Indexing.Disabled), out var val) && val == "true")
            {
                indexingStatus = IndexRunningStatus.Disabled;
            }
            var disabled        = dbRecord.Disabled;
            var topology        = dbRecord.Topology;
            var clusterTopology = ServerStore.GetClusterTopology(context);

            var nodesTopology = new NodesTopology();

            if (topology != null)
            {
                foreach (var member in topology.Members)
                {
                    var url  = clusterTopology.GetUrlFromTag(member);
                    var node = new InternalReplication
                    {
                        Database = databaseName,
                        NodeTag  = member,
                        Url      = url
                    };
                    nodesTopology.Members.Add(GetNodeId(node));
                    SetNodeStatus(topology, member, nodesTopology);
                }

                foreach (var promotable in topology.Promotables)
                {
                    var node   = GetNode(databaseName, clusterTopology, promotable, out var promotableTask);
                    var mentor = topology.WhoseTaskIsIt(promotableTask, ServerStore.IsPassive());
                    nodesTopology.Promotables.Add(GetNodeId(node, mentor));
                    SetNodeStatus(topology, promotable, nodesTopology);
                }

                foreach (var rehab in topology.Rehabs)
                {
                    var node   = GetNode(databaseName, clusterTopology, rehab, out var promotableTask);
                    var mentor = topology.WhoseTaskIsIt(promotableTask, ServerStore.IsPassive());
                    nodesTopology.Rehabs.Add(GetNodeId(node, mentor));
                    SetNodeStatus(topology, rehab, nodesTopology);
                }
            }

            if (online == false)
            {
                // If state of database is found in the cache we can continue
                if (ServerStore.DatabaseInfoCache.TryWriteOfflineDatabaseStatusToRequest(
                        context, writer, databaseName, disabled, indexingStatus, nodesTopology))
                {
                    return;
                }
                // We won't find it if it is a new database or after a dirty shutdown, so just report empty values then
            }

            var size = new Size(GetTotalSize(db));

            var databaseInfo = new DatabaseInfo
            {
                Name      = databaseName,
                Disabled  = disabled,
                TotalSize = size,

                IsAdmin     = true, //TODO: implement me!
                IsEncrypted = dbRecord.Encrypted,
                UpTime      = online ? (TimeSpan?)GetUptime(db) : null,
                BackupInfo  = GetBackupInfo(db),

                Alerts         = db?.NotificationCenter.GetAlertCount() ?? 0,
                RejectClients  = false, //TODO: implement me!
                LoadError      = null,
                IndexingErrors = db?.IndexStore.GetIndexes().Sum(index => index.GetErrorCount()) ?? 0,

                DocumentsCount             = db?.DocumentsStorage.GetNumberOfDocuments() ?? 0,
                HasRevisionsConfiguration  = db?.DocumentsStorage.RevisionsStorage.Configuration != null,
                HasExpirationConfiguration = db?.ExpiredDocumentsCleaner != null,
                IndexesCount   = db?.IndexStore.GetIndexes().Count() ?? 0,
                IndexingStatus = indexingStatus,

                NodesTopology            = nodesTopology,
                ReplicationFactor        = topology?.ReplicationFactor ?? -1,
                DynamicNodesDistribution = topology?.DynamicNodesDistribution ?? false
            };

            var doc = databaseInfo.ToJson();

            context.Write(writer, doc);
        }
Exemplo n.º 4
0
        public Task GetTopology()
        {
            var name = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name");

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                var dbId = Constants.Documents.Prefix + name;
                using (context.OpenReadTransaction())
                    using (var dbBlit = ServerStore.Cluster.Read(context, dbId, out long _))
                    {
                        if (TryGetAllowedDbs(name, out var _, requireAdmin: false) == false)
                        {
                            return(Task.CompletedTask);
                        }

                        if (dbBlit == null)
                        {
                            // here we return 503 so clients will try to failover to another server
                            // if this is a newly created db that we haven't been notified about it yet
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
                            HttpContext.Response.Headers["Database-Missing"] = name;
                            using (var writer = new BlittableJsonTextWriter(context, HttpContext.Response.Body))
                            {
                                context.Write(writer,
                                              new DynamicJsonValue
                                {
                                    ["Type"]    = "Error",
                                    ["Message"] = "Database " + name + " wasn't found"
                                });
                            }
                            return(Task.CompletedTask);
                        }

                        var clusterTopology = ServerStore.GetClusterTopology(context);
                        var dbRecord        = JsonDeserializationCluster.DatabaseRecord(dbBlit);
                        using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                        {
                            context.Write(writer, new DynamicJsonValue
                            {
                                [nameof(Topology.Nodes)] = new DynamicJsonArray(
                                    dbRecord.Topology.Members.Select(x => new DynamicJsonValue
                                {
                                    [nameof(ServerNode.Url)]        = GetUrl(x, clusterTopology),
                                    [nameof(ServerNode.ClusterTag)] = x,
                                    [nameof(ServerNode.ServerRole)] = ServerNode.Role.Member,
                                    [nameof(ServerNode.Database)]   = dbRecord.DatabaseName
                                })
                                    .Concat(dbRecord.Topology.Rehabs.Select(x => new DynamicJsonValue
                                {
                                    [nameof(ServerNode.Url)]        = GetUrl(x, clusterTopology),
                                    [nameof(ServerNode.ClusterTag)] = x,
                                    [nameof(ServerNode.Database)]   = dbRecord.DatabaseName,
                                    [nameof(ServerNode.ServerRole)] = ServerNode.Role.Rehab
                                })
                                            )
                                    ),
                                [nameof(Topology.Etag)] = dbRecord.Topology.Stamp.Index
                            });
                        }
                    }
            }
            return(Task.CompletedTask);
        }
Exemplo n.º 5
0
 public override void SetResponse(JsonOperationContext context, BlittableJsonReaderObject response, bool fromCache)
 {
     Result = JsonDeserializationCluster.DatabaseRecord(response);
 }
Exemplo n.º 6
0
        public DatabaseRecord GetDatabaseRecord()
        {
            var databaseRecord = new DatabaseRecord();

            ReadObject(reader =>
            {
                if (reader.TryGet(nameof(databaseRecord.Revisions), out BlittableJsonReaderObject revisions) &&
                    revisions != null)
                {
                    try
                    {
                        databaseRecord.Revisions = JsonDeserializationCluster.RevisionsConfiguration(revisions);
                    }
                    catch (Exception e)
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.Info("Wasn't able to import the reivions configuration from smuggler file. Skiping.", e);
                        }
                    }
                }

                if (reader.TryGet(nameof(databaseRecord.Expiration), out BlittableJsonReaderObject expiration) &&
                    expiration != null)
                {
                    try
                    {
                        databaseRecord.Expiration = JsonDeserializationCluster.ExpirationConfiguration(expiration);
                    }
                    catch (Exception e)
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.Info("Wasn't able to import the expiration configuration from smuggler file. Skiping.", e);
                        }
                    }
                }

                if (reader.TryGet(nameof(databaseRecord.RavenConnectionStrings), out BlittableJsonReaderObject ravenConnectionStrings) &&
                    ravenConnectionStrings != null)
                {
                    try
                    {
                        foreach (var connectionName in ravenConnectionStrings.GetPropertyNames())
                        {
                            if (ravenConnectionStrings.TryGet(connectionName, out BlittableJsonReaderObject connection) == false)
                            {
                                if (_log.IsInfoEnabled)
                                {
                                    _log.Info($"Wasn't able to import the RavenDB connection string {connectionName} from smuggler file. Skiping.");
                                }

                                continue;
                            }

                            var connectionString = JsonDeserializationCluster.RavenConnectionString(connection);
                            databaseRecord.RavenConnectionStrings[connectionString.Name] = connectionString;
                        }
                    }
                    catch (Exception e)
                    {
                        databaseRecord.RavenConnectionStrings.Clear();
                        if (_log.IsInfoEnabled)
                        {
                            _log.Info("Wasn't able to import the RavenDB connection strings from smuggler file. Skiping.", e);
                        }
                    }
                }

                if (reader.TryGet(nameof(databaseRecord.SqlConnectionStrings), out BlittableJsonReaderObject sqlConnectionStrings) &&
                    sqlConnectionStrings != null)
                {
                    try
                    {
                        foreach (var connectionName in sqlConnectionStrings.GetPropertyNames())
                        {
                            if (ravenConnectionStrings.TryGet(connectionName, out BlittableJsonReaderObject connection) == false)
                            {
                                if (_log.IsInfoEnabled)
                                {
                                    _log.Info($"Wasn't able to import the SQL connection string {connectionName} from smuggler file. Skiping.");
                                }

                                continue;
                            }

                            var connectionString = JsonDeserializationCluster.SqlConnectionString(connection);
                            databaseRecord.SqlConnectionStrings[connectionString.Name] = connectionString;
                        }
                    }
                    catch (Exception e)
                    {
                        databaseRecord.SqlConnectionStrings.Clear();
                        if (_log.IsInfoEnabled)
                        {
                            _log.Info("Wasn't able to import the SQL connection strings from smuggler file. Skiping.", e);
                        }
                    }
                }

                if (reader.TryGet(nameof(databaseRecord.Client), out BlittableJsonReaderObject client) &&
                    client != null)
                {
                    try
                    {
                        databaseRecord.Client = JsonDeserializationCluster.ClientConfiguration(expiration);
                    }
                    catch (Exception e)
                    {
                        if (_log.IsInfoEnabled)
                        {
                            _log.Info("Wasn't able to import the client configuration from smuggler file. Skiping.", e);
                        }
                    }
                }
            });


            return(databaseRecord);
        }
        public Task GetServerWideTasksForStudio()
        {
            var taskName     = GetStringQueryString("name", required: false);
            var typeAsString = GetStringQueryString("type", required: false);
            var tryParse     = Enum.TryParse(typeAsString, out OngoingTaskType type);

            if (typeAsString != null && tryParse == false)
            {
                throw new ArgumentException($"{typeAsString} is unknown task type.");
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                using (context.OpenReadTransaction())
                    using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        var result = new ServerWideTasksResult();

                        var blittables = ServerStore.Cluster.GetServerWideConfigurations(context, OngoingTaskType.Backup, taskName);
                        foreach (var blittable in blittables)
                        {
                            var configuration = JsonDeserializationCluster.ServerWideBackupConfiguration(blittable);

                            if (taskName != null && type == OngoingTaskType.Backup &&
                                string.Equals(taskName, configuration.Name) == false)
                            {
                                continue;
                            }

                            result.Tasks.Add(new ServerWideTasksResult.ServerWideBackupTask
                            {
                                TaskId             = configuration.TaskId,
                                TaskName           = configuration.Name,
                                TaskState          = configuration.Disabled ? OngoingTaskState.Disabled : OngoingTaskState.Enabled,
                                ExcludedDatabases  = configuration.ExcludedDatabases,
                                BackupType         = configuration.BackupType,
                                RetentionPolicy    = configuration.RetentionPolicy,
                                BackupDestinations = configuration.GetDestinations(),
                                IsEncrypted        = configuration.BackupEncryptionSettings != null &&
                                                     configuration.BackupEncryptionSettings.EncryptionMode != EncryptionMode.None
                            });
                        }

                        blittables = ServerStore.Cluster.GetServerWideConfigurations(context, OngoingTaskType.Replication, taskName);
                        foreach (var blittable in blittables)
                        {
                            var configuration = JsonDeserializationCluster.ServerWideExternalReplication(blittable);

                            if (taskName != null && type == OngoingTaskType.Replication &&
                                string.Equals(taskName, configuration.Name) == false)
                            {
                                continue;
                            }

                            result.Tasks.Add(new ServerWideTasksResult.ServerWideExternalReplicationTask
                            {
                                TaskId                = configuration.TaskId,
                                TaskName              = configuration.Name,
                                TaskState             = configuration.Disabled ? OngoingTaskState.Disabled : OngoingTaskState.Enabled,
                                ExcludedDatabases     = configuration.ExcludedDatabases,
                                TopologyDiscoveryUrls = configuration.TopologyDiscoveryUrls,
                                DelayReplicationFor   = configuration.DelayReplicationFor,
                            });
                        }

                        context.Write(writer, result.ToJson());
                        writer.Flush();

                        return(Task.CompletedTask);
                    }
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
        }