123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * database.cpp
- *
- * Created on: Dec 4, 2015
- * Author: Philipp Hinz
- */
- #include <cstdio>
- #include <stdlib.h>
- #include <inttypes.h>
- #include <cstdarg>
- #include <cstring>
- #include <string>
- #include <stdexcept>
- #include <pthread.h>
- #include <sys/time.h>
- #include "sqlite/sqlite3.h"
- #include "global.h"
- #include "database.h"
- #include "logger.h"
- using namespace std;
- sqlite3 *db; /**< The database connector */
- /**
- * Helper function to allow the use of vsprintf() with a string
- * See: http://codereview.stackexchange.com/questions/52522/mimic-sprintf-with-stdstring-output
- */
- std::string string_vsprintf(const char* format, std::va_list args) {
- va_list tmp_args; //unfortunately you cannot consume a va_list twice
- va_copy(tmp_args, args); //so we have to copy it
- const int required_len = vsnprintf(nullptr, 0, format, tmp_args) + 1;
- va_end(tmp_args);
- std::string buf(required_len, '\0');
- if (std::vsnprintf(&buf[0], buf.size(), format, args) < 0) {
- throw std::runtime_error { "string_vsprintf encoding error" };
- }
- return buf;
- }
- /**
- * Allows the format of printf but returns a string
- * Source: http://codereview.stackexchange.com/questions/52522/mimic-sprintf-with-stdstring-output
- * @return printf formatted string
- * @param format input string as char array
- */
- std::string string_sprintf(const char* format, ...)
- __attribute__ ((format (printf, 1, 2)));
- std::string string_sprintf(const char* format, ...) {
- std::va_list args;
- va_start(args, format);
- std::string str { string_vsprintf(format, args) };
- va_end(args);
- return str;
- }
- static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
- int i;
- for (i = 0; i < argc; i++) {
- printf("%s = '%s'\n", azColName[i], argv[i] ? argv[i] : "NULL");
- }
- printf("\n");
- return 0;
- }
- /**
- * Opens and initializes a sqlite3 database connection
- * @return 0 on success
- */
- int sqlOpen() {
- int rc = sqlite3_open(SQL_DATABASE, &db);
- if (rc) {
- logger_error("Can't open database: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- return (1);
- }
- logger(V_BASIC, "Successfully opened SQLite connection to %s\n",
- SQL_DATABASE);
- return 0;
- }
- /**
- * Closes the database connection
- */
- void sqlClose() {
- sqlite3_close(db);
- logger(V_BASIC, "Closed SQLite connection.\n");
- }
- /**
- * Executes a SQL statement
- * @param *query SQL query string
- * @return 0 on success
- */
- int sqlExecute(string query) {
- char *zErrMsg = 0;
- int rc;
- struct timeval tv1, tv2;
- //pthread_mutex_lock(&mutex);
- logger(V_SQL, "Executing SQL Query: %s\n", query.c_str());
- gettimeofday(&tv1, NULL);
- rc = sqlite3_exec(db, query.c_str(), NULL, 0, &zErrMsg);
- gettimeofday(&tv2, NULL);
- if (verbose == V_SQL)
- printf("Time taken in execution = %f seconds\n",
- (double) (tv2.tv_usec - tv1.tv_usec) / 1000000
- + (double) (tv2.tv_sec - tv1.tv_sec));
- //pthread_mutex_unlock(&mutex);
- if (rc != SQLITE_OK) {
- logger_error("SQL error (%d): %s\n", rc, zErrMsg);
- sqlite3_free(zErrMsg);
- return rc;
- }
- return 0;
- }
- int sqlExecute2(char *query) {
- char *zErrMsg = 0;
- int rc;
- logger(V_SQL, "Executing SQL Query: %s\n", query);
- rc = sqlite3_exec(db, query, &callback, 0, &zErrMsg);
- if (rc != SQLITE_OK) {
- logger_error("SQL error (%d): %s\n", rc, zErrMsg);
- sqlite3_free(zErrMsg);
- return rc;
- }
- return 0;
- }
- /**
- * Sets up the database and creates the needed structure
- * @return 0 on success
- */
- int sqlSetup() {
- sqlExecute("CREATE TABLE IF NOT EXISTS config "
- "(id INTEGER PRIMARY KEY, "
- "value NUMERIC);");
- return 0;
- }
- /**
- * Reads a configuration key from the database
- * @param id Config ID key
- * @return value as integer (up to 64bit), 0 for not found
- */
- uint64_t sqlGetConf(config_key_t id) {
- sqlite3_stmt *stmt;
- uint64_t out;
- string query = string_sprintf("SELECT id, value FROM config "
- "WHERE id = %d", id);
- int rc = sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, NULL);
- if (rc != SQLITE_OK) {
- logger_error("SQL error (%d): %s\n", rc, sqlite3_errmsg(db));
- sqlite3_finalize(stmt);
- return 0;
- }
- rc = sqlite3_step(stmt);
- if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
- logger_error("SQL error (%d): %s\n", rc, sqlite3_errmsg(db));
- sqlite3_finalize(stmt);
- return 0;
- }
- if (rc == SQLITE_DONE) { // no results
- sqlite3_finalize(stmt);
- return 0;
- }
- out = sqlite3_column_int64(stmt, 1);
- sqlite3_finalize(stmt);
- return out;
- }
- /**
- * Saves a configuration key to the database
- * @param id Config ID key
- * @param value Integer value
- * @return 0 on success
- */
- int sqlSetConf(config_key_t id, uint64_t value) {
- int rc = sqlExecute(string_sprintf("REPLACE INTO config (id, value) "
- "VALUES (%d, %lld);", id, value));
- if (rc != SQLITE_OK)
- return EXIT_FAILURE;
- return EXIT_SUCCESS;
- }
- /**
- * Logs the flow curve
- * @param sweep identification for the curve
- * @param flow the cumulative measured amount
- * @param deltaT time between the last flow interrupt and the current one
- */
- int sqlLogFlow(uint64_t sweep, uint64_t flow, uint64_t deltaT) {
- int rc = sqlExecute(string_sprintf("INSERT INTO flowLog (sweep, flow, timestamp) "
- "VALUES (%lld, %lld, %lld);", sweep, flow, deltaT));
- if (rc != SQLITE_OK)
- return EXIT_FAILURE;
- return EXIT_SUCCESS;
- }
- /**
- * Converts the GUID from int to char array
- * @param *guid Pointer to the uint8_t GUID
- * @return pointer to the converted string
- */
- char *inttochar(uint8_t *guid) {
- char *out = new char[9];
- for (int i = 0; i < 8; i++) {
- out[i] = (char) guid[i];
- }
- out[8] = '\0';
- return out;
- }
- /**
- * Converts the GUID from char to int array
- * @param *guid Pointer to the char GUID
- * @return pointer to the converted int array
- */
- uint8_t *chartoint(const unsigned char *guid) {
- uint8_t *out = new uint8_t[8];
- for (int i = 0; i < 8; i++) {
- out[i] = (uint8_t) guid[i];
- }
- return out;
- }
- /**
- * Converts the GUID from int64 to int8 array
- * @param guid 64bit GUID
- * @return pointer to the converted int array
- */
- uint8_t *int64to8bit(sqlite_int64 guid) {
- uint8_t *out = new uint8_t[8];
- for (int i = 7; i >= 0; i--) {
- out[i] = guid & 0xff;
- guid = guid >> 8;
- }
- return out;
- }
- sqlite_int64 int8to64bit(uint8_t *guid) {
- sqlite_int64 out = 0;
- for (int i = 0; i < 8; i++) {
- out |= guid[i] << (8 * (7 - i));
- }
- return out;
- }
- void sqltest() {
- sqlSetup();
- //sqlExecute2("SELECT * FROM nodes;");
- }
|