/ src / class_sqlThread.py.bak
class_sqlThread.py.bak
  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      import helper_sql
 16      import helper_startup
 17      import paths
 18      import queues
 19      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)