Exemple #1
0
            private async Task ZUIDStoreAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, uint pUIDValidity, cStoreFeedbackCollector pFeedbackCollector, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cUIDStoreFeedback pFeedback, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZStoreAsync), pMC, pMailboxHandle, pUIDValidity, pFeedbackCollector, pOperation, pFlags, pIfUnchangedSinceModSeq, pFeedback);

                // no validation ... all the parameters have been validated already by the cSession by the time we get here

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUIDValidity);
                    if (!lSelectedMailbox.SelectedForUpdate)
                    {
                        throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);
                    }

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.AddUIDValidity(pUIDValidity);                                                  // the command is sensitive to UIDValidity changes

                    // build the command
                    lBuilder.Add(kUIDStoreCommandPartUIDStoreSpace, new cTextCommandPart(cSequenceSet.FromUInts(pFeedbackCollector.UInts)), cCommandPart.Space);
                    if (pIfUnchangedSinceModSeq != null)
                    {
                        lBuilder.Add(kStoreCommandPartLParenUnchangedSinceSpace, new cTextCommandPart(pIfUnchangedSinceModSeq.Value), kStoreCommandPartRParenSpace);
                    }
                    lBuilder.Add(pOperation, pFlags);

                    // add the hook
                    var lHook = new cCommandHookStore(pFeedbackCollector, pFeedback, lSelectedMailbox);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    // note: the base spec states that non-existent UIDs are ignored without comment => a NO from a UID STORE is unexpected

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid store success");
                        return;
                    }

                    fCapabilities lTryIgnoring;
                    if (pIfUnchangedSinceModSeq == null)
                    {
                        lTryIgnoring = 0;
                    }
                    else
                    {
                        lTryIgnoring = fCapabilities.condstore;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Exemple #2
0
            private async Task ZStoreAsync(cMethodControl pMC, cStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZStoreAsync), pMC, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq);

                // no validation ... all the parameters have been validated already by the cSession by the time we get here

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pFeedback);
                    if (!lSelectedMailbox.SelectedForUpdate)
                    {
                        throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);
                    }

                    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);

                    // collector
                    cStoreFeedbackCollector lFeedbackCollector = new cStoreFeedbackCollector();

                    // resolve the handles to MSNs
                    foreach (var lItem in pFeedback)
                    {
                        var lMSN = lSelectedMailbox.GetMSN(lItem.MessageHandle);
                        if (lMSN != 0)
                        {
                            lFeedbackCollector.Add(lMSN, lItem);
                        }
                    }

                    // if no handles were resolved, we are done
                    if (lFeedbackCollector.Count == 0)
                    {
                        return;
                    }

                    // build the command
                    lBuilder.Add(kStoreCommandPartStoreSpace, new cTextCommandPart(cSequenceSet.FromUInts(lFeedbackCollector.UInts)), cCommandPart.Space);
                    if (pIfUnchangedSinceModSeq != null)
                    {
                        lBuilder.Add(kStoreCommandPartLParenUnchangedSinceSpace, new cTextCommandPart(pIfUnchangedSinceModSeq.Value), kStoreCommandPartRParenSpace);
                    }
                    lBuilder.Add(pOperation, pFlags);

                    // add the hook
                    var lHook = new cCommandHookStore(lFeedbackCollector, null, lSelectedMailbox);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    // NOTE: updates may have been done on both OK and NO responses (see rfc 2180/ 7162) so we can't throw on a NO for this command ... NO indicates that some (or all) of the messages have pending deletes

                    // throw on a bad
                    if (lResult.ResultType == eCommandResultType.bad)
                    {
                        fCapabilities lTryIgnoring;
                        if (pIfUnchangedSinceModSeq == null)
                        {
                            lTryIgnoring = 0;
                        }
                        else
                        {
                            lTryIgnoring = fCapabilities.condstore;
                        }
                        throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                    }

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("store success");
                    }
                    else
                    {
                        lContext.TraceInformation("store possible partial success");
                    }
                }
            }