-
Notifications
You must be signed in to change notification settings - Fork 0
/
tlog.py
202 lines (177 loc) · 6 KB
/
tlog.py
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
# from threading import Event, Semaphore, Lock, Thread
from multiprocessing import Process, Queue
# from queue import Queue
import sqlite3
from datetime import datetime
SIG_STOP = 'done'
class TransactionLog:
def __init__(self, filename, exec_queue=Queue(200), recv_queue=Queue(100)):
self.filename = filename
self.exec_queue = exec_queue
self.receive_data = recv_queue
self.listener_thread = Process(target=self._queue_listener)
self.listener_thread.daemon = True
self.listener_thread.start()
# listener_thread.join()
def _queue_listener(self):
db = sqlite3.connect(self.filename)
# Create TLog table and Accounts table if they doesn't exist
db.execute(
"""CREATE TABLE IF NOT EXISTS TLog(
time TEXT,
type TEXT,
account TEXT,
info TEXT)
"""
)
db.execute(
"""CREATE TABLE IF NOT EXISTS Accounts(
id TEXT PRIMARY KEY,
name TEXT,
salt BLOB,
password_hash BLOB,
cash INTEGER,
properties TEXT,
is_banker BOOL)
"""
)
while True:
try:
next_command = self.exec_queue.get()
except KeyboardInterrupt:
pass
if next_command == SIG_STOP:
break
update, com, args = next_command
if update:
if args is not None:
db.execute(com, args)
else:
db.execute(com)
db.commit()
else:
if args is not None:
self.receive_data.put(db.execute(com, args).fetchall())
else:
self.receive_data.put(db.execute(com).fetchall())
db.commit()
db.close()
def _send_transaction_to_listener(self, trans_type, account, info):
timestamp = datetime.now()
self.exec_queue.put((
True,
"INSERT INTO TLog VALUES (?, ?, ?, ?)",
(
timestamp,
trans_type,
account,
info
)
))
def log_account_created(self, ident, cash):
trans_type = 'Create'
info = f'Started with ${cash}'
self._send_transaction_to_listener(trans_type, ident, info)
def log_account_deleted(self, ident):
trans_type = 'Delete'
self._send_transaction_to_listener(trans_type, ident, None)
def log_account_deposit(self, ident, amount):
trans_type = 'Deposit'
info = f'${amount}'
self._send_transaction_to_listener(trans_type, ident, info)
def log_account_withdraw(self, ident, amount):
trans_type = 'Withdraw'
info = f'${amount}'
self._send_transaction_to_listener(trans_type, ident, info)
def log_account_transfer(self, payer, payee, info):
trans_type = 'Transfer'
self._send_transaction_to_listener(trans_type, payer, info)
self._send_transaction_to_listener(trans_type, payee, info)
def log_server_started(self):
trans_type = 'Server Start'
id_num = None
info = 'Server has started'
self._send_transaction_to_listener(trans_type, id_num, info)
def log_accounts_reloaded(self):
trans_type = 'Reload'
id_num = None
info = 'Reloaded all accounts'
self._send_transaction_to_listener(trans_type, id_num, info)
def log_get_by_id(self, ident):
self.exec_queue.put((
False,
"SELECT * FROM TLog WHERE account=? ORDER BY time",
(ident,)
))
return self.receive_data.get()
def purge_logs(self):
self.exec_queue.put((
True,
"DELETE FROM TLog",
None
))
def create_account(self, ident, name, pw_salt, pw_hash, cash, is_banker):
self.exec_queue.put((
True,
"INSERT INTO Accounts VALUES (?, ?, ?, ?, ?, '{}', ?)",
(ident, name, pw_salt, pw_hash, cash, is_banker)
))
def update_account(self, ident, cash):
self.exec_queue.put((
True,
"UPDATE Accounts SET cash=? WHERE id=?",
(cash, ident)
))
def update_properties(self, ident, properties):
self.exec_queue.put((
True,
"UPDATE Accounts SET properties=? WHERE id=?",
(properties, ident)
))
def delete_account(self, ident):
self.exec_queue.put((
True,
"DELETE FROM Accounts WHERE id=?",
(ident,)
))
def get_all_accounts(self):
self.exec_queue.put((
False,
"SELECT * FROM Accounts",
None
))
return self.receive_data.get()
def set_account_password(self, ident, salt, hashed_pass):
self.exec_queue.put((
True,
"UPDATE Accounts SET salt=? password_hash=? WHERE id=?",
(salt, hashed_pass, ident)
))
def retrieve_hashed_password(self, ident):
self.exec_queue.put((
False,
"SELECT salt, password_hash FROM Accounts WHERE id=?",
(ident,)
))
return self.receive_data.get()
def nuke_tables(self):
self.exec_queue.put((
True,
"DELETE FROM Accounts",
None
))
trans_type = 'Nuke Data'
id_num = None
info = 'Accounts and TLog were purged'
self._send_transaction_to_listener(trans_type, id_num, info)
self.purge_logs()
def stop_db(self):
trans_type = 'Server Stop'
id_num = None
info = 'Server has stopped'
self._send_transaction_to_listener(trans_type, id_num, info)
yield 'Logged server stop'
self.exec_queue.put(SIG_STOP)
yield 'Signaled db listener close'
self.listener_thread.join()
yield 'Stopped TLog'