/// <summary> /// Queues a wait for a get message. Allows us to send only one request and notify /// multiple threads of a GET response /// </summary> /// <returns>True there was already a get request out and there is no need to send another, false if not</returns> private bool QueueGetWaiter(ClientRequestMsg request, ResponseWaiter waiter) { bool requestExisted = false; if (request.Type == ClientRequestMsg.RequestType.GET) { lock (_getResponseWaiters) { string uuid = request.GetUuid(); //if someone is already waiting for a response, //make a note, we dont have to send out a request if (_getResponseWaiters.ContainsKey(uuid)) { requestExisted = true; } else { _getResponseWaiters.Add(request.GetUuid(), new List <ResponseWaiter>()); } //insert us as a waiter _getResponseWaiters[uuid].Add(waiter); } } return(requestExisted); }
public string GetAssetIds(string prefix) { //build the request ClientRequestMsg request = new ClientRequestMsg(ClientRequestMsg.RequestType.STORED_ASSET_IDS_GET, prefix); //send request and wait for response try { ResponseWaiter responseWaiter = this.SendRequest(request, null); responseWaiter.waitEvent.WaitOne(); //we got a response //is there an error? this.CheckThrowError(responseWaiter); //ErrorMessage takes the status string out of the data field return(responseWaiter.response.ErrorMessage); } catch (SocketException e) { //a socket exception means we need to signal all waiters this.HandleSendError(e); throw new AssetServerError(e.Message, e); } }
/// <summary> /// Attempts to retrieve the given asset from the server synchronously /// </summary> /// <param name="uuid">The asset UUID as a string</param> /// <returns>Asset</returns> public Asset GetAsset(string uuid) { uuid = Util.FixUuid(uuid); //build the request ClientRequestMsg request = new ClientRequestMsg(ClientRequestMsg.RequestType.GET, uuid); //send request and wait for response try { ResponseWaiter responseWaiter = this.SendRequest(request, null); responseWaiter.waitEvent.WaitOne(); //we got a response //is there an error? this.CheckThrowError(responseWaiter); //no error, return the asset return(responseWaiter.asset); } catch (SocketException e) { //a socket exception means we need to signal all waiters this.HandleSendError(e); throw new AssetServerError(e.Message, e); } }
public Task <IResponse> WaitForResponse(uint requestId) { if (!_responseWaiters.TryGetValue(requestId, out var responseWaiter)) { responseWaiter = new ResponseWaiter(requestId, this); _responseWaiters[requestId] = responseWaiter; } return(responseWaiter.Wait()); }
private Asset TryConstructAsset(ServerResponseMsg message, ResponseWaiter topWaiter) { if (topWaiter.type == ClientRequestMsg.RequestType.GET) { if (message.Status == ServerResponseMsg.Result.FOUND) { return(new Asset(message.Data)); } } return(null); }
/// <summary> /// Checks the server response for errors and throws an exception if /// there is a problem /// </summary> /// <param name="serverResponseMsg">The response from the server</param> private void CheckThrowError(ResponseWaiter responseWaiter) { if (responseWaiter.error != null) { throw new AssetServerError(responseWaiter.error.Message, responseWaiter.error); } AssetServerError err = DetermineErrorFromStatus(responseWaiter.response); if (err != null) { throw err; } }
/// <summary> /// Calls all asynchronus callbacks for GET waiters /// </summary> /// <param name="uuid">The asset UUID as a string</param> /// <returns>Asset</returns> private void HandleAsyncResponse(ResponseWaiter waiter) { if (waiter.callBack != null) { if (waiter.response.Status == ServerResponseMsg.Result.FOUND) { waiter.callBack(waiter.asset, null); } else { waiter.callBack(null, this.DetermineErrorFromStatus(waiter.response)); } } }
public async Task <T> SendAndWaitAsync <T>(string methodName, MidgeParameters parameters, int timeout = 100000) { Guid commandToken = Guid.NewGuid(); var request = CreateRequest(methodName, parameters, commandToken); ResponseWaiter waiter = new ResponseWaiter(commandToken); _waiters.TryAdd(commandToken, waiter); await RestClient.SendMessageAsync(request.ToString()); await waiter.WaitAsync(timeout); var result = waiter.Result.ToObject <T>(_jsonSerializer); return(result); }
/// <summary> /// Attempts to retrieve the given asset from the server /// </summary> /// <param name="uuid">The asset UUID as a string</param> /// <returns>Asset</returns> public void PutAsset(Asset asset) { //build the request ClientRequestMsg request = new ClientRequestMsg(ClientRequestMsg.RequestType.PUT, asset.Uuid, asset.Serialize().data); //send request and wait for response try { ResponseWaiter responseWaiter = this.SendRequest(request, null); responseWaiter.waitEvent.WaitOne(); //we got a response //is there an error? this.CheckThrowError(responseWaiter); } catch (SocketException e) { //a socket exception means we need to signal all waiters this.HandleSendError(e); throw new AssetServerError(e.Message, e); } }
/// <summary> /// Sends the given request to the server /// </summary> /// <param name="request">The request to send</param> private ResponseWaiter SendRequest(ClientRequestMsg request, AsyncAssetCallback callBack) { ResponseWaiter waiter = new ResponseWaiter(); waiter.callBack = callBack; waiter.type = request.Type; if (!this.QueueGetWaiter(request, waiter)) { lock (_sendSync) { //we need to enqueue the right waiter here in the right order lock (_waitingRequests) { _waitingRequests.Enqueue(waiter); } request.Send(_conn); } } return(waiter); }
/// <summary> /// Attempts to retrieve the given asset from the server synchronously /// </summary> /// <param name="uuid">The asset UUID as a string</param> /// <returns>Asset</returns> public void MaintPurgeLocals() { string uuid = ZERO_UUID; //build the request ClientRequestMsg request = new ClientRequestMsg(ClientRequestMsg.RequestType.MAINT_PURGELOCALS, uuid); //send request and wait for response try { ResponseWaiter responseWaiter = this.SendRequest(request, null); responseWaiter.waitEvent.WaitOne(); //we got a response //is there an error? this.CheckThrowError(responseWaiter); } catch (SocketException e) { //a socket exception means we need to signal all waiters this.HandleSendError(e); throw new AssetServerError(e.Message, e); } }
private Asset TryConstructAsset(ServerResponseMsg message, ResponseWaiter topWaiter) { if (topWaiter.type == ClientRequestMsg.RequestType.GET) { if (message.Status == ServerResponseMsg.Result.FOUND) { return new Asset(message.Data); } } return null; }
/// <summary> /// Sends the given request to the server /// </summary> /// <param name="request">The request to send</param> private ResponseWaiter SendRequest(ClientRequestMsg request, AsyncAssetCallback callBack) { ResponseWaiter waiter = new ResponseWaiter(); waiter.callBack = callBack; waiter.type = request.Type; if (!this.QueueGetWaiter(request, waiter)) { lock (_sendSync) { //we need to enqueue the right waiter here in the right order lock (_waitingRequests) { _waitingRequests.Enqueue(waiter); } request.Send(_conn); } } return waiter; }
/// <summary> /// Queues a wait for a get message. Allows us to send only one request and notify /// multiple threads of a GET response /// </summary> /// <returns>True there was already a get request out and there is no need to send another, false if not</returns> private bool QueueGetWaiter(ClientRequestMsg request, ResponseWaiter waiter) { bool requestExisted = false; if (request.Type == ClientRequestMsg.RequestType.GET) { lock (_getResponseWaiters) { string uuid = request.GetUuid(); //if someone is already waiting for a response, //make a note, we dont have to send out a request if (_getResponseWaiters.ContainsKey(uuid)) { requestExisted = true; } else { _getResponseWaiters.Add(request.GetUuid(), new List<ResponseWaiter>()); } //insert us as a waiter _getResponseWaiters[uuid].Add(waiter); } } return requestExisted; }