static sqlite3 *openDatabase(void) { sqlite3 *db; int res; if (!databaseName) { databaseName = getenv(DATABASE_NAME_ENVAR); if(!databaseName) databaseName = DEFAULT_DATABASE_NAME; } if (deleteDatabase) { res = remove(databaseName); if (res) evlog(LOG_ALWAYS, "Could not remove database file %s", databaseName); else evlog(LOG_OFTEN, "Removed database file %s", databaseName); } res = sqlite3_open_v2(databaseName, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); /* use default sqlite_vfs object */ if (res != SQLITE_OK) sqlite_error(res, db, "Opening %s failed", databaseName); evlog(LOG_OFTEN, "Writing to %s.",databaseName); return db; }
static void sqlite_error(int res, sqlite3 *db, const char *format, ...) { va_list args; evlog(LOG_ALWAYS, "Fatal SQL error %d", res); va_start(args, format); vlog(LOG_ALWAYS, format, args); va_end(args); evlog(LOG_ALWAYS, "SQLite message: %s\n", sqlite3_errmsg(db)); exit(1); }
int main(int argc, char *argv[]) { sqlite3 *db; int64 count; parseArgs(argc, argv); db = openDatabase(); if (rebuild) { dropGlueTables(db); } makeTables(db); fillGlueTables(db); count = writeEventsToSQL(db); evlog(LOG_ALWAYS, "Imported %llu events from %s to %s, serial %lu.", count, logFileName, databaseName, logSerial); if (runTests) { /* TODO: more unit tests in here */ testTableExists(db); } closeDatabase(db); return 0; }
static void closeDatabase(sqlite3 *db) { int res = sqlite3_close(db); if (res != SQLITE_OK) sqlite_error(res, db, "Closing database failed"); evlog(LOG_SOMETIMES, "Closed %s.", databaseName); }
static void makeTables(sqlite3 *db) { size_t i; evlog(LOG_SOMETIMES, "Creating tables."); for (i=0; i < (sizeof(createStatements)/sizeof(createStatements[0])); ++i) { runStatement(db, createStatements[i], "Table creation"); } }
static void dropGlueTables(sqlite3 *db) { size_t i; int res; char sql[1024]; evlog(LOG_ALWAYS, "Dropping glue tables so they are rebuilt."); for (i=0; i < (sizeof(glueTables)/sizeof(glueTables[0])); ++i) { evlog(LOG_SOMETIMES, "Dropping table %s", glueTables[i]); sprintf(sql, "DROP TABLE %s", glueTables[i]); res = sqlite3_exec(db, sql, NULL, /* No callback */ NULL, /* No callback closure */ NULL); /* error messages handled by sqlite_error */ /* Don't check for errors. */ (void)res; } }
static void testTableExists(sqlite3 *db) { size_t i; int defects = 0; int tests = 0; for (i=0; i < (sizeof(tableTests)/sizeof(tableTests[0])); ++i) { const char *name = tableTests[i].name; int exists = tableExists(db, name); if (exists) evlog(LOG_OFTEN, "Table exists: %s", name); else evlog(LOG_OFTEN, "Table does not exist: %s", name); if (exists != tableTests[i].exists) { evlog(LOG_ALWAYS, "tableExists test failed on table %s", name); ++ defects; } ++ tests; } evlog(LOG_ALWAYS, "%d tests, %d defects found.", tests, defects); }
static void runStatement(sqlite3 *db, const char *sql, const char *description) { int res; evlog(LOG_SELDOM, "%s: %s", description, sql); res = sqlite3_exec(db, sql, NULL, /* No callback */ NULL, /* No callback closure */ NULL); /* error messages handled by sqlite_error */ if (res != SQLITE_OK) sqlite_error(res, db, "%s failed - statement %s", description, sql); }
static sqlite3_stmt *prepareStatement(sqlite3 *db, const char *sql) { int res; sqlite3_stmt *statement; evlog(LOG_SELDOM, "Preparing statement %s", sql); res = sqlite3_prepare_v2(db, sql, -1, /* prepare whole string as statement */ &statement, NULL); if (res != SQLITE_OK) sqlite_error(res, db, "statement preparation failed: %s", sql); return statement; }
static FILE *openLog(sqlite3 *db) { FILE *input; registerLogFile(db, logFileName); if (!logFileName) { input = stdin; logFileName = "<stdin>"; } else { input = fopen(logFileName, "r"); if (input == NULL) error("unable to open %s", logFileName); } evlog(LOG_OFTEN, "Reading %s.", logFileName ? logFileName : "standard input"); return input; }
static void logFileCompleted(sqlite3 *db, int64 completed) { sqlite3_stmt *statement; int res; statement = prepareStatement(db, "UPDATE event_log SET completed=? WHERE serial=?"); res = sqlite3_bind_int64(statement, 2, logSerial); if (res != SQLITE_OK) sqlite_error(res, db, "event_log update bind of serial failed."); res = sqlite3_bind_int64(statement, 1, completed); if (res != SQLITE_OK) sqlite_error(res, db, "event_log update bind of completed failed."); res = sqlite3_step(statement); if (res != SQLITE_DONE) sqlite_error(res, db, "insert into event_log failed."); evlog(LOG_SOMETIMES, "Marked in event_log: %lu events", completed); finalizeStatement(db, statement); }
void evoff_() { #ifdef EVENTLOG evlog(EVKEY_DISABLE, EVKEY_LAST_ARG); #endif }
void evon_() { #ifdef EVENTLOG evlog(EVKEY_ENABLE, EVKEY_LAST_ARG); #endif }
static int64 readLog(FILE *input, sqlite3 *db) { int64 eventCount = 0; /* declare statements for every event type */ EVENT_LIST(EVENT_TYPE_DECLARE_STATEMENT, X); /* prepare statements for every event type */ EVENT_LIST(EVENT_TYPE_PREPARE_STATEMENT, X); runStatement(db, "BEGIN", "Transaction start"); while (TRUE) { /* loop for each event */ char line[MAX_LOG_LINE_LENGTH]; char *p; char *q; int last_index=0; sqlite3_stmt *statement = NULL; int res; int64 clock_field; long code; p = fgets(line, MAX_LOG_LINE_LENGTH, input); if (!p) { if (feof(input)) break; else error("Couldn't read line after event %llu", eventCount); } eventCount++; clock_field = strtoll(p, &q, 16); if (q == p) error("event %llu clock field not a hex integer: %s", eventCount, p); if (*q != ' ') error("event %llu code field not preceded by ' ': %s", eventCount, q); while(*q == ' ') ++q; p = q; code = strtol(p, &q, 16); if (q == p) error("event %llu code field not an integer: %s", eventCount, p); p = q; /* Write event to SQLite. */ switch (code) { /* this macro sets statement and last_index */ EVENT_LIST(EVENT_TYPE_WRITE_SQL, X); default: error("Event %llu has Unknown event code %d", eventCount, code); } /* bind the fields we store for every event */ \ res = sqlite3_bind_int64(statement, last_index+1, logSerial); if (res != SQLITE_OK) sqlite_error(res, db, "Event %llu bind of log_serial failed.", eventCount); res = sqlite3_bind_int64(statement, last_index+2, clock_field); if (res != SQLITE_OK) sqlite_error(res, db, "Event %llu bind of clock failed.", eventCount); res = sqlite3_step(statement); if (res != SQLITE_DONE) sqlite_error(res, db, "insert of event %llu failed.", eventCount); res = sqlite3_reset(statement); if (res != SQLITE_OK) sqlite_error(res, db, "Couldn't reset insert statement of event %llu", eventCount); if (progress) { if ((eventCount % SMALL_TICK) == 0) { printf("."); fflush(stdout); if (((eventCount / SMALL_TICK) % BIG_TICK) == 0) { printf("\n"); fflush(stdout); evlog(LOG_SOMETIMES, "%lu events.", (unsigned long)eventCount); } } } } if (progress) { printf("\n"); fflush(stdout); } runStatement(db, "COMMIT", "Transaction finish"); logFileCompleted(db, eventCount); /* finalize all the statements */ EVENT_LIST(EVENT_TYPE_FINALIZE_STATEMENT, X); return eventCount; }
static void registerLogFile(sqlite3 *db, const char *filename) { sqlite3_stmt *statement; int res; const unsigned char *name; int64 completed; int64 file_size; int64 file_modtime; if (filename) { struct stat st; res = stat(filename, &st); if (res != 0) error("Couldn't stat() %s", filename); file_size = st.st_size; file_modtime = st.st_mtime; statement = prepareStatement(db, "SELECT name, serial, completed FROM event_log" " WHERE size = ? AND modtime = ?"); res = sqlite3_bind_int64(statement, 1, file_size); if (res != SQLITE_OK) sqlite_error(res, db, "event_log bind of size failed."); res = sqlite3_bind_int64(statement, 2, file_modtime); if (res != SQLITE_OK) sqlite_error(res, db, "event_log bind of modtime failed."); res = sqlite3_step(statement); switch(res) { case SQLITE_DONE: evlog(LOG_SOMETIMES, "No log file matching '%s' found in database.", filename); break; case SQLITE_ROW: name = sqlite3_column_text(statement, 0); logSerial = sqlite3_column_int64(statement, 1); completed = sqlite3_column_int64(statement, 2); evlog(force ? LOG_OFTEN : LOG_ALWAYS, "Log file matching '%s' already in event_log, named \"%s\" (serial %lu, completed %lu).", filename, name, logSerial, completed); if (force) { evlog(LOG_OFTEN, "Continuing anyway because -f specified."); } else { evlog(LOG_ALWAYS, "Exiting. Specify -f to force events into SQL anyway."); exit(0); } break; default: sqlite_error(res, db, "select from event_log failed."); } finalizeStatement(db, statement); } else { /* stdin */ filename = "<stdin>"; file_size = 0; file_modtime = 0; } statement = prepareStatement(db, "INSERT into event_log (name, size, modtime, completed)" " VALUES (?, ?, ?, 0)"); res = sqlite3_bind_text(statement, 1, filename, -1, SQLITE_STATIC); if (res != SQLITE_OK) sqlite_error(res, db, "event_log insert bind of name failed."); res = sqlite3_bind_int64(statement, 2, file_size); if (res != SQLITE_OK) sqlite_error(res, db, "event_log insert bind of size failed."); res = sqlite3_bind_int64(statement, 3, file_modtime); if (res != SQLITE_OK) sqlite_error(res, db, "event_log insert bind of modtime failed."); res = sqlite3_step(statement); if (res != SQLITE_DONE) sqlite_error(res, db, "insert into event_log failed."); logSerial = sqlite3_last_insert_rowid(db); evlog(LOG_SOMETIMES, "Log file %s added to event_log with serial %lu", filename, logSerial); finalizeStatement(db, statement); }