public IHttpActionResult PutActiveRequest(int id, ActiveRequest activeRequest) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } if (id != activeRequest.ID) { return(BadRequest()); } db.Entry(activeRequest).State = EntityState.Modified; try { db.SaveChanges(); } catch (DbUpdateConcurrencyException) { if (!ActiveRequestExists(id)) { return(NotFound()); } else { throw; } } return(StatusCode(HttpStatusCode.NoContent)); }
public IHttpActionResult PostActiveRequest(ActiveRequest activeRequest) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } db.ActiveRequests.Add(activeRequest); try { db.SaveChanges(); } catch (DbUpdateException) { if (ActiveRequestExists(activeRequest.ID)) { return(Conflict()); } else { throw; } } return(CreatedAtRoute("DefaultApi", new { id = activeRequest.ID }, activeRequest)); }
public void ModifyActiveRequest(ActiveRequest newActiveRequest) { var activeRequest = data.ActiveRequests.Where(x => x.Id == newActiveRequest.Id).FirstOrDefault(); if (activeRequest != null) { activeRequest = newActiveRequest; data.SaveChanges(); } }
public IHttpActionResult GetActiveRequest(int id) { ActiveRequest activeRequest = db.ActiveRequests.Find(id); if (activeRequest == null) { return(NotFound()); } return(Ok(activeRequest)); }
public IHttpActionResult DeleteActiveRequest(int id) { ActiveRequest activeRequest = db.ActiveRequests.Find(id); if (activeRequest == null) { return(NotFound()); } db.ActiveRequests.Remove(activeRequest); db.SaveChanges(); return(Ok(activeRequest)); }
private Task <SMPPMessage> _submitMessage(SMPPMessage message) { ActiveRequest sendingMessage = _activeRequests.AddMessage(message); sendingMessage.SendTask = _sendMessage(message); sendingMessage.SendTask.ContinueWith((task) => { if (task.Status != TaskStatus.RanToCompletion) { _activeRequests.CompleteError(sendingMessage, task.Exception); } }); return(sendingMessage.TaskCompletion.Task); }
public void Active([FromBody] ActiveRequest activeRequest) { using (var client = new WebClient()) { try { var json = Newtonsoft.Json.JsonConvert.SerializeObject(activeRequest); var dataByte = System.Text.Encoding.UTF8.GetBytes(json); client.Headers[HttpRequestHeader.ContentType] = "application/json"; dataByte = client.UploadData(this.svconfig.admindbip + "/api/OnSite/Active/", "POST", dataByte); } catch (Exception e) { throw new Exception(e.Message); } } }
private bool FindActiveRequest(EasyRequest easy, out IntPtr gcHandlePtr, out ActiveRequest activeRequest) { // We maintain an IntPtr=>ActiveRequest mapping, which makes it cheap to look-up by GCHandle ptr but // expensive to look up by EasyRequest. If we find this becoming a bottleneck, we can add a reverse // map that stores the other direction as well. foreach (KeyValuePair<IntPtr, ActiveRequest> pair in _activeOperations) { if (pair.Value.Easy == easy) { gcHandlePtr = pair.Key; activeRequest = pair.Value; return true; } } gcHandlePtr = IntPtr.Zero; activeRequest = default(ActiveRequest); return false; }
/// <summary> /// 获取公众号或企业号的jsapi_tickets /// </summary> /// <returns>返回json数据</returns> public string GetJsApiTicketsJson() { string sJsApiTicketsJson = string.Empty; string sUrl = string.Empty; if (this._wxPlatType == WxPlatFormTypeEnum.QY) { sUrl = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket"; sJsApiTicketsJson = ActiveRequest.SendRequest(this.GetEntityByAction(sUrl, "", null, "get")); } else if (this._wxPlatType == WxPlatFormTypeEnum.GZ) { sUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; Dictionary <string, string> dictParams = new Dictionary <string, string>() { { "type", "jsapi" } }; sJsApiTicketsJson = ActiveRequest.SendRequest(this.GetEntityByAction(sUrl, "", dictParams, "get")); } return(sJsApiTicketsJson); }
public override bool GetPiece(int index, int begin, byte[] piece) { bool isFind = false; int pieceLength = piece.Length; bool doIHave; ActiveRequest newRequest = new ActiveRequest(index, begin, pieceLength); foreach (ActiveRequest request in requests) { if (request.Equals(newRequest)) { requests.Remove(request); isFind = true; break; } } if (!isFind) { return(false); } last = DateTime.Now; measure.UpdateRate(pieceLength); if (downloader.MeasureFunction != null) { downloader.MeasureFunction(pieceLength); } downloader.DownloadMeasure.UpdateRate(pieceLength); downloader.StorageWrapper.PieceCameIn(index, begin, piece); doIHave = downloader.StorageWrapper.DoIHave(index); if (doIHave) { downloader.PiecePicker.Complete(index); } this.FixDownload(); return(doIHave); }
public void RemoveActiveRequest(ActiveRequest request) { data.ActiveRequests.Remove(request); data.SaveChanges(); }
private void WorkerLoop() { Debug.Assert(!Monitor.IsEntered(_incomingRequests), "No locks should be held while invoking Process"); Debug.Assert(_runningWorker != null && _runningWorker.Id == Task.CurrentId, "This is the worker, so it must be running"); Debug.Assert(_wakeupRequestedPipeFd != null && !_wakeupRequestedPipeFd.IsInvalid, "Should have a valid pipe for wake ups"); // Create the multi handle to use for this round of processing. This one handle will be used // to service all easy requests currently available and all those that come in while // we're processing other requests. Once the work quiesces and there are no more requests // to process, this multi handle will be released as the worker goes away. The next // time a request arrives and a new worker is spun up, a new multi handle will be created. SafeCurlMultiHandle multiHandle = CreateAndConfigureMultiHandle(); // Clear our active operations table. This should already be clear, either because // all previous operations completed without unexpected exception, or in the case of an // unexpected exception we should have cleaned up gracefully anyway. But just in case... Debug.Assert(_activeOperations.Count == 0, "We shouldn't have any active operations when starting processing."); _activeOperations.Clear(); bool endingSuccessfully = false; try { // Continue processing as long as there are any active operations while (true) { // First handle any requests in the incoming requests queue. while (true) { IncomingRequest request; lock (_incomingRequests) { if (_incomingRequests.Count == 0) break; request = _incomingRequests.Dequeue(); } HandleIncomingRequest(multiHandle, request); } // If we have no active operations, we're done. if (_activeOperations.Count == 0) { endingSuccessfully = true; return; } // We have one or more active operations. Run any work that needs to be run. ThrowIfCURLMError(Interop.Http.MultiPerform(multiHandle)); // Complete and remove any requests that have finished being processed. CURLMSG message; IntPtr easyHandle; CURLcode result; while (Interop.Http.MultiInfoRead(multiHandle, out message, out easyHandle, out result)) { Debug.Assert(message == CURLMSG.CURLMSG_DONE, "CURLMSG_DONE is supposed to be the only message type"); if (message == CURLMSG.CURLMSG_DONE) { IntPtr gcHandlePtr; CURLcode getInfoResult = Interop.Http.EasyGetInfoPointer(easyHandle, CURLINFO.CURLINFO_PRIVATE, out gcHandlePtr); Debug.Assert(getInfoResult == CURLcode.CURLE_OK, "Failed to get info on a completing easy handle"); if (getInfoResult == CURLcode.CURLE_OK) { ActiveRequest completedOperation; bool gotActiveOp = _activeOperations.TryGetValue(gcHandlePtr, out completedOperation); Debug.Assert(gotActiveOp, "Expected to find GCHandle ptr in active operations table"); if (gotActiveOp) { DeactivateActiveRequest(multiHandle, completedOperation.Easy, gcHandlePtr, completedOperation.CancellationRegistration); FinishRequest(completedOperation.Easy, result); } } } } // Wait for more things to do. bool isWakeupRequestedPipeActive; bool isTimeout; ThrowIfCURLMError(Interop.Http.MultiWait(multiHandle, _wakeupRequestedPipeFd, out isWakeupRequestedPipeActive, out isTimeout)); if (isWakeupRequestedPipeActive) { // We woke up (at least in part) because a wake-up was requested. // Read the data out of the pipe to clear it. Debug.Assert(!isTimeout, "should not have timed out if isExtraFileDescriptorActive"); VerboseTrace("curl_multi_wait wake-up notification"); ReadFromWakeupPipeWhenKnownToContainData(); } VerboseTraceIf(isTimeout, "curl_multi_wait timeout"); // PERF NOTE: curl_multi_wait uses poll (assuming it's available), which is O(N) in terms of the number of fds // being waited on. If this ends up being a scalability bottleneck, we can look into using the curl_multi_socket_* // APIs, which would let us switch to using epoll by being notified when sockets file descriptors are added or // removed and configuring the epoll context with EPOLL_CTL_ADD/DEL, which at the expense of a lot of additional // complexity would let us turn the O(N) operation into an O(1) operation. The additional complexity would come // not only in the form of additional callbacks and managing the socket collection, but also in the form of timer // management, which is necessary when using the curl_multi_socket_* APIs and which we avoid by using just // curl_multi_wait/perform. } } finally { // If we got an unexpected exception, something very bad happened. We may have some // operations that we initiated but that weren't completed. Make sure to clean up any // such operations, failing them and releasing their resources. if (_activeOperations.Count > 0) { Debug.Assert(!endingSuccessfully, "We should only have remaining operations if we got an unexpected exception"); foreach (KeyValuePair<IntPtr, ActiveRequest> pair in _activeOperations) { ActiveRequest failingOperation = pair.Value; IntPtr failingOperationGcHandle = pair.Key; DeactivateActiveRequest(multiHandle, failingOperation.Easy, failingOperationGcHandle, failingOperation.CancellationRegistration); // Complete the operation's task and clean up any of its resources failingOperation.Easy.FailRequest(CreateHttpRequestException()); failingOperation.Easy.Cleanup(); // no active processing remains, so cleanup } // Clear the table. _activeOperations.Clear(); } // Finally, dispose of the multi handle. multiHandle.Dispose(); } }
public void Active([FromBody] ActiveRequest activeRequest) { repoOnSite.Active(activeRequest.ActiveThruDateTime, activeRequest.centerId); }
/// <summary> /// 查询部门 /// </summary> /// <param name="listJson">传递的json数据</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string List(string listJson, Dictionary <string, string> dictParam) { return(ActiveRequest.SendRequest(this.GetEntityByAction(this._strDepartmentUrl + DepartmentAction.list.ToString(), listJson, dictParam, "get"))); }
/// <summary> /// 删除部门 /// </summary> /// <param name="deleteJson">传递的json数据</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string Delete(string deleteJson, Dictionary <string, string> dictParam) { return(ActiveRequest.SendRequest(this.GetEntityByAction(this._strDepartmentUrl + DepartmentAction.delete.ToString(), deleteJson, dictParam, "get"))); }
public JsonResult SendRequest(string accessToken, string startingAddressMainText, string startingAddressSecondaryText, string startingAddressLocationLat, string startingAddressLocationLng, string finishAddressMainText, string finishAddressSecondaryText, string finishAddressLocationLat, string finishAddressLocationLng) { if (HttpContext.Request.RequestType == "POST") { var newAccessToken = _accessTokenService.GenerateAccessToken(accessToken); if (newAccessToken == null) { return(Json(new { status = "INVALID ACCESSTOKEN" })); } var userId = _accessTokenService.GetUserId(newAccessToken); if (userId == null) { return(Json(new { status = "ERR1", accessToken = newAccessToken })); } var client = _clientService.GetAll().Where(x => x.UserId == userId).FirstOrDefault(); if (client == null) { return(Json(new { status = "ERR2", accessToken = newAccessToken })); } var anotherRequest = _requestService.GetClientRequest().Where(c => c.Client.Id == client.Id).FirstOrDefault(); if (anotherRequest != null) { return(Json(new { status = "ERR3", accessToken = accessToken })); } var requestInfo = new RequestInfo() { CreatedBy = CreatedBy.Client, CreatedDateTime = DateTime.Now, CreatorUserId = userId, LastModificationDateTime = DateTime.Now, RequestStatus = RequestStatusEnum.NoCarChosen, StartingAddress = startingAddressMainText + " " + startingAddressSecondaryText, FinishAddress = finishAddressMainText + " " + finishAddressSecondaryText, StartingLocation = new Models.Models.Location() { Latitude = double.Parse(startingAddressLocationLat), Longitude = double.Parse(startingAddressLocationLng) }, FinishLocation = new Models.Models.Location() { Latitude = double.Parse(finishAddressLocationLat), Longitude = double.Parse(finishAddressLocationLng) } }; _requestService.AddRequestInfo(requestInfo); var activeRequest = new ActiveRequest(); activeRequest.Request = requestInfo; activeRequest.DateTimeChosenCar = DateTime.Now; var appropriateCar = _carService.AppropriateCar(new Models.Models.Location() { Latitude = double.Parse(startingAddressLocationLat), Longitude = double.Parse(startingAddressLocationLng) }); if (appropriateCar != null) { activeRequest.AppropriateCar = appropriateCar; requestInfo.RequestStatus = RequestStatusEnum.NotTaken; _requestService.ModifyRequestInfo(requestInfo); } _requestService.AddActiveRequest(activeRequest); var clientRequest = new ClientRequest() { Client = client, Request = requestInfo }; _requestService.AddClientRequest(clientRequest); return(Json(new { accessToken = newAccessToken, status = "OK" })); } return(Json(new { })); }
/// <summary> /// 批量删除成员 /// </summary> /// <param name="batchDeleteJson">json字符串</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string BatchDelete(string batchDeleteJson) { string strUrl = this._strDepartmentUrl + "user/" + UserAction.batchdelete.ToString(); return(ActiveRequest.SendRequest(this.GetEntityByAction(strUrl, batchDeleteJson))); }
/// <summary> /// 更新成员 /// </summary> /// <param name="updateJson">json字符串</param> /// <returns></returns> public string Update(string updateJson) { string strUrl = this._strDepartmentUrl + "user/" + UserAction.update.ToString(); return(ActiveRequest.SendRequest(this.GetEntityByAction(strUrl, updateJson))); }
private void _initializeComponents() { // Parent Vbox VBox ParentContent = new VBox(); // Request URL in frame Frame RequestUrl = new Frame() { Label = Director.Properties.Resources.RequestInfoBox, Padding = 10 }; VBox RequestUrlContent = new VBox(); RequestUrlContent.PackStart(new Label(Director.Properties.Resources.RequestUrl)); TextEntry RequestUrlField = new TextEntry() { Text = ActiveRequest.Url }; RequestUrlContent.PackStart(RequestUrlField, expand: true, fill: true); RequestUrlContent.PackStart(InvalidRequestUrl, vpos: WidgetPlacement.End); // Method RequestUrlContent.PackStart(new Label(Director.Properties.Resources.RequestMethod)); RequestHttpMethod = new ComboBox(); RequestHttpMethod.Items.Add(1, "GET"); RequestHttpMethod.Items.Add(2, "HEAD"); RequestHttpMethod.Items.Add(3, "POST"); RequestHttpMethod.Items.Add(4, "PUT"); RequestHttpMethod.Items.Add(5, "PATCH"); RequestHttpMethod.Items.Add(6, "DELETE"); RequestHttpMethod.Items.Add(7, "OPTIONS"); try { RequestHttpMethod.SelectedText = ActiveRequest.HTTP_METHOD; } catch { RequestHttpMethod.SelectedText = ActiveRequest.HTTP_METHOD = "GET"; } RequestUrlContent.PackStart(RequestHttpMethod); RequestHttpMethod.SelectionChanged += delegate { ActiveRequest.HTTP_METHOD = RequestHttpMethod.SelectedText; if (RequestSettings.CurrentTab.Child is OverviewWidget) { ((OverviewWidget)RequestSettings.CurrentTab.Child).RefreshOverview(); } }; // Wait in seconds RequestUrlContent.PackStart(new Label(Director.Properties.Resources.WaitPreviousRequest)); TextEntry WaitTime = new TextEntry() { Text = ActiveRequest.WaitAfterPreviousRequest + "" }; RequestUrlContent.PackStart(WaitTime, expand: true, fill: true); RequestUrlContent.PackStart(InvalidTime, vpos: WidgetPlacement.End); WaitTime.Changed += delegate { try { ActiveRequest.WaitAfterPreviousRequest = int.Parse(WaitTime.Text); if (ActiveRequest.WaitAfterPreviousRequest < 0) { ActiveRequest.WaitAfterPreviousRequest = 0; WaitTime.Text = "0"; throw new InvalidCastException(); } InvalidTime.Visible = false; } catch { InvalidTime.Visible = true; } }; // Repeat count RequestUrlContent.PackStart(new Label(Director.Properties.Resources.NumberOfCallRepeats)); TextEntry RepeatCounter = new TextEntry() { Text = ActiveRequest.RepeatsCounter + "" }; RequestUrlContent.PackStart(RepeatCounter, expand: true, fill: true); RequestUrlContent.PackStart(InvalidRepeatCount, vpos: WidgetPlacement.End); RepeatCounter.Changed += delegate { try { ActiveRequest.RepeatsCounter = int.Parse(RepeatCounter.Text); if (ActiveRequest.RepeatsCounter < 0) { ActiveRequest.RepeatsCounter = 0; RepeatCounter.Text = "0"; throw new InvalidCastException(); } InvalidRepeatCount.Visible = false; } catch { InvalidRepeatCount.Visible = true; } }; // Time between repeaters RequestUrlContent.PackStart(new Label(Director.Properties.Resources.TimeBetweenRequests)); TextEntry RequestTimeouts = new TextEntry() { Text = ActiveRequest.RepeatsTimeout + "" }; RequestUrlContent.PackStart(RequestTimeouts, expand: true, fill: true); RequestUrlContent.PackStart(InvalidBetweenRepeatTime, vpos: WidgetPlacement.End); RequestTimeouts.Changed += delegate { try { ActiveRequest.RepeatsTimeout = int.Parse(RequestTimeouts.Text); if (ActiveRequest.RepeatsTimeout < 0) { ActiveRequest.RepeatsTimeout = 0; RequestTimeouts.Text = "0"; throw new InvalidCastException(); } InvalidBetweenRepeatTime.Visible = false; } catch { InvalidBetweenRepeatTime.Visible = true; } }; // Set content RequestUrl.Content = RequestUrlContent; ParentContent.PackStart(RequestUrl, expand: false, fill: true); // Change request URL field RequestUrlField.Changed += delegate { try { ActiveRequest.SetUrl(RequestUrlField.Text); InvalidRequestUrl.Hide(); } catch { InvalidRequestUrl.Show(); } if (RequestSettings.CurrentTab.Child is OverviewWidget) { ((OverviewWidget)RequestSettings.CurrentTab.Child).RefreshOverview(); } }; // Create Notebook RequestSettings = new Notebook() { ExpandHorizontal = true, ExpandVertical = true, TabOrientation = NotebookTabOrientation.Top }; _initializeTabs(); RequestSettings.CurrentTabChanged += delegate { if (RequestSettings.CurrentTab.Child is OverviewWidget) { ((OverviewWidget)RequestSettings.CurrentTab.Child).RefreshOverview(); } }; ParentContent.PackStart(RequestSettings, true, true); // Close btn Button ConfirmButton = new Button(Image.FromResource(DirectorImages.OK_ICON), Director.Properties.Resources.Confirm) { WidthRequest = 150, ExpandHorizontal = false, ExpandVertical = false }; ConfirmButton.Clicked += delegate { Close(); }; ParentContent.PackStart(ConfirmButton, expand: false, hpos: WidgetPlacement.End); // Set content Content = ParentContent; }
private void WorkerLoop() { Debug.Assert(!Monitor.IsEntered(_incomingRequests), "No locks should be held while invoking Process"); Debug.Assert(_runningWorker != null && _runningWorker.Id == Task.CurrentId, "This is the worker, so it must be running"); Debug.Assert(_wakeupRequestedPipeFd != 0, "Should have a valid pipe for wake ups"); // Create the multi handle to use for this round of processing. This one handle will be used // to service all easy requests currently available and all those that come in while // we're processing other requests. Once the work quiesces and there are no more requests // to process, this multi handle will be released as the worker goes away. The next // time a request arrives and a new worker is spun up, a new multi handle will be created. SafeCurlMultiHandle multiHandle = Interop.libcurl.curl_multi_init(); if (multiHandle.IsInvalid) { throw CreateHttpRequestException(); } // Clear our active operations table. This should already be clear, either because // all previous operations completed without unexpected exception, or in the case of an // unexpected exception we should have cleaned up gracefully anyway. But just in case... Debug.Assert(_activeOperations.Count == 0, "We shouldn't have any active operations when starting processing."); _activeOperations.Clear(); bool endingSuccessfully = false; try { // Continue processing as long as there are any active operations while (true) { // First handle any requests in the incoming requests queue. while (true) { IncomingRequest request; lock (_incomingRequests) { if (_incomingRequests.Count == 0) { break; } request = _incomingRequests.Dequeue(); } HandleIncomingRequest(multiHandle, request); } // If we have no active operations, we're done. if (_activeOperations.Count == 0) { endingSuccessfully = true; return; } // We have one or more active operations. Run any work that needs to be run. int running_handles; ThrowIfCURLMError(Interop.libcurl.curl_multi_perform(multiHandle, out running_handles)); // Complete and remove any requests that have finished being processed. int pendingMessages; IntPtr messagePtr; while ((messagePtr = Interop.libcurl.curl_multi_info_read(multiHandle, out pendingMessages)) != IntPtr.Zero) { Interop.libcurl.CURLMsg message = Marshal.PtrToStructure <Interop.libcurl.CURLMsg>(messagePtr); Debug.Assert(message.msg == Interop.libcurl.CURLMSG.CURLMSG_DONE, "CURLMSG_DONE is supposed to be the only message type"); IntPtr gcHandlePtr; ActiveRequest completedOperation; if (message.msg == Interop.libcurl.CURLMSG.CURLMSG_DONE) { int getInfoResult = Interop.libcurl.curl_easy_getinfo(message.easy_handle, CURLINFO.CURLINFO_PRIVATE, out gcHandlePtr); Debug.Assert(getInfoResult == CURLcode.CURLE_OK, "Failed to get info on a completing easy handle"); if (getInfoResult == CURLcode.CURLE_OK) { bool gotActiveOp = _activeOperations.TryGetValue(gcHandlePtr, out completedOperation); Debug.Assert(gotActiveOp, "Expected to find GCHandle ptr in active operations table"); if (gotActiveOp) { DeactivateActiveRequest(multiHandle, completedOperation.Easy, gcHandlePtr, completedOperation.CancellationRegistration); FinishRequest(completedOperation.Easy, message.result); } } } } // Wait for more things to do. Even with our cancellation mechanism, we specify a timeout so that // just in case something goes wrong we can recover gracefully. This timeout is relatively long. // Note, though, that libcurl has its own internal timeout, which can be requested separately // via curl_multi_timeout, but which is used implicitly by curl_multi_wait if it's shorter // than the value we provide. const int FailsafeTimeoutMilliseconds = 1000; int numFds; unsafe { Interop.libcurl.curl_waitfd extraFds = new Interop.libcurl.curl_waitfd { fd = _wakeupRequestedPipeFd, events = Interop.libcurl.CURL_WAIT_POLLIN, revents = 0 }; ThrowIfCURLMError(Interop.libcurl.curl_multi_wait(multiHandle, &extraFds, 1, FailsafeTimeoutMilliseconds, out numFds)); if ((extraFds.revents & Interop.libcurl.CURL_WAIT_POLLIN) != 0) { // We woke up (at least in part) because a wake-up was requested. // Read the data out of the pipe to clear it. Debug.Assert(numFds >= 1, "numFds should have been at least one, as the extraFd was set"); VerboseTrace("curl_multi_wait wake-up notification"); ReadFromWakeupPipeWhenKnownToContainData(); } VerboseTraceIf(numFds == 0, "curl_multi_wait timeout"); } // PERF NOTE: curl_multi_wait uses poll (assuming it's available), which is O(N) in terms of the number of fds // being waited on. If this ends up being a scalability bottleneck, we can look into using the curl_multi_socket_* // APIs, which would let us switch to using epoll by being notified when sockets file descriptors are added or // removed and configuring the epoll context with EPOLL_CTL_ADD/DEL, which at the expense of a lot of additional // complexity would let us turn the O(N) operation into an O(1) operation. The additional complexity would come // not only in the form of additional callbacks and managing the socket collection, but also in the form of timer // management, which is necessary when using the curl_multi_socket_* APIs and which we avoid by using just // curl_multi_wait/perform. } } finally { // If we got an unexpected exception, something very bad happened. We may have some // operations that we initiated but that weren't completed. Make sure to clean up any // such operations, failing them and releasing their resources. if (_activeOperations.Count > 0) { Debug.Assert(!endingSuccessfully, "We should only have remaining operations if we got an unexpected exception"); foreach (KeyValuePair <IntPtr, ActiveRequest> pair in _activeOperations) { ActiveRequest failingOperation = pair.Value; IntPtr failingOperationGcHandle = pair.Key; DeactivateActiveRequest(multiHandle, failingOperation.Easy, failingOperationGcHandle, failingOperation.CancellationRegistration); // Complete the operation's task and clean up any of its resources failingOperation.Easy.FailRequest(CreateHttpRequestException()); failingOperation.Easy.Cleanup(); // no active processing remains, so cleanup } // Clear the table. _activeOperations.Clear(); } // Finally, dispose of the multi handle. multiHandle.Dispose(); } }
/// <summary> /// Add an Active Request /// </summary> /// <param name="request"></param> public void AddActiveRequest(ActiveRequest request) { data.ActiveRequests.Add(request); data.SaveChanges(); }
/// <summary> /// Refresh overview summary. /// </summary> public void RefreshOverview() { ActiveRequest.CreateOverview(Overview, Font.WithSize(17).WithWeight(FontWeight.Bold)); }
private void Process() { Debug.Assert(!Monitor.IsEntered(_incomingRequests), "No locks should be held while invoking Process"); Debug.Assert(_workerRunning, "This is the worker, so it must be running"); Debug.Assert(_wakeupRequestedPipeFd != 0, "Should have a valid pipe for wake ups"); // Create the multi handle to use for this round of processing. This one handle will be used // to service all easy requests currently available and all those that come in while // we're processing other requests. Once the work quiesces and there are no more requests // to process, this multi handle will be released as the worker goes away. The next // time a request arrives and a new worker is spun up, a new multi handle will be created. SafeCurlMultiHandle multiHandle = Interop.libcurl.curl_multi_init(); if (multiHandle.IsInvalid) { throw CreateHttpRequestException(); } // Clear our active operations table. This should already be clear, either because // all previous operations completed without unexpected exception, or in the case of an // unexpected exception we should have cleaned up gracefully anyway. But just in case... Debug.Assert(_activeOperations.Count == 0, "We shouldn't have any active operations when starting processing."); _activeOperations.Clear(); bool endingSuccessfully = false; try { // Continue processing as long as there are any active operations while (true) { // Activate any new operations that were submitted, and cancel any operations // that should no longer be around. lock (_incomingRequests) { while (_incomingRequests.Count > 0) { EasyRequest easy = _incomingRequests.Dequeue(); Debug.Assert(easy._associatedMultiAgent == null || easy._associatedMultiAgent == this, "An incoming request must only be associated with no or this agent"); if (easy._associatedMultiAgent == null) { // Handle new request ActivateNewRequest(multiHandle, easy); } else { // Handle cancellation request. Debug.Assert(easy.CancellationToken.IsCancellationRequested, "_associatedMultiAgent should only be non-null if cancellation was requested"); IntPtr gcHandlePtr; ActiveRequest activeRequest; if (FindActiveRequest(easy, out gcHandlePtr, out activeRequest)) { DeactivateActiveRequest(multiHandle, easy, gcHandlePtr, activeRequest.CancellationRegistration); easy.FailRequest(new OperationCanceledException(easy.CancellationToken)); easy.Cleanup(); // no active processing remains, so we can cleanup } else { Debug.Assert(easy.Task.IsCompleted, "We should only not be able to find the request if it was already completed."); } } } } // If we have no active operations, we're done. if (_activeOperations.Count == 0) { endingSuccessfully = true; return; } // We have one or more active operaitons. Run any work that needs to be run. int running_handles; ThrowIfCURLMError(Interop.libcurl.curl_multi_perform(multiHandle, out running_handles)); // Complete and remove any requests that have finished being processed. int pendingMessages; IntPtr messagePtr; while ((messagePtr = Interop.libcurl.curl_multi_info_read(multiHandle, out pendingMessages)) != IntPtr.Zero) { Interop.libcurl.CURLMsg message = Marshal.PtrToStructure <Interop.libcurl.CURLMsg>(messagePtr); IntPtr gcHandlePtr; ActiveRequest completedOperation; if (message.msg == Interop.libcurl.CURLMSG.CURLMSG_DONE && Interop.libcurl.curl_easy_getinfo(message.easy_handle, CURLINFO.CURLINFO_PRIVATE, out gcHandlePtr) == CURLcode.CURLE_OK && _activeOperations.TryGetValue(gcHandlePtr, out completedOperation)) { DeactivateActiveRequest(multiHandle, completedOperation.Easy, gcHandlePtr, completedOperation.CancellationRegistration); FinishRequest(completedOperation.Easy, message.result); } } // Wait for more things to do. Even with our cancellation mechanism, we specify a timeout so that // just in case something goes wrong we can recover gracefully. This timeout is relatively long. // Note, though, that libcurl has its own internal timeout, which can be requested separately // via curl_multi_timeout, but which is used implicitly by curl_multi_wait if it's shorter // than the value we provide. const int FailsafeTimeoutMilliseconds = 1000; int numFds; unsafe { Interop.libcurl.curl_waitfd extraFds = new Interop.libcurl.curl_waitfd { fd = _wakeupRequestedPipeFd, events = Interop.libcurl.CURL_WAIT_POLLIN, revents = 0 }; ThrowIfCURLMError(Interop.libcurl.curl_multi_wait(multiHandle, &extraFds, 1, FailsafeTimeoutMilliseconds, out numFds)); if ((extraFds.revents & Interop.libcurl.CURL_WAIT_POLLIN) != 0) { // We woke up (at least in part) because a wake-up was requested. Read the data out of the pipe // to clear it. It's possible but unlikely that there will be tons of extra data in the pipe, // more than we end up reading out here (it's unlikely because we only write a byte to the pipe when // transitioning from 0 to 1 incoming request or when cancellation is requested, and that would // need to happen many times in a single iteration). In that unlikely case, we'll simply loop // around again as normal and end up waking up spuriously from the next curl_multi_wait. For now, // this is preferable to making additional syscalls to poll and read from the pipe). const int ClearBufferSize = 4096; // some sufficiently large size to clear the pipe in any normal case byte * clearBuf = stackalloc byte[ClearBufferSize]; while (Interop.CheckIo((long)Interop.libc.read(_wakeupRequestedPipeFd, clearBuf, (IntPtr)ClearBufferSize))) { ; } } } // PERF NOTE: curl_multi_wait uses poll (assuming it's available), which is O(N) in terms of the number of fds // being waited on. If this ends up being a scalability bottleneck, we can look into using the curl_multi_socket_* // APIs, which would let us switch to using epoll by being notified when sockets file descriptors are added or // removed and configuring the epoll context with EPOLL_CTL_ADD/DEL, which at the expense of a lot of additional // complexity would let us turn the O(N) operation into an O(1) operation. The additional complexity would come // not only in the form of additional callbacks and managing the socket collection, but also in the form of timer // management, which is necessary when using the curl_multi_socket_* APIs and which we avoid by using just // curl_multi_wait/perform. } } finally { // If we got an unexpected exception, something very bad happened. We may have some // operations that we initiated but that weren't completed. Make sure to clean up any // such operations, failing them and releasing their resources. if (_activeOperations.Count > 0) { Debug.Assert(!endingSuccessfully, "We should only have remaining operations if we got an unexpected exception"); foreach (KeyValuePair <IntPtr, ActiveRequest> pair in _activeOperations) { ActiveRequest failingOperation = pair.Value; IntPtr failingOperationGcHandle = pair.Key; DeactivateActiveRequest(multiHandle, failingOperation.Easy, failingOperationGcHandle, failingOperation.CancellationRegistration); // Complete the operation's task and clean up any of its resources failingOperation.Easy.FailRequest(CreateHttpRequestException()); failingOperation.Easy.Cleanup(); // no active processing remains, so cleanup } // Clear the table. _activeOperations.Clear(); } // Finally, dispose of the multi handle. multiHandle.Dispose(); } }
/// <summary> /// 邀请成员关注 /// </summary> /// <param name="sendJson">json字符串</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string Send(string sendJson) { string strUrl = this._strDepartmentUrl + "invite/" + UserAction.send.ToString(); return(ActiveRequest.SendRequest(this.GetEntityByAction(strUrl, sendJson))); }
/// <summary> /// 创建菜单 /// </summary> /// <param name="strJson">传递的json数据</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns>返回json结果</returns> public string Create(string strJson, Dictionary <string, string> dictParam) { return(ActiveRequest.SendRequest(this.GetEntityByAction(this._strMenuUrl + MenuAction.create.ToString(), strJson, dictParam))); }
/// <summary> /// 删除成员 /// </summary> /// <param name="deleteJson">json字符串</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string Delete(string deleteJson, Dictionary <string, string> dictParam) { string strUrl = this._strDepartmentUrl + "user/" + UserAction.delete.ToString(); return(ActiveRequest.SendRequest(this.GetEntityByAction(strUrl, deleteJson, dictParam, "get"))); }
/// <summary> /// 获取菜单列表(全部菜单) /// </summary> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string Get(Dictionary <string, string> dictParam) { string strUrl = this._strMenuUrl + MenuAction.get.ToString(); return(ActiveRequest.SendRequest(this.GetEntityByAction(strUrl, "", dictParam, "get"))); }
/// <summary> /// 获取部门成员 /// </summary> /// <param name="simpleListJson">json字符串</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string SimpleList(string simpleListJson, Dictionary <string, string> dictParam) { string strUrl = this._strDepartmentUrl + "user/" + UserAction.simplelist.ToString(); return(ActiveRequest.SendRequest(this.GetEntityByAction(strUrl, simpleListJson, dictParam, "get"))); }
/// <summary> /// 创建部门 /// </summary> /// <param name="createJson">json字符串</param> /// <param name="dictParam">url上的除access_token参数</param> /// <returns></returns> public string Create(string createJson, Dictionary <string, string> dictParam) { return(ActiveRequest.SendRequest(this.GetEntityByAction(this._strDepartmentUrl + DepartmentAction.create.ToString(), createJson, dictParam))); }
/// <summary> /// 更新部门 /// </summary> /// <param name="UpdateJson">json字符串</param> /// <returns></returns> public string Update(string UpdateJson) { return(ActiveRequest.SendRequest(this.GetEntityByAction(this._strDepartmentUrl + DepartmentAction.update.ToString(), UpdateJson))); }