private IEnumerable <cFetchCacheItemsGroup> ZFetchCacheItemsGroups(cMessageHandleList pMessageHandles, cMessageCacheItems pItems) { Dictionary <cMessageCacheItems, cFetchCacheItemsGroup> lGroups = new Dictionary <cMessageCacheItems, cFetchCacheItemsGroup>(); foreach (var lMessageHandle in pMessageHandles) { cMessageCacheItems lItems; if (lMessageHandle.Expunged) { lItems = cMessageCacheItems.Empty; // none to get } else { lItems = lMessageHandle.Missing(pItems); // might also be none to get } cFetchCacheItemsGroup lGroup; if (!lGroups.TryGetValue(lItems, out lGroup)) { lGroup = new cFetchCacheItemsGroup(lItems); lGroups.Add(lItems, lGroup); } if (lMessageHandle.UID == null) { lGroup.MSNHandleCount++; } lGroup.MessageHandles.Add(lMessageHandle); } return(lGroups.Values); }
private void ZExists(int pMessageCount, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSelectedMailboxCache), nameof(ZExists), pMessageCount); if (pMessageCount < mItems.Count) { throw new cUnexpectedServerActionException(0, "count should only go up", lContext); } int lToAdd = pMessageCount - mItems.Count; cMessageHandleList lMessageHandles = new cMessageHandleList(); for (int i = 0; i < lToAdd; i++) { cItem lItem = new cItem(this, mCacheSequence++); mItems.Add(lItem); lMessageHandles.Add(lItem); } mUIDNextUnknownCount += lToAdd; mUnseenUnknownCount += lToAdd; mSynchroniser.InvokeMailboxMessageDelivery(mMailboxCacheItem, lMessageHandles, lContext); ZSetMailboxStatus(lContext); }
internal static cMessageHandleList FromMessages(IEnumerable <cMessage> pMessages) { if (pMessages == null) { throw new ArgumentNullException(nameof(pMessages)); } object lMessageCache = null; cMessageHandleList lMessageHandles = new cMessageHandleList(); foreach (var lMessage in pMessages) { if (lMessage == null) { throw new ArgumentOutOfRangeException(nameof(pMessages), "contains nulls"); } if (lMessageCache == null) { lMessageCache = lMessage.MessageHandle.MessageCache; } else if (!ReferenceEquals(lMessage.MessageHandle.MessageCache, lMessageCache)) { throw new ArgumentOutOfRangeException(nameof(pMessages), "contains mixed message caches"); } lMessageHandles.Add(lMessage.MessageHandle); } return(new cMessageHandleList(lMessageHandles.Distinct())); }
public async Task FetchCacheItemsAsync(cMethodControl pMC, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cProgress pProgress, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(FetchCacheItemsAsync), pMC, pMessageHandles, pItems); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandles == null) { throw new ArgumentNullException(nameof(pMessageHandles)); } if (pItems == null) { throw new ArgumentNullException(nameof(pItems)); } if (pProgress == null) { throw new ArgumentNullException(nameof(pProgress)); } mMailboxCache.CheckInSelectedMailbox(pMessageHandles); // to be repeated inside the select lock // split the handles into groups based on what attributes need to be retrieved, for each group do the retrieval foreach (var lGroup in ZFetchCacheItemsGroups(pMessageHandles, pItems)) { await ZFetchCacheItemsAsync(pMC, lGroup, pProgress, lContext).ConfigureAwait(false); } }
public cMessageHandleList SetUnseenCount(int pMessageCount, cUIntList pMSNs, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSelectedMailboxCache), nameof(SetUnseenCount), pMSNs); // the message count is required because messages can be delivered during the search, after the search results are calculated // it should be the message count that existed when the command was submitted // corrollary: fetches may arrive during the search that set the flags after the results were calculated // - that is why this code only changes the unseen == null entries // (I don't have to worry about expunges, as they are not allowed during a search command) int lMessageCount = pMessageCount; cMessageHandleList lMessageHandles = new cMessageHandleList(); bool lSetMailboxStatus = false; foreach (var lMSN in pMSNs) { int lItemIndex = (int)lMSN - 1; if (lItemIndex >= lMessageCount) { lMessageCount = lItemIndex + 1; } var lItem = mItems[lItemIndex]; if (lItem.Unseen == null) { lItem.Unseen = true; mUnseenCount++; mUnseenUnknownCount--; lSetMailboxStatus = true; } lMessageHandles.Add(lItem); } if (mUnseenUnknownCount > 0) { for (int i = 0; i < lMessageCount; i++) { var lItem = mItems[i]; if (lItem.Unseen == null) { lItem.Unseen = false; mUnseenUnknownCount--; lSetMailboxStatus = true; } } } if (lSetMailboxStatus) { ZSetMailboxStatus(lContext); } return(lMessageHandles); }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSetUnseenCountCommandHook), nameof(CommandCompleted), pResult); if (pResult.ResultType == eCommandResultType.ok && mMSNs != null) { MessageHandles = mSelectedMailbox.SetUnseenCount(mMessageCount, new cUIntList(mMSNs.Distinct()), lContext); } }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSearchCommandHook), nameof(CommandCompleted), pResult); if (pResult.ResultType != eCommandResultType.ok || mMSNs == null) { return; } MessageHandles = new cMessageHandleList(mMSNs.Distinct().Select(lMSN => mSelectedMailbox.GetHandle(lMSN))); }
internal static cMessageHandleList FromMessageHandle(iMessageHandle pMessageHandle) { if (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } var lResult = new cMessageHandleList(); lResult.Add(pMessageHandle); return(lResult); }
private List <cMessage> ZMessagesFlatMessageList(cMessageHandleList pMessageHandles, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMessagesFlatMessageList), pMessageHandles); var lResult = new List <cMessage>(pMessageHandles.Count); foreach (var lMessageHandle in pMessageHandles) { lResult.Add(new cMessage(this, lMessageHandle)); } return(lResult); }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cCommandHookSearchExtended), nameof(CommandCompleted), pResult); if (pResult.ResultType != eCommandResultType.ok || mSequenceSets == null) { return; } if (!cUIntList.TryConstruct(mSequenceSets, mSelectedMailbox.MessageCache.Count, !mSort, out var lMSNs)) { return; } MessageHandles = new cMessageHandleList(lMSNs.Select(lMSN => mSelectedMailbox.GetHandle(lMSN))); }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSetUnseenCountExtendedCommandHook), nameof(CommandCompleted), pResult); if (pResult.ResultType != eCommandResultType.ok || mSequenceSets == null) { return; } if (!cUIntList.TryConstruct(mSequenceSets, mSelectedMailbox.MessageCache.Count, true, out var lMSNs)) { return; } MessageHandles = mSelectedMailbox.SetUnseenCount(mMessageCount, lMSNs, lContext); }
private async Task ZFetchCacheItemsAsync(cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZFetchCacheItemsAsync), pMessageHandles, pItems); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandles == null) { throw new ArgumentNullException(nameof(pMessageHandles)); } if (pItems == null) { throw new ArgumentNullException(nameof(pItems)); } if (pMessageHandles.Count == 0) { return; } if (pItems.IsEmpty) { return; } if (pConfiguration == null) { using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); var lProgress = new cProgress(); await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); } } else { var lMC = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken); var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); } }
public void InvokeMailboxMessageDelivery(iMailboxHandle pMailboxHandle, cMessageHandleList pMessageHandles, cTrace.cContext pParentContext) { if (MailboxMessageDelivery == null) { return; // pre-check for efficiency only } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeMailboxMessageDelivery), pMailboxHandle, pMessageHandles); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new cMailboxMessageDeliveryEventArgs(pMailboxHandle, pMessageHandles), lContext); // NOTE the event is fired by parallel code in the ZInvokeEvents routine: when adding an event you must put code there also }
public cSelectedMailbox CheckInSelectedMailbox(cMessageHandleList pMessageHandles) { if (pMessageHandles == null) { throw new ArgumentNullException(nameof(pMessageHandles)); } if (pMessageHandles.Count == 0) { throw new ArgumentOutOfRangeException(nameof(pMessageHandles)); } if (mSelectedMailbox == null || !ReferenceEquals(pMessageHandles[0].MessageCache, mSelectedMailbox.MessageCache)) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.MailboxNotSelected); } return(mSelectedMailbox); }
public override void CommandCompleted(cCommandResult pResult, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSortCommandHook), nameof(CommandCompleted), pResult); if (pResult.ResultType != eCommandResultType.ok || mMSNs == null) { return; } cMessageHandleList lMessageHandles = new cMessageHandleList(); foreach (var lMSN in mMSNs) { lMessageHandles.Add(mSelectedMailbox.GetHandle(lMSN)); } MessageHandles = lMessageHandles; }
public Task <cCopyFeedback> CopyAsync(cMethodControl pMC, cMessageHandleList pSourceMessageHandles, iMailboxHandle pDestinationMailboxHandle, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CopyAsync), pMC, pSourceMessageHandles, pDestinationMailboxHandle); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pSourceMessageHandles == null) { throw new ArgumentNullException(nameof(pSourceMessageHandles)); } if (pDestinationMailboxHandle == null) { throw new ArgumentNullException(nameof(pDestinationMailboxHandle)); } if (pSourceMessageHandles.Count == 0) { throw new ArgumentOutOfRangeException(nameof(pSourceMessageHandles)); } cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pSourceMessageHandles); // to be repeated inside the select lock var lDestinationItem = mMailboxCache.CheckHandle(pDestinationMailboxHandle); if (pSourceMessageHandles.TrueForAll(h => h.UID != null)) { var lMessageHandle = pSourceMessageHandles.Find(h => h.Expunged); if (lMessageHandle != null) { throw new cMessageExpungedException(lMessageHandle); } return(ZUIDCopyAsync(pMC, lSelectedMailbox.MailboxHandle, pSourceMessageHandles[0].UID.UIDValidity, new cUIntList(from h in pSourceMessageHandles select h.UID.UID), lDestinationItem, lContext)); } else { return(ZCopyAsync(pMC, pSourceMessageHandles, lDestinationItem, lContext)); } }
internal cStoreFeedback(IEnumerable <cMessage> pMessages, eStoreOperation pOperation, cStorableFlags pFlags) { if (pMessages == null) { throw new ArgumentNullException(nameof(pMessages)); } if (pFlags == null) { throw new ArgumentNullException(nameof(pFlags)); } object lMessageCache = null; cMessageHandleList lMessageHandles = new cMessageHandleList(); foreach (var lMessage in pMessages) { if (lMessage == null) { throw new ArgumentOutOfRangeException(nameof(pMessages), "contains nulls"); } var lMessageHandle = lMessage.MessageHandle; if (lMessageCache == null) { lMessageCache = lMessageHandle.MessageCache; } else if (!ReferenceEquals(lMessageHandle.MessageCache, lMessageCache)) { throw new ArgumentOutOfRangeException(nameof(pMessages), "contains mixed message caches"); } lMessageHandles.Add(lMessageHandle); } mItems = new List <cStoreFeedbackItem>(from lMessageHandle in lMessageHandles.Distinct() select new cStoreFeedbackItem(lMessageHandle)); mOperation = pOperation; mFlags = pFlags; }
private async Task <cCopyFeedback> ZCopyAsync(cMessageHandleList pSourceMessageHandles, iMailboxHandle pDestinationMailboxHandle, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZCopyAsync), pSourceMessageHandles, pDestinationMailboxHandle); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pSourceMessageHandles == null) { throw new ArgumentNullException(nameof(pSourceMessageHandles)); } if (pDestinationMailboxHandle == null) { throw new ArgumentNullException(nameof(pDestinationMailboxHandle)); } if (pSourceMessageHandles.Count == 0) { return(null); } using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); return(await lSession.CopyAsync(lMC, pSourceMessageHandles, pDestinationMailboxHandle, lContext).ConfigureAwait(false)); } }
private async Task <cCopyFeedback> ZCopyAsync(cMethodControl pMC, cMessageHandleList pSourceMessageHandles, cMailboxCacheItem pDestinationItem, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZCopyAsync), pMC, pSourceMessageHandles, pDestinationItem); using (var lBuilder = new cCommandDetailsBuilder()) { lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pSourceMessageHandles); lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe) lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe // uidvalidity must be captured before the handles are resolved var lUIDValidity = lSelectedMailbox.MessageCache.UIDValidity; lBuilder.AddUIDValidity(lUIDValidity); // resolve the handles to MSNs cUIntList lMSNs = new cUIntList(); foreach (var lMessageHandle in pSourceMessageHandles) { var lMSN = lSelectedMailbox.GetMSN(lMessageHandle); if (lMSN == 0) { if (lMessageHandle.Expunged) { throw new cMessageExpungedException(lMessageHandle); } else { throw new ArgumentOutOfRangeException(nameof(pSourceMessageHandles)); } } lMSNs.Add(lMSN); } // build the command lBuilder.Add(kCopyCommandPart, new cTextCommandPart(cSequenceSet.FromUInts(lMSNs)), cCommandPart.Space, pDestinationItem.MailboxNameCommandPart); // add the hook var lHook = new cCommandHookCopy(lUIDValidity); lBuilder.Add(lHook); // submit the command var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false); if (lResult.ResultType == eCommandResultType.ok) { lContext.TraceInformation("copy success"); return(lHook.Feedback); } if (lResult.ResultType == eCommandResultType.no) { throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext); } throw new cProtocolErrorException(lResult, 0, lContext); } }
private async Task ZFetchCacheItemsAsync(cMethodControl pMC, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchCacheItemsAsync), pMC, pMessageHandles, pItems); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandles == null) { throw new ArgumentNullException(nameof(pMessageHandles)); } if (pItems == null) { throw new ArgumentNullException(nameof(pItems)); } if (pMessageHandles.Count == 0) { throw new ArgumentOutOfRangeException(nameof(pMessageHandles)); } if (pItems.IsEmpty) { throw new ArgumentOutOfRangeException(nameof(pItems)); } using (var lBuilder = new cCommandDetailsBuilder()) { lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pMessageHandles); lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe) lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe // uidvalidity must be captured before the handles are resolved lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity); // resolve MSNs cUIntList lMSNs = new cUIntList(); foreach (var lMessageHandle in pMessageHandles) { var lMSN = lSelectedMailbox.GetMSN(lMessageHandle); if (lMSN != 0) { lMSNs.Add(lMSN); } } if (lMSNs.Count == 0) { return; } // build command lBuilder.Add(kFetchCommandPartFetchSpace, new cTextCommandPart(cSequenceSet.FromUInts(lMSNs)), cCommandPart.Space); lBuilder.Add(pItems, lSelectedMailbox.MessageCache.NoModSeq); // go var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false); if (lResult.ResultType == eCommandResultType.ok) { lContext.TraceInformation("fetch success"); return; } if (lResult.ResultType == eCommandResultType.no) { throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext); } throw new cProtocolErrorException(lResult, 0, lContext); } }
internal cMessageDeliveryEventArgs(cMessageHandleList pMessageHandles) { MessageHandles = pMessageHandles; }
internal cMailboxMessageDeliveryEventArgs(iMailboxHandle pMailboxHandle, cMessageHandleList pMessageHandles) : base(pMessageHandles) { MailboxHandle = pMailboxHandle; }
private async Task ZFetchCacheItemsAsync(cMethodControl pMC, cFetchCacheItemsGroup pGroup, cProgress pProgress, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchCacheItemsAsync), pMC, pGroup); if (pGroup.Items.IsEmpty) { // the group where we already have everything that we need pProgress.Increment(pGroup.MessageHandles.Count, lContext); return; } int lExpungedCount; int lIndex = 0; cUIDList lUIDs = new cUIDList(); if (pGroup.MSNHandleCount > 0) { // this is where we use straight fetch (not UID fetch) ////////////////////////////////////////////////////// // sort the handles so we might get good sequence sets pGroup.MessageHandles.SortByCacheSequence(); int lMSNHandleCount = pGroup.MSNHandleCount; Stopwatch lStopwatch = new Stopwatch(); while (lIndex < pGroup.MessageHandles.Count && lMSNHandleCount != 0) { // the number of messages to fetch this time int lFetchCount = mFetchCacheItemsSizer.Current; // the number of UID handles we need to fetch to top up the number of handles to the limit // int lUIDHandleCount; if (lFetchCount > lMSNHandleCount) { lUIDHandleCount = lFetchCount - lMSNHandleCount; } else { lUIDHandleCount = 0; } // get the handles to fetch this time lExpungedCount = 0; cMessageHandleList lMessageHandles = new cMessageHandleList(); while (lIndex < pGroup.MessageHandles.Count && lMessageHandles.Count < lFetchCount) { var lMessageHandle = pGroup.MessageHandles[lIndex++]; if (lMessageHandle.Expunged) { lExpungedCount++; } else { if (lMessageHandle.UID == null) { lMessageHandles.Add(lMessageHandle); lMSNHandleCount--; } else if (lUIDHandleCount > 0) { lMessageHandles.Add(lMessageHandle); lUIDHandleCount--; } else { lUIDs.Add(lMessageHandle.UID); } } } // if other fetching is occurring at the same time (retrieving UIDs) then there mightn't be any // if (lMessageHandles.Count > 0) { // fetch lStopwatch.Restart(); await ZFetchCacheItemsAsync(pMC, lMessageHandles, pGroup.Items, lContext).ConfigureAwait(false); lStopwatch.Stop(); // store the time taken so the next fetch is a better size mFetchCacheItemsSizer.AddSample(lMessageHandles.Count, lStopwatch.ElapsedMilliseconds); } // update progress if (lExpungedCount > 0 || lMessageHandles.Count > 0) { pProgress.Increment(lExpungedCount + lMessageHandles.Count, lContext); } } } lExpungedCount = 0; while (lIndex < pGroup.MessageHandles.Count) { var lMessageHandle = pGroup.MessageHandles[lIndex++]; if (lMessageHandle.Expunged) { lExpungedCount++; } else { lUIDs.Add(lMessageHandle.UID); } } if (lExpungedCount > 0) { pProgress.Increment(lExpungedCount, lContext); } if (lUIDs.Count == 0) { return; } // uid fetch the remainder var lMailboxHandle = pGroup.MessageHandles[0].MessageCache.MailboxHandle; await ZUIDFetchCacheItemsAsync(pMC, lMailboxHandle, lUIDs, pGroup.Items, pProgress, lContext).ConfigureAwait(false); }
private async Task ZMessagesFetchAsync(cMethodControl pMC, cSession pSession, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMessagesFetchAsync), pMC, pMessageHandles, pItems); if (pMessageHandles.Count == 0) { return; } if (pItems.IsEmpty) { return; } if (pMessageHandles.TrueForAll(h => h.Contains(pItems))) { return; } cProgress lProgress; if (pConfiguration == null) { lProgress = new cProgress(); } else { mSynchroniser.InvokeActionInt(pConfiguration.SetCount, pMessageHandles.Count, lContext); lProgress = new cProgress(mSynchroniser, pConfiguration.Increment); } await pSession.FetchCacheItemsAsync(pMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false); }
public async Task <cMessageHandleList> UIDFetchCacheItemsAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUIDList pUIDs, cMessageCacheItems pItems, cProgress pProgress, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchCacheItemsAsync), pMC, pMailboxHandle, pUIDs, pItems); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMailboxHandle == null) { throw new ArgumentNullException(nameof(pMailboxHandle)); } if (pUIDs == null) { throw new ArgumentNullException(nameof(pUIDs)); } if (pItems == null) { throw new ArgumentNullException(nameof(pItems)); } if (pProgress == null) { throw new ArgumentNullException(nameof(pProgress)); } if (pUIDs.Count == 0) { throw new ArgumentOutOfRangeException(nameof(pUIDs)); } if (pItems.IsEmpty) { throw new ArgumentOutOfRangeException(nameof(pItems)); } uint lUIDValidity = pUIDs[0].UIDValidity; mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity); // to be repeated inside the select lock // split the list into those messages I have handles for and those I dont ///////////////////////////////////////////////////////////////////////// cMessageHandleList lMessageHandles = new cMessageHandleList(); cUIDList lUIDs = new cUIDList(); // check the selected mailbox and resolve uids -> handles whilst blocking select exclusive access // using (var lBlock = await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)) { cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity); foreach (var lUID in pUIDs) { var lMessageHandle = lSelectedMailbox.GetHandle(lUID); if (lMessageHandle == null) { lUIDs.Add(lUID); // don't have a handle } else if (lMessageHandle.ContainsNone(pItems)) { lUIDs.Add(lUID); // have to get all the attributes, may as well fetch them with the ones where I might need all the attributes } else { lMessageHandles.Add(lMessageHandle); } } } // for the messages I have handles for, fetch the missing attributes //////////////////////////////////////////////////////////////////// if (lMessageHandles.Count > 0) { // split the handles into groups based on what attributes need to be retrieved, for each group do the retrieval foreach (var lGroup in ZFetchCacheItemsGroups(lMessageHandles, pItems)) { await ZFetchCacheItemsAsync(pMC, lGroup, pProgress, lContext).ConfigureAwait(false); } } // for the messages only identified by UID or where I have to get all the items //////////////////////////////////////////////////////////////////////////////////// if (lUIDs.Count > 0) { await ZUIDFetchCacheItemsAsync(pMC, pMailboxHandle, lUIDs, pItems, pProgress, lContext).ConfigureAwait(false); // resolve uids -> handles whilst blocking select exclusive access // using (var lBlock = await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)) { cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity); foreach (var lUID in lUIDs) { var lMessageHandle = lSelectedMailbox.GetHandle(lUID); if (lMessageHandle != null) { lMessageHandles.Add(lMessageHandle); } } } } return(lMessageHandles); }