Пример #1
0
        /// <summary>
        /// Creates the on-wire representation of the given response.
        /// </summary>
        /// <param name="response">Response to serialize</param>
        /// <returns>Serialized data</returns>
        public byte[] SerializeResponseAsBytes(RequestResponse response)
        {
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            return(this.protocol.SerializeResponse(response, this.UsedMarshalVersion));
        }
Пример #2
0
 private void SerializeResponse(RequestResponse response)
 {
     if (this.enqueueResponse == null)
     {
         // queue == null is a corner case, so we can safely send and flush here.
         byte[] bytes = this.SerializeResponseAsBytes(response);
         this.SendResponsePacket(bytes, true);
     }
     else
     {
         this.enqueueResponse(response);
     }
 }
Пример #3
0
        /// <summary>
        /// Recreates a response from its on-wire representation.
        /// </summary>
        /// <param name="responseBytes">Data to deserialize</param>
        /// <returns>Deserialized response</returns>
        public RequestResponse DeserializeResponseFromBytes(byte[] responseBytes)
        {
            if (responseBytes == null)
            {
                throw new ArgumentNullException(nameof(responseBytes));
            }

            RequestResponse response = this.protocol.DeserializeResponse(responseBytes, this.UsedMarshalVersion);

            // If the response is a message to the client with WatcherCall as the content then
            // set the registered watcher corresponding to the watcher id in the watcher call.
            if (response.CallId == ulong.MaxValue)
            {
                WatcherCall watcherCall = response.Content as WatcherCall;
                if (watcherCall != null)
                {
                    watcherCall.Watcher = this.watchers.GetObjectForId(watcherCall.WatcherId, watcherCall.Kind.HasFlag(WatcherKind.OneUse));
                }
            }

            return(response);
        }
Пример #4
0
            /// <summary>
            /// runs the command encoded in the given path
            /// </summary>
            /// <param name="path">the command encoded in the path</param>
            /// <param name="data">optionally, the data associated with the request</param>
            /// <param name="session">Client session</param>
            /// <param name="lockList">the lock list of the invocation</param>
            /// <param name="requestedCommand">Requested command on return</param>
            /// <param name="content">More info on the command on return</param>
            /// <returns>code for possible error</returns>
            public Code RunCommandPath(string path, byte[] data, ClientSession session, ILockListTransaction lockList, out string requestedCommand, out object content)
            {
                if (path == null)
                {
                    throw new ArgumentNullException(nameof(path));
                }

                Code result = Code.Apierror;

                requestedCommand = "unknown";
                content          = "unknown command";

                if (!this.IsCommand(path))
                {
                    return(result);
                }

                string[] pieces = path.Split('/');

                if (pieces.Length >= 2)
                {
                    requestedCommand = pieces[1].ToLower();

                    if (!this.IsCommandAllowed(session, requestedCommand))
                    {
                        content = "command not allowed now";
                        return(Code.Apierror);
                    }

                    RingMasterEventSource.Log.RunCommand(requestedCommand);
                    this.backend.auditConsumer?.OnRunCommand(requestedCommand);

                    switch (requestedCommand)
                    {
                    case "getsetting":
                    {
                        content = RingMasterBackendCore.GetSetting(pieces[2]);
                        result  = Code.Ok;
                        break;
                    }

                    case "gc":
                    {
                        GC.Collect();
                        content = "GC scheduled";
                        result  = Code.Ok;
                        break;
                    }

                    case "takecheckpoint":
                    {
                        bool ok = this.backend.Factory.TakeCheckpoint();
                        content = string.Format("Checkpoint {0}scheduled", ok ? string.Empty : "not ");
                        result  = Code.Ok;
                        break;
                    }

                    case "buildtreefile":
                    {
                        string   commandResult;
                        string[] args = Encoding.UTF8.GetString(data).Split('|');
                        try
                        {
                            int             ver  = int.Parse(args[2]);
                            RequestResponse resp = this.backend.BuildTreeFile(nodepath: args[0], filename: args[1], version: ver);
                            commandResult = resp.ResultCode == (int)Code.Ok ? "success" : "failed";
                            result        = (Code)resp.ResultCode;
                        }
                        catch (Exception e)
                        {
                            commandResult = "failed:" + e.Message;
                            result        = Code.Systemerror;
                        }

                        content = string.Format("buildtreefile: nodepath={0} filename={1} result={2}", args[0], args[1], commandResult);

                        break;
                    }

                    case "mount":
                    {
                        string   commandResult;
                        string[] args = Encoding.UTF8.GetString(data).Split('|');
                        try
                        {
                            RequestResponse resp = this.backend.Mount(nodepath: args[0], filename: args[1], allowremount: false);
                            commandResult = resp.ResultCode == (int)Code.Ok ? "success" : "failed";
                            result        = (Code)resp.ResultCode;
                        }
                        catch (Exception e)
                        {
                            commandResult = "failed:" + e.Message;
                            result        = Code.Unknown;
                        }

                        content = string.Format("mount: nodepath={0} filename={1} result={2}", args[0], args[1], commandResult);

                        break;
                    }

                    case "remountroot":
                    {
                        string commandResult;
                        string filepath = Encoding.UTF8.GetString(data);
                        try
                        {
                            RequestResponse resp = this.backend.Mount(nodepath: "/", filename: filepath, allowremount: true, mountRoot: true);
                            commandResult = resp.ResultCode == (int)Code.Ok ? "success" : "failed";
                            result        = (Code)resp.ResultCode;
                        }
                        catch (Exception e)
                        {
                            commandResult = "failed:" + e.Message;
                            result        = Code.Unknown;
                        }

                        content = string.Format("mountroot: nodepath=/ filename={0} result={1}", filepath, commandResult);

                        break;
                    }

                    case "unmount":
                    {
                        string   commandResult;
                        string[] args = Encoding.UTF8.GetString(data).Split('|');

                        try
                        {
                            RequestResponse resp = this.backend.Unmount(args[0]);
                            commandResult = resp.ResultCode == (int)Code.Ok ? "success" : "failed";
                            result        = (Code)resp.ResultCode;
                        }
                        catch (Exception e)
                        {
                            commandResult = "failed:" + e.Message;
                            result        = Code.Unknown;
                        }

                        content = string.Format("mount: nodepath={0} result={1}", args[0], commandResult);

                        break;
                    }

                    case "remount":
                    {
                        string   commandResult;
                        string[] args = Encoding.UTF8.GetString(data).Split('|');
                        try
                        {
                            RequestResponse resp = this.backend.Mount(nodepath: args[0], filename: args[1], allowremount: true);
                            commandResult = resp.ResultCode == (int)Code.Ok ? "success" : "failed";
                            result        = (Code)resp.ResultCode;
                        }
                        catch (Exception e)
                        {
                            commandResult = "failed:" + e.Message;
                            result        = Code.Unknown;
                        }

                        content = string.Format("remount: nodepath={0} result={1}", args[0], commandResult);

                        break;
                    }

                    case "measure":
                    {
                        StringBuilder sb = new StringBuilder();

                        Dictionary <string, object> results;
                        try
                        {
                            this.backend.CanMeasure = true;
                            ((IUnsafeTreeAccess)this.backend).LockRootNoSync();

                            results = this.backend.MeasureFullTree(PlatformHelper.ProcessorCount, maxTimeForMeasurementInMillis);
                        }
                        finally
                        {
                            this.backend.CanMeasure = false;
                            ((IUnsafeTreeAccess)this.backend).ReleaseRoot();
                        }

                        if (results != null)
                        {
                            foreach (KeyValuePair <string, object> line in results)
                            {
                                string text;
                                string child_i = line.Key;

                                Exception e = line.Value as Exception;

                                if (e != null)
                                {
                                    text = string.Format("Metrics for {0}: {1}", child_i, e);
                                }
                                else
                                {
                                    ulong metrics = (ulong)line.Value;
                                    text = string.Format("Metrics for {0} is {1:X}", child_i, metrics);
                                }

                                sb.AppendLine(text);
                            }
                        }

                        content = sb.ToString();
                        result  = Code.Ok;
                        break;
                    }

                    case "getlocaltime":
                    {
                        content = string.Format("local time: " + DateTime.UtcNow.ToString("o"));
                        result  = Code.Ok;
                        break;
                    }

                    case "getcommands":
                    {
                        content = this.GetCommands();
                        result  = Code.Ok;
                        break;
                    }

                    case "trace":
                    {
                        string message = "<null>";
                        if (data != null)
                        {
                            message = Encoding.UTF8.GetString(data);
                        }

                        content = "traced: " + message;
                        result  = Code.Ok;
                        Trace.TraceInformation(message);
                        break;
                    }

                    case "failoverinto":
                    {
                        string replica = "<any>";
                        if (data != null)
                        {
                            replica = Encoding.UTF8.GetString(data);
                        }

                        content = "Failing over into: " + replica + " in 10 seconds";
                        this.backend.FailoverInto(replica, 10000);
                        result = Code.Ok;
                        break;
                    }

                    case "downloadurlintolocation":
                    {
                        string arguments = null;

                        if (data != null)
                        {
                            arguments = Encoding.UTF8.GetString(data);
                        }

                        // we run this one command asynchronously with any potential replication
                        bool hasStarted = this.backend.DownloadUrlIntoLocation(arguments);
                        if (hasStarted)
                        {
                            content = string.Format("DownloadUrlIntoLocation started arguments={0}", arguments);
                            result  = Code.Ok;
                        }
                        else
                        {
                            content = string.Format("DownloadUrlIntoLocation functionality is not implemented");
                            result  = Code.Unimplemented;
                        }

                        break;
                    }

                    case "poisonpill":
                    {
                        string spec = null;

                        if (data != null)
                        {
                            spec = Encoding.UTF8.GetString(data);
                        }

                        RequestResponse res = this.GeneratePoisonPill(spec, session, lockList);
                        if (res != null)
                        {
                            content = string.Format("poison pill executed. Result = {0}", res.Content);
                            result  = (Code)res.ResultCode;
                        }
                        else
                        {
                            content = "Poison pills not allowed from config";
                            result  = Code.Authfailed;
                        }

                        break;
                    }

                    case "importcheckpoint":
                    {
                        string location = null;

                        if (data != null)
                        {
                            location = Encoding.UTF8.GetString(data);
                        }

                        RingMasterThreadPool.Instance.QueueUserWorkItem(_ =>
                            {
                                Thread.Sleep(5000);
                                bool ok = this.backend.ImportCheckpoint(location);
                                Trace.TraceWarning("Import checkpoint {0}: {1}", location, ok ? "Succeeded" : "Failed");
                                if (ok)
                                {
                                    Trace.TraceWarning("This instance will die now");
                                    Environment.Exit(1);
                                }
                            });

                        content = "Importing checkpoint " + location + "file and restarting";
                        result  = Code.Ok;

                        break;
                    }

                    case "getstats":
                    {
                        lock (this.SyncObject)
                        {
                            content = string.Format("PersistentData.TotalNodes={0} PersistentData.TotalData={1} EphemeralData.TotalNodes={2} EphemeralData.TotalData={3}", this.backend.Factory.TotalNodes, this.backend.Factory.TotalData, this.backend.EphemeralFactory.TotalNodes, this.backend.EphemeralFactory.TotalData);
                        }

                        result = Code.Ok;

                        break;
                    }

                    case "dumpnodes":
                    {
                        bool scanEphemerals = pieces.Length > 2 && string.Equals(pieces[2], "scanephemerals", StringComparison.InvariantCultureIgnoreCase);
                        content = this.backend.Factory.DumpAllNodesForDebug();

                        if (scanEphemerals)
                        {
                            lock (this.SyncObject)
                            {
                                content = content + Environment.NewLine + "---Eph:" + Environment.NewLine + this.backend.ScanForEphemeral() + Environment.NewLine + "---";
                            }
                        }

                        result = Code.Ok;

                        break;
                    }

                    case "getverbositylevel":
                    {
                        content = "verbosity level is " + this.backend.GetVerbosityLevel();
                        result  = Code.Ok;
                        break;
                    }

                    case "setverbositylevel":
                    {
                        int vlev = int.Parse(pieces[2]);
                        content = string.Format("verbosity level was {0} now is set to {1}", this.backend.GetVerbosityLevel(), vlev);
                        this.backend.SetupVerbosityLevel(vlev);
                        result = Code.Ok;
                        break;
                    }

                    case "cleanuprsl":
                    {
                        RingMasterThreadPool.Instance.QueueUserWorkItem(_ =>
                            {
                                Thread.Sleep(10000);
                                Trace.TraceWarning("This instance will wipe its state {0} now", this.backend.GetType().Name);
                                this.backend.Factory.WipeAllDataAndShutdown();
                                Trace.TraceWarning("This instance will die now");
                                Environment.Exit(1);
                            });
                        content = "cleaning up RSL folder and restarting";
                        result  = Code.Ok;
                        break;
                    }

                    case "restart":
                    {
                        uint waitMS = 10000;

                        if (pieces.Length > 2)
                        {
                            if (!uint.TryParse(pieces[2], out waitMS))
                            {
                                waitMS = 10000;
                            }
                        }

                        // 2 minutes max wait
                        waitMS = Math.Min(waitMS, 120000);

                        RingMasterThreadPool.Instance.QueueUserWorkItem(_ =>
                            {
                                Thread.Sleep((int)waitMS);
                                Trace.TraceInformation("This instance will stop {0} now", this.backend.GetType().Name);
                                this.backend.Stop();

                                Thread.Sleep(2000);
                                Trace.TraceInformation("This instance will restart {0} now", this.backend.GetType().Name);
                                this.backend.Start(CancellationToken.None);
                            });

                        content = "restarted in " + waitMS + " miliseconds";
                        result  = Code.Ok;
                        break;
                    }

                    case "die":
                    {
                        RingMasterThreadPool.Instance.QueueUserWorkItem(_ =>
                            {
                                Thread.Sleep(10000);
                                Trace.TraceWarning("This instance will die now");
                                Environment.Exit(1);
                            });

                        if (pieces.Length > 2)
                        {
                            this.backend.FailoverInto(pieces[2]);
                        }

                        content = "die in 10 seconds";
                        result  = Code.Ok;
                        break;
                    }
                    }
                }

                return(result);
            }