173
173
def __init__(self, path=None):
174
174
self.db_path = path
176
if 'UNIT_STATE_DB' in os.environ:
177
self.db_path = os.environ['UNIT_STATE_DB']
179
self.db_path = os.path.join(
180
os.environ.get('CHARM_DIR', ''), '.unit-state.db')
176
self.db_path = os.path.join(
177
os.environ.get('CHARM_DIR', ''), '.unit-state.db')
181
178
self.conn = sqlite3.connect('%s' % self.db_path)
182
179
self.cursor = self.conn.cursor()
183
180
self.revision = None
202
206
return json.loads(result[0])
204
208
def getrange(self, key_prefix, strip=False):
206
Get a range of keys starting with a common prefix as a mapping of
209
:param str key_prefix: Common prefix among all keys
210
:param bool strip: Optionally strip the common prefix from the key
211
names in the returned dict
212
:return dict: A (possibly empty) dict of key-value mappings
214
self.cursor.execute("select key, data from kv where key like ?",
215
['%s%%' % key_prefix])
209
stmt = "select key, data from kv where key like '%s%%'" % key_prefix
210
self.cursor.execute(*self._scoped_query(stmt))
216
211
result = self.cursor.fetchall()
223
218
(k[len(key_prefix):], json.loads(v)) for k, v in result])
225
220
def update(self, mapping, prefix=""):
227
Set the values of multiple keys at once.
229
:param dict mapping: Mapping of keys to values
230
:param str prefix: Optional prefix to apply to all keys in `mapping`
233
221
for k, v in mapping.items():
234
222
self.set("%s%s" % (prefix, k), v)
236
224
def unset(self, key):
238
Remove a key from the database entirely.
240
225
self.cursor.execute('delete from kv where key=?', [key])
241
226
if self.revision and self.cursor.rowcount:
242
227
self.cursor.execute(
243
228
'insert into kv_revisions values (?, ?, ?)',
244
229
[key, self.revision, json.dumps('DELETED')])
246
def unsetrange(self, keys=None, prefix=""):
248
Remove a range of keys starting with a common prefix, from the database
251
:param list keys: List of keys to remove.
252
:param str prefix: Optional prefix to apply to all keys in ``keys``
256
keys = ['%s%s' % (prefix, key) for key in keys]
257
self.cursor.execute('delete from kv where key in (%s)' % ','.join(['?'] * len(keys)), keys)
258
if self.revision and self.cursor.rowcount:
260
'insert into kv_revisions values %s' % ','.join(['(?, ?, ?)'] * len(keys)),
261
list(itertools.chain.from_iterable((key, self.revision, json.dumps('DELETED')) for key in keys)))
263
self.cursor.execute('delete from kv where key like ?',
265
if self.revision and self.cursor.rowcount:
267
'insert into kv_revisions values (?, ?, ?)',
268
['%s%%' % prefix, self.revision, json.dumps('DELETED')])
270
231
def set(self, key, value):
272
Set a value in the database.
274
:param str key: Key to set the value for
275
:param value: Any JSON-serializable value to be set
277
232
serialized = json.dumps(value)
279
self.cursor.execute('select data from kv where key=?', [key])
235
'select data from kv where key=?', [key])
280
236
exists = self.cursor.fetchone()
282
238
# Skip mutations to the same value
487
443
data = hookenv.execution_environment()
488
444
self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
489
445
self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
490
self.kv.set('env', dict(data['env']))
446
self.kv.set('env', data['env'])
491
447
self.kv.set('unit', data['unit'])
492
448
self.kv.set('relid', data.get('relid'))
493
449
return conf_delta, rels_delta