Esempio n. 1
0
            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);
            }
Esempio n. 2
0
                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);
                }
Esempio n. 3
0
        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()));
        }
Esempio n. 4
0
            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);
                }
            }
Esempio n. 5
0
                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);
                }
Esempio n. 6
0
                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);
                    }
                }
Esempio n. 7
0
                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)));
                }
Esempio n. 8
0
        internal static cMessageHandleList FromMessageHandle(iMessageHandle pMessageHandle)
        {
            if (pMessageHandle == null)
            {
                throw new ArgumentNullException(nameof(pMessageHandle));
            }
            var lResult = new cMessageHandleList();

            lResult.Add(pMessageHandle);
            return(lResult);
        }
Esempio n. 9
0
        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)));
                }
Esempio n. 11
0
                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);
                }
Esempio n. 12
0
        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);
            }
        }
Esempio n. 13
0
            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
            }
Esempio n. 14
0
 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);
 }
Esempio n. 15
0
                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;
                }
Esempio n. 16
0
            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));
                }
            }
Esempio n. 17
0
        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;
        }
Esempio n. 18
0
        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));
            }
        }
Esempio n. 19
0
            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);
                }
            }
Esempio n. 20
0
            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);
                }
            }
Esempio n. 21
0
 internal cMessageDeliveryEventArgs(cMessageHandleList pMessageHandles)
 {
     MessageHandles = pMessageHandles;
 }
Esempio n. 22
0
 internal cMailboxMessageDeliveryEventArgs(iMailboxHandle pMailboxHandle, cMessageHandleList pMessageHandles) : base(pMessageHandles)
 {
     MailboxHandle = pMailboxHandle;
 }
Esempio n. 23
0
            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);
            }
Esempio n. 24
0
        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);
        }
Esempio n. 25
0
            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);
            }