1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
#!/usr/bin/python
#Copyright (c) 2018 A. Mennucci
#License: GNU GPL v2
import os, sys, atexit, tempfile, subprocess
from os.path import join
from copy import copy
import time, string, shutil, pickle, lockfile, logging, logging.handlers
if sys.version_info.major == 2:
string_types = (str, unicode) # python2
from urllib import quote as urllib_quote
else:
string_types = (str, bytes) # python3
import urllib, urllib.parse
from urllib.parse import quote as urllib_quote
import sqlite3 as dbapi
logger=logging.getLogger(__name__)
#http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python
#from enum import Enum
class Enum(object):
def __init__(self, *k):
pass
def enum(*enums):
d=dict([ (enums[k],k) for k in range(len(enums)) ])
return type('Enum', (object,), d)
if dbapi != None:
pass
# ===== sqlite machinery
#def convert_blob(s):
# return s #this is always a string
#
# Register the adapter
#sqlite.register_adapter(StringType, adapt_blob)
#
# Register the converter
#dbapi.register_converter("blob", convert_blob)
#dbapi.register_converter("text", convert_blob)
class SQL_queue(object):
dbname=None
sql_connection=None
sql_connection_add=None
fields=('id','priority','old_name','new_name','delta','forensic','other_info','ctime')
fields_enum=enum(*fields)
schema="""
create table deltas_queue (
id integer unique primary key autoincrement,
priority integer,
old_name text,
new_name text,
delta text,
forensic text,
other_info text,
ctime integer
) ;
CREATE INDEX IF NOT EXISTS deltas_queue_priority ON deltas_queue ( priority );
CREATE INDEX IF NOT EXISTS deltas_queue_delta ON deltas_queue ( delta ) ;
CREATE INDEX IF NOT EXISTS deltas_queue_ctime ON deltas_queue ( ctime ) ;
CREATE INDEX IF NOT EXISTS deltas_queue_priority_ctime ON deltas_queue ( priority, ctime ) ;
"""
def __init__(self,dbname):
assert type(dbname) in string_types
if not os.path.exists(dbname):
r=my_subprocess_Popen(['sqlite3',dbname], stdin=subprocess.PIPE)
r.stdin.write(self.schema)
r.stdin.close()
r.wait()
assert 0 == r.returncode
assert os.path.exists(dbname)
self.dbname=dbname
self.sql_connection = self._connect()
# will be created when needed
self.sql_connection_add = None
def _connect(self):
return dbapi.connect(self.dbname, isolation_level='EXCLUSIVE') # detect_types=dbapi.PARSE_DECLTYPES | dbapi.PARSE_COLNAMES)
def __del__(self):
if self.sql_connection != None:
self.sql_connection.close()
if self.sql_connection_add != None:
self.sql_connection_add.close()
def _get_connection_cursor(self):
connection = self.sql_connection
cursor = connection.cursor()
return connection, cursor
def queue_add_begin(self):
assert self.sql_connection_add == None
self.sql_connection_add = self._connect()
def queue_add(self, priority, old_name, new_name, delta, forensic, other_info='', ctime=None):
if self.sql_connection_add == None:
raise Exception(' should use queue_add_begin() before ')
if ctime==None:
ctime=int(time.time())
with self.sql_connection_add as S:
S.execute('INSERT INTO deltas_queue VALUES (null, ?, ?, ?, ?, ?, ?, ?)',\
(priority, old_name, new_name, delta, forensic, other_info, ctime))
S.commit()
def queue_add_commit(self):
self.sql_connection_add = None
def queue_peek(self):
conn,cursor = self._get_connection_cursor()
cursor.execute('SELECT * FROM deltas_queue ORDER BY priority , ctime LIMIT 1')
return cursor.fetchone()
def queue_get(self, id_):
conn,cursor = self._get_connection_cursor()
cursor.execute('SELECT * FROM deltas_queue WHERE id = ? ', (id_,))
return cursor.fetchone()
def queue_pop(self, id_=None):
"pop one value, if 'id' is set that value"
#http://stackoverflow.com/questions/15856976/transactions-with-python-sqlite3
connection, cursor = self._get_connection_cursor()
try:
connection.execute('begin exclusive transaction')
if id_ == None:
cursor.execute('SELECT * FROM deltas_queue ORDER BY priority , ctime LIMIT 1 ')
else:
cursor.execute('SELECT * FROM deltas_queue WHERE id = ? ', (id_,))
x=cursor.fetchone()
if x is not None:
id_ = x[0]
connection.execute('DELETE FROM deltas_queue where id = ? ', (id_,))
connection.commit()
#cursor.execute('commit transaction')
except:
connection.rollback()
#cursor.execute('rollback')
raise
return x
def queue_del(self, id_):
"delete queued item by 'id'"
connection, cursor = self._get_connection_cursor()
try:
cursor.execute('DELETE FROM deltas_queue where id = ? ', (id_,))
connection.commit() #cursor.executescript('commit transaction')
except:
connection.rollback() #cursor.executescript('rollback')
raise
def iterate(self):
"returns a cursor onto the database"
connection, cursor = self._get_connection_cursor()
cursor.execute('SELECT * FROM deltas_queue ORDER BY priority , ctime')
return cursor
def queue_peek_delta(self, delta):
conn,cursor = self._get_connection_cursor()
cursor.execute('SELECT * FROM deltas_queue WHERE delta = ?', (delta, ))
return cursor.fetchone()
_html_top="""<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="StyleSheet" href="style.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>debdeltas Server History Page</title>
</head>
<body>
"""
def html(db,W):
s=SQL_queue(db)
if type(W) in string_types:
W=open(W,'w').write
W(_html_top)
W('Queue state at '+time.ctime()+'\n')
F=list(SQL_queue.fields)
FE=SQL_queue.fields_enum
W('<table class="queue"><tr>')
for j in F:
W('<th>' + j.replace('_',' ')+'</th>')
W('</tr>\n')
count=0
for x in s.iterate():
count+=1
x=list(x)
x=[('%.3f' % j) if isinstance(j,float) else j for j in x]
x=[(j.split('/')[-1]) if (type(j) in string_types) else j for j in x]
x=['' if (j == None) else j for j in x]
x[FE.ctime]=time.ctime(x[FE.ctime])
W('<tr>')
for j in x:
W('<td>'+str(j)+'</td>')
W('</tr>\n')
if (count % 40) == 0:
W('<tr>')
for j in F:
W('<th>'+j.replace('_',' ')+'</th>')
W('</tr>\n')
W('</table></body></html>\n')
W('total %d elements in queue\n' % count)
if __name__ == '__main__' and len(sys.argv) > 1:
if sys.argv[1] == 'html' :
W= sys.argv[3] if (len(sys.argv) > 3) else sys.stdout.write
html(sys.argv[2],W)
else: raise ValueError('unknown command %r' % sys.argv[1])
|