home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 108 / MacAddict108.iso / Software / Internet & Communication / JunkMatcher 1.5.5.dmg / JunkMatcher.app / Contents / Resources / Engine / EmailDB.py < prev    next >
Encoding:
Python Source  |  2005-06-01  |  5.2 KB  |  180 lines

  1. #
  2. #  EmailDB.py
  3. #  JunkMatcher
  4. #
  5. #  Created by Benjamin Han on 2/1/05.
  6. #  Copyright (c) 2005 Benjamin Han. All rights reserved.
  7. #
  8.  
  9. # This program is free software; you can redistribute it and/or
  10. # modify it under the terms of the GNU General Public License
  11. # as published by the Free Software Foundation; either version 2
  12. # of the License, or (at your option) any later version.
  13.  
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. # GNU General Public License for more details.
  18.  
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program; if not, write to the Free Software
  21. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22.  
  23. #!/usr/bin/env python
  24.  
  25. # IMPORTANT: EmailDB can have only a single instance!
  26.  
  27. from consts import *
  28. from utilities import *
  29. from rwlock import *     # to ensure thread-safety, since we will have only one global SiteDB
  30.  
  31. # so the reference to libgdbm.3.dylib would work in gdbm.so
  32. # because Panther doesn't ship Python with gdbm module so I include my own
  33. os.chdir('%slib' % ROOT_PATH)
  34.  
  35. import gdbm, fcntl, md5, cPickle, zlib
  36.  
  37. # EmailDB is implemented to accomodate multiple readers and (xor) single writer
  38. _emailDBRWLock = RWLock()
  39.  
  40.  
  41. class EmailDB:
  42.     """A compressed database of emails
  43.        -------------------------------
  44.        """
  45.     def __init__ (self, fn, readOnly = False):
  46.         self.fn = fn
  47.         self.readOnly = readOnly
  48.         self.open()
  49.  
  50.     def open (self):
  51.         # we only allows one thread to open the db, regardless whether it's read-only or not
  52.         _emailDBRWLock.acquire_write()
  53.             
  54.         if hasattr(self, 'db'):
  55.             # another thread already opened it
  56.             return
  57.  
  58.         if self.readOnly:
  59.             self.db = gdbm.open(self.fn, 'ru')
  60.         else:
  61.             if os.path.exists(self.fn):
  62.                 self.db = gdbm.open(self.fn, 'ws')
  63.             else:
  64.                 self.db = gdbm.open(self.fn, 'cs')
  65.  
  66.         _emailDBRWLock.release()
  67.  
  68.     def reOpen (self):
  69.         """Will close the db first if it's already opened.
  70.  
  71.         NOTE: NOT RECOMMENDED FOR MULTIPLE THREADS! (can open the db multiple times)"""
  72.         if hasattr(self, 'db'):
  73.             self.db.close()
  74.             del self.db
  75.  
  76.         self.open()
  77.  
  78.     def addEntry (self, msgSrc):
  79.         k = md5.new(msgSrc).hexdigest()
  80.  
  81.         _emailDBRWLock.acquire_write()
  82.  
  83.         try:
  84.             # use version 2 of pickle protocol
  85.             self.db[k] = zlib.compress(cPickle.dumps(msgSrc, cPickle.HIGHEST_PROTOCOL))
  86.         except Exception, e:
  87.             printException(u'Exception in EmailDB.addEntry()', e)
  88.         
  89.         _emailDBRWLock.release()
  90.         
  91.         return k
  92.  
  93.     def getEntry (self, md5Key):
  94.         _emailDBRWLock.acquire_read()
  95.  
  96.         try:
  97.             ret = cPickle.loads(zlib.decompress(self.db[md5Key]))
  98.         except Exception, e:
  99.             printException(u'Exception in EmailDB.getEntry(); key = %s' % md5Key, e)
  100.             return None
  101.         _emailDBRWLock.release()
  102.  
  103.         return ret
  104.  
  105.     def recycle (self):
  106.         # don't recycle it if it's in read-only mode
  107.         if not self.readOnly:
  108.             _emailDBRWLock.acquire_write()
  109.  
  110.             try:
  111.                 self.db.close()
  112.                 os.remove(self.fn)
  113.                 try:
  114.                     self.db = gdbm.open(self.fn, 'ws')
  115.                 except:
  116.                     self.db = gdbm.open(self.fn, 'cs')
  117.             except Exception, e:
  118.                 printException('Exception in EmailDB.recycle()', e)
  119.  
  120.             _emailDBRWLock.release()
  121.  
  122.     def close (self):
  123.         """Close the database. WARNING: don't try to do anything afterwards!"""
  124.         self.db.close()
  125.         del self.db
  126.  
  127.  
  128. if __name__ == '__main__':
  129.     import datetime
  130.  
  131.     def usage ():
  132.         print 'Usage: ./EmailDB.py <action> <dbFN> [arg]'
  133.         print '   * action can be one of "add", "get", and "list" (no double quotes);'
  134.         print '   * dbFN is the name of the email database;'
  135.         print '   * if action is "add", arg is the name of the file containing email raw source;'
  136.         print '     if action is "get", it\'s a key to retrieve a message.'        
  137.         
  138.     argc = len(sys.argv)
  139.     if  argc < 3:
  140.         usage()
  141.         sys.exit(1)
  142.  
  143.     action = sys.argv[1]
  144.     dbFN = sys.argv[2]    
  145.  
  146.     emailDB = EmailDB(dbFN, True)
  147.     if action == 'add':
  148.         if argc < 4:
  149.             usage()
  150.             sys.exit(1)
  151.             
  152.         arg = sys.argv[3]
  153.         
  154.         # for testing purposes, we pass None as the matchResult
  155.         print '* Added', emailDB.addEntry(open(arg).read())
  156.         print '* In %s:' % dbFN
  157.         for k in emailDB.db.keys():
  158.             print '  ', k
  159.             
  160.     elif action == 'get':
  161.         if argc < 4:
  162.             usage()
  163.             sys.exit(1)
  164.  
  165.         arg = sys.argv[3]
  166.         
  167.         print '* Getting %s:' % arg
  168.         msgSrc = emailDB.getEntry(arg)
  169.         
  170.         print '* Message source:'        
  171.         print msgSrc
  172.  
  173.     elif action == 'list':
  174.         print '* In %s:' % dbFN
  175.         for k in emailDB.db.keys():
  176.             print '  ', k
  177.  
  178.     else:
  179.         print '* Unknown action...'
  180.