Example #1
0
        /// <summary>
        /// Enqueue a request.
        /// </summary>
        /// <param name="request">Request to enqueue</param>
        /// <returns>A task that resolves to the response sent by the server</returns>
        public async Task <RequestResponse> Request(IRingMasterRequest request)
        {
            // Register the request in the requestMap - the request map keeps track of the request
            // throughout its lifetime.
            RequestWrapper requestWrapper = this.RegisterRequest(request);

            // Attempt to add the request to the outgoing request queue.
            if (this.outgoingRequests.TryAdd(requestWrapper))
            {
                // Once the request is added to the outgoing request queue, it stays there until a connection
                // is available to send it.  If the request's timeout expires before a connection is available, then
                // the request is completed with OperationTimedout resultCode.
                this.instrumentation.RequestQueued(requestWrapper.CallId, requestWrapper.WrappedRequest.RequestType, this.outgoingRequests.Count);
                this.outgoingRequestsAvailable.Release();
            }
            else
            {
                // The outgoing request queue is full, so remove the request from the requestMap and throw a RequestQueueFull exception.
                lock (this.requestMap)
                {
                    this.RemoveRequestFromMap(requestWrapper.CallId);
                }

                int pendingRequestCount = this.outgoingRequestsAvailable.CurrentCount;
                RingMasterClientEventSource.Log.RequestQueueFull(requestWrapper.CallId, pendingRequestCount);
                this.instrumentation.RequestQueueFull(requestWrapper.CallId, requestWrapper.WrappedRequest.RequestType, pendingRequestCount);
                throw RingMasterClientException.RequestQueueFull(pendingRequestCount);
            }

            return(await requestWrapper.TaskCompletionSource.Task);
        }
        /// <summary>
        /// Enqueue a request.
        /// </summary>
        /// <param name="request">Request to enqueue</param>
        /// <returns>A task that resolves to the response sent by the server</returns>
        public async Task <RequestResponse> Request(IRingMasterRequest request)
        {
            bool haswatcher = false;

            switch (request.RequestType)
            {
            case RingMasterRequestType.Exists:
            {
                var existsRequest = (RequestExists)request;
                haswatcher = existsRequest.Watcher != null;
                break;
            }

            case RingMasterRequestType.GetData:
            {
                var getDataRequest = (RequestGetData)request;
                haswatcher = getDataRequest.Watcher != null;
                break;
            }

            case RingMasterRequestType.GetChildren:
            {
                var getChildrenRequest = (RequestGetChildren)request;
                haswatcher = getChildrenRequest.Watcher != null;
                break;
            }
            }

            if (!haswatcher)
            {
                return(await this.ProcessCacheRequest(this.cache, request));
            }

            return(await this.baseHandler.Request(request));
        }
Example #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RequestWrapper"/> class.
 /// </summary>
 /// <param name="callId">Id of the call</param>
 /// <param name="wrappedRequest">Request to wrap</param>
 public RequestWrapper(ulong callId, IRingMasterRequest wrappedRequest)
 {
     this.WrappedRequest       = wrappedRequest;
     this.TaskCompletionSource = new TaskCompletionSource <RequestResponse>();
     this.CallId            = callId;
     this.creationTimeTicks = DateTime.UtcNow.Ticks;
 }
 /// <summary>
 /// Process a request
 /// </summary>
 /// <param name="request">Request to be processed</param>
 /// <returns>
 /// Task that resolves to the response corresponding to the request
 /// </returns>
 public Task <RequestResponse> Request(IRingMasterRequest request)
 {
     return(this.Request <RequestResponse>(ringMaster =>
     {
         return ringMaster.Request(request);
     }));
 }
        /// <inheritdoc/>
        public Task <RequestResponse> Request(IRingMasterRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            request.TimeStreamId = this.timeStreamId;
            return(this.handler.Request(request));
        }
Example #6
0
        /// <summary>
        /// Registers the request.
        /// </summary>
        /// <param name="request">Request to register</param>
        /// <returns>Wrapper that represents the request and its metadata</returns>
        private RequestWrapper RegisterRequest(IRingMasterRequest request)
        {
            RequestWrapper requestWrapper;

            lock (this.requestMap)
            {
                requestWrapper = this.AddRequestToMap(request);
            }

            return(requestWrapper);
        }
Example #7
0
        /// <summary>
        /// Gets <see cref="IRingMasterRequest"/> that correspond to the given <see cref="Op"/>s.
        /// </summary>
        /// <param name="ops">List of operations</param>
        /// <returns>List of <see cref="IRingMasterRequest"/>s</returns>
        protected static IReadOnlyList <IRingMasterRequest> GetRequests(IReadOnlyList <Op> ops)
        {
            if (ops == null)
            {
                throw new ArgumentNullException("ops");
            }

            IRingMasterRequest[] requests = new IRingMasterRequest[ops.Count];
            for (int i = 0; i < requests.Length; i++)
            {
                requests[i] = ops[i].Request;
            }

            return(requests);
        }
Example #8
0
        /// <summary>
        /// Deserialize <see cref="RequestBatch"/>.
        /// </summary>
        /// <param name="callid">Id of the call</param>
        /// <param name="uid"><c>uid</c> associated with the request</param>
        /// <returns>The deserialized request</returns>
        private RequestBatch DeserializeRequestBatch(ulong callid, ulong uid)
        {
            ushort numReq = this.binaryReader.ReadUInt16();

            IRingMasterRequest[] req = new IRingMasterRequest[numReq];

            for (int i = 0; i < req.Length; i++)
            {
                this.DeserializeRingMasterRequest(callid, out req[i]);
            }

            bool completeSynchronously = this.binaryReader.ReadBoolean();

            return(new RequestBatch(req, completeSynchronously, uid));
        }
Example #9
0
        /// <summary>
        /// Create a batch request which contains the given requests and book keeping requests.
        /// </summary>
        /// <param name="batchId">Id of the batch</param>
        /// <param name="requests">Requests to include in the batch</param>
        /// <returns>A <see cref="RequestBatch"/> that contains the given requests and book keeping requests</returns>
        private static RequestBatch CreateBatch(ulong batchId, params IRingMasterRequest[] requests)
        {
            var requestArray = new IRingMasterRequest[2 + requests.Length];

            requestArray[0] = new RequestSetData(TestExecutionQueue.LastAppliedBatchIdPath, data: BitConverter.GetBytes(batchId), version: -1);
            requests.CopyTo(requestArray, 1);
            requestArray[requestArray.Length - 1] = new RequestGetData(TestExecutionQueue.TransactionCrcPath, options: RequestGetData.GetDataOptions.None, watcher: null);

            var batchRequest = new RequestBatch(requestArray, completeSynchronously: true);

            batchRequest.Uid = batchId;
            batchRequest.ExecutionQueueId            = TransactionManagerExecutionQueueId;
            batchRequest.ExecutionQueueTimeoutMillis = 10000;

            return(batchRequest);
        }
Example #10
0
        /// <inheritdoc />
        public Task <RequestResponse> Request(IRingMasterRequest request)
        {
            var tcs = new TaskCompletionSource <RequestResponse>();

            this.RequestOverlapped(
                request,
                (response, ex) =>
            {
                if (ex != null)
                {
                    tcs.SetException(ex);
                }
                else
                {
                    tcs.SetResult(response);
                }
            });

            return(tcs.Task);
        }
Example #11
0
        /// <summary>
        /// Handles ringmaster requests.
        /// </summary>
        /// <param name="request">RingMaster request</param>
        /// <param name="onCompletion">Action to execute when the replication is completed</param>
        /// <remarks>
        /// Implementing the <see cref="IRingMasterRequestHandlerOverlapped"/> makes it possible for
        /// several libraries to work directly with the RingMasterBackendCore. This class
        /// is being implemented here to avoid having to expose internal classes outside of
        /// this library.
        /// </remarks>
        public void RequestOverlapped(IRingMasterRequest request, Action <RequestResponse, Exception> onCompletion)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            RequestCall call = MarshallerChannel.LocalRequest(request);

            call.CallId = (ulong)Interlocked.Increment(ref this.lastAssignedCallId);

            this.executor.ProcessMessage(
                call.Request,
                this.session,
                (response, ex) =>
            {
                response.CallId = call.CallId;
                onCompletion?.Invoke(response, ex);
            });
        }
Example #12
0
            private RequestResponse Process(IRingMasterRequest req, List <Action> actions)
            {
                IRingMasterBackendRequest breq = req as IRingMasterBackendRequest;

                if (breq != null)
                {
                    req = breq.WrappedRequest;
                }

                switch (req.RequestType)
                {
                case RingMasterRequestType.Check:
                    return(this.ProcessT((Requests.RequestCheck)req, actions));

                case RingMasterRequestType.Create:
                    return(this.ProcessT((Requests.RequestCreate)req, actions));

                case RingMasterRequestType.GetChildren:
                    return(this.ProcessT((Requests.RequestGetChildren)req, actions));

                case RingMasterRequestType.GetData:
                    return(this.ProcessT((Requests.RequestGetData)req, actions));

                case RingMasterRequestType.Delete:
                    return(this.ProcessT((Requests.RequestDelete)req, actions));

                case RingMasterRequestType.Exists:
                    return(this.ProcessT((Requests.RequestExists)req, actions));

                case RingMasterRequestType.Multi:
                    return(this.ProcessT((Requests.RequestMulti)req, actions));

                case RingMasterRequestType.Move:
                    return(this.ProcessT((Requests.RequestMove)req, actions));
                }

                return(new RequestResponse()
                {
                    ResultCode = (int)RingMasterException.Code.Unimplemented
                });
            }
Example #13
0
            private string ToString(IRingMasterRequest req)
            {
                IRingMasterBackendRequest breq = req as IRingMasterBackendRequest;

                if (breq != null)
                {
                    req = breq.WrappedRequest;
                }

                if (req.RequestType == RingMasterRequestType.Multi)
                {
                    return(string.Format("Request[Type:{0}, Requests:{1}]", req.RequestType, string.Join(";", ((Requests.RequestMulti)req).Requests.Select(c => this.ToString(c)).ToArray())));
                }

                if (req.RequestType == RingMasterRequestType.Move)
                {
                    return(string.Format("Request[Type:{0}, Path:{1}, PathDst:{2}]", req.RequestType, req.Path, ((Requests.RequestMove)req).PathDst));
                }

                return(string.Format("Request[Type:{0}, Path:{1}]", req.RequestType, req.Path));
            }
Example #14
0
        /// <summary>
        /// Deserialize <see cref="RequestMulti"/>.
        /// </summary>
        /// <param name="callid">Id of the call</param>
        /// <param name="uid"><c>uid</c> associated with the request</param>
        /// <returns>The deserialized request</returns>
        private RequestMulti DeserializeRequestMulti(ulong callid, ulong uid)
        {
            ushort numReq = this.binaryReader.ReadUInt16();

            IRingMasterRequest[] req = new IRingMasterRequest[numReq];

            for (int i = 0; i < req.Length; i++)
            {
                this.DeserializeRingMasterRequest(callid, out req[i]);
            }

            bool completeSynchronously = this.binaryReader.ReadBoolean();

            string scheduledName = null;

            if (this.serializationVersionUsed >= SerializationFormatVersions.Version20)
            {
                scheduledName = this.binaryReader.ReadNullableString();
            }

            return(new RequestMulti(req, completeSynchronously, scheduledName, uid));
        }
Example #15
0
        /// <summary>
        /// Adds the <paramref name="request"/> to <see cref="requestMap"/> with the given request ID
        /// </summary>
        /// <param name="request">Request to add</param>
        /// <returns>Wrapper for the request</returns>
        /// <remarks>This should be called while locking <see cref="requestMap"/></remarks>
        private RequestWrapper AddRequestToMap(IRingMasterRequest request)
        {
            ulong requestId = (ulong)Interlocked.Increment(ref this.requestId);

            RequestWrapper requestWrapper = new RequestWrapper(requestId, request);

            this.requestMap.Add(requestId, requestWrapper);

            if (this.newestPendingRequest != null)
            {
                requestWrapper.Previous        = this.newestPendingRequest;
                this.newestPendingRequest.Next = requestWrapper;
            }
            else
            {
                // There are no pending requests so we should set oldestPendingRequest also
                this.oldestPendingRequest = requestWrapper;
            }

            this.newestPendingRequest = requestWrapper;

            return(requestWrapper);
        }
Example #16
0
        /// <summary>
        /// Serialize a request preamble.
        /// </summary>
        /// <param name="request">Request to serialize</param>
        private void SerializeRequestPreamble(IRingMasterRequest request)
        {
            this.binaryWriter.Write((ushort)request.RequestType);
            this.binaryWriter.Write((ulong)request.Uid);
            this.binaryWriter.Write((string)request.Path);
            this.SerializeSessionAuth(request.Auth);
            this.SerializeOperationOverrides(request.Overrides);

            if (this.versionToUse >= SerializationFormatVersions.Version17)
            {
                bool hasExecutionQueueData = request.ExecutionQueueId != Guid.Empty;
                this.binaryWriter.Write((bool)hasExecutionQueueData);
                if (hasExecutionQueueData)
                {
                    this.binaryWriter.Write((Guid)request.ExecutionQueueId);
                    this.binaryWriter.Write((int)request.ExecutionQueueTimeoutMillis);
                }
            }

            if (this.versionToUse >= SerializationFormatVersions.Version21)
            {
                this.binaryWriter.Write((ulong)request.TimeStreamId);
            }
        }
        private void CacheInvalidate(IRingMasterClientCache cache, IRingMasterRequest req)
        {
            if (cache == null || req == null)
            {
                return;
            }

            switch (req.RequestType)
            {
            case RingMasterRequestType.GetData:
            case RingMasterRequestType.GetChildren:
            case RingMasterRequestType.GetAcl:
            case RingMasterRequestType.Exists:
                return;

            case RingMasterRequestType.Create:
            {
                cache.Invalidate(this.cachePrefix, req.Path);
                cache.Invalidate(this.cachePrefix, PrefixedClientCache.GetParent(req.Path));
                break;
            }

            case RingMasterRequestType.Delete:
            {
                RequestDelete delete = req as RequestDelete;

                if (delete.IsCascade)
                {
                    cache.Wipe(this.cachePrefix);
                }
                else
                {
                    cache.Invalidate(this.cachePrefix, req.Path);
                    cache.Invalidate(this.cachePrefix, PrefixedClientCache.GetParent(req.Path));
                }

                break;
            }

            case RingMasterRequestType.Move:
            {
                RequestMove move = req as RequestMove;

                cache.Invalidate(this.cachePrefix, move.Path);
                cache.Invalidate(this.cachePrefix, PrefixedClientCache.GetParent(move.Path));
                cache.Invalidate(this.cachePrefix, PrefixedClientCache.GetParent(move.PathDst));
                break;
            }

            default:
            {
                cache.Invalidate(this.cachePrefix, req.Path);

                AbstractRingMasterCompoundRequest list = req as AbstractRingMasterCompoundRequest;

                if (list != null && list.Requests != null)
                {
                    foreach (IRingMasterRequest child in list.Requests)
                    {
                        this.CacheInvalidate(cache, child);
                    }
                }

                break;
            }
            }
        }
Example #18
0
        /// <summary>
        /// Serialize a <see cref="IRingMasterRequest"/>
        /// </summary>
        /// <param name="ringMasterRequest">Request to serialize</param>
        private void SerializeRingmasterRequest(IRingMasterRequest ringMasterRequest)
        {
            this.SerializeRequestPreamble(ringMasterRequest);

            switch (ringMasterRequest.RequestType)
            {
            case RingMasterRequestType.Init:
                this.SerializeRequestBody((RequestInit)ringMasterRequest);
                break;

            case RingMasterRequestType.SetAuth:
                this.SerializeRequestSetAuth((RequestSetAuth)ringMasterRequest);
                break;

            case RingMasterRequestType.Create:
                this.SerializeRequestCreate((RequestCreate)ringMasterRequest);
                break;

            case RingMasterRequestType.Multi:
                this.SerializeRequestMulti((RequestMulti)ringMasterRequest);
                break;

            case RingMasterRequestType.Move:
                this.SerializeRequestMove((RequestMove)ringMasterRequest);
                break;

            case RingMasterRequestType.Batch:
                this.SerializeRequestBatch((RequestBatch)ringMasterRequest);
                break;

            case RingMasterRequestType.Delete:
                this.SerializeRequestDelete((RequestDelete)ringMasterRequest);
                break;

            case RingMasterRequestType.Check:
                this.SerializeRequestCheck((RequestCheck)ringMasterRequest);
                break;

            case RingMasterRequestType.Sync:
                // Sync request has no body, so there is nothing to serialize.
                break;

            case RingMasterRequestType.Exists:
                this.SerializeRequestExists((RequestExists)ringMasterRequest);
                break;

            case RingMasterRequestType.GetAcl:
                this.SerializeRequestGetAcl((RequestGetAcl)ringMasterRequest);
                break;

            case RingMasterRequestType.GetData:
                this.SerializeRequestGetData((RequestGetData)ringMasterRequest);
                break;

            case RingMasterRequestType.GetChildren:
                this.SerializeRequestGetChildren((RequestGetChildren)ringMasterRequest);
                break;

            case RingMasterRequestType.SetAcl:
                this.SerializeRequestSetAcl((RequestSetAcl)ringMasterRequest);
                break;

            case RingMasterRequestType.SetData:
                this.SerializeRequestSetData((RequestSetData)ringMasterRequest);
                break;

            case RingMasterRequestType.GetSubtree:
                this.SerializeRequestGetSubtree((RequestGetSubtree)ringMasterRequest);
                break;

            case RingMasterRequestType.None:
            default:
                throw new ArgumentException("unknown type " + ringMasterRequest.GetType());
            }
        }
Example #19
0
        private void ProcessRequest(IRingMasterRequest request, Action<RequestResponse, Exception> onCompletion)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            switch (request.RequestType)
            {
                case RingMasterRequestType.Init:
                    {
                        var initRequest = (RequestInit)request;

                        this.requestHandler = this.onInitSession(initRequest);

                        var initResponse = new RequestResponse
                        {
                            ResultCode = (int)RingMasterException.Code.Ok,
                            Content = new string[] { initRequest.SessionId.ToString(), Guid.NewGuid().ToString() },
                        };

                        this.requestOrdering.Release();

                        RingMasterServerEventSource.Log.ProcessSessionInit(this.Id, initResponse.ResultCode);
                        onCompletion?.Invoke(initResponse, null);
                        return;
                    }

                case RingMasterRequestType.GetData:
                    {
                        var getDataRequest = (RequestGetData)request;
                        getDataRequest.Watcher = this.MakeWatcher(getDataRequest.Watcher);
                        break;
                    }

                case RingMasterRequestType.GetChildren:
                    {
                        var getChildrenRequest = (RequestGetChildren)request;
                        getChildrenRequest.Watcher = this.MakeWatcher(getChildrenRequest.Watcher);
                        break;
                    }

                case RingMasterRequestType.Exists:
                    {
                        var existsRequest = (RequestExists)request;
                        existsRequest.Watcher = this.MakeWatcher(existsRequest.Watcher);
                        break;
                    }
            }

            if (this.server.Redirect != null)
            {
                RedirectSuggested redirect = this.server.Redirect();

                this.requestOrdering.Release();

                RingMasterServerEventSource.Log.RedirectionSuggested(this.Id, redirect?.SuggestedConnectionString);
                onCompletion?.Invoke(
                    new RequestResponse()
                    {
                        ResponsePath = request.Path,
                        ResultCode = (int)RingMasterException.Code.Sessionmoved,
                        Stat = default(Stat),
                        Content = redirect,
                    },
                    null);

                return;
            }

            if (this.requestHandler != null)
            {
                QueuedWorkItemPool.Default.Queue(
                    () =>
                    {
                        // Give a signal that the next request can be started. For read requests in the same session,
                        // they may be processed concurrently. For write requests, they will be ordered by locking.
                        this.requestOrdering.Release();

                        this.requestHandler.RequestOverlapped(request, onCompletion);
                    });
                return;
            }

            throw new InvalidOperationException("Session has not been initialized");
        }
        /// <summary>
        /// Gets the response from the cache.
        /// </summary>
        /// <param name="cache">The cache to use.</param>
        /// <param name="req">The request provided.</param>
        /// <returns>the response if cached, or null if not found</returns>
        private RequestResponse GetCachedResponse(IRingMasterClientCache cache, IRingMasterRequest req)
        {
            if (cache == null || req == null)
            {
                return(null);
            }

            switch (req.RequestType)
            {
            case RingMasterRequestType.GetData:
            {
                IRingMasterClientCacheDataEntry data;

                if (this.cache.TryGetInfo(this.cachePrefix, req.Path, CachedKind.NodeData | CachedKind.NodeStats, out data))
                {
                    RequestResponse response = new RequestResponse()
                    {
                        CallId       = 0,
                        ResponsePath = req.Path,
                        ResultCode   = (int)RingMasterException.Code.Ok,
                        Content      = data.Data,
                        Stat         = data.Stat,
                    };

                    return(response);
                }

                break;
            }

            case RingMasterRequestType.GetChildren:
            {
                IRingMasterClientCacheDataEntry data;

                if (!string.IsNullOrEmpty(((RequestGetChildren)req).RetrievalCondition))
                {
                    break;
                }

                if (this.cache.TryGetInfo(this.cachePrefix, req.Path, CachedKind.NodeChildren | CachedKind.NodeStats, out data))
                {
                    RequestResponse response = new RequestResponse()
                    {
                        CallId       = 0,
                        ResponsePath = req.Path,
                        ResultCode   = (int)RingMasterException.Code.Ok,
                        Content      = data.Children,
                        Stat         = data.Stat,
                    };

                    return(response);
                }

                break;
            }

            case RingMasterRequestType.GetAcl:
            {
                IRingMasterClientCacheDataEntry data;

                if (this.cache.TryGetInfo(this.cachePrefix, req.Path, CachedKind.NodeAcls | CachedKind.NodeStats, out data))
                {
                    RequestResponse response = new RequestResponse()
                    {
                        CallId       = 0,
                        ResponsePath = req.Path,
                        ResultCode   = (int)RingMasterException.Code.Ok,
                        Content      = data.Acls,
                        Stat         = data.Stat,
                    };

                    return(response);
                }

                break;
            }

            case RingMasterRequestType.Exists:
            {
                IRingMasterClientCacheDataEntry data;

                if (this.cache.TryGetInfo(this.cachePrefix, req.Path, CachedKind.NodeStats, out data))
                {
                    RequestResponse response = new RequestResponse()
                    {
                        CallId       = 0,
                        ResponsePath = req.Path,
                        ResultCode   = (int)RingMasterException.Code.Ok,
                        Content      = data.Stat,
                        Stat         = data.Stat,
                    };

                    return(response);
                }

                break;
            }

            default:
            {
                this.CacheInvalidate(cache, req);
                break;
            }
            }

            return(null);
        }
        /// <summary>
        /// Processes the request in regards to the given cache object.
        /// </summary>
        /// <param name="cache">The cache object to use.</param>
        /// <param name="req">The request to process.</param>
        /// <returns><c>a response</c> if the processing was completed, <c>null</c> otherwise.</returns>
        private async Task <RequestResponse> ProcessCacheRequest(IRingMasterClientCache cache, IRingMasterRequest req)
        {
            if (cache != null && req != null)
            {
                RequestResponse cachedResponse = this.GetCachedResponse(cache, req);

                if (cachedResponse != null)
                {
                    return(cachedResponse);
                }

                switch (req.RequestType)
                {
                case RingMasterRequestType.GetData:
                {
                    RequestResponse resp = await this.baseHandler.Request(req);

                    string prefix = this.cachePrefix;

                    if (prefix != null)
                    {
                        cache.SetInfo(prefix, req.Path, CachedKind.NodeData | CachedKind.NodeStats, new PrefixedClientCache.DataEntry()
                            {
                                Data = (byte[])resp.Content, Stat = resp.Stat
                            });
                    }

                    return(resp);
                }

                case RingMasterRequestType.GetChildren:
                {
                    RequestResponse resp = await this.baseHandler.Request(req);

                    string prefix = this.cachePrefix;

                    if (prefix != null)
                    {
                        RequestGetChildren gchil = req as RequestGetChildren;

                        if (string.IsNullOrEmpty(gchil.RetrievalCondition))
                        {
                            cache.SetInfo(prefix, req.Path, CachedKind.NodeChildren | CachedKind.NodeStats, new PrefixedClientCache.DataEntry()
                                {
                                    Children = (IReadOnlyList <string>)resp.Content, Stat = resp.Stat
                                });
                        }
                    }

                    return(resp);
                }

                case RingMasterRequestType.GetAcl:
                {
                    RequestResponse resp = await this.baseHandler.Request(req);

                    string prefix = this.cachePrefix;

                    if (prefix != null)
                    {
                        cache.SetInfo(prefix, req.Path, CachedKind.NodeAcls | CachedKind.NodeStats, new PrefixedClientCache.DataEntry()
                            {
                                Acls = (IReadOnlyList <Acl>)resp.Content, Stat = resp.Stat
                            });
                    }

                    return(resp);
                }

                case RingMasterRequestType.Exists:
                {
                    RequestResponse resp = await this.baseHandler.Request(req);

                    string prefix = this.cachePrefix;

                    if (prefix != null)
                    {
                        cache.SetInfo(prefix, req.Path, CachedKind.NodeStats, new PrefixedClientCache.DataEntry()
                            {
                                Stat = resp.Stat
                            });
                    }

                    return(resp);
                }
                }
            }

            return(await this.baseHandler.Request(req));
        }
Example #22
0
 /// <summary>
 /// Process the given <see cref="IRingMasterRequest"/>
 /// </summary>
 /// <param name="request">Request to send</param>
 /// <returns>A task that resolves to the response sent by the server</returns>
 public Task <RequestResponse> Request(IRingMasterRequest request)
 {
     return(this.requestHandler.Request(request));
 }
Example #23
0
 public void RequestOverlapped(IRingMasterRequest request, Action <RequestResponse, Exception> onCompletion)
 {
     onCompletion?.Invoke(this.Implementation(request), null);
 }
Example #24
0
 public Task <RequestResponse> Request(IRingMasterRequest request)
 {
     return(Task.FromResult(this.Implementation(request)));
 }
Example #25
0
 /// <summary>
 /// Create a new instance of the <see cref="Op"/> class that represents the given request.
 /// </summary>
 /// <param name="request"><see cref="IRingMasterRequest"/> to encapsulate</param>
 /// <returns>An Multi operation that encapsulates the given request</returns>
 public static Op Run(IRingMasterRequest request)
 {
     return(new Op(OpCode.Multi, request));
 }
Example #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Op"/> class with the given <see cref="IRingMasterRequest"/>.
 /// </summary>
 /// <param name="type">Type of the operation</param>
 /// <param name="request">The request to associate with the operation</param>
 private Op(OpCode type, IRingMasterRequest request)
 {
     this.OpType  = type;
     this.Request = request;
 }
Example #27
0
        /// <summary>
        /// Deserialize <see cref="IRingMasterRequest"/>
        /// </summary>
        /// <param name="callid">Id of the call</param>
        /// <param name="ringMasterRequest">The ring master request.</param>
        /// <exception cref="System.ArgumentException">unknown type  + type</exception>
        private void DeserializeRingMasterRequest(ulong callid, out IRingMasterRequest ringMasterRequest)
        {
            RingMasterRequestType type = (RingMasterRequestType)this.binaryReader.ReadUInt16();

            ulong  uid  = this.binaryReader.ReadUInt64();
            string path = this.binaryReader.ReadString();

            ISessionAuth        sessionAuth        = this.DeserializeSessionAuth();
            IOperationOverrides operationOverrides = this.DeserializeOperationOverrides();
            Guid executionQueueId = Guid.Empty;
            int  executionQueueTimeoutMilliseconds = 0;

            if (this.serializationVersionUsed >= SerializationFormatVersions.Version17)
            {
                bool hasExecutionQueueData = this.binaryReader.ReadBoolean();

                if (hasExecutionQueueData)
                {
                    executionQueueId = this.binaryReader.ReadGuid();
                    executionQueueTimeoutMilliseconds = this.binaryReader.ReadInt32();
                }
            }

            ulong timeStreamId = 0;

            if (this.serializationVersionUsed >= SerializationFormatVersions.Version21)
            {
                timeStreamId = this.binaryReader.ReadUInt64();
            }

            AbstractRingMasterRequest request = null;

            switch (type)
            {
            case RingMasterRequestType.Init:
                request = this.DeserializeRequestInit(uid);
                break;

            case RingMasterRequestType.SetAuth:
                request = this.DeserializeRequestSetAuth(uid);
                break;

            case RingMasterRequestType.Create:
                request = this.DeserializeRequestCreate(uid, path);
                break;

            case RingMasterRequestType.Move:
                request = this.DeserializeRequestMove(uid, path);
                break;

            case RingMasterRequestType.Multi:
                request = this.DeserializeRequestMulti(callid, uid);
                break;

            case RingMasterRequestType.Batch:
                request = this.DeserializeRequestBatch(callid, uid);
                break;

            case RingMasterRequestType.Delete:
                request = this.DeserializeRequestDelete(uid, path);
                break;

            case RingMasterRequestType.Check:
                request = this.DeserializeRequestCheck(uid, path);
                break;

            case RingMasterRequestType.Sync:
                request = this.DeserializeRequestSync(uid, path);
                break;

            case RingMasterRequestType.Exists:
                request = this.DeserializeRequestExists(uid, path);
                break;

            case RingMasterRequestType.GetAcl:
                request = this.DeserializeRequestGetAcl(uid, path);
                break;

            case RingMasterRequestType.GetData:
                request = this.DeserializeRequestGetData(uid, path);
                break;

            case RingMasterRequestType.GetChildren:
                request = this.DeserializeRequestGetChildren(uid, path);
                break;

            case RingMasterRequestType.SetData:
                request = this.DeserializeRequestSetData(uid, path);
                break;

            case RingMasterRequestType.SetAcl:
                request = this.DeserializeRequestSetAcl(uid, path);
                break;

            case RingMasterRequestType.GetSubtree:
                request = this.DeserializeRequestGetSubtree(uid, path);
                break;

            case RingMasterRequestType.None:
            default:
                throw new ArgumentException("unknown type " + type);
            }

            if (request != null)
            {
                request.TimeStreamId = timeStreamId;
                request.Auth         = sessionAuth;
                request.Overrides    = operationOverrides;

                request.ExecutionQueueId            = executionQueueId;
                request.ExecutionQueueTimeoutMillis = executionQueueTimeoutMilliseconds;
            }

            ringMasterRequest = request;
        }
Example #28
0
        private RequestResponse ProcessRequest(IRingMasterRequest request, IZooKeeperRequest zkprRequest)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (zkprRequest == null)
            {
                throw new ArgumentNullException(nameof(zkprRequest));
            }

            switch (request.RequestType)
            {
            case RingMasterRequestType.Init:
            {
                var             initRequest  = (Requests.RequestInit)request;
                RequestResponse initResponse = null;

                if (this.requestHandler == null)
                {
                    this.requestHandler = this.onInitSession(initRequest);
                    if (((zkprRequest as ZkprProtocolMessages.CreateSession).SessionId != 0) || (zkprRequest as ZkprProtocolMessages.CreateSession).IsNullPassword == false)
                    {
                        initResponse = new RequestResponse
                        {
                            ResultCode = (int)RingMasterException.Code.Authfailed,
                            Content    = new string[] { "0", string.Empty },
                        };
                    }
                }

                if (initResponse == null)
                {
                    initResponse = (this.requestHandler as CoreRequestHandler).InitResponse;
                }

                ZooKeeperServerEventSource.Log.ProcessSessionInit(this.Id, initResponse.ResultCode);
                return(initResponse);
            }

            case RingMasterRequestType.GetData:
            {
                var getDataRequest = (Requests.RequestGetData)request;
                getDataRequest.Watcher = this.MakeWatcher(getDataRequest.Watcher);
                break;
            }

            case RingMasterRequestType.GetChildren:
            {
                var getChildrenRequest = (Requests.RequestGetChildren)request;
                getChildrenRequest.Watcher = this.MakeWatcher(getChildrenRequest.Watcher);
                break;
            }

            case RingMasterRequestType.Exists:
            {
                var existsRequest = (Requests.RequestExists)request;
                existsRequest.Watcher = this.MakeWatcher(existsRequest.Watcher);
                break;
            }
            }

            if (this.server.Redirect != null)
            {
                RedirectSuggested redirect = this.server.Redirect();

                ZooKeeperServerEventSource.Log.RedirectionSuggested(this.Id, redirect?.SuggestedConnectionString);
                return(new RequestResponse()
                {
                    ResponsePath = request.Path,
                    ResultCode = (int)RingMasterException.Code.Sessionmoved,
                    Stat = default(Stat),
                    Content = redirect,
                });
            }

            if (this.requestHandler != null)
            {
                using (var completed = new AutoResetEvent(false))
                {
                    RequestResponse response = null;
                    this.requestHandler.RequestOverlapped(request, (r, e) =>
                    {
                        response = r;
                        completed.Set();
                    });

                    completed.WaitOne();
                    return(response);
                }
            }

            throw new InvalidOperationException("Session has not been initialized");
        }
Example #29
0
        /// <summary>
        /// Deserialize <see cref="IZooKeeperRequest"/>
        /// </summary>
        /// <param name="xid">the callid</param>
        /// <param name="type">type of the call</param>
        /// <param name="sessionState">The PerSession State</param>
        /// <param name="ringMasterRequest">The ring master request.</param>
        /// <exception cref="System.ArgumentException">unknown type  + type</exception>
        /// <returns>The Zookeeper Request</returns>
        private IZooKeeperRequest DeserializeZooKeeperRequest(int xid, ZooKeeperRequestType type, ZkprPerSessionState sessionState, out IRingMasterRequest ringMasterRequest)
        {
            ringMasterRequest = null;
            switch (type)
            {
            case ZooKeeperRequestType.Notification:     // "0" for Createing a session
                ringMasterRequest = null;
                return(this.DeserializeNotification(xid));

            case ZooKeeperRequestType.CreateSession:
                ZkprProtocolMessages.CreateSession cs = this.DeserializeCreateSession();
                ringMasterRequest            = new RequestInit((ulong)cs.SessionId, cs.IsNullPassword ? string.Empty : cs.Password);
                sessionState.ConnectRecieved = true;
                return(cs);

            case ZooKeeperRequestType.Exists:
                ZkprProtocolMessages.Exists ex = this.DeserializeExists(xid);
                ringMasterRequest = new RequestExists(ex.Path, ex.Watch == false ? null : new Watcher((ulong)xid, WatcherKind.OneUse));
                return(ex);

            case ZooKeeperRequestType.GetChildren:
                ZkprProtocolMessages.GetChildren gc = this.DeserializeGetChildren(xid);
                ringMasterRequest = new RequestGetChildren(gc.Path, gc.Watch == false ? null : new Watcher((ulong)xid, WatcherKind.OneUse), null);
                return(gc);

            case ZooKeeperRequestType.GetChildren2:
                ZkprProtocolMessages.GetChildren2 gc2 = this.DeserializeGetChildren2(xid);
                ringMasterRequest = new RequestGetChildren(gc2.Path, gc2.Watch == false ? null : new Watcher((ulong)xid, WatcherKind.OneUse), null);
                return(gc2);

            case ZooKeeperRequestType.GetData:
                ZkprProtocolMessages.GetData gd = this.DeserializeGetData(xid);
                ringMasterRequest = new RequestGetData(gd.Path, RequestGetData.GetDataOptions.None, gd.Watch == false ? null : new Watcher((ulong)xid, WatcherKind.OneUse));
                return(gd);

            case ZooKeeperRequestType.Create:
                ZkprProtocolMessages.Create cr   = this.DeserializeCreate(xid);
                IReadOnlyList <Acl>         acls = this.TranslateZkprAclListToRMAclList(cr.Acls);
                CreateMode cm = this.TranslateZkprCreatFlagsToRmCreateMode(cr.Flags);
                ringMasterRequest = new RequestCreate(cr.Path, cr.Data, acls, cm);
                return(cr);

            case ZooKeeperRequestType.Create2:
                ZkprProtocolMessages.Create2 cr2   = this.DeserializeCreate2(xid);
                IReadOnlyList <Acl>          acls2 = this.TranslateZkprAclListToRMAclList(cr2.Acls);
                CreateMode cm2 = this.TranslateZkprCreatFlagsToRmCreateMode(cr2.Flags);
                ringMasterRequest = new RequestCreate(cr2.Path, cr2.Data, acls2, cm2);
                return(cr2);

            case ZooKeeperRequestType.SetData:
                ZkprProtocolMessages.SetData sd = this.DeserializeSetData(xid);
                ringMasterRequest = new RequestSetData(sd.Path, sd.Data, sd.Version);
                return(sd);

            case ZooKeeperRequestType.Delete:
                ZkprProtocolMessages.Delete dl = this.DeserializeDelete(xid);
                ringMasterRequest = new RequestDelete(dl.Path, dl.Version, false);
                return(dl);

            case ZooKeeperRequestType.Ping:
                ringMasterRequest = null;
                return(this.DeserializePing(xid));

            case ZooKeeperRequestType.CloseSession:
                ringMasterRequest            = null;
                sessionState.ConnectRecieved = false;     // Renegotiate the CreateSession
                return(this.DeserializeCloseSession(xid));

            case ZooKeeperRequestType.GetACL:
                ZkprProtocolMessages.GetACL ga = this.DeserializeGetACL(xid);
                ringMasterRequest = new RequestGetAcl(ga.Path, null);
                return(ga);

            case ZooKeeperRequestType.SetACL:
                ZkprProtocolMessages.SetACL sa      = this.DeserializeSetACL(xid);
                IReadOnlyList <Acl>         sa_acls = this.TranslateZkprAclListToRMAclList(sa.Acls);
                ringMasterRequest = new RequestSetAcl(sa.Path, sa_acls, sa.Version);
                return(sa);

            case ZooKeeperRequestType.Multi:
                ZkprProtocolMessages.Multi mu    = this.DeserializeMulti(xid);
                IReadOnlyList <Op>         rmOps = this.TranslateZkprOpsListToRmOpsList(mu.Ops);
                ringMasterRequest = new RequestMulti(rmOps, false);
                return(mu);

            case ZooKeeperRequestType.Auth:
                ZkprProtocolMessages.Auth au = this.DeserializeAuth(xid);
                ringMasterRequest = new RequestSetAuth(au.RmAuthId);
                return(au);

            case ZooKeeperRequestType.Check:
            case ZooKeeperRequestType.Sync:
            case ZooKeeperRequestType.Reconfig:
            case ZooKeeperRequestType.SetWatches:
            case ZooKeeperRequestType.RemoveWatches:
            case ZooKeeperRequestType.CreateContainer:
            case ZooKeeperRequestType.DeleteContainer:
            case ZooKeeperRequestType.Sasl:
            case ZooKeeperRequestType.Error:
            default:
                break;
            }

            return(null);
        }