Skip to content

Commit

Permalink
Settings storage changed from JSON to SQLite since configurator can d…
Browse files Browse the repository at this point in the history
…elete task same time daemon will update last index for it. SQLite will correctly handle concurrency issues.
  • Loading branch information
grigoryvp committed Mar 1, 2012
1 parent 77a10d4 commit 0fee43f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 36 deletions.
3 changes: 3 additions & 0 deletions common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env python
# coding:utf-8 vi:et:ts=2

import os

COMM_PORT = 17963
COMM_ADDR = 'http://localhost:{0}/'.format( COMM_PORT )
FILE_CFG = os.path.expanduser( "~/.parabridge" )

26 changes: 8 additions & 18 deletions parabridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,18 @@ def status( i_oArgs ) :
print( "Daemon is not running." )

def task_add( i_oArgs ) :
for mTask in Settings.get( 'tasks' ) :
if i_oArgs.task_name == mTask[ 'name' ] :
logging.warning( "Already has '{0}' task".format( i_oArgs.task_name ) )
return
mTask = {
'name' : i_oArgs.task_name,
'src' : i_oArgs.task_src,
'dst' : i_oArgs.task_dst
}
Settings.set( 'tasks', Settings.get( 'tasks' ) + [ mTask ] )
sName = i_oArgs.task_name
sSrc = i_oArgs.task_src
sDst = i_oArgs.task_dst
if not Settings.taskAdd( sName, sSrc, sDst ) :
logging.warning( "Already has '{0}' task".format( sName ) )

def task_del( i_oArgs ) :
lTasks = Settings.get( 'tasks' )
for mTask in lTasks :
if i_oArgs.task_name == mTask[ 'name' ] :
lTasks.remove( mTask )
Settings.set( 'tasks', lTasks )
return
logging.warning( "No task named '{0}'".format( i_oArgs.task_name ) )
if not Settings.taskDelByName( i_oArgs.task_name ) :
logging.warning( "No task named '{0}'".format( i_oArgs.task_name ) )

def task_list( i_oArgs ) :
lTasks = Settings.get( 'tasks' )
lTasks = Settings.taskList()
if 0 == len( lTasks ) :
print( "Tasks list is empty." )
return
Expand Down
72 changes: 54 additions & 18 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,74 @@
import json
import xmlrpclib
import socket
import sqlite3
import uuid
from common import *

SQL_CREATE = """CREATE TABLE IF NOT EXISTS task (
guid TEXT,
name TEXT UNIQUE,
src TEXT,
dst TEXT,
index_last INTEGER)"""
SQL_TASK_ADD = """INSERT INTO task (guid, name, src, dst, index_last)
VALUES (:guid, :name, :src, :dst, :index_last)"""
SQL_TASK_LIST = """SELECT * FROM task"""
SQL_TASK_DEL_BY_NAME = """DELETE FROM task WHERE name = :name"""

class Settings( object ) :

m_mItems = { 'tasks' : [] }
sPath = os.path.expanduser( "~/.parabridge" )
if os.path.exists( sPath ) :
m_mItems.update( json.load( open( sPath ) ) )
m_fInit = False
m_fNotify = False

@classmethod
def init( self, notify = False ) :
self.m_fNotify = notify
self.m_fInit = True
with sqlite3.connect( FILE_CFG ) as oConn :
oConn.execute( SQL_CREATE )

## Notify daemon process so it can read updated settings.
@classmethod
def notifyIfNeeded( self ) :
if not self.m_fNotify : return
try :
xmlrpclib.ServerProxy( COMM_ADDR ).cfg_changed()
except socket.error :
pass

@classmethod
def set( self, i_sName, i_uVal ) :
if not m_fInit : raise Exception( "Init not called." )
self.m_mItems[ i_sName ] = i_uVal
sPath = os.path.expanduser( "~/.parabridge" )
json.dump( self.m_mItems, open( sPath, 'w' ) )
## Notify daemon process so it can read updated settings.
if m_fNotify :
def taskAdd( self, i_sName, i_sSrc, i_sDst ) :
with sqlite3.connect( FILE_CFG ) as oConn :
try :
oSrv = xmlrpclib.ServerProxy( COMM_ADDR )
oSrv.cfg_changed()
except socket.error :
pass
mValues = {
'guid' : str( uuid.uuid4() ),
'name' : i_sName,
'src' : i_sSrc,
'dst' : i_sDst,
'index_last' : 0 }
oConn.execute( SQL_TASK_ADD, mValues )
except sqlite3.IntegrityError :
## Name not unique.
return False
else :
return True
finally :
self.notifyIfNeeded()

@classmethod
def get( self, i_sName ) :
if not m_fInit : raise Exception( "Init not called." )
return self.m_mItems[ i_sName ]
def taskDelByName( self, i_sName ) :
with sqlite3.connect( FILE_CFG ) as oConn :
oRet = oConn.execute( SQL_TASK_DEL_BY_NAME, { 'name' : i_sName } )
self.notifyIfNeeded()
return 1 == oRet.rowcount

@classmethod
def taskList( self ) :
with sqlite3.connect( FILE_CFG ) as oConn :
try :
oConn.row_factory = sqlite3.Row
return oConn.execute( SQL_TASK_LIST ).fetchall()
finally :
self.notifyIfNeeded()

0 comments on commit 0fee43f

Please sign in to comment.