-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Once the Uber server is working on db001, I'd like to add an interface to the Uber server to the class gdaAttack() which can be found in common/gdaScore.py.
Currently there are two interfaces, postgres and aircloak. I want to add a third, called uber_dp. This will result in changes deep within gdaAttack(), upon which pretty much everything runs, so we need to be very careful here and validate that all of the examples in common/examples and attacks/examples work after the changes.
Note that the type of interface is specified in the common/config/master.json config file, as "type". Here is where a database is configured as uber_dp.
When gdaAttack() is called, it is handed a dict containing various parameters. An example of the config file for these parameters is for instance attacks/dumbList_Infer.py.json. For uber_dp, we need to add two additional parameters, "budget" and "epsilon".
The tricky part will be establishing the connection itself and making the queries. This all happens in a method called _dbWorker(), which runs as a thread. _dbWorker() calls _processQuery(), which is the thing that makes the query and returns the answer.
_dbWorker() sets up its connection with this code:
# Establish connection to database
connStr = str(f"host={d['host']} port={d['port']} dbname={d['dbname']} user={d['user']} password={d['password']}")
if self._vb: print(f" {me}: Connect to DB with DSN '{connStr}'")
conn = psycopg2.connect(connStr)
cur = conn.cursor()
You'll need to add a ifelse here like if d['type'] == 'uber_dp': ..... else: and put your connection setup there. (Note that both aircloak and postgres use the same underlying interface, which is why there isn't an ifelse currently.)
Note also that there is an interface to a cache sqlite database, with handles connInsert, curInsert, connRead, curRead. These will continue to run as is, so the new interface doesn't affect that.
In _processQuery(), the following code executes the query:
try:
cur.execute(query['sql'])
except psycopg2.Error as e:
reply = dict(error=e.pgerror)
else:
ans = cur.fetchall()
numCells = self._computeNumCells(ans)
reply = dict(answer=ans,cells=numCells)
You will need to add an ifelse to do the uber_dp query instead. Note in particular that the cur.fetchall() call returns a data structure that is a list of lists like this:
[
[[a1],[b1],[c1],...],
[[a2],[b2],[c2],...],
....
[[aN],[bN],[cN],...]
]
where a, b, c, etc. are the columns returned by the query, and 1, 2, ..., N are the rows returned by the query. Your interface much replicate this structure. When the uber server returns an error, or returns an out-of-budget message, this will be encoded in the error type (i.e. reply = dict(error=e.pgerror)).
If this is done right, then all the code running above this should work unchanged.
Please regard this particular issue as a kind of master issue. You should make specific smaller issues that we can test one at a time as you go. Each of the smaller issues will have an associated push, where the example functions are all verified as running.
Note that there are a number of helper methods that currently work with both postgres and aircloak interfaces. These include getColNamesAndTypes() and getTableNames(). I don't expect these to work with uber_dp, so you don't need to worry about that.
As always, let me know if you have questions.