/// <summary>
        /// Looks up the specified entry in the cache.
        /// </summary>
        /// <param name="msgId">The message id to lookup</param>
        /// <param name="zone">The zone associated with the message</param>
        /// <param name="remove">If TRUE, the entry will be removed from the cache</param>
        /// <returns>The entry associated with the specified message ID or NULL if no entry was found</returns>
        private IRequestInfo Lookup(string msgId,
                                    IZone zone,
                                    bool remove)
        {
            RequestCacheFileEntry e = (RequestCacheFileEntry)fCache[msgId];

            if (e == null)
            {
                return(null);
            }

            if (remove)
            {
                fCache.Remove(msgId);
                try
                {
                    fFile.Seek(e.Location, SeekOrigin.Begin);
                    fFile.WriteByte(0);
                }
                catch (Exception ioe)
                {
                    throw new AdkException
                              ("Error removing entry from SIF_Request ID cache: " + ioe.Message, zone,
                              null);
                }
            }

            return(e);
        }
        public override IRequestInfo StoreRequestInfo(SIF_Request request,
                                                      Query q,
                                                      IZone zone)
        {
            // validate that the userdata supplied with the query is serializable
            if (q.UserData != null)
            {
                Type userDataType = q.UserData.GetType();
                if (!userDataType.IsSerializable)
                {
                    throw new ArgumentException
                              ("Query.UserData contains " + userDataType.AssemblyQualifiedName +
                              " which is not serializable");
                }
            }

            try
            {
                RequestCacheFileEntry entry = new RequestCacheFileEntry(true);
                entry.SetObjectType(request.SIF_Query.SIF_QueryObject.ObjectName);
                entry.SetMessageId(request.MsgId);
                entry.SetUserData(q.UserData);
                Store(fFile, entry);
                return(entry);
            }
            catch (Exception thr)
            {
                throw new AdkException
                          ("Error writing to SIF_Request ID cache (MsgId: " + request.MsgId + ") " + thr,
                          zone, thr);
            }
        }
        private void Store(FileStream outStream,
                           RequestCacheFileEntry entry)
        {
            Boolean success;

            //cStore serialized Request in 2 parts
            //.NET framework returns null if Error occurs during
            //deserialization.
            //In our case, when State error occurs, we'd still
            //like to get the requestCacheFileEntry back
            //so I'm splitting the serialization into 2 parts:
            //State  and  requestCacheFileEntry
            //string l
            //
            entry.SetRequestTime(DateTime.Now);



            //store RequestFileCacheEntry to memory in HashTable
            fCache[entry.MessageId] = entry;


            // ******************************************************************
            //                                                          *********
            //             Serialize RequestCacheFile                   *********
            //                                                          *********
            outStream.Seek(0, SeekOrigin.End);
            entry.Location = outStream.Position;
            byte isActive = entry.IsActive ? (byte)1 : (byte)0;

            outStream.WriteByte(isActive);
            outStream.Flush();


            success = WriteNext(outStream, entry);
            if (success == false)
            {
                outStream.SetLength(entry.Location);
                return;
            }

            // ******************************************************************
            //                                                          *********
            //             Serialize State Information                  *********
            //                                                          *********
            // object l_objState = entry.State;
            WriteNext(outStream, entry.State);
        }
        private void Initialize(Agent agent,
                                bool isRetry)
        {
            fFormatter                = new BinaryFormatter();
            fFormatter.Binder         = new SimpleObjectBinder();
            fFormatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
            //  Ensure the requests.adk file exists in the work directory
            String   fileName         = agent.WorkDir + Path.DirectorySeparatorChar + "requests.adk";
            FileInfo currentCacheFile = new FileInfo(fileName);

            if (!currentCacheFile.Exists)
            {
                if ((Adk.Debug & AdkDebugFlags.Lifecycle) != 0)
                {
                    Agent.Log.Debug("Creating SIF_Request ID cache: " + fileName);
                }
            }

            try
            {
                fFile = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Read);
            }
            catch (Exception ioe)
            {
                throw new AdkException
                          ("Error opening or creating SIF_Request ID cache: " + ioe.Message, null, ioe);
            }

            //  Read the file contents into memory
            if ((Adk.Debug & AdkDebugFlags.Lifecycle) != 0)
            {
                Agent.Log.Debug("Reading SIF_Request ID cache: " + fileName);
            }

            // At startup, we pack the file by writing all of the active entries into
            // a second file and then replacing the original file with this copy
            String     tmpName = null;
            FileStream tmp     = null;

            try
            {
                tmpName = agent.WorkDir + Path.DirectorySeparatorChar + "requests.$dk";
                tmp     = new FileStream(tmpName, FileMode.OpenOrCreate, FileAccess.Write);
                tmp.SetLength(0);

                int    days = 90;
                String str  = agent.Properties["adkglobal.requestCache.age"];
                if (str != null)
                {
                    try
                    {
                        days = Int32.Parse(str);
                    }
                    catch (Exception ex)
                    {
                        Agent.Log.Warn
                        (
                            "Error parsing property 'adkglobal.requestCache.age', default of 90 days will be used: " +
                            ex.Message, ex);
                    }
                }

                DateTime maxAge            = DateTime.Now.Subtract(TimeSpan.FromDays(days));
                RequestCacheFileEntry next = null;
                while ((next = Read(fFile, false)) != null)
                {
                    if (next.IsActive && next.RequestTime > maxAge)
                    {
                        Store(tmp, next);
                    }
                }

                tmp.Close();
                fFile.Close();

                //
                //  Overwrite the requests.adk file with the temporary, then
                //  delete the temporary.
                //
                //if ((currentCacheFile.Attributes & FileAttributes.ReadOnly) != 0)
                //{
                //   currentCacheFile.Attributes = FileAttributes.Normal;
                //}
                currentCacheFile.Delete();
                File.Move(tmpName, fileName);

                try
                {
                    fFile = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
                }
                catch (Exception fnfe)
                {
                    throw new AdkException
                              ("Error opening or creating SIF_Request ID cache: " + fnfe, null, fnfe);
                }

                if ((Adk.Debug & AdkDebugFlags.Lifecycle) != 0)
                {
                    Agent.Log.Debug
                        ("Read " + fCache.Count + " pending SIF_Request IDs from cache");
                }
            }
            catch (Exception ioe)
            {
                //  Make sure the files are closed
                if (tmp != null)
                {
                    try
                    {
                        tmp.Close();
                    }
                    catch (Exception ex)
                    {
                        Agent.Log.WarnFormat("Exception thrown while closing FileStream: {0}", ex);
                    }
                }
                if (fFile != null)
                {
                    try
                    {
                        fFile.Close();
                    }
                    catch (Exception ex)
                    {
                        Agent.Log.WarnFormat("Exception thrown while closing file: {0}", ex);
                    }
                }
                if ((currentCacheFile.Attributes & FileAttributes.ReadOnly) != 0)
                {
                    throw new AdkException
                              ("Error opening or creating SIF_Request ID cache: " + ioe, null, ioe);
                }

                if (isRetry)
                {
                    // We've already tried reinitializing. rethrow
                    if (ioe is AdkException)
                    {
                        throw;
                    }
                    else
                    {
                        throw new AdkException
                                  ("Error opening or creating SIF_Request ID cache: " + ioe, null, ioe);
                    }
                }
                else
                {
                    Agent.Log.Warn
                        ("Could not read SIF_Request ID cache (will start with fresh cache): " +
                        ioe);

                    //
                    //  Delete the files and re-initialize from scratch. We don't
                    //  want a file error here to prevent the agent from running, so
                    //  no exception is thrown to the caller.
                    //
                    File.Delete(fileName);
                    File.Delete(tmpName);
                    Initialize(agent, true);
                }
            }
        }
        public override IRequestInfo StoreRequestInfo(SIF_Request request,
                                                       Query q,
                                                       IZone zone)
        {
            // validate that the userdata supplied with the query is serializable
            if (q.UserData != null)
            {
                Type userDataType = q.UserData.GetType();
                if (!userDataType.IsSerializable)
                {
                    throw new ArgumentException
                        ("Query.UserData contains " + userDataType.AssemblyQualifiedName +
                          " which is not serializable");
                }
            }

            try
            {
                RequestCacheFileEntry entry = new RequestCacheFileEntry(true);
                entry.SetObjectType(request.SIF_Query.SIF_QueryObject.ObjectName);
                entry.SetMessageId(request.MsgId);
                entry.SetUserData(q.UserData);
                Store(fFile, entry);
                return entry;
            }
            catch (Exception thr)
            {
                throw new AdkException
                    ("Error writing to SIF_Request ID cache (MsgId: " + request.MsgId + ") " + thr,
                      zone, thr);
            }
        }
        private void Store(FileStream outStream,
                            RequestCacheFileEntry entry)
        {
            Boolean success;
            //cStore serialized Request in 2 parts
            //.NET framework returns null if Error occurs during
            //deserialization.
            //In our case, when State error occurs, we'd still
            //like to get the requestCacheFileEntry back
            //so I'm splitting the serialization into 2 parts:
            //State  and  requestCacheFileEntry
            //string l
            //
            entry.SetRequestTime(DateTime.Now);

            //store RequestFileCacheEntry to memory in HashTable
            fCache[entry.MessageId] = entry;

            // ******************************************************************
            //                                                          *********
            //             Serialize RequestCacheFile                   *********
            //                                                          *********
            outStream.Seek(0, SeekOrigin.End);
            entry.Location = outStream.Position;
            byte isActive = entry.IsActive ? (byte)1 : (byte)0;
            outStream.WriteByte(isActive);
            outStream.Flush();

            success = WriteNext(outStream, entry);
            if (success == false)
            {
                outStream.SetLength(entry.Location);
                return;
            }

            // ******************************************************************
            //                                                          *********
            //             Serialize State Information                  *********
            //                                                          *********
            // object l_objState = entry.State;
            WriteNext(outStream, entry.State);
        }