/// <summary>
        /// Return quota information by executing a <c>GetQuotaRoot</c> command passed
        /// as an argument.
        /// </summary>
        /// <param name="gqr">
        /// A command for which the Query() has been called.
        /// </param>
        /// <param name="info">
        /// A structure that receives the returned quota information.
        /// </param>
        /// <returns>
        /// <c>true</c> on success.
        /// </returns>
        /// <remarks>
        /// The quota root name is not always the same as the mailbox name, see
        /// the description of the return value.
        /// </remarks>
        public bool QuotaInfos(ZIMapCommand.GetQuotaRoot gqr, out QuotaInfo info)
        {
            info = new QuotaInfo();
            if(factory == null || gqr == null) return false;

            // check result ...
            if(!gqr.CheckSuccess("")) return false;
            ZIMapCommand.GetQuotaRoot.Item[] quota = gqr.Quota;
            if(quota == null || quota.Length == 0)
            {   MonitorInfo("QuotaInfo: nothing found");
                return false;
            }

            // return results ...
            MonitorInfo("QuotaInfo: got " + quota.Length + " quota");
            foreach(ZIMapCommand.GetQuotaRoot.Item item in quota)
            {   if(item.Resource == "MESSAGE")
                {   info.MessageUsage += item.Usage;
                    info.MessageLimit += item.Limit;
                }
                else if(item.Resource == "STORAGE")
                {   info.StorageUsage += item.Usage;
                    info.StorageLimit += item.Limit;
                }
            }
            info.QuotaRoot = (gqr.Roots.Length > 0) ? gqr.Roots[gqr.Roots.Length-1] : "";
            return true;
        }
 /// <summary>
 /// A xtor to create a MailInfo from data returned by ZIMapCommand.Fetch
 /// </summary>
 public MailInfo(ZIMapCommand.Fetch.Item item)
 {
     Index   = item.Index;
     UID     = item.UID;
     Size    = item.Size;
     Parts   = item.Parts;
     Flags   = item.Flags;
     Literal = item.Literal(0);
     UserData= null;
 }
Example #3
0
 /// <summary>
 /// An iterator to get the next command for with a pending request.
 /// </summary>
 /// <param name="current">
 /// Returns the next command.
 /// </param>
 /// <returns>
 /// A value of <c>true</c> if the command is pending.
 /// </returns>
 /// <remarks>
 /// This iterator is typically used after all commands where submitted
 /// to fetch the results that are still pending.  It should be called in
 /// a loop as long as it returns <c>true</c>.
 /// </remarks>
 public bool NextPending(ref ZIMapCommand.Generic current)
 {
     uint uidx = FindIndex(current);
     if(uidx == uint.MaxValue)
         parent.RaiseError(ZIMapException.Error.InvalidArgument);
     uint ucnt = (uint)commands.Length;
     while(ucnt > 0)
     {   ucnt--;
         if(current != null) uidx++;
         if(uidx >= commands.Length) uidx = 0;
         current = commands[uidx];
         if(current.IsPending) return true;
     }
     return false;
 }
Example #4
0
 private uint FindIndex(ZIMapCommand.Generic cmd)
 {
     if(commands == null) return uint.MaxValue;
     if(cmd == null) return 0;
     for(uint uidx=0; uidx < commands.Length; uidx++)
         if(object.ReferenceEquals(commands[uidx], cmd)) return uidx;
     return uint.MaxValue;
 }
Example #5
0
        // return running or completed command, never null (unless exception)
        private ZIMapCommand[] GetCommands(bool bCompleted)
        {
            if(GetCommands() == null) return null;          // parent closed
            int cntCompleted = 0;  int cntRunning = 0;
            // pass1: count the commands
            foreach(ZIMapCommand cmd in commands)
                switch(cmd.State)
                {   case ZIMapCommand.CommandState.Running:
                            cntRunning++; break;
                    case ZIMapCommand.CommandState.Completed:
                    case ZIMapCommand.CommandState.Failed:
                            cntCompleted++; break;
                }

            // pass2: copy to array
            int cnt = bCompleted ? cntCompleted : cntRunning;
            ZIMapCommand[] arr = new ZIMapCommand[cnt];
            if(cnt <= 0) return arr;
            int run = 0;
            foreach(ZIMapCommand cmd in commands)
            {   switch(cmd.State)
                {   case ZIMapCommand.CommandState.Running:
                            if(bCompleted) continue; break;
                    case ZIMapCommand.CommandState.Completed:
                    case ZIMapCommand.CommandState.Failed:
                            if(bCompleted) break; continue;
                    default:
                         continue;
                }
                arr[run++] = cmd; if(run >= cnt) break;
            }
            return arr;
        }
Example #6
0
 /// <summary>
 /// An iterator to get the next command for executing a request.
 /// </summary>
 /// <param name="current">
 /// Returns the next command. On the initial call the value should 
 /// be <c>null</c>.  
 /// </param>
 /// <returns>
 /// The result of <see cref="ZIMapCommand.IsPending"/>.
 /// </returns>
 /// <remarks>
 /// If the return value is <c>true</c> the caller must fetch and read the result
 /// and call  <see cref="ZIMapCommand.Reset"/> before the command can be reused.
 /// <para/>
 /// If the value of <paramref name="current"/> references a command whose state
 /// is <see cref="ZIMapCommand.CommandState.Queued"/> the queued command will
 /// be sent automatically.
 /// </remarks>
 /// <para />
 /// Here a simple usage expample:
 /// <para /><example><code lang="C#">
 /// uint ucnt = NNN;                        // number of messages
 /// uint usnd = 0;                          // send counter
 /// uint urcv = 0;                          // receive counter
 /// ZIMapCommand.Generic current = null;
 /// ZIMapFactory.Bulk bulk = app.Factory.CreateBulk("XXXX", 4, false);
 /// 
 /// while(urcv &lt; ucnt)
 /// {   // step 1: queue request and check for response ...
 ///     bool done = bulk.NextCommand(ref current);
 /// 
 ///     // step 2: check server reply for error ...
 ///     if(done) 
 ///     {   urcv++;
 ///         if(!current.CheckSuccess("Command failed")) done = false; 
 ///     }
 /// 
 ///     // step 3: process data sent by server ...
 ///     if(done)
 ///     {          
 ///     }
 /// 
 ///     // step 4: create a new request
 ///     if(usnd &lt; ucnt)
 ///     {   current.Reset();
 ///         current.Queue();
 ///         usnd++;
 ///     }
 /// }
 /// bulk.Dispose();
 /// </code></example>            
 public bool NextCommand(ref ZIMapCommand.Generic current)
 {
     if(current != null && current.State == ZIMapCommand.CommandState.Queued)
         current.Execute(false);
     uint uidx = FindIndex(current);
     if(uidx == uint.MaxValue)
         parent.RaiseError(ZIMapException.Error.InvalidArgument);
     if(current != null) uidx++;
     if(uidx >= commands.Length) uidx = 0;
     current = commands[uidx];
     return current.State != ZIMapCommand.CommandState.Created;
 }
Example #7
0
 /// <summary>
 /// Attach a command to the factory, send request to server. 
 /// </summary>
 /// <param name="command">
 /// The command that is to be attached and/or sent.
 /// </param>
 /// <returns>
 /// Returns <c>true</c> on success.
 /// </returns>
 /// <remarks>
 /// Normally this method is not invoked directly, but it get's called
 /// automatically from <see cref="ZIMapCommand.Queue"/>.  This is also
 /// the case for commands that were explicitly detached from the 
 /// factory.
 /// <para />
 /// If the command is already attached to the factory it will first be
 /// detached.  Then the command will be attached to the factory and will
 /// be placed at the beginning of the commands list.  If the command
 /// is not in the state <see cref="ZIMapCommand.CommandState.Queued"/>
 /// it will be queued (in other words: the request will be sent to
 /// the server).
 /// <para />
 /// Usually commands get never explicitly detached from the factory that
 /// owns them until they are disposed, see <see cref="DetachCommand"/>.
 /// An error of type <see cref="ZIMapException.Error.InvalidArgument"/>
 /// is raised if the command was created by another factory instance.
 /// </remarks>
 public bool QueueCommand(ZIMapCommand command)
 {
     if(GetCommands() == null) return false;         // parent closed
     if(command.Parent != Parent)                    // my command?
     {   RaiseError(ZIMapException.Error.InvalidArgument, "wrong owner");
         return false;
     }
     commands.Remove(command);                       // may fail: ok
     commands.Add(command);                          // move to start
     if(command.State == ZIMapCommand.CommandState.Queued)
         return true;                                // no change
     return command.Queue();                         // tell the command
 }
Example #8
0
 /// <summary>
 /// Wait for running commands to complete.
 /// </summary>
 /// <param name="waitfor">
 /// Stop waiting after the completion of the given command, can be <c>null</c>.
 /// </param>
 /// <returns>
 /// <c>true</c> on success.
 /// </returns>
 /// <remarks>
 /// This routine just waits for the results being receiced from the server.
 /// If does not send queued commands.  For a <c>null</c> argument the
 /// routine waits for all running commands to complete.
 /// </remarks>
 public bool ExecuteRunning(ZIMapCommand waitfor)
 {
     while(HasRunningCommands)
     {   ZIMapProtocol.ReceiveData rs;
         MonitorDebug("ExecuteRunning: waiting");
         if( ((ZIMapConnection)Parent).ProtocolLayer.Receive(out rs) )
         {    Completed(rs);
              if(waitfor != null && waitfor.Tag == rs.Tag)
                 break;
         }
         else
         {   MonitorError("ExecuteRunning: receive failed");
             return false;
         }
     }
     return true;
 }
Example #9
0
 /// <summary>
 /// Send all commands that are queued and optionally wait for the
 /// completion of all commands or of a specific command.
 /// </summary>
 /// <param name="waitfor">
 /// Waits for all commands to complete if <c>null</c> -or- for a
 /// single cammand if a non-null object reference is passed.
 /// </param>
 /// <returns>
 /// <c>true</c> on success.
 /// </returns>
 /// <remarks>((ZIMapConnection)factory.Parent)
 /// Even if the server returns an error status for one or more commands
 /// this routine signals success. Only network level or protocal error
 /// will cause <c>false</c> to be returned.
 /// </remarks>
 public bool ExecuteCommands(ZIMapCommand waitfor)
 {
     if(!ExecuteCommands(false))                     // send queued commands
         return false;
     return ExecuteRunning(waitfor);                 // Wait for results
 }
Example #10
0
        /// <summary>
        /// Release and cancel commands.
        /// </summary>
        /// <remarks>
        /// When a command instance is passed as 1st argument this command and all commands
        /// with a lower Tag number (e.g. that are older) get disposed unless they are still
        /// busy. The given command must have been sent (e.g. must have a non-zero Tag).
        /// This method is invoked by <see cref="ZIMapCommand.Dispose"/> method if the owning
        /// factorie's <see cref="EnableAutoDispose"/> property is set.
        /// <para />
        /// Unsually one would like that only commands having the <see cref="ZIMapCommand.AutoDispose"/>
        /// property set are affected.  A call with <paramref name="overrideAutoDispose"/> 
        /// set <c>true</c> will include all commands.
        /// </remarks>
        public bool DisposeCommands(ZIMapCommand lastToDispose, bool overrideAutoDispose)
        {
            if(lastToDispose == null && overrideAutoDispose)
                MonitorDebug( "Disposing " + commands.Count + " command(s)");

            uint tag = 0;
            if(lastToDispose != null)                       // get target tag
            {   tag = lastToDispose.Tag;
                MonitorDebug("Disposing (auto): " + tag);
                if(tag == 0)
                {   RaiseError(ZIMapException.Error.CommandState, "not sent, no tag");
                    return false;
                }
            }

            bool auto = autoDispose;
            try
            {   autoDispose = false;                        // prevent recursion
                foreach(ZIMapCommand cmd in GetCommands(true))
                {   if(cmd.Tag > tag) continue;             // younger than target
                    if(!overrideAutoDispose && !cmd.AutoDispose)
                                                  continue; // no autoDispose
                    MonitorDebug("Disposing (auto): " + cmd.Tag);
                    cmd.Dispose();
                }
            }
            finally
            {   autoDispose = auto;
            }
            return true;
        }
Example #11
0
 /// <summary>
 /// Remove a command from the commands list of the factory.
 /// </summary>
 /// <param name="command">
 /// The command to be removed.
 /// </param>
 /// <returns>
 /// Returns <c>true</c> on success.
 /// </returns>
 /// <remarks>
 /// An error of type <see cref="ZIMapException.Error.InvalidArgument"/>
 /// is raised if the command was created by another factory instance.
 /// <para />
 /// Usually commands get never explicitly detached from the factory that
 /// owns them until they are disposed.  But an application that wants to keep
 /// a command alife for a long time (to access the returned data or to reuse
 /// it later) should eventually detach the command from the factory.
 /// The <see cref="QueueCommand"/> method will (re-)attach it automatically 
 /// when the command is reused.  This also happens when 
 /// <see cref="ZIMapCommand.Queue"/> is called.
 /// </remarks>
 public bool DetachCommand(ZIMapCommand command)
 {
     if(GetCommands() == null) return false;         // parent closed
     if(command.Parent != Parent)                    // my command?
     {   RaiseError(ZIMapException.Error.InvalidArgument, "wrong owner");
         return false;
     }
     if(!commands.Remove(command))
                               return false;         // not in list
     if(command.State != ZIMapCommand.CommandState.Disposed)
         command.Reset();                            // tell the command
     return true;
 }