/// <summary> /// Check the user name and throw exception if user name does not match /// </summary> /// <param name="brokerQueue">indicating the broker queue</param> /// <param name="userName">indicating the user name</param> private static void ThrowIfUserNameDoesNotMatch(BrokerQueue brokerQueue, string userName) { if (!string.Equals(userName, brokerQueue.UserName, StringComparison.OrdinalIgnoreCase)) { throw new BrokerQueueException((int)BrokerQueueErrorCode.E_BQ_USER_NOT_MATCH, String.Format("the user name is not the user who create the queue. username: {0}, ownername={1}", userName, brokerQueue.UserName)); } }
internal void RemoveBrokerQueue(BrokerQueue queue) { if (queue != null) { bool containsQueue; lock (this.needDispatchQueueClientIdTable) { containsQueue = this.needDispatchQueueClientIdTable.ContainsKey(queue.ClientId); } if (containsQueue) { try { lock (this.needDispatchQueueClientIdTable) { this.needDispatchQueueClientIdTable.Remove(queue.ClientId); } } catch (Exception e) { BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .RemoveBrokerQueue: Remove the broker queue with the client id, {0}, from the client table raised exception, {1}", queue.ClientId, e); } } lock (this.waitBrokerQueuesForPeekRequests) { this.waitBrokerQueuesForPeekRequests.Remove(queue); } } }
/// <summary> /// Initializes a new instance of the ExceptionEventArgs class for the broker queue. /// </summary> /// <param name="exception">the exception.</param> /// <param name="queue">the client id.</param> internal ExceptionEventArgs(Exception exception, BrokerQueue queue) : base(queue) { if (exception == null) { throw new ArgumentNullException("exception"); } this.exceptionField = exception; }
private bool HandleResponseWithoutAsyncToken(BrokerQueue queue, BrokerQueueItem requestItem) { bool isHandled = false; Guid persistId = requestItem.PersistId; object asyncToken = requestItem.PersistAsyncToken.AsyncToken; int dispatcherNumber = requestItem.DispatchNumber; if (asyncToken != null && this.responsesWithoutAsyncTokenTable.Count > 0) { bool needPutResponse = false; DispatcherAsyncTokenItem asyncTokenItem = null; try { lock (this.responsesWithoutAsyncTokenTable) { this.responsesWithoutAsyncTokenTable.TryGetValue(persistId, out asyncTokenItem); } if (asyncTokenItem != null) { lock (this.responsesWithoutAsyncTokenTable) { this.responsesWithoutAsyncTokenTable.Remove(persistId); } needPutResponse = true; lock (this.requestsAsyncTokenTable) { this.requestsAsyncTokenTable.Remove(persistId); } } } catch (Exception e) { if (needPutResponse) { BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PrefetchRequestCallback: fail to remove the async token from the table, Exception: {0}", e); } else { BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PrefetchRequestCallback: can not get the response async token, Exception: {0}", e); } } if (needPutResponse && dispatcherNumber == 0) { asyncTokenItem.PersistAsyncToken.AsyncToken = asyncToken; queue.PutResponseAsync(asyncTokenItem.Message, requestItem); isHandled = true; } } return(isHandled); }
/// <summary> /// trigger the prefetch operation. /// </summary> private void TriggerPrefetch() { this.needPrefetch = true; while (this.needPrefetch && this.waitBrokerQueuesForPeekRequests.Count > 0) { BrokerQueue queue = null; lock (this.waitBrokerQueuesForPeekRequests) { if (this.waitBrokerQueuesForPeekRequests.Count > 0) { queue = this.waitBrokerQueuesForPeekRequests[this.waitBrokerQueuesForPeekRequests.Count - 1]; this.waitBrokerQueuesForPeekRequests.Remove(queue); } } if (queue != null) { ThreadPool.QueueUserWorkItem(this.waitCallbackToGetRequestAsync, queue); } } }
public BrokerQueue GetPersistQueueByClient(string clientId, string userName, out bool isNewCreate) { BrokerTracing.TraceInfo($"[GetPersistQueueByClient] username:{userName}, sessionid:{this.sessionId}, client:{clientId}"); isNewCreate = false; if (string.IsNullOrEmpty(clientId)) { clientId = BrokerQueueFactory.defaultClientId; } BrokerQueue brokerQueue = null; lock (this.clientBrokerQueueDic) { this.clientBrokerQueueDic.TryGetValue(clientId, out brokerQueue); } if (brokerQueue == null) { lock (this.thisLockObj) { lock (this.clientBrokerQueueDic) { this.clientBrokerQueueDic.TryGetValue(clientId, out brokerQueue); } if (brokerQueue == null) { ISessionPersist sessionPersist = null; if (string.IsNullOrEmpty(this.persistName)) { sessionPersist = new MemoryPersist(userName, this.sessionId, clientId); brokerQueue = new BrokerPersistQueue( this.brokerQueueDispatcher, this.persistName, this.sessionId, clientId, sessionPersist, 1, // no request cache // no request cache 1, // no response cache // no response cache 0, // no timeout // no timeout false, // no in-memory cache this.sharedData, this); this.brokerQueueDispatcher.AddBrokerQueue(brokerQueue, null); } else { ParamCheckUtility.ThrowIfNull(this.sharedData.BrokerInfo.AzureStorageConnectionString, "StorageConnectString"); sessionPersist = new AzureQueuePersist(userName, this.sessionId, clientId, this.sharedData.BrokerInfo.AzureStorageConnectionString); isNewCreate = sessionPersist.IsNewCreated; brokerQueue = new BrokerPersistQueue( this.brokerQueueDispatcher, this.persistName, this.sessionId, clientId, sessionPersist, BrokerQueueConstants.DefaultThresholdForRequestPersist, BrokerQueueConstants.DefaultThresholdForResponsePersist, BrokerQueueConstants.DefaultMessagesInCacheTimeout, isNewCreate, // need in-memory quick cache for newly-created durable queue // need in-memory quick cache for newly-created durable queue this.sharedData, this); // // For an existing durable queue, if EndOfMessage is not received, or there are requests waiting to be processed, // then schedule the broker queue for dispatching; // for an newly created durable queue, it will be added to brokerQueueDispatcher when BrokerQueuePersist.Flush // is called (with quick cache filled), so no need to call AddBrokerQueue here (bug #21453) // if (!isNewCreate && (!brokerQueue.EOMReceived || sessionPersist.RequestsCount > 0)) { this.brokerQueueDispatcher.AddBrokerQueue(brokerQueue, null); } } lock (this.clientBrokerQueueDic) { this.clientBrokerQueueDic.Add(clientId, brokerQueue); } } } } // Bug 6313: Check the user name ThrowIfUserNameDoesNotMatch(brokerQueue, userName); return(brokerQueue); }
/// <summary> /// Callback to get request /// </summary> /// <param name="state">indicating the state</param> private void WaitCallbackToGetRequestAsync(object state) { BrokerQueue queue = (BrokerQueue)state; queue.GetRequestAsync(this.PrefetchRequestCallback, queue); }
private void PrefetchRequestCallback(BrokerQueueItem queueItem, object state) { try { #if DEBUG BrokerTracing.TraceVerbose("[BrokerQueueDispatcher] .PrefetchRequestCallback: received one request. request id={0}", GetMessageId(queueItem)); #endif bool isCached = false; bool shouldDisposeQueueItem = false; Guid persistId = Guid.Empty; object asyncToken = null; int dispatcherNumber = 0; if (queueItem != null) { dispatcherNumber = queueItem.DispatchNumber; persistId = queueItem.PersistId; asyncToken = queueItem.PersistAsyncToken.AsyncToken; if (this.requestsAsyncTokenTable.Count > 0 && dispatcherNumber == 0) { // if the request is already in the cache or dispatched. lock (this.requestsAsyncTokenTable) { if (this.requestsAsyncTokenTable.ContainsKey(persistId)) { try { DispatcherAsyncTokenItem asyncTokenItem = this.requestsAsyncTokenTable[persistId]; if (asyncTokenItem.AsyncToken == null) { asyncTokenItem.AsyncToken = asyncToken; } // the duplicated request item is of no use after retrieving out its async token. so we should dispose it if possible shouldDisposeQueueItem = true; } catch (Exception e) { // the request in the table is removed by another thread. BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PrefetchRequestCallback: The request async token is removed from the table, Exception: {0}", e); } isCached = true; } } } if (!isCached) { bool needQueue = true; // if there are pending requests callback, then dispatch the request through the pending requests callback. if (this.requestCallbackQueue.Count > 0) { try { BrokerQueueCallbackItem requestCallback; if (this.requestCallbackQueue.TryDequeue(out requestCallback)) { this.RegisterReemit(queueItem); requestCallback.Callback(queueItem, requestCallback.CallbackState); needQueue = false; #if DEBUG BrokerTracing.TraceVerbose("[BrokerQueueDispatcher] .PrefetchRequestCallback: Invoked callback for request."); #endif } else { BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PrefetchRequestCallback: The requests callback queue is empty."); } } catch (InvalidOperationException e) { // the request callback queue is drained by other threads. BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PrefetchRequestCallback: The requests callback queue is empty, Exception: {0}", e); } catch (Exception e) { // request callback raise exception. BrokerTracing.TraceWarning("[BrokerQueueDispatcher] .PrefetchRequestCallback: The requests callback raise exception, Exception: {0}", e); } } if (needQueue) { // if no pending requests callback, then append the request to the cache queue. this.requestCacheQueue.Enqueue(queueItem); if (this.requestCacheQueue.Count >= this.GetCacheContainerSize()) { this.needPrefetch = false; } else { this.needPrefetch = true; } } } } BrokerQueue brokerQueue = (BrokerQueue)state; // try to get the next request. if (this.needPrefetch) { // hop to another thread to avoid recursive stack overflow for memory queue that will call the callback at the same thread. ThreadPool.QueueUserWorkItem(this.GetRequestThreadProc, state); } else { lock (this.waitBrokerQueuesForPeekRequests) { this.waitBrokerQueuesForPeekRequests.Add(brokerQueue); } if (this.requestCacheQueue.Count < this.sharedData.DispatcherCount + this.watermarkerForTriggerPrefetch) { this.TriggerPrefetch(); } } // drain the pending requests callback. this.HandlePendingRequestCallback(); // check if the response already come back. if (!this.HandleResponseWithoutAsyncToken(brokerQueue, queueItem) && shouldDisposeQueueItem) { // if its response is not back, and we've decided that the request queue item is of no use, dispose it. queueItem.Dispose(); } } catch (Exception e) { BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PrefetchRequestCallback: raised unknown exception: {0}", e); } }
internal void AddBrokerQueue(BrokerQueue queue, IEnumerable <BrokerQueueItem> requests) { if (queue != null) { if (requests != null) { foreach (BrokerQueueItem request in requests) { if (request != null) { if (request.PersistAsyncToken.AsyncToken == null) { lock (this.requestsAsyncTokenTable) { if (!this.requestsAsyncTokenTable.ContainsKey(request.PersistId)) { this.requestsAsyncTokenTable.Add(request.PersistId, new DispatcherAsyncTokenItem()); } else { BrokerTracing.TraceError("[BrokerQueueDispatcher] .AddBrokerQueue: There are duplicate persist id, {0}", request.PersistId); } } } this.requestCacheQueue.Enqueue(request); } } } bool containsQueue; lock (this.needDispatchQueueClientIdTable) { containsQueue = this.needDispatchQueueClientIdTable.ContainsKey(queue.ClientId); } if (!containsQueue) { bool needDispatch = true; try { lock (this.needDispatchQueueClientIdTable) { this.needDispatchQueueClientIdTable.Add(queue.ClientId, null); } } catch (ArgumentException e) { needDispatch = false; // the key already exists in the table. BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .AddBrokerQueue: the broker queue with client id, {0}, already exists, Exception: {1}", queue.ClientId, e); } catch (Exception e) { BrokerTracing.TraceWarning("[BrokerQueueDispatcher] .AddBrokerQueue: add a broker queue with client id, {0}, to the client table raised exception, Exception: {1}", queue.ClientId, e); } if (needDispatch) { if (this.needPrefetch) { queue.GetRequestAsync(this.PrefetchRequestCallback, queue); } else { lock (this.waitBrokerQueuesForPeekRequests) { this.waitBrokerQueuesForPeekRequests.Add(queue); } } } } } }
/// <summary> /// Initializes a new instance of the BrokerQueueEventArgs class. /// </summary> /// <param name="queue">the broker queue.</param> public BrokerQueueEventArgs(BrokerQueue queue) { this.queueField = queue; }