Ejemplo n.º 1
0
        public async Task DeleteOngoingTask()
        {
            if (ResourceNameValidator.IsValidResourceName(Database.Name, ServerStore.Configuration.Core.DataDirectory.FullPath, out string errorMessage) == false)
            {
                throw new BadRequestException(errorMessage);
            }

            var id       = GetLongQueryString("id");
            var typeStr  = GetQueryStringValueAndAssertIfSingleAndNotEmpty("type");
            var taskName = GetStringQueryString("taskName", required: false);

            if (Enum.TryParse <OngoingTaskType>(typeStr, true, out var type) == false)
            {
                throw new ArgumentException($"Unknown task type: {type}", "type");
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                var(index, _) = await ServerStore.DeleteOngoingTask(id, taskName, type, Database.Name);

                await Database.RachisLogIndexNotifications.WaitForIndexNotification(index);

                HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(writer, new DynamicJsonValue
                    {
                        [nameof(ModifyOngoingTaskResult.TaskId)]           = id,
                        [nameof(ModifyOngoingTaskResult.RaftCommandIndex)] = index
                    });
                    writer.Flush();
                }
            }
        }
Ejemplo n.º 2
0
        public async Task UpdateExternalReplication()
        {
            if (ResourceNameValidator.IsValidResourceName(Database.Name, ServerStore.Configuration.Core.DataDirectory.FullPath, out string errorMessage) == false)
            {
                throw new BadRequestException(errorMessage);
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                var updateJson = await context.ReadForMemoryAsync(RequestBodyStream(), "read-update-replication");

                if (updateJson.TryGet(nameof(UpdateExternalReplicationCommand.Watcher), out BlittableJsonReaderObject watcherBlittable) == false)
                {
                    throw new InvalidDataException($"{nameof(UpdateExternalReplicationCommand.Watcher)} was not found.");
                }

                var watcher = JsonDeserializationClient.ExternalReplication(watcherBlittable);
                if (ServerStore.LicenseManager.CanAddExternalReplication(out var licenseLimit) == false)
                {
                    SetLicenseLimitResponse(licenseLimit);
                    return;
                }

                var(index, _) = await ServerStore.UpdateExternalReplication(Database.Name, watcher);

                await Database.RachisLogIndexNotifications.WaitForIndexNotification(index);

                string responsibleNode;
                using (context.OpenReadTransaction())
                {
                    var record = ServerStore.Cluster.ReadDatabase(context, Database.Name);
                    responsibleNode = record.Topology.WhoseTaskIsIt(watcher, ServerStore.Engine.CurrentState);
                }

                HttpContext.Response.StatusCode = (int)HttpStatusCode.Created;

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(writer, new DynamicJsonValue
                    {
                        [nameof(ModifyOngoingTaskResult.TaskId)]           = watcher.TaskId == 0 ? index : watcher.TaskId,
                        [nameof(ModifyOngoingTaskResult.RaftCommandIndex)] = index,
                        [nameof(OngoingTask.ResponsibleNode)] = responsibleNode
                    });
                    writer.Flush();
                }
            }
        }
Ejemplo n.º 3
0
        public Task GetOngoingTaskInfo()
        {
            if (ResourceNameValidator.IsValidResourceName(Database.Name, ServerStore.Configuration.Core.DataDirectory.FullPath, out string errorMessage) == false)
            {
                throw new BadRequestException(errorMessage);
            }

            var key     = GetLongQueryString("key");
            var typeStr = GetQueryStringValueAndAssertIfSingleAndNotEmpty("type");

            using (ServerStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
            {
                using (context.OpenReadTransaction())
                {
                    var clusterTopology = ServerStore.GetClusterTopology(context);
                    var record          = ServerStore.Cluster.ReadDatabase(context, Database.Name);
                    var dbTopology      = record?.Topology;

                    if (Enum.TryParse <OngoingTaskType>(typeStr, true, out var type) == false)
                    {
                        throw new ArgumentException($"Unknown task type: {type}", "type");
                    }

                    string tag;

                    switch (type)
                    {
                    case OngoingTaskType.Replication:

                        var watcher = record?.ExternalReplication.Find(x => x.TaskId == key);
                        if (watcher == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            break;
                        }
                        var taskInfo = GetExternalReplicationInfo(dbTopology, clusterTopology, watcher);

                        WriteResult(context, taskInfo);

                        break;

                    case OngoingTaskType.Backup:

                        var backupConfiguration = record?.PeriodicBackups?.Find(x => x.TaskId == key);
                        if (backupConfiguration == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            break;
                        }

                        tag = dbTopology?.WhoseTaskIsIt(backupConfiguration, ServerStore.Engine.CurrentState);
                        var backupDestinations = GetBackupDestinations(backupConfiguration);
                        var backupStatus       = Database.PeriodicBackupRunner.GetBackupStatus(key);
                        var nextBackup         = Database.PeriodicBackupRunner.GetNextBackupDetails(record, backupConfiguration, backupStatus);

                        var backupTaskInfo = new OngoingTaskBackup
                        {
                            TaskId          = backupConfiguration.TaskId,
                            BackupType      = backupConfiguration.BackupType,
                            TaskName        = backupConfiguration.Name,
                            TaskState       = backupConfiguration.Disabled ? OngoingTaskState.Disabled : OngoingTaskState.Enabled,
                            ResponsibleNode = new NodeId
                            {
                                NodeTag = tag,
                                NodeUrl = clusterTopology.GetUrlFromTag(tag)
                            },
                            BackupDestinations    = backupDestinations,
                            LastFullBackup        = backupStatus.LastFullBackup,
                            LastIncrementalBackup = backupStatus.LastIncrementalBackup,
                            NextBackup            = nextBackup
                        };

                        WriteResult(context, backupTaskInfo);
                        break;

                    case OngoingTaskType.SqlEtl:

                        var sqlEtl = record?.SqlEtls?.Find(x => x.TaskId == key);
                        if (sqlEtl == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            break;
                        }

                        WriteResult(context, new OngoingTaskSqlEtlDetails()
                        {
                            TaskId        = sqlEtl.TaskId,
                            TaskName      = sqlEtl.Name,
                            Configuration = sqlEtl,
                            TaskState     = GetEtlTaskState(sqlEtl)
                        });
                        break;

                    case OngoingTaskType.RavenEtl:

                        var ravenEtl = record?.RavenEtls?.Find(x => x.TaskId == key);
                        if (ravenEtl == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            break;
                        }

                        WriteResult(context, new OngoingTaskRavenEtlDetails()
                        {
                            TaskId        = ravenEtl.TaskId,
                            TaskName      = ravenEtl.Name,
                            Configuration = ravenEtl,
                            TaskState     = GetEtlTaskState(ravenEtl)
                        });
                        break;

                    case OngoingTaskType.Subscription:

                        var nameKey = GetQueryStringValueAndAssertIfSingleAndNotEmpty("taskName");
                        var itemKey = SubscriptionState.GenerateSubscriptionItemKeyName(record.DatabaseName, nameKey);
                        var doc     = ServerStore.Cluster.Read(context, itemKey);
                        if (doc == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            break;
                        }

                        var subscriptionState = JsonDeserializationClient.SubscriptionState(doc);
                        tag = dbTopology?.WhoseTaskIsIt(subscriptionState, ServerStore.Engine.CurrentState);

                        var subscriptionStateInfo = new SubscriptionStateWithNodeDetails
                        {
                            Query = subscriptionState.Query,
                            ChangeVectorForNextBatchStartingPoint = subscriptionState.ChangeVectorForNextBatchStartingPoint,
                            SubscriptionId           = subscriptionState.SubscriptionId,
                            SubscriptionName         = subscriptionState.SubscriptionName,
                            LastBatchAckTime         = subscriptionState.LastBatchAckTime,
                            Disabled                 = subscriptionState.Disabled,
                            LastClientConnectionTime = subscriptionState.LastClientConnectionTime,
                            MentorNode               = subscriptionState.MentorNode,
                            ResponsibleNode          = new NodeId
                            {
                                NodeTag = tag,
                                NodeUrl = clusterTopology.GetUrlFromTag(tag)
                            }
                        };

                        // Todo: here we'll need to talk with the running node? TaskConnectionStatus = subscriptionState.Disabled ? OngoingTaskConnectionStatus.NotActive : OngoingTaskConnectionStatus.Active,

                        WriteResult(context, subscriptionStateInfo.ToJson());
                        break;

                    default:
                        HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                        break;
                    }
                }
            }

            return(Task.CompletedTask);
        }
Ejemplo n.º 4
0
        public Task Put()
        {
            var name = RouteMatch.Url.Substring(RouteMatch.MatchLength);

            string errorMessage;

            if (
                ResourceNameValidator.IsValidResourceName(name, ServerStore.Configuration.Core.DataDirectory,
                                                          out errorMessage) == false)
            {
                HttpContext.Response.StatusCode = 400;
                return(HttpContext.Response.WriteAsync(errorMessage));
            }

            TransactionOperationContext context;

            using (ServerStore.ContextPool.AllocateOperationContext(out context))
            {
                var dbId = Constants.Database.Prefix + name;

                var  etagAsString = HttpContext.Request.Headers["ETag"];
                long etag;
                var  hasEtagInRequest = long.TryParse(etagAsString, out etag);

                using (context.OpenReadTransaction())
                {
                    var existingDatabase = ServerStore.Read(context, dbId);
                    if (
                        DatabaseHelper.CheckExistingDatabaseName(existingDatabase, name, dbId, etagAsString,
                                                                 out errorMessage) == false)
                    {
                        HttpContext.Response.StatusCode = 400;
                        return(HttpContext.Response.WriteAsync(errorMessage));
                    }
                }

                var dbDoc = context.ReadForDisk(RequestBodyStream(), dbId);

                //TODO: Fix this
                //int size;
                //var buffer = context.GetNativeTempBuffer(dbDoc.SizeInBytes, out size);
                //dbDoc.CopyTo(buffer);

                //var reader = new BlittableJsonReaderObject(buffer, dbDoc.SizeInBytes, context);
                //object result;
                //if (reader.TryGetMember("SecureSettings", out result))
                //{
                //    var secureSettings = (BlittableJsonReaderObject) result;
                //    secureSettings.Unloading = new DynamicJsonValue(secureSettings);
                //    foreach (var propertyName in secureSettings.GetPropertyNames())
                //    {
                //        secureSettings.TryGetMember(propertyName, out result);
                //        // protect
                //        secureSettings.Unloading[propertyName] = "fooo";
                //    }
                //}

                long?newEtag = null;

                ServerStore.DatabasesLandlord.UnloadAndLock(name, () =>
                {
                    using (var tx = context.OpenWriteTransaction())
                    {
                        newEtag = hasEtagInRequest ? ServerStore.Write(context, dbId, dbDoc, etag) :
                                  ServerStore.Write(context, dbId, dbDoc);
                        tx.Commit();
                    }
                });

                HttpContext.Response.StatusCode = 201;

                using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(writer, new DynamicJsonValue
                    {
                        ["ETag"] = newEtag,
                        ["Key"]  = dbId
                    });
                    writer.Flush();
                }
            }
            return(Task.CompletedTask);
        }