Code Search for Developers
 
 
  

IMAPTypes.h from AlphaMail at Krugle


Show IMAPTypes.h syntax highlighted

#ifndef IMAP_TYPES
#define IMAP_TYPES

#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <exception>
#include <sstream>
#include <time.h>
#include <sys/types.h>

#include <boost/utility.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread.hpp>

#include <imap_debug.h>

namespace IMAP 
{
   class MessageAttributes;

   class CacheError : public std::exception {
         const char *msg;
      public:
         CacheError(const char *m) throw() { msg = m; }
         const char *what() const throw() {
            return msg;
         }
   };

   /**
    * Item is a reference counting data structure, with some helper methods
    * added in (for example, it insures that access time is kept up to date. It
    * is used to keep track of a pointer to actual data (of type S). This class
    * is an implementation detail of CacheEntry, and should not be used outside
    * of it.
    */
   template<class S>
   struct Item : public boost::noncopyable {
      Item(S *p) : ptr(p) { 
         time(&access_time);
         refcnt = 1; 
      }

      ~Item() { 
         delete ptr; 
      }

      S &getItem(bool update_access_time = true) { 
         if(update_access_time) time(&access_time);
         return *ptr; 
      }

      time_t getLastAccessTime() const { return access_time; }

      void touch() { time(&access_time); }

      Item *ref() { 
         boost::mutex::scoped_lock lk(object_mutex);
         refcnt++; 
         return this; 
      }

      /**
       * Dereference the specified data item, and return the reference count.
       */
      int deref() { 
         boost::mutex::scoped_lock lk(object_mutex);
         refcnt--; 
         return refcnt;
      }

      int getReferenceCount() { 
         boost::mutex::scoped_lock lk(object_mutex);
         return refcnt; 
      }

      private:
         S *ptr;
         time_t access_time;
         int refcnt;
         boost::mutex object_mutex;
   };

   /** A CacheEntry implements a reference counting scheme for time-stamped
    * items. (@see IMAP::Item). It allows you to use assigment to copy pointers
    * to a single item in a way that insures the item continues to exist until
    * no more CacheEntry objects exists that have reference to it.
    *
    * This is a memory management tool, and is meant to be used much like
    * auto_ptr<T>, but with reference counting and time stamping added in.
    * These added features let you cache a set of objects in a central store
    * where time can be used as a criteria for expiration, but also provides
    * the safety of not actually freeing the object until all users of it have
    * released their cache entries.
    *
    * The scheme is intended to be used in the following pattern:
    *
    * 1) The real object of interest is allocated via new() (p = new thing()).
    * 2) A new CacheEntry object is created using the pointer from step 1 as an
    * argument (i.e. vector<CacheEntry<T> > a; a.push_back(CacheEntry(p));)
    * 3) Other CacheEntry objects are created as copies of this cache entry. If
    * the original CacheEntry is deleted, the underlying object is still in
    * existence.
    * 4) At any point when all CacheEntry objects that point to the object are
    * destroyed, the final CacheEntry cleans up the memory.
    */
   template<class T>
   class CacheEntry
   {
      public:
         /**
          * Containers often need a way to create an empty object. This
          * constructor creates a CacheEntry that does not currently reference
          * an object.
          */
         CacheEntry()
         {
            boost::recursive_mutex::scoped_lock lk(object_mutex);
            item = NULL;
            /*
            message.str("");
            message << "Created cache entry:" << std::endl << *this;
            DEBUG(message.str());
            */
         }
         /**
          * Create a CacheEntry, and make it responsible for deleting the
          * memory associated with an object.
          *
          * @param i A pointer to the object to be managed.
          */
         CacheEntry(T *i) 
         {
            boost::recursive_mutex::scoped_lock lk(object_mutex);
            item = new Item<T>(i);
            /*
            message.str("");
            message << "Created cache entry:" << std::endl << *this;
            DEBUG(message.str());
            */
         }
         /**
          * Copy constructor. Insures that proper reference counting is done
          * when new cache entries are created that are supposed to reference
          * an existing object. Also handles the case where an empty cache
          * entry is copied.
          */
         CacheEntry(const CacheEntry<T> &i) {
            boost::recursive_mutex::scoped_lock lk(object_mutex);
            boost::recursive_mutex::scoped_lock lk2(const_cast<boost::recursive_mutex&>(i.object_mutex));
            if(i.item) {
               this->item = i.item->ref();
            } else {
               item = NULL;
            }
            /*
            message.str("");
            message << "Copied cache entry" << std::endl <<
               "Source: " << i << std::endl <<
               "Dest:   " << *this;
            DEBUG(message.str());
            */
         }
         ~CacheEntry() {
            boost::recursive_mutex::scoped_lock lk(object_mutex);
            /*
            message.str("");
            message << "Deleting cache entry: " << *this; 
            DEBUG(message.str());
            */
            if(item != NULL && item->deref() == 0) {
               DEBUG("Deleting referenced item");
               delete item;
            }
            //DEBUG("Done with destructor");
         }

         /**
          * Stop managing the current object, and start managing a different
          * one.
          * @param b The object to manage.
          */
         CacheEntry &operator=(T *b) {
            boost::recursive_mutex::scoped_lock lk(object_mutex);

            /*
            message.str("");
            message << "Managing a new item: " << std::endl <<
               "   Reference: " << b << std::endl <<
               "   CacheEntry (before copy):   " << *this << std::endl;
               */
            // LHS is being re-assigned...drop the reference
            if(item != NULL && item->deref() == 0) {
               /*
               message << "(deleted old referenced item. item: " << item <<
                  std::endl << "   reference: " << &(item->getItem()) << ')'
                  << std::endl;
                  */
               delete item;
            }

            item = new Item<T>(b);
            //message << "   CacheEntry (after copy):   " << *this << std::endl;
            //DEBUG(message.str());
         }

         CacheEntry &operator=(const CacheEntry &b)
         {
            boost::recursive_mutex::scoped_lock lk(object_mutex);
            boost::recursive_mutex::scoped_lock lk2(const_cast<boost::recursive_mutex&>(b.object_mutex));

            //message.str("");
            //message << "Copying cache entry. Src: " << b << std::endl <<
               //"   dest:" << *this << std::endl;

            // LHS is being re-assigned...drop the reference
            if(item != NULL && item->deref() == 0) {
               //message << "   Deleted item: " << (void*)item << std::endl
                       //<< "    which ref'd: " << (void*)&(item->getItem()) 
                       //<< std::endl;
               delete item;
            }
            if(b.item)
               item = b.item->ref();
            else 
               item = NULL;

            //message << "   Dest (after copy): " << *this << std::endl;

            //DEBUG(message.str());

            return *this;
         }

         /**
          * Check to see if this CacheEntry is managing an object.
          */
         bool isEmpty() const { return (item == NULL); }

         /**
          * Get the managed item. This returns a reference to the acual
          * underlying item. Changes to the item are seen by all users, so
          * multi-threaded applications should implement locking when
          * necessary.
          *
          * @returns A reference to the cached item
          * @throws CacheError if an attempt is made to get a non-existent
          * item.
          */
         T &getItem(bool update_access_time = true) { 
            boost::recursive_mutex::scoped_lock lk(object_mutex);
            if(item) 
               return item->getItem(update_access_time); 
            else 
               throw(CacheError("Attempt to dereference an empty cache cell"));
         }

         /**
          * Determine how long it has been since the managed object has been
          * accessed.
          * @returns The number of seconds since the object was accessed.
          */
         int getIdleTime() const { 
            time_t now;
            time(&now);
            return (now - item->getLastAccessTime());
         }

         /**
          * Get the time of last access (in seconds since epoch. see time(2)).
          * @returns The last access time, in a format as reported by the
          * time(2) system call.
          */
         time_t getLastAccessTime() const { 
            if(item) return item->getLastAccessTime(); 
            else return 0;
         }

         /**
          * Force an update of the last access time, without actually using the
          * object.
          */
         void touch() { 
            if(item) item->touch(); 
         }

      private:
         template<class X>
         friend std::ostream &operator<<(std::ostream &out, 
                                         const CacheEntry<X> &ce);
         std::ostringstream message; 
         Item<T> *item;
         boost::recursive_mutex object_mutex;
   };

   template<class T>
   inline std::ostream &operator<<(std::ostream &out, const CacheEntry<T> &ce)
   {
      boost::recursive_mutex::scoped_lock 
         lk(const_cast<boost::recursive_mutex&>(ce.object_mutex));

      out << "   CacheEntry: " << (const void *)&ce << std::endl <<
             "         Item: " << (const void *)ce.item << std::endl;
      if(ce.item) {
         out <<
             "    Reference: " << (const void *)&(ce.item->getItem()) << 
             std::endl <<
             "    Ref count: " << ce.item->getReferenceCount() << std::endl;
      }

      return out;
   }

   // Message attributes should include a UID
   typedef u_int32_t IMAPUID;
   typedef int IMAPFlags;

   // A (possibly sorted) list of cache entries of attributes for messages
   typedef std::vector<CacheEntry<MessageAttributes> > MessageList;

   // A map of message UIDs to their attributes
   typedef std::map<IMAPUID, CacheEntry<MessageAttributes> > MessageMap;
   typedef std::vector<IMAPUID> UIDList;

   // UID->thread level map
   typedef std::map<IMAPUID, u_int8_t> ThreadLevelMap;

   typedef std::vector<std::string> FolderList;

   class IMAPError : public std::exception {
         const char *msg;
      public:
         IMAPError(const char *m) throw() { msg = m; }
         const char *what() const throw() {
            return msg;
         }
   };

   class BadFolder : public IMAPError {
      public:
         BadFolder(const char *m) throw() : IMAPError(m) {}
   };

class InvalidCommand : public IMAPError {
   public:
      InvalidCommand(const char *m) throw() : IMAPError(m) {}
};

class IMAPFolder;
};

namespace Middleware {
   typedef std::map<std::string, IMAP::CacheEntry<IMAP::IMAPFolder> > CacheMap;
   typedef unsigned long RequestProcessorID;
};

#endif




See more files for this project here

AlphaMail

AlphaMail is an accelerated web mail interface with a C++ middleware layer that is more effective than an IMAP proxy which is a highly scalable (10k+ users). The interface includes modern features, Section 508 compliance, and universal browser support.

Project homepage: http://sourceforge.net/projects/alphamail
Programming language(s): C++,Java,JavaScript,Perl
License: other

  CacheManager.h
  IMAPFolder.h
  IMAPParser.h
  IMAPParserFactory.h
  IMAPRegexParser.h
  IMAPTypes.h
  MessageAttributes.h
  RequestProcessor.h
  Runnable.h
  ThreadCleanup.h
  imap_debug.h
  middleware.h