class_sqlThread.py
1 """ 2 sqlThread is defined here 3 """ 4 5 import os 6 import shutil # used for moving the messages.dat file 7 import sqlite3 8 import sys 9 import threading 10 import time 11 12 from six.moves.reprlib import repr 13 14 try: 15 from . import helper_sql 16 from . import helper_startup 17 from . import paths 18 from . import queues 19 from . import state 20 from .addresses import encodeAddress 21 from .bmconfigparser import config, config_ready 22 from .debug import logger 23 from .tr import _translate 24 except ImportError: 25 from . import helper_sql, helper_startup, paths, queues, state 26 from .addresses import encodeAddress 27 from .bmconfigparser import config, config_ready 28 from .debug import logger 29 from .tr import _translate 30 31 32 class sqlThread(threading.Thread): 33 """A thread for all SQL operations""" 34 35 def __init__(self): 36 threading.Thread.__init__(self, name="SQL") 37 38 def run(self): # pylint: disable=too-many-locals, too-many-branches, too-many-statements 39 """Process SQL queries from `.helper_sql.sqlSubmitQueue`""" 40 helper_sql.sql_available = True 41 config_ready.wait() 42 self.conn = sqlite3.connect(state.appdata + 'messages.dat') 43 self.conn.text_factory = str 44 self.cur = self.conn.cursor() 45 46 self.cur.execute('PRAGMA secure_delete = true') 47 48 # call create_function for encode address 49 self.create_function() 50 51 try: 52 self.cur.execute( 53 '''CREATE TABLE inbox (msgid blob, toaddress text, fromaddress text, subject text,''' 54 ''' received text, message text, folder text, encodingtype int, read bool, sighash blob,''' 55 ''' UNIQUE(msgid) ON CONFLICT REPLACE)''') 56 self.cur.execute( 57 '''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text,''' 58 ''' message text, ackdata blob, senttime integer, lastactiontime integer,''' 59 ''' sleeptill integer, status text, retrynumber integer, folder text, encodingtype int, ttl int)''') 60 self.cur.execute( 61 '''CREATE TABLE subscriptions (label text, address text, enabled bool)''') 62 self.cur.execute( 63 '''CREATE TABLE addressbook (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''') 64 self.cur.execute( 65 '''CREATE TABLE blacklist (label text, address text, enabled bool)''') 66 self.cur.execute( 67 '''CREATE TABLE whitelist (label text, address text, enabled bool)''') 68 self.cur.execute( 69 '''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int,''' 70 ''' usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)''') 71 self.cur.execute( 72 '''CREATE TABLE inventory (hash blob, objecttype int, streamnumber int, payload blob,''' 73 ''' expirestime integer, tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''') 74 self.cur.execute( 75 '''INSERT INTO subscriptions VALUES''' 76 '''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''') 77 self.cur.execute( 78 '''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''') 79 self.cur.execute('''INSERT INTO settings VALUES('version','11')''') 80 self.cur.execute('''INSERT INTO settings VALUES('lastvacuumtime',?)''', ( 81 int(time.time()),)) 82 self.cur.execute( 83 '''CREATE TABLE objectprocessorqueue''' 84 ''' (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''') 85 self.conn.commit() 86 logger.info('Created messages database file') 87 except Exception as err: 88 if str(err) == 'table inbox already exists': 89 logger.debug('Database file already exists.') 90 91 else: 92 sys.stderr.write( 93 'ERROR trying to create database file (message.dat). Error message: %s\n' % str(err)) 94 os._exit(0) 95 96 # If the settings version is equal to 2 or 3 then the 97 # sqlThread will modify the pubkeys table and change 98 # the settings version to 4. 99 settingsversion = config.getint( 100 'bitmessagesettings', 'settingsversion') 101 102 # People running earlier versions of PyBitmessage do not have the 103 # usedpersonally field in their pubkeys table. Let's add it. 104 if settingsversion == 2: 105 item = '''ALTER TABLE pubkeys ADD usedpersonally text DEFAULT 'no' ''' 106 parameters = '' 107 self.cur.execute(item, parameters) 108 self.conn.commit() 109 110 settingsversion = 3 111 112 # People running earlier versions of PyBitmessage do not have the 113 # encodingtype field in their inbox and sent tables or the read field 114 # in the inbox table. Let's add them. 115 if settingsversion == 3: 116 item = '''ALTER TABLE inbox ADD encodingtype int DEFAULT '2' ''' 117 parameters = '' 118 self.cur.execute(item, parameters) 119 120 item = '''ALTER TABLE inbox ADD read bool DEFAULT '1' ''' 121 parameters = '' 122 self.cur.execute(item, parameters) 123 124 item = '''ALTER TABLE sent ADD encodingtype int DEFAULT '2' ''' 125 parameters = '' 126 self.cur.execute(item, parameters) 127 self.conn.commit() 128 129 settingsversion = 4 130 131 config.set( 132 'bitmessagesettings', 'settingsversion', str(settingsversion)) 133 config.save() 134 135 helper_startup.updateConfig() 136 137 # From now on, let us keep a 'version' embedded in the messages.dat 138 # file so that when we make changes to the database, the database 139 # version we are on can stay embedded in the messages.dat file. Let us 140 # check to see if the settings table exists yet. 141 item = '''SELECT name FROM sqlite_master WHERE type='table' AND name='settings';''' 142 parameters = '' 143 self.cur.execute(item, parameters) 144 if self.cur.fetchall() == []: 145 # The settings table doesn't exist. We need to make it. 146 logger.debug( 147 "In messages.dat database, creating new 'settings' table.") 148 self.cur.execute( 149 '''CREATE TABLE settings (key text, value blob, UNIQUE(key) ON CONFLICT REPLACE)''') 150 self.cur.execute('''INSERT INTO settings VALUES('version','1')''') 151 self.cur.execute('''INSERT INTO settings VALUES('lastvacuumtime',?)''', ( 152 int(time.time()),)) 153 logger.debug('In messages.dat database, removing an obsolete field from the pubkeys table.') 154 self.cur.execute( 155 '''CREATE TEMPORARY TABLE pubkeys_backup(hash blob, transmitdata blob, time int,''' 156 ''' usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE);''') 157 self.cur.execute( 158 '''INSERT INTO pubkeys_backup SELECT hash, transmitdata, time, usedpersonally FROM pubkeys;''') 159 self.cur.execute('''DROP TABLE pubkeys''') 160 self.cur.execute( 161 '''CREATE TABLE pubkeys''' 162 ''' (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)''') 163 self.cur.execute( 164 '''INSERT INTO pubkeys SELECT hash, transmitdata, time, usedpersonally FROM pubkeys_backup;''') 165 self.cur.execute('''DROP TABLE pubkeys_backup;''') 166 logger.debug( 167 'Deleting all pubkeys from inventory.' 168 ' They will be redownloaded and then saved with the correct times.') 169 self.cur.execute( 170 '''delete from inventory where objecttype = 'pubkey';''') 171 logger.debug('replacing Bitmessage announcements mailing list with a new one.') 172 self.cur.execute( 173 '''delete from subscriptions where address='BM-BbkPSZbzPwpVcYZpU4yHwf9ZPEapN5Zx' ''') 174 self.cur.execute( 175 '''INSERT INTO subscriptions VALUES''' 176 '''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''') 177 logger.debug('Commiting.') 178 self.conn.commit() 179 logger.debug('Vacuuming message.dat. You might notice that the file size gets much smaller.') 180 self.cur.execute(''' VACUUM ''') 181 182 # After code refactoring, the possible status values for sent messages 183 # have changed. 184 self.cur.execute( 185 '''update sent set status='doingmsgpow' where status='doingpow' ''') 186 self.cur.execute( 187 '''update sent set status='msgsent' where status='sentmessage' ''') 188 self.cur.execute( 189 '''update sent set status='doingpubkeypow' where status='findingpubkey' ''') 190 self.cur.execute( 191 '''update sent set status='broadcastqueued' where status='broadcastpending' ''') 192 self.conn.commit() 193 194 # Let's get rid of the first20bytesofencryptedmessage field in 195 # the inventory table. 196 item = '''SELECT value FROM settings WHERE key='version';''' 197 parameters = '' 198 self.cur.execute(item, parameters) 199 if int(self.cur.fetchall()[0][0]) == 2: 200 logger.debug( 201 'In messages.dat database, removing an obsolete field from' 202 ' the inventory table.') 203 self.cur.execute( 204 '''CREATE TEMPORARY TABLE inventory_backup''' 205 '''(hash blob, objecttype text, streamnumber int, payload blob,''' 206 ''' receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE);''') 207 self.cur.execute( 208 '''INSERT INTO inventory_backup SELECT hash, objecttype, streamnumber, payload, receivedtime''' 209 ''' FROM inventory;''') 210 self.cur.execute('''DROP TABLE inventory''') 211 self.cur.execute( 212 '''CREATE TABLE inventory''' 213 ''' (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer,''' 214 ''' UNIQUE(hash) ON CONFLICT REPLACE)''') 215 self.cur.execute( 216 '''INSERT INTO inventory SELECT hash, objecttype, streamnumber, payload, receivedtime''' 217 ''' FROM inventory_backup;''') 218 self.cur.execute('''DROP TABLE inventory_backup;''') 219 item = '''update settings set value=? WHERE key='version';''' 220 parameters = (3,) 221 self.cur.execute(item, parameters) 222 223 # Add a new column to the inventory table to store tags. 224 item = '''SELECT value FROM settings WHERE key='version';''' 225 parameters = '' 226 self.cur.execute(item, parameters) 227 currentVersion = int(self.cur.fetchall()[0][0]) 228 if currentVersion == 1 or currentVersion == 3: 229 logger.debug( 230 'In messages.dat database, adding tag field to' 231 ' the inventory table.') 232 item = '''ALTER TABLE inventory ADD tag blob DEFAULT '' ''' 233 parameters = '' 234 self.cur.execute(item, parameters) 235 item = '''update settings set value=? WHERE key='version';''' 236 parameters = (4,) 237 self.cur.execute(item, parameters) 238 239 # Add a new column to the pubkeys table to store the address version. 240 # We're going to trash all of our pubkeys and let them be redownloaded. 241 item = '''SELECT value FROM settings WHERE key='version';''' 242 parameters = '' 243 self.cur.execute(item, parameters) 244 currentVersion = int(self.cur.fetchall()[0][0]) 245 if currentVersion == 4: 246 self.cur.execute('''DROP TABLE pubkeys''') 247 self.cur.execute( 248 '''CREATE TABLE pubkeys (hash blob, addressversion int, transmitdata blob, time int,''' 249 '''usedpersonally text, UNIQUE(hash, addressversion) ON CONFLICT REPLACE)''') 250 self.cur.execute( 251 '''delete from inventory where objecttype = 'pubkey';''') 252 item = '''update settings set value=? WHERE key='version';''' 253 parameters = (5,) 254 self.cur.execute(item, parameters) 255 256 # Add a new table: objectprocessorqueue with which to hold objects 257 # that have yet to be processed if the user shuts down Bitmessage. 258 item = '''SELECT value FROM settings WHERE key='version';''' 259 parameters = '' 260 self.cur.execute(item, parameters) 261 currentVersion = int(self.cur.fetchall()[0][0]) 262 if currentVersion == 5: 263 self.cur.execute('''DROP TABLE knownnodes''') 264 self.cur.execute( 265 '''CREATE TABLE objectprocessorqueue''' 266 ''' (objecttype text, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''') 267 item = '''update settings set value=? WHERE key='version';''' 268 parameters = (6,) 269 self.cur.execute(item, parameters) 270 271 # changes related to protocol v3 272 # In table inventory and objectprocessorqueue, objecttype is now 273 # an integer (it was a human-friendly string previously) 274 item = '''SELECT value FROM settings WHERE key='version';''' 275 parameters = '' 276 self.cur.execute(item, parameters) 277 currentVersion = int(self.cur.fetchall()[0][0]) 278 if currentVersion == 6: 279 logger.debug( 280 'In messages.dat database, dropping and recreating' 281 ' the inventory table.') 282 self.cur.execute('''DROP TABLE inventory''') 283 self.cur.execute( 284 '''CREATE TABLE inventory''' 285 ''' (hash blob, objecttype int, streamnumber int, payload blob, expirestime integer,''' 286 ''' tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''') 287 self.cur.execute('''DROP TABLE objectprocessorqueue''') 288 self.cur.execute( 289 '''CREATE TABLE objectprocessorqueue''' 290 ''' (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''') 291 item = '''update settings set value=? WHERE key='version';''' 292 parameters = (7,) 293 self.cur.execute(item, parameters) 294 logger.debug( 295 'Finished dropping and recreating the inventory table.') 296 297 # The format of data stored in the pubkeys table has changed. Let's 298 # clear it, and the pubkeys from inventory, so that they'll 299 # be re-downloaded. 300 item = '''SELECT value FROM settings WHERE key='version';''' 301 parameters = '' 302 self.cur.execute(item, parameters) 303 currentVersion = int(self.cur.fetchall()[0][0]) 304 if currentVersion == 7: 305 logger.debug( 306 'In messages.dat database, clearing pubkeys table' 307 ' because the data format has been updated.') 308 self.cur.execute( 309 '''delete from inventory where objecttype = 1;''') 310 self.cur.execute( 311 '''delete from pubkeys;''') 312 # Any sending messages for which we *thought* that we had 313 # the pubkey must be rechecked. 314 self.cur.execute( 315 '''UPDATE sent SET status='msgqueued' WHERE status='doingmsgpow' or status='badkey';''') 316 query = '''update settings set value=? WHERE key='version';''' 317 parameters = (8,) 318 self.cur.execute(query, parameters) 319 logger.debug('Finished clearing currently held pubkeys.') 320 321 # Add a new column to the inbox table to store the hash of 322 # the message signature. We'll use this as temporary message UUID 323 # in order to detect duplicates. 324 item = '''SELECT value FROM settings WHERE key='version';''' 325 parameters = '' 326 self.cur.execute(item, parameters) 327 currentVersion = int(self.cur.fetchall()[0][0]) 328 if currentVersion == 8: 329 logger.debug( 330 'In messages.dat database, adding sighash field to' 331 ' the inbox table.') 332 item = '''ALTER TABLE inbox ADD sighash blob DEFAULT '' ''' 333 parameters = '' 334 self.cur.execute(item, parameters) 335 item = '''update settings set value=? WHERE key='version';''' 336 parameters = (9,) 337 self.cur.execute(item, parameters) 338 339 # We'll also need a `sleeptill` field and a `ttl` field. Also we 340 # can combine the pubkeyretrynumber and msgretrynumber into one. 341 342 item = '''SELECT value FROM settings WHERE key='version';''' 343 parameters = '' 344 self.cur.execute(item, parameters) 345 currentVersion = int(self.cur.fetchall()[0][0]) 346 if currentVersion == 9: 347 logger.info( 348 'In messages.dat database, making TTL-related changes:' 349 ' combining the pubkeyretrynumber and msgretrynumber' 350 ' fields into the retrynumber field and adding the' 351 ' sleeptill and ttl fields...') 352 self.cur.execute( 353 '''CREATE TEMPORARY TABLE sent_backup''' 354 ''' (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text,''' 355 ''' ackdata blob, lastactiontime integer, status text, retrynumber integer,''' 356 ''' folder text, encodingtype int)''') 357 self.cur.execute( 358 '''INSERT INTO sent_backup SELECT msgid, toaddress, toripe, fromaddress,''' 359 ''' subject, message, ackdata, lastactiontime,''' 360 ''' status, 0, folder, encodingtype FROM sent;''') 361 self.cur.execute('''DROP TABLE sent''') 362 self.cur.execute( 363 '''CREATE TABLE sent''' 364 ''' (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text,''' 365 ''' ackdata blob, senttime integer, lastactiontime integer, sleeptill int, status text,''' 366 ''' retrynumber integer, folder text, encodingtype int, ttl int)''') 367 self.cur.execute( 368 '''INSERT INTO sent SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata,''' 369 ''' lastactiontime, lastactiontime, 0, status, 0, folder, encodingtype, 216000 FROM sent_backup;''') 370 self.cur.execute('''DROP TABLE sent_backup''') 371 logger.info('In messages.dat database, finished making TTL-related changes.') 372 logger.debug('In messages.dat database, adding address field to the pubkeys table.') 373 # We're going to have to calculate the address for each row in the pubkeys 374 # table. Then we can take out the hash field. 375 self.cur.execute('''ALTER TABLE pubkeys ADD address text DEFAULT '' ;''') 376 377 # replica for loop to update hashed address 378 self.cur.execute('''UPDATE pubkeys SET address=(enaddr(pubkeys.addressversion, 1, hash)); ''') 379 380 # Now we can remove the hash field from the pubkeys table. 381 self.cur.execute( 382 '''CREATE TEMPORARY TABLE pubkeys_backup''' 383 ''' (address text, addressversion int, transmitdata blob, time int,''' 384 ''' usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)''') 385 self.cur.execute( 386 '''INSERT INTO pubkeys_backup''' 387 ''' SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys;''') 388 self.cur.execute('''DROP TABLE pubkeys''') 389 self.cur.execute( 390 '''CREATE TABLE pubkeys''' 391 ''' (address text, addressversion int, transmitdata blob, time int, usedpersonally text,''' 392 ''' UNIQUE(address) ON CONFLICT REPLACE)''') 393 self.cur.execute( 394 '''INSERT INTO pubkeys SELECT''' 395 ''' address, addressversion, transmitdata, time, usedpersonally FROM pubkeys_backup;''') 396 self.cur.execute('''DROP TABLE pubkeys_backup''') 397 logger.debug( 398 'In messages.dat database, done adding address field to the pubkeys table' 399 ' and removing the hash field.') 400 self.cur.execute('''update settings set value=10 WHERE key='version';''') 401 402 # Update the address colunm to unique in addressbook table 403 item = '''SELECT value FROM settings WHERE key='version';''' 404 parameters = '' 405 self.cur.execute(item, parameters) 406 currentVersion = int(self.cur.fetchall()[0][0]) 407 if currentVersion == 10: 408 logger.debug( 409 'In messages.dat database, updating address column to UNIQUE' 410 ' in the addressbook table.') 411 self.cur.execute( 412 '''ALTER TABLE addressbook RENAME TO old_addressbook''') 413 self.cur.execute( 414 '''CREATE TABLE addressbook''' 415 ''' (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''') 416 self.cur.execute( 417 '''INSERT INTO addressbook SELECT label, address FROM old_addressbook;''') 418 self.cur.execute('''DROP TABLE old_addressbook''') 419 self.cur.execute('''update settings set value=11 WHERE key='version';''') 420 421 # Are you hoping to add a new option to the keys.dat file of existing 422 # Bitmessage users or modify the SQLite database? Add it right 423 # above this line! 424 425 try: 426 testpayload = '\x00\x00' 427 t = ('1234', 1, testpayload, '12345678', 'no') 428 self.cur.execute('''INSERT INTO pubkeys VALUES(?,?,?,?,?)''', t) 429 self.conn.commit() 430 self.cur.execute( 431 '''SELECT transmitdata FROM pubkeys WHERE address='1234' ''') 432 queryreturn = self.cur.fetchall() 433 for row in queryreturn: 434 transmitdata, = row 435 self.cur.execute('''DELETE FROM pubkeys WHERE address='1234' ''') 436 self.conn.commit() 437 if transmitdata == '': 438 logger.fatal( 439 'Problem: The version of SQLite you have cannot store Null values.' 440 ' Please download and install the latest revision of your version of Python' 441 ' (for example, the latest Python 2.7 revision) and try again.\n') 442 logger.fatal( 443 'PyBitmessage will now exit very abruptly.' 444 ' You may now see threading errors related to this abrupt exit' 445 ' but the problem you need to solve is related to SQLite.\n\n') 446 os._exit(0) 447 except Exception as err: 448 if str(err) == 'database or disk is full': 449 logger.fatal( 450 '(While null value test) Alert: Your disk or data storage volume is full.' 451 ' sqlThread will now exit.') 452 queues.UISignalQueue.put(( 453 'alert', ( 454 _translate( 455 "MainWindow", 456 "Disk full"), 457 _translate( 458 "MainWindow", 459 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 460 True))) 461 os._exit(0) 462 else: 463 logger.error(err) 464 465 # Let us check to see the last time we vaccumed the messages.dat file. 466 # If it has been more than a month let's do it now. 467 item = '''SELECT value FROM settings WHERE key='lastvacuumtime';''' 468 parameters = '' 469 self.cur.execute(item, parameters) 470 queryreturn = self.cur.fetchall() 471 for row in queryreturn: 472 value, = row 473 if int(value) < int(time.time()) - 86400: 474 logger.info('It has been a long time since the messages.dat file has been vacuumed. Vacuuming now...') 475 try: 476 self.cur.execute(''' VACUUM ''') 477 except Exception as err: 478 if str(err) == 'database or disk is full': 479 logger.fatal( 480 '(While VACUUM) Alert: Your disk or data storage volume is full.' 481 ' sqlThread will now exit.') 482 queues.UISignalQueue.put(( 483 'alert', ( 484 _translate( 485 "MainWindow", 486 "Disk full"), 487 _translate( 488 "MainWindow", 489 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 490 True))) 491 os._exit(0) 492 item = '''update settings set value=? WHERE key='lastvacuumtime';''' 493 parameters = (int(time.time()),) 494 self.cur.execute(item, parameters) 495 496 helper_sql.sql_ready.set() 497 498 while True: 499 item = helper_sql.sqlSubmitQueue.get() 500 if item == 'commit': 501 try: 502 self.conn.commit() 503 except Exception as err: 504 if str(err) == 'database or disk is full': 505 logger.fatal( 506 '(While committing) Alert: Your disk or data storage volume is full.' 507 ' sqlThread will now exit.') 508 queues.UISignalQueue.put(( 509 'alert', ( 510 _translate( 511 "MainWindow", 512 "Disk full"), 513 _translate( 514 "MainWindow", 515 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 516 True))) 517 os._exit(0) 518 elif item == 'exit': 519 self.conn.close() 520 logger.info('sqlThread exiting gracefully.') 521 522 return 523 elif item == 'movemessagstoprog': 524 logger.debug('the sqlThread is moving the messages.dat file to the local program directory.') 525 526 try: 527 self.conn.commit() 528 except Exception as err: 529 if str(err) == 'database or disk is full': 530 logger.fatal( 531 '(while movemessagstoprog) Alert: Your disk or data storage volume is full.' 532 ' sqlThread will now exit.') 533 queues.UISignalQueue.put(( 534 'alert', ( 535 _translate( 536 "MainWindow", 537 "Disk full"), 538 _translate( 539 "MainWindow", 540 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 541 True))) 542 os._exit(0) 543 self.conn.close() 544 shutil.move( 545 paths.lookupAppdataFolder() + 'messages.dat', paths.lookupExeFolder() + 'messages.dat') 546 self.conn = sqlite3.connect(paths.lookupExeFolder() + 'messages.dat') 547 self.conn.text_factory = str 548 self.cur = self.conn.cursor() 549 elif item == 'movemessagstoappdata': 550 logger.debug('the sqlThread is moving the messages.dat file to the Appdata folder.') 551 552 try: 553 self.conn.commit() 554 except Exception as err: 555 if str(err) == 'database or disk is full': 556 logger.fatal( 557 '(while movemessagstoappdata) Alert: Your disk or data storage volume is full.' 558 ' sqlThread will now exit.') 559 queues.UISignalQueue.put(( 560 'alert', ( 561 _translate( 562 "MainWindow", 563 "Disk full"), 564 _translate( 565 "MainWindow", 566 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 567 True))) 568 os._exit(0) 569 self.conn.close() 570 shutil.move( 571 paths.lookupExeFolder() + 'messages.dat', paths.lookupAppdataFolder() + 'messages.dat') 572 self.conn = sqlite3.connect(paths.lookupAppdataFolder() + 'messages.dat') 573 self.conn.text_factory = str 574 self.cur = self.conn.cursor() 575 elif item == 'deleteandvacuume': 576 self.cur.execute('''delete from inbox where folder='trash' ''') 577 self.cur.execute('''delete from sent where folder='trash' ''') 578 self.conn.commit() 579 try: 580 self.cur.execute(''' VACUUM ''') 581 except Exception as err: 582 if str(err) == 'database or disk is full': 583 logger.fatal( 584 '(while deleteandvacuume) Alert: Your disk or data storage volume is full.' 585 ' sqlThread will now exit.') 586 queues.UISignalQueue.put(( 587 'alert', ( 588 _translate( 589 "MainWindow", 590 "Disk full"), 591 _translate( 592 "MainWindow", 593 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 594 True))) 595 os._exit(0) 596 else: 597 parameters = helper_sql.sqlSubmitQueue.get() 598 rowcount = 0 599 try: 600 self.cur.execute(item, parameters) 601 rowcount = self.cur.rowcount 602 except Exception as err: 603 if str(err) == 'database or disk is full': 604 logger.fatal( 605 '(while cur.execute) Alert: Your disk or data storage volume is full.' 606 ' sqlThread will now exit.') 607 queues.UISignalQueue.put(( 608 'alert', ( 609 _translate( 610 "MainWindow", 611 "Disk full"), 612 _translate( 613 "MainWindow", 614 'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'), 615 True))) 616 os._exit(0) 617 else: 618 logger.fatal( 619 'Major error occurred when trying to execute a SQL statement within the sqlThread.' 620 ' Please tell Atheros about this error message or post it in the forum!' 621 ' Error occurred while trying to execute statement: "%s" Here are the parameters;' 622 ' you might want to censor this data with asterisks (***)' 623 ' as it can contain private information: %s.' 624 ' Here is the actual error message thrown by the sqlThread: %s', 625 str(item), 626 str(repr(parameters)), 627 str(err)) 628 logger.fatal('This program shall now abruptly exit!') 629 630 os._exit(0) 631 632 helper_sql.sqlReturnQueue.put((self.cur.fetchall(), rowcount)) 633 # helper_sql.sqlSubmitQueue.task_done() 634 635 def create_function(self): 636 # create_function 637 try: 638 self.conn.create_function("enaddr", 3, func=encodeAddress, deterministic=True) 639 except (TypeError, sqlite3.NotSupportedError) as err: 640 logger.debug( 641 "Got error while pass deterministic in sqlite create function {}, Passing 3 params".format(err)) 642 self.conn.create_function("enaddr", 3, encodeAddress)