diff --git a/db.c b/db.c new file mode 100644 index 0000000..1c1977d --- /dev/null +++ b/db.c @@ -0,0 +1,92 @@ +/* $Id$ */ +/* + * Copyright (c) 2016 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "extern.h" + +/* + * When the database is busy or locked, sleep for a random amount of + * time before continuing. + * We could put all sorts of heuristics in here to back off, but we do + * something really simple. + */ +static void +db_sleep(size_t attempt) +{ + + if (attempt < 10) + usleep(arc4random_uniform(100000)); + else + usleep(arc4random_uniform(500000)); +} + +/* + * Open the database and stash the resulting handle in the kreq + */ +int +db_open(struct kreq *r, const char *file) +{ + size_t attempt; + sqlite3 *db; + int rc; + + attempt = 0; + // TODO max attempt, return 0 +again: + rc = sqlite3_open(file, &db); + if (SQLITE_BUSY == rc) { + db_sleep(attempt++); + goto again; + } else if (SQLITE_LOCKED == rc) { + fprintf(stderr, "sqlite3_open: %s\n", + sqlite3_errmsg(db)); + db_sleep(attempt++); + goto again; + } else if (SQLITE_PROTOCOL == rc) { + fprintf(stderr, "sqlite3_open: %s\n", + sqlite3_errmsg(db)); + db_sleep(attempt++); + goto again; + } else if (SQLITE_OK == rc) { + sqlite3_busy_timeout(db, 500); + r->arg = sql; + return(1); + } +} + +/* + * Close the database stashed in the kreq's argument. + */ +void +db_close(struct kreq *r) +{ + if (SQLITE_OK == sqlite3_close(r->arg)) { + r->arg = NULL; + return; + } + fprintf(stderr, "sqlite3_close: %s\n", sqlite3_errmsg(db)); +} diff --git a/extern.h b/extern.h new file mode 100644 index 0000000..9c421d7 --- /dev/null +++ b/extern.h @@ -0,0 +1,29 @@ +/* $Id$ */ +/* + * Copyright (c) 2016 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef EXTERN_H +#define EXTERN_H + +__BEGIN_DECLS + +void db_close(struct kreq *); +int db_open(struct kreq *, const char *); + +void json_emptydoc(struct kreq *); + +__END_DECLS + +#endif diff --git a/json.c b/json.c new file mode 100644 index 0000000..7fd7933 --- /dev/null +++ b/json.c @@ -0,0 +1,41 @@ +/* $Id$ */ +/* + * Copyright (c) 2016 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include + +#include +#include + +#include "extern.h" + +/* + * Emit an empty JSON document. + */ +void +json_emptydoc(struct kreq *r) +{ + struct kjsonreq req; + + kjson_open(&req, r); + kjson_obj_open(&req); + kjson_obj_close(&req); + kjson_close(&req); +} +