#!/usr/bin/env python
# -*- coding: utf-8 -*-
from datetime import datetime
import time
from twisted.internet import reactor,threads,defer
from library import constants
from library.utils import do_debug
from library.ftp import hylaproto_t
from library.constants import *
class DbError(Exception): pass
class ArchiveDb(object):
""" Common class that talk with the db where the fax are stored
"""
def __init__(self, vals, db_type):
"""
"""
kw = {}
args = ()
#Are the filter active?
self.filter_data = {VIEW_DONE:0, VIEW_RECEIVE:0, VIEW_SEND:0}
#the db type
self._db_type = db_type
if db_type == CO.DB_TYPE_FILE:
args = (vals,)
elif db_type == CO.DB_TYPE_PGSQL:
args = vals.split(",")
elif db_type == CO.DB_TYPE_MYSQL:
args = ( dict( ( (k, v) for k, v in zip(('server', 'db', 'user', 'pass'), vals.split(",")) ) ), )
else:
raise ValueError("")
if db_type == CO.DB_TYPE_FILE:
self._db = CO.DB_CLASSES[db_type](*args, **kw)
self._db.conn()
else:
self._db = CO.DB_CLASSES[db_type]()
kw["no_cursors_class"] = True
ret = self._db.conn(*args, **kw)
if ret and ret[0]:
raise DbError(ret[1])
#
# Filter methods
#
def SetFilterActiveView(self, filter_active, view):
"""
"""
self.filter_data[view] = filter_active
#
# Fileds data
#
def get_fields(self):
""" Return the filed's list
"""
if do_debug.debug1: do_debug("DB: get_fields")
q = """SELECT pref_name from hylapex_db_fax_specifications WHERE
fax_tid = (SELECT DISTINCT(fax_tid) from hylapex_db_fax_specifications LIMIT 1)"""
if do_debug.debug2: do_debug(q)
ec, ret = self._db.queryReturn(q)
if ec:
#return errors
return ret
else:
if do_debug.debug4: do_debug(ret)
return ["Fax id", "Date"] + sorted( x[0] for x in ret )
def get_rcv_fields_data(self, fields, filterRcv=None, file_name=None,
callback=None, errback=None):
""" Return the data fields. If filterRcv are passed, see the n or d key
"""
if do_debug.debug1: do_debug("DB: Return the data fields from db")
if not isinstance(callback, (list, tuple)):
callback = [callback]
do_callback = filter(lambda x: callable(x), callback)
if self._db_type == CO.DB_TYPE_FILE or not do_callback:
#don't need to use thread. Hope the sqlite is quick enougth :)
data = self._get_rcv_fields_data(fields, filterRcv, file_name)
if do_callback:
callback(data)
return
else:
return data
else:
errback = errback or self._generic_error
d_receive_data = threads.deferToThread(self._get_rcv_fields_data, fields, filterRcv, file_name)
for cb in callback:
d_receive_data.addCallback(cb)
d_receive_data.addErrback(errback)
def set_recv_field_data(self, file_name, data):
""" Set the data to the db
"""
if do_debug.debug1: do_debug("DB: set_recv_field_data")
q_temp = """UPDATE hylapex_db_fax_specifications SET pref_value='%s'
WHERE pref_name='%s' AND
fax_tid = (SELECT id FROM hylapex_db_fax WHERE fax_id='%s');\n"""
q = ""
for k, v in data.iteritems():
q += q_temp % (v, k, file_name)
if do_debug.debug2: do_debug(q)
return self._db.queryNoReturn(q)
#
# File (fax)
#
def get_file(self, file_name):
""" Fetch the file from the db and return it
"""
if do_debug.debug1: do_debug("DB: get_file")
q = """SELECT file_data FROM hylapex_db_fax_file WHERE
fax_tid = (SELECT id FROM hylapex_db_fax WHERE fax_id='%s')""" % file_name
ec, ret = self._db.queryReturn(q)
if do_debug.debug2: do_debug(q)
if do_debug.debug4: do_debug(ret)
if ec:
return ret
else:
return ret[0][0]
#
# Delete a file
#
def delete_file(self, file_name):
"""
"""
if do_debug.debug1: do_debug("DB: delete_file")
q_sel = "(SELECT id FROM hylapex_db_fax WHERE fax_id='%s')" % file_name
q = """ DELETE FROM hylapex_db_fax_file WHERE fax_tid=%s ;
DELETE FROM hylapex_db_fax_specifications WHERE fax_tid=%s ;
DELETE FROM hylapex_db_fax WHERE fax_id='%s';
""" % (q_sel, q_sel, file_name)
if do_debug.debug2: do_debug(q)
return self._db.queryNoReturn(q)
#
# Internal methods
#
def _get_rcv_fields_data(self, fields, filterRcv=None, file_name=None):
""" Internal receive data method.
"""
if do_debug.debug1: do_debug("DB: Internal receive data method")
q = "SELECT id, fax_id, date_receive FROM hylapex_db_fax"
if filterRcv is None:
filterRcv = {}
filter_n = self._get_rcv_filter_active(filterRcv, "n")
filter_d = self._get_rcv_filter_active(filterRcv, "d")
if file_name is not None:
q += " WHERE fax_id='%s' " % file_name
elif filter_d:
time_query = time.time() - int(filter_d) * 60 * 60 * 24
date = datetime.fromtimestamp(time_query)
q += " WHERE date_receive > '%s'" % date
q += " ORDER BY date_receive DESC"
if filter_n:
q += " LIMIT %s " % filter_n
if do_debug.debug2: do_debug(q)
ec, ret = self._db.queryReturn(q)
if ec:
return ret
if do_debug.debug4: do_debug(ret)
field_select_lst = []
for fl in fields.split(";"):
field_select_lst.append( "%s" % fl.split(",")[0] )
field_select = ",".join( ( "'%s'" % x for x in field_select_lst ))
d = []
for fax_id in ret:
id_, fax_id, date_rcv = fax_id
#some db library returns datetime values, others string, so handle differences
if not isinstance(date_rcv, datetime):
date_rcv = time.strftime(hylaproto_t.RCV_FORMAT_DATE,
time.strptime(date_rcv, "%Y-%m-%d %H:%M:%S") )
else:
date_rcv = date_rcv.strftime(hylaproto_t.RCV_FORMAT_DATE)
q = """SELECT pref_name, pref_value FROM hylapex_db_fax_specifications
WHERE pref_name IN (%s) AND fax_tid=%s""" % (field_select, id_)
if do_debug.debug2: do_debug(q)
data_ret = self._db.queryReturn(q)[1]
if do_debug.debug4: do_debug(data_ret)
data_fax = dict( [("Fax id", fax_id), ("Date", date_rcv)] + list(data_ret))
tmp_lst = []
for x in field_select_lst:
#if select a value that aren't into the db, add a null value
try:
p = data_fax[x]
except KeyError:
p = ""
tmp_lst.append(p)
d.append(tmp_lst)
return d
def _get_rcv_filter_active(self, filterRcv, filter_key):
"""
"""
if (self.filter_data[VIEW_RECEIVE] and
"n" in filterRcv and filterRcv[filter_key] and int(filterRcv[filter_key])):
return filterRcv[filter_key]
else:
return None
def _generic_error(self, *args, **kw):
""" Generic error
"""
print "Generic error on ArchiveDb"
print args
print kw
|