diff --git a/apps/modes_gui b/apps/modes_gui index 985579e..4a75772 100755 --- a/apps/modes_gui +++ b/apps/modes_gui @@ -252,11 +252,12 @@ class mainwindow(QtGui.QMainWindow): self.outputs = [self.datamodelout.output] self.updates = [] + self.lock = threading.Lock() #grab a lock to ensure sql and kml don't step on each other #output options to populate outputs, updates if self.ui.check_kml.checkState(): #we spawn a thread to run every 30 seconds (or whatever) to generate KML - self.kmlgen = air_modes.output_kml(self.ui.line_kmlfilename.text(), self.dbname, my_position) #create a KML generating thread + self.kmlgen = air_modes.output_kml(self.ui.line_kmlfilename.text(), self.dbname, my_position, self.lock) #create a KML generating thread if self.ui.check_sbs1.checkState(): sbs1port = int(self.ui.line_sbs1port.text()) @@ -281,7 +282,7 @@ class mainwindow(QtGui.QMainWindow): self.outputs.append(self.output_live_data) #create SQL database for KML and dashboard displays - self.dbwriter = air_modes.output_sql(my_position, self.dbname) + self.dbwriter = air_modes.output_sql(my_position, self.dbname, self.lock) self.outputs.append(self.dbwriter.output) #now the db will update itself #output to update reports/sec widget diff --git a/apps/modes_rx b/apps/modes_rx index 7d13265..18313d1 100755 --- a/apps/modes_rx +++ b/apps/modes_rx @@ -194,8 +194,9 @@ if __name__ == '__main__': if options.kml is not None: #we spawn a thread to run every 30 seconds (or whatever) to generate KML dbname = 'adsb.db' - sqldb = air_modes.output_sql(my_position, dbname) #input into the db - kmlgen = air_modes.output_kml(options.kml, dbname, my_position) #create a KML generating thread to read from the db + lock = threading.Lock() + sqldb = air_modes.output_sql(my_position, dbname, lock) #input into the db + kmlgen = air_modes.output_kml(options.kml, dbname, my_position, lock) #create a KML generating thread to read from the db outputs.append(sqldb.output) if options.sbs1 is True: diff --git a/python/kml.py b/python/kml.py index 521630d..908a4ab 100644 --- a/python/kml.py +++ b/python/kml.py @@ -23,12 +23,13 @@ import sqlite3 import string, math, threading, time class output_kml(threading.Thread): - def __init__(self, filename, dbname, localpos, timeout=5): + def __init__(self, filename, dbname, localpos, lock, timeout=5): threading.Thread.__init__(self) self._dbname = dbname self._filename = filename self.my_coords = localpos self._timeout = timeout + self._lock = lock self.done = False self.setDaemon(1) @@ -50,6 +51,10 @@ class output_kml(threading.Thread): f = open(self._filename, 'w') f.write(kmlstr) f.close() + + def locked_execute(self, c, query): + with self._lock: + c.execute(query) def draw_circle(self, center, rng): retstr = "" diff --git a/python/sql.py b/python/sql.py index fb97673..057b02e 100644 --- a/python/sql.py +++ b/python/sql.py @@ -26,69 +26,65 @@ import sqlite3 from air_modes.exceptions import * class output_sql(air_modes.parse): - def __init__(self, mypos, filename): + def __init__(self, mypos, filename, lock): air_modes.parse.__init__(self, mypos) - self._lock = threading.Lock() - - #create the database - self.filename = filename - self.db = sqlite3.connect(filename) - #now execute a schema to create the tables you need - c = self.db.cursor() - query = """CREATE TABLE IF NOT EXISTS "positions" ( + self._lock = lock + with self._lock: + #create the database + self.filename = filename + self.db = sqlite3.connect(filename) + #now execute a schema to create the tables you need + c = self.db.cursor() + query = """CREATE TABLE IF NOT EXISTS "positions" ( "icao" INTEGER KEY NOT NULL, "seen" TEXT NOT NULL, "alt" INTEGER, "lat" REAL, "lon" REAL );""" - self.locked_execute(c, query) - query = """CREATE TABLE IF NOT EXISTS "vectors" ( + self.execute(c, query) + query = """CREATE TABLE IF NOT EXISTS "vectors" ( "icao" INTEGER KEY NOT NULL, "seen" TEXT NOT NULL, "speed" REAL, "heading" REAL, "vertical" REAL );""" - self.locked_execute(c, query) - query = """CREATE TABLE IF NOT EXISTS "ident" ( + self.execute(c, query) + query = """CREATE TABLE IF NOT EXISTS "ident" ( "icao" INTEGER PRIMARY KEY NOT NULL, "ident" TEXT NOT NULL );""" - self.locked_execute(c, query) - c.close() - self.db.commit() - #we close the db conn now to reopen it in the output() thread context. - self.db.close() - self.db = None + self.execute(c, query) + c.close() + self.db.commit() + #we close the db conn now to reopen it in the output() thread context. + self.db.close() + self.db = None def __del__(self): self.db = None - def locked_execute(self, c, query): - with self._lock: - c.execute(query) - def output(self, message): - try: - #we're checking to see if the db is empty, and creating the db object - #if it is. the reason for this is so that the db writing is done within - #the thread context of output(), rather than the thread context of the - #constructor. that way you can spawn a thread to do output(). - if self.db is None: - self.db = sqlite3.connect(self.filename) + with self._lock: + try: + #we're checking to see if the db is empty, and creating the db object + #if it is. the reason for this is so that the db writing is done within + #the thread context of output(), rather than the thread context of the + #constructor. that way you can spawn a thread to do output(). + if self.db is None: + self.db = sqlite3.connect(self.filename) - query = self.make_insert_query(message) - if query is not None: - with self._lock: - c = self.db.cursor() - c.execute(query) - c.close() - self.db.commit() + query = self.make_insert_query(message) + if query is not None: + c = self.db.cursor() + c.execute(query) + c.close() + self.db.commit() - except ADSBError: - pass + except ADSBError: + pass def make_insert_query(self, message): #assembles a SQL query tailored to our database