Skip to content

Commit

Permalink
fire up the new db!
Browse files Browse the repository at this point in the history
  • Loading branch information
maxtaco committed Feb 17, 2014
1 parent 709a3d6 commit 76ca64a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 103 deletions.
10 changes: 0 additions & 10 deletions sql/schema.sql
Expand Up @@ -17,13 +17,3 @@ CREATE TABLE IF NOT EXISTS `lookup` (

CREATE INDEX IF NOT EXISTS `lookup_index_1` ON `lookup`(`key_type`, `key`);

CREATE TABLE IF NOT EXISTS `key_import_log` (
`fingerprint` CHAR(40) NOT NULL PRIMARY KEY,
`uid` CHAR(32) NOT NULL,
`ctime` INTEGER(8) NOT NULL,
`mtime` INTEGER(8) NOT NULL,
`state` INTEGER(4) NOT NULL
);

CREATE INDEX IF NOT EXISTS `key_import_log_index_1` ON `key_import_log` (`uid`);
CREATE INDEX IF NOT EXISTS `key_import_log_index_2` ON `key_import_log` (`state`, `mtime`);
138 changes: 47 additions & 91 deletions src/db.iced
@@ -1,15 +1,23 @@

{env} = require './env'
sqlite3 = require 'sqlite3'
{Database} = sqlite3
fs = require 'fs'
path = require 'path'
{make_esc} = require 'iced-error'
{chain,make_esc} = require 'iced-error'
{mkdirp} = require './fs'
{Lock} = require('iced-utils').lock
{util} = require 'pgp-utils'
log = require './log'
{constants} = require './constants'
Datastore = require 'nedb'

##=======================================================================

pair2str = (type, name) -> (type + ":" + name)
str2pair = (s) -> if (m = s.match /^([^:]+):(.*)?/)? then [ m[0], m[1] ] else s
dict2str = ({type,name}) ->
type or= key[-2...]
pair2str(type,key)

##=======================================================================

Expand Down Expand Up @@ -43,126 +51,74 @@ class DB
esc = make_esc cb, "DB::open"
err = null
fn = @get_filename()
log.debug "+ opening sqlite3 database file: #{fn}"
log.debug "+ opening NEDB database file: #{fn}"
await mkdirp fn, esc defer()

db = null
await
db = new Database @get_filename(), sqlite3.OPEN_READWRITE|sqlite3.OPEN_CREATE, esc defer()
@db = db

@db = new Datastore { filename : @get_filename () }
await @db.loadDatabase esc defer()
await @_init_db esc defer()
log.debug "- DB opened"
cb null

#-----

get_import_state : ({uid, fingerprint}, cb) ->
q = "SELECT state FROM key_import_log WHERE uid=$uid AND fingerprint=$fingerprint"
await @db.get q, { $uid: uid, $fingerprint : fingerprint }, defer err, row
ret = if row? then row.state else constants.import_state.NONE
cb err, ret

#-----

select_key_imports_by_state : (state, cb) ->
q = "SELECT fingerprint FROM key_import_log WHERE state=$state"
await @db.all q, { $state : state }, defer err, rows
ret = if err? then null else (o.fingerprint for o in rows)
cb err, ret
put : ({type, key, value, name, names}, cb) ->
docs = [ { key : dict2str({type, key}), value : value } ]

#-----
if names and names.length
for name in names
docs.push { name : pair2str(name.type, name.name), name_to_key : pair2str(type,key) }

batch_update_key_import : ({fingerprints, state}, cb) ->
q = "UPDATE key_import_log SET state=? WHERE fingerprint IN (?)"
args = [ state, fingerprints.join(",") ]
await @db.run q, args, defer err
await @db.insert docs, defer err
cb err

#-----

put : ({type, key, value, name, names}, cb) ->
type or= key[-2...]
esc = make_esc cb, "DB::put"

names = [ name ] if name? and not names?

if names? and names.length
await @lock.acquire defer()
await @db.run "BEGIN", esc defer()

q = "REPLACE INTO kvstore(type,key,value) VALUES(?,?,?)"
args = [ type, key, JSON.stringify(value) ]
await @db.run q, args, esc defer()

if names and names.length
for name in names
q = "REPLACE INTO lookup(name_type,name,key_type,key) VALUES(?,?,?,?)"
args = [ name.type, name.name, type, key ]
await @db.run q, args, esc defer()
await @db.run "COMMIT", esc defer()
@lock.release()

remove : ({type, key}, cb) ->
k = pair2str(type,key)
log.debug "+ DB remove #{k}"
esc = make_esc cb, "DB::remove"
await @db.delete { key : k }, { mutli : true }, esc defer()
await @db.delete { name_to_key : k }, { multi : true }, esc defer()
log.debug "- DB remove #{k} -> ok"
cb null

#-----

remove : ({type, key}, cb) ->
esc = make_esc cb, "Db::remove"
await @lock.acquire defer()
await @db.run "BEGIN", esc defer()
q = "DELETE FROM kvstore WHERE type=? AND key=?"
await @db.run q, [ type, key ], defer err
q = "DELETE FROM lookup WHERE key_type=? AND key=?"
await @db.run q, [ type, key ], defer e2
await @db.run "COMMIT", esc defer()
@lock.release()
cb err
find1 : (q, cb) ->
await @db.find q, defer err, docs
err = value = null
if err? then # noop
else if (l = docs.length) is 0 then value = null
else if l > 1 then err = new E.CorruptionError "Got #{s} docs back; only wanted 1"
else value = docs[0].value
cb err, value

#-----

get : ({type, key}, cb) ->
type or= key[-2...]
q = "SELECT value FROM kvstore WHERE type=? AND key=?"
args = [ type, key ]
await @db.get q, args, defer err, row
value = null
if row?
try
value = JSON.parse row.value
catch e
err = e
k = dict2str { type,key }
await @find1 { key : k }, defer err, value
cb err, value

#-----

lookup : ({type, name}, cb) ->
q = """SELECT k.type AS type, k.key AS k, k.value AS value
FROM lookup AS l
INNER JOIN kvstore AS k ON (l.key_type = k.type AND l.key = k.key)
WHERE l.name_type = ?
AND l.name = ?"""
args = [ type, name ]
await @db.get q, args, defer err, row
value = null
if row?
try
row.value = JSON.parse row.value
catch e
err = e
cb err, row
k = dict2str { type, key : name }
err = value = null
await @find1 { name : k }, defer err, value
if value? and not err?
await @find1 { key : value }, defer err, value
cb err, value

#-----

_init_db : (cb) ->
log.debug "+ DB::_init_db"
esc = make_esc cb, "DB::_init_db"
sql_file = path.join __dirname, "..", "sql", "schema.sql"
log.debug "+ run sql setup file: #{sql_file}"
await fs.readFile sql_file, esc defer data
commands = data.toString('utf8').split(/\s*;\s*/)
for c in commands when c.match /\S+/
await @db.run (c + ";"), esc defer()
log.debug "- database initialized"
await @db.ensureIndex { fieldName : "key" , unique : true }, esc defer()
await @db.ensureIndex { fieldName : "name", unique : true }, esc defer()
await @db.ensureIndex { fieldName : "name_to_key" }, esc defer()
log.debug "- DB::_init_db"
cb null

##=======================================================================
Expand Down
4 changes: 2 additions & 2 deletions src/fs.iced
Expand Up @@ -5,7 +5,7 @@ C = require 'constants'
{base58} = require './basex'
crypto = require 'crypto'
path = require 'path'
mkdirp = require 'mkdirp'
{mkdir_p} = require('iced-utils').fs
{constants} = require './constants'

##======================================================================
Expand Down Expand Up @@ -119,7 +119,7 @@ exports.mkdirp = (fn, cb) ->
err = null
await fs.exists d, defer found
unless found
await mkdirp d, constants.permissions.dir, defer err, n
await mkdir_p d, constants.permissions.dir, defer err, n
if not err? and n > 0
log.info "Made directory '#{d}'"
cb err, d, n
Expand Down

0 comments on commit 76ca64a

Please sign in to comment.