all repos — litestore @ ce9af5ab540d97c66234bb9132adb0c6c6a2cbbb

A minimalist nosql document store.

Added support for logging.
h3rald h3rald@h3rald.com
Fri, 06 Feb 2015 21:32:32 +0100
commit

ce9af5ab540d97c66234bb9132adb0c6c6a2cbbb

parent

0716dcbda094e67ac919c9fbef2f61a5b8c5c7b1

8 files changed, 60 insertions(+), 28 deletions(-)

jump to
M .gitignore.gitignore

@@ -1,3 +1,4 @@

+*.log.txt nimcache *.ls litestore
M lib/cli.nimlib/cli.nim

@@ -1,6 +1,7 @@

import parseopt2, - strutils + strutils, + logging import types

@@ -15,11 +16,13 @@ LS [-p:<port> -a:<address>] [<file>] [--pack:<directory> | --unpack:<directory>]

Options: -a, --address Specify address (default: 0.0.0.0). + --export Export the previously-packed specified directory to the current directory. -h, --help Display this message. - -p, --port Specify port number (default: 70700). + --import Import the specified directory (Store all its contents). + -l, --log Specify the log level: debug, info, warn, error, fatal, none (default: info) + -p, --port Specify port number (default: 9500). + --purge Delete exported files (used in conjunction with --export). -r, --readonly Allow only data retrieval operations. - --pack Pack the specified directory (Store all its contents). - --unpack Unpack the previously-packed specified directory to the current directory. -v, --version Display the program version. """

@@ -30,6 +33,8 @@ address = "0.0.0.0"

operation = opRun directory = "" readonly = false + purge = false + logLevel = lvlInfo for kind, key, val in getOpt():

@@ -40,12 +45,16 @@ of "address", "a":

address = val of "port", "p": port = val.parseInt - of "pack": - operation = opPack + of "log", "l": + logLevel = logging.LevelNames.find(val.toUpper).Level + of "import": + operation = opImport directory = val - of "unpack": - operation = opUnpack + of "export": + operation = opExport directory = val + of "purge": + purge = true of "version", "v": echo version quit(0)

@@ -67,7 +76,13 @@ LS.port = port

LS.address = address LS.operation = operation LS.file = file +LS.purge = purge LS.directory = directory LS.appversion = version LS.readonly = readonly LS.appname = "LiteStore" + +# Initialize loggers + +logging.handlers.add(newConsoleLogger(logLevel, "$date $time - ")) +logging.handlers.add(newRollingFileLogger("litestore.log.txt", fmReadWrite, logLevel, "$date $time - ", 100000))
M lib/core.nimlib/core.nim

@@ -165,7 +165,7 @@ tag_array.add(obj)

return %tag_array -proc packDir*(store: Datastore, dir: string) = +proc importDir*(store: Datastore, dir: string) = if not dir.dirExists: raise newException(EDirectoryNotFound, "Directory '$1' not found." % dir) for f in dir.walkDirRec():

@@ -181,10 +181,10 @@ if d_ct.isBinary:

d_binary = 1 d_searchable = 0 discard store.createDocument(d_id, d_contents, d_ct, d_binary, d_searchable) - store.db.exec(SQL_INSERT_TAG, "$collection:"&dir, d_id) + store.db.exec(SQL_INSERT_TAG, "$dir:"&dir, d_id) -proc unpackDir*(store: Datastore, dir: string) = - let docs = store.db.getAllRows(SQL_SELECT_DOCUMENTS_BY_TAG, "$collection:"&dir) +proc exportDir*(store: Datastore, dir: string, purge = false) = + let docs = store.db.getAllRows(SQL_SELECT_DOCUMENTS_BY_TAG, "$dir:"&dir) for doc in docs: let file = doc[0] var data: string

@@ -194,6 +194,8 @@ else:

data = doc[1] file.parentDir.createDir file.writeFile(data) + if purge: + store.db.exec(SQL_DELETE_DOCUMENTS_BY_TAG, "$dir:"&dir) proc destroyDocumentsByTag*(store: Datastore, tag: string): int64 = result = 0
M lib/queries.nimlib/queries.nim

@@ -121,3 +121,9 @@

const SQL_COUNT_DOCUMENTS* = sql""" SELECT COUNT(id) FROM documents """ + +const SQL_DELETE_DOCUMENTS_BY_TAG* = sql""" +DELETE FROM documents, tags +WHERE documents.id = tags.document_id AND +tag_id = ? +"""
M lib/server.nimlib/server.nim

@@ -1,11 +1,17 @@

-import asynchttpserver2, asyncdispatch, times, strutils, pegs, strtabs, cgi +import asynchttpserver2, asyncdispatch, times, strutils, pegs, strtabs, cgi, logging import types, utils, api_v1 proc getReqInfo(req: Request): string = - return $getLocalTime(getTime()) & " - " & req.hostname & " " & req.reqMethod & " " & req.url.path + var url = req.url.path + if req.url.anchor != "": + url = url & "#" & req.url.anchor + if req.url.query != "": + url = url & "?" & req.url.query + return req.hostname & " " & req.reqMethod & " " & url proc handleCtrlC() {.noconv.} = - echo "\nExiting..." + echo "" + info("Exiting...") quit() proc parseApiUrl(req: Request): ResourceInfo =

@@ -38,9 +44,9 @@

proc serve*(LS: LiteStore) = var server = newAsyncHttpServer() proc handleHttpRequest(req: Request): Future[void] {.async.} = - echo getReqInfo(req) + info getReqInfo(req) let res = req.route(LS) await req.respond(res.code, res.content, res.headers) - echo LS.appname, " v", LS.appversion, " started on ", LS.address, ":", LS.port, "." + info(LS.appname & " v" & LS.appversion & " started on " & LS.address & ":" & $LS.port & ".") asyncCheck server.serve(LS.port.Port, handleHttpRequest, LS.address)
M lib/types.nimlib/types.nim

@@ -23,7 +23,7 @@ tag*: string

startswith*: bool endswith*: bool negated*: bool - Operation* = enum opRun, opPack, opUnpack + Operation* = enum opRun, opImport, opExport LiteStore* = object store*: Datastore address*: string

@@ -31,6 +31,7 @@ port*: int

operation*: Operation directory*: string file*: string + purge*: bool readonly*: bool appname*: string appversion*: string
M lib/utils.nimlib/utils.nim

@@ -1,4 +1,4 @@

-import json, db_sqlite, strutils, pegs, asyncdispatch, asynchttpserver2, times +import json, db_sqlite, strutils, pegs, asyncdispatch, asynchttpserver2, times, logging import types, queries, contenttypes proc dbQuote*(s: string): string =

@@ -93,11 +93,12 @@

proc destroyDocumentSystemTags*(store: Datastore, docid) = store.db.exec(SQL_DELETE_DOCUMENT_SYSTEM_TAGS, docid) -proc error*(code, msg) = +proc fail*(code, msg) = stderr.writeln(msg) quit(code) proc resError*(code: HttpCode, message: string): Response = + warn(message) result.code = code result.content = """{"error":"$1"}""" % message result.headers = ctJsonHeader()
M litestore.nimlitestore.nim

@@ -27,23 +27,23 @@ if not LS.file.fileExists:

try: LS.file.createDatastore() except: - error(1, "Unable to create datastore '$1'" % [LS.file]) + fail(1, "Unable to create datastore '$1'" % [LS.file]) try: LS.store = LS.file.openDatastore() except: - error(2, "Unable to open datastore '$1'" % [LS.file]) + fail(2, "Unable to open datastore '$1'" % [LS.file]) case LS.operation: - of opPack: - LS.store.packDir(LS.directory) - of opUnpack: - LS.store.unpackDir(LS.directory) + of opImport: + LS.store.importDir(LS.directory) + of opExport: + LS.store.exportDir(LS.directory, LS.purge) of opRun: # STARTTEST LS.file.destroyDatastore() LS.file.createDatastore() LS.store = LS.file.openDatastore() - LS.store.packDir("nimcache") - LS.store.packDir("lib") + LS.store.importDir("nimcache") + LS.store.importDir("lib") # ENDTEST LS.serve runForever()