示例#1
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);
                }
示例#2
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()));
        }
示例#3
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);
                }
示例#4
0
        internal static cMessageHandleList FromMessageHandle(iMessageHandle pMessageHandle)
        {
            if (pMessageHandle == null)
            {
                throw new ArgumentNullException(nameof(pMessageHandle));
            }
            var lResult = new cMessageHandleList();

            lResult.Add(pMessageHandle);
            return(lResult);
        }
示例#5
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;
                }
示例#6
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;
        }
示例#7
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);
            }
示例#8
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);
            }