Support for MySQL and Sqlite share logging
[bitcoin:eloipool.git] / sharelogging / sql.py
1 # Eloipool - Python Bitcoin pool server
2 # Copyright (C) 2011-2012  Luke Dashjr <luke-jr+eloipool@utopios.org>
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as
6 # published by the Free Software Foundation, either version 3 of the
7 # License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 import logging
18 from util import shareLogFormatter
19
20 _logger = logging.getLogger('sharelogging.sql')
21
22 class sql:
23         _psf = {
24                 'qmark': '?',
25                 'format': '%s',
26         }
27         
28         def __init__(self, **ka):
29                 self.opts = ka
30                 dbe = ka['engine']
31                 if 'statement' not in ka:
32                         _logger.warn('"statement" not specified for sql logger, but default may vary!')
33                 getattr(self, 'setup_%s' % (dbe,))()
34         
35         def setup_mysql(self, **ka):
36                 import pymysql
37                 self.db = pymysql.connect(**self.opts.get('dbopts', {}))
38                 self.modsetup(mysql)
39         
40         def setup_postgres(self, **ka):
41                 import psycopg2
42                 self.db = psycopg2.connect(**self.opts.get('dbopts', {}))
43                 ka.setdefault('statement', "insert into shares (rem_host, username, our_result, upstream_result, reason, solution) values ({Q(remoteHost)}, {username}, {YN(not(rejectReason))}, {YN(upstreamResult)}, {rejectReason}, decode({solution}, 'hex'))")
44                 self.modsetup(psycopg2)
45         
46         def setup_sqlite(self, **ka):
47                 import sqlite3
48                 self.db = sqlite3.connect(**self.opts.get('dbopts', {}))
49                 self.modsetup(sqlite3)
50         
51         def modsetup(self, mod):
52                 psf = self._psf[mod.paramstyle]
53                 self.opts.setdefault('statement', "insert into shares (remoteHost, username, rejectReason, upstreamResult, solution) values ({remoteHost}, {username}, {rejectReason}, {upstreamResult}, {solution})")
54                 stmt = self.opts['statement']
55                 self.pstmt = shareLogFormatter(stmt, psf)
56         
57         def logShare(self, share):
58                 (stmt, params) = self.pstmt.applyToShare(share)
59                 dbc = self.db.cursor()
60                 dbc.execute(stmt, params)
61                 self.db.commit()