diff --git a/CMakeLists.txt b/CMakeLists.txt index b093826..79d9af1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.6) project(meta_exporter) -set(CMAKE_C_FLAGS "-O1 -Wall -std=gnu99") +set(CMAKE_C_FLAGS "-O1 -Wall -std=gnu99 -g") set(LIBS pthread mnl) set(SOURCE @@ -40,6 +40,7 @@ if (SQLITE3) metadata_writer_json_helpers.c metadata_writer_inventory_conn.c metadata_writer_inventory_gps.c + metadata_writer_inventory_system.c metadata_writer_sqlite_monitor.c) add_definitions("-DSQLITE_SUPPORT") endif() diff --git a/files/metadata-exporter.conf.example b/files/metadata-exporter.conf.example index c7fa1fe..d9d30e6 100644 --- a/files/metadata-exporter.conf.example +++ b/files/metadata-exporter.conf.example @@ -16,7 +16,8 @@ "netlink": { "conn" : true, "pos" : true, - "iface": true + "iface": true, + "system": true, }, "sqlite": { "database": "/tmp/metadata.db", diff --git a/metadata_exporter.c b/metadata_exporter.c index e8b8820..486966b 100644 --- a/metadata_exporter.c +++ b/metadata_exporter.c @@ -223,6 +223,38 @@ static struct json_object *create_fake_gps_rmc_obj() } #endif +static struct json_object *create_fake_restart_obj() +{ + struct json_object *obj = NULL, *obj_add = NULL; + struct timeval tv; + + if (!(obj = json_object_new_object())) { + return NULL; + } + + gettimeofday(&tv, NULL); + if (!(obj_add = json_object_new_int64(tv.tv_sec))) { + json_object_put(obj); + return NULL; + } + json_object_object_add(obj, "timestamp", obj_add); + + if (!(obj_add = json_object_new_int(META_TYPE_SYSTEM))) { + json_object_put(obj); + return NULL; + } + json_object_object_add(obj, "event_type", obj_add); + + if (!(obj_add = json_object_new_string("861107030230685"))) { + json_object_put(obj); + return NULL; + } + json_object_object_add(obj, "imei", obj_add); + + return obj; +} + +#if 0 static struct json_object *create_fake_conn_obj(uint64_t l3_id, uint64_t l4_id, uint8_t event_param, char *event_value_str, uint64_t tstamp) { @@ -373,6 +405,7 @@ static struct json_object *create_fake_conn_obj(uint64_t l3_id, uint64_t l4_id, return obj; } +#endif static ssize_t send_netlink_json(uint8_t *snd_buf, struct json_object *parsed_obj, int32_t sock_fd, @@ -552,16 +585,18 @@ static void test_netlink(uint32_t packets) while(1) { gettimeofday(&tv, NULL); - if (i == 0) + /*if (i == 0) obj_to_send = create_fake_conn_obj(0, 0, CONN_EVENT_META_UPDATE, "1,2,1,", i+1); else - obj_to_send = create_fake_conn_obj(0, 0, CONN_EVENT_META_UPDATE, "1,2,1,4", i+1); + obj_to_send = create_fake_conn_obj(0, 0, CONN_EVENT_META_UPDATE, "1,2,1,4", i+1);*/ /*if (i < 4) obj_to_send = create_fake_conn_obj(1, 2, CONN_EVENT_L3_UP, "1,2,1", i+1); else obj_to_send = create_fake_conn_obj(1, 2, CONN_EVENT_DATA_USAGE_UPDATE, "1,2,1,4", tv.tv_sec);*/ + obj_to_send = create_fake_restart_obj(); + if (!obj_to_send) continue; diff --git a/metadata_exporter.h b/metadata_exporter.h index de7732a..924edc6 100644 --- a/metadata_exporter.h +++ b/metadata_exporter.h @@ -53,6 +53,7 @@ #define META_TYPE_MUNIN 0x05 #define META_TYPE_SYSEVENT 0x06 #define META_TYPE_RADIO 0x08 +#define META_TYPE_SYSTEM 0x10 enum iface_event { IFACE_EVENT_DEV_STATE=1, @@ -190,6 +191,8 @@ struct md_iface_event { uint8_t event_type; }; +typedef struct md_iface_event md_system_event_t; + struct md_conn_event { MD_EVENT; uint8_t event_type; diff --git a/metadata_input_netlink.c b/metadata_input_netlink.c index 9b84542..40b5dbc 100644 --- a/metadata_input_netlink.c +++ b/metadata_input_netlink.c @@ -679,6 +679,19 @@ static uint8_t md_input_netlink_add_json_key_value(const char *key, return RETVAL_SUCCESS; } +static void md_input_netlink_handle_system_event(struct md_input_netlink *min, + struct json_object *obj) +{ + //recycle iface event, it contains all fields we need (currently) + memset(min->mse, 0, sizeof(md_system_event_t)); + min->mse->md_type = META_TYPE_SYSTEM; + + if (md_input_netlink_parse_iface_event(min, obj, min->mse) == RETVAL_FAILURE) + return; + + mde_publish_event_obj(min->parent, (struct md_event*) min->mse); +} + static void md_input_netlink_handle_event(void *ptr, int32_t fd, uint32_t events) { struct md_input_netlink *min = ptr; @@ -746,6 +759,9 @@ static void md_input_netlink_handle_event(void *ptr, int32_t fd, uint32_t events case META_TYPE_RADIO: md_input_netlink_handle_radio_event(min, nlh_obj); break; + case META_TYPE_SYSTEM: + md_input_netlink_handle_system_event(min, nlh_obj); + break; default: META_PRINT(min->parent->logfile, "Unknown event type\n"); break; @@ -773,7 +789,7 @@ static uint8_t md_input_netlink_config(struct md_input_netlink *min) backend_event_loop_update(min->parent->event_loop, EPOLLIN, EPOLL_CTL_ADD, mnl_socket_get_fd(min->metadata_sock), min->event_handle); - //TODO: Move to handler + //TODO: guard with check for flag min->mce = calloc(sizeof(struct md_conn_event), 1); if (min->mce == NULL) return RETVAL_FAILURE; @@ -786,6 +802,11 @@ static uint8_t md_input_netlink_config(struct md_input_netlink *min) if (min->mre == NULL) return RETVAL_FAILURE; + min->mse = calloc(sizeof(md_system_event_t), 1); + if (min->mre == NULL) + return RETVAL_FAILURE; + + return RETVAL_SUCCESS; } @@ -797,14 +818,17 @@ static uint8_t md_input_netlink_init(void *ptr, json_object* config) json_object* subconfig; if (json_object_object_get_ex(config, "netlink", &subconfig)) { json_object_object_foreach(subconfig, key, val) { - if (!strcmp(key, "conn")) + if (!strcmp(key, "conn")) { md_nl_mask |= META_TYPE_CONNECTION; - else if (!strcmp(key, "pos")) + } else if (!strcmp(key, "pos")) { md_nl_mask |= META_TYPE_POS; - else if (!strcmp(key, "iface")) + } else if (!strcmp(key, "iface")) { md_nl_mask |= META_TYPE_INTERFACE; - else if (!strcmp(key, "radio")) + } else if (!strcmp(key, "radio")) { md_nl_mask |= META_TYPE_RADIO; + } else if (!strcmp(key, "system")) { + md_nl_mask |= META_TYPE_SYSTEM; + } } } @@ -826,6 +850,7 @@ void md_netlink_usage() fprintf(stderr, " \"pos\":\t\tReceive netlink position events\n"); fprintf(stderr, " \"iface\":\t\tReceive netlink interface events\n"); fprintf(stderr, " \"radio\":\t\tReceive netlink radio events (QXDM + neigh. cells)\n"); + fprintf(stderr, " \"system\":\t\tReceive netlink system (reboot) events\n"); fprintf(stderr, "},\n"); } diff --git a/metadata_input_netlink.h b/metadata_input_netlink.h index 2ed4cef..c706379 100644 --- a/metadata_input_netlink.h +++ b/metadata_input_netlink.h @@ -38,6 +38,7 @@ struct md_input_netlink { struct md_conn_event *mce; struct md_iface_event *mie; struct md_radio_event *mre; + md_system_event_t *mse; }; void md_netlink_usage(); diff --git a/metadata_writer_inventory_system.c b/metadata_writer_inventory_system.c new file mode 100644 index 0000000..005f1b6 --- /dev/null +++ b/metadata_writer_inventory_system.c @@ -0,0 +1,84 @@ +#include +#include + +#include "metadata_writer_inventory_system.h" +#include "metadata_exporter_log.h" +#include "metadata_writer_sqlite_helpers.h" +#include "metadata_writer_json_helpers.h" + +uint8_t md_inventory_handle_system_event(struct md_writer_sqlite *mws, + md_system_event_t *mse) +{ + sqlite3_stmt *stmt = mws->insert_system; + sqlite3_clear_bindings(stmt); + sqlite3_reset(stmt); + + if (sqlite3_bind_int(stmt, 1, mws->node_id) || + sqlite3_bind_int(stmt, 2, mws->session_id) || // BootCount + sqlite3_bind_int(stmt, 3, mws->session_id_multip) || // BootMultiplier + sqlite3_bind_int(stmt, 4, mse->tstamp) || + sqlite3_bind_int(stmt, 5, mse->sequence) || + sqlite3_bind_text(stmt, 6, mse->imei, strlen(mse->imei), + SQLITE_STATIC)) { + META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Failed to bind values to " + "INSERT query (system)\n"); + return RETVAL_FAILURE; + } + + if (sqlite3_step(stmt) != SQLITE_DONE) { + return RETVAL_FAILURE; + } else { + return RETVAL_SUCCESS; + } +} + +static uint8_t md_inventory_system_dump_db_json(struct md_writer_sqlite *mws, + FILE *output) +{ + const char *json_str; + sqlite3_reset(mws->dump_system); + + json_object *jarray = json_object_new_array(); + + if (md_json_helpers_dump_write(mws->dump_system, jarray)) + { + json_object_put(jarray); + return RETVAL_FAILURE; + } + + json_str = json_object_to_json_string_ext(jarray, JSON_C_TO_STRING_PLAIN); + fprintf(output, "%s", json_str); + + json_object_put(jarray); + return RETVAL_SUCCESS; +} + +static uint8_t md_inventory_system_delete_db(struct md_writer_sqlite *mws) +{ + int32_t retval; + + sqlite3_reset(mws->delete_system); + retval = sqlite3_step(mws->delete_system); + + if (retval != SQLITE_DONE) { + META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Failed to delete system %s\n", + sqlite3_errstr(retval)); + return RETVAL_FAILURE; + } + + return RETVAL_SUCCESS; +} + +uint8_t md_inventory_system_copy_db(struct md_writer_sqlite *mws) +{ + uint8_t retval = RETVAL_SUCCESS; + + retval = md_writer_helpers_copy_db(mws->system_prefix, + mws->system_prefix_len, md_inventory_system_dump_db_json, mws, + md_inventory_system_delete_db); + + if (retval == RETVAL_SUCCESS) + mws->num_system_events = 0; + + return retval; +} diff --git a/metadata_writer_inventory_system.h b/metadata_writer_inventory_system.h new file mode 100644 index 0000000..d50d3f1 --- /dev/null +++ b/metadata_writer_inventory_system.h @@ -0,0 +1,11 @@ +#ifndef METADATA_WRITER_INVENTORY_SYSTEM_H +#define METADATA_WRITER_INVENTORY_SYSTEM_H + +#include "metadata_exporter.h" +#include "metadata_writer_sqlite.h" + +uint8_t md_inventory_handle_system_event(struct md_writer_sqlite *mws, + md_system_event_t *mse); +uint8_t md_inventory_system_copy_db(struct md_writer_sqlite *mws); + +#endif diff --git a/metadata_writer_sqlite.c b/metadata_writer_sqlite.c index 462382f..3f3ff91 100644 --- a/metadata_writer_sqlite.c +++ b/metadata_writer_sqlite.c @@ -40,6 +40,7 @@ #include "metadata_writer_sqlite_helpers.h" #include "metadata_writer_inventory_gps.h" #include "metadata_writer_sqlite_monitor.h" +#include "metadata_writer_inventory_system.h" #include "netlink_helpers.h" #include "system_helpers.h" #include "backend_event_loop.h" @@ -75,11 +76,13 @@ static void md_sqlite_copy_db(struct md_writer_sqlite *mws, uint8_t from_timeout mws->timeout_added = 0; } - META_PRINT_SYSLOG(mws->parent, LOG_INFO, "Will export DB. # meta %u # gps %u # monitor %u usage %u\n", + META_PRINT_SYSLOG(mws->parent, LOG_INFO, "Will export DB. # meta %u " + "# gps %u # monitor %u usage %u system %u\n", mws->num_conn_events, mws->num_gps_events, mws->num_munin_events, - mws->num_usage_events); + mws->num_usage_events, + mws->num_system_events); if (mws->num_conn_events) { retval = md_inventory_conn_copy_db(mws); @@ -109,6 +112,13 @@ static void md_sqlite_copy_db(struct md_writer_sqlite *mws, uint8_t from_timeout num_failed++; } + if (mws->num_system_events) { + retval = md_inventory_system_copy_db(mws); + + if (retval == RETVAL_FAILURE) + num_failed++; + } + if (num_failed != 0) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "%u DB dump(s) failed\n", num_failed); mws->file_failed = 1; @@ -264,16 +274,24 @@ static sqlite3* md_sqlite_configure_db(struct md_writer_sqlite *mws, const char return NULL; } + if (sqlite3_exec(db_handle, CREATE_REBOOT_SQL, NULL, NULL, &db_errmsg)) { + META_PRINT_SYSLOG(mws->parent, LOG_ERR, "db create (reboot) failed with message: %s\n", db_errmsg); + sqlite3_close_v2(db_handle); + return NULL; + } + return db_handle; } static int md_sqlite_configure(struct md_writer_sqlite *mws, - const char *db_filename, uint32_t node_id, const char* nodeid_file, uint32_t db_interval, + const char *db_filename, uint32_t node_id, uint32_t db_interval, uint32_t db_events, const char *meta_prefix, const char *gps_prefix, - const char *monitor_prefix, const char *usage_prefix) + const char *monitor_prefix, const char *usage_prefix, + const char *system_prefix) { sqlite3 *db_handle = md_sqlite_configure_db(mws, db_filename); - const char *dump_events, *dump_updates, *dump_gps, *dump_monitor, *dump_usage; + const char *dump_events, *dump_updates, *dump_gps, *dump_monitor, + *dump_usage, *dump_system; if (db_handle == NULL) return RETVAL_FAILURE; @@ -282,7 +300,7 @@ static int md_sqlite_configure(struct md_writer_sqlite *mws, mws->node_id = node_id; } else { #ifdef MONROE - mws->node_id = system_helpers_get_nodeid(nodeid_file); + mws->node_id = system_helpers_get_nodeid(mws->node_id_file); #endif } @@ -292,12 +310,14 @@ static int md_sqlite_configure(struct md_writer_sqlite *mws, dump_gps = DUMP_GPS; dump_monitor = DUMP_MONITOR; dump_usage = DUMP_USAGE; + dump_system = NULL; } else { dump_events = DUMP_EVENTS_JSON; dump_updates = DUMP_UPDATES_JSON; dump_gps = DUMP_GPS_JSON; dump_monitor = DUMP_MONITOR_JSON; dump_usage = DUMP_USAGE_JSON; + dump_system = DUMP_SYSTEM_JSON; } //Only set variables that are not 0 @@ -343,7 +363,13 @@ static int md_sqlite_configure(struct md_writer_sqlite *mws, sqlite3_prepare_v2(mws->db_handle, dump_usage, -1, &(mws->dump_usage), NULL) || sqlite3_prepare_v2(mws->db_handle, DELETE_USAGE_TABLE, -1, - &(mws->delete_usage), NULL)) { + &(mws->delete_usage), NULL) || + sqlite3_prepare_v2(mws->db_handle, INSERT_REBOOT_EVENT, -1, + &(mws->insert_system), NULL) || + (dump_system && sqlite3_prepare_v2(mws->db_handle, dump_system, -1, + &(mws->dump_system), NULL)) || + sqlite3_prepare_v2(mws->db_handle, DELETE_SYSTEM_TABLE, -1, + &(mws->delete_system), NULL)) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Statement failed: %s\n", sqlite3_errmsg(mws->db_handle)); sqlite3_close_v2(db_handle); @@ -396,8 +422,18 @@ static int md_sqlite_configure(struct md_writer_sqlite *mws, mws->usage_prefix_len = strlen(usage_prefix); } + if (system_prefix) { + memset(mws->system_prefix, 0, sizeof(mws->system_prefix)); + memcpy(mws->system_prefix, system_prefix, strlen(system_prefix)); + + //We need to reset the last six characthers to X, so keep track of the + //length of the original prefix + mws->system_prefix_len = strlen(system_prefix); + } + if (mws->node_id && (md_sqlite_update_nodeid_db(mws, UPDATE_EVENT_ID) || - md_sqlite_update_nodeid_db(mws, UPDATE_UPDATES_ID))) { + md_sqlite_update_nodeid_db(mws, UPDATE_UPDATES_ID) || + md_sqlite_update_nodeid_db(mws, UPDATE_SYSTEM_ID))) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Could not update old ements with id 0\n"); return RETVAL_FAILURE; } @@ -423,6 +459,7 @@ void md_sqlite_usage() fprintf(stderr, " \"gps_prefix\":\t\tlocation + filename prefix for GPS data (max 116 characters)\n"); fprintf(stderr, " \"monitor_prefix\":\tlocation + filename prefix for monitor data (max 116 characters)\n"); fprintf(stderr, " \"usage_prefix\":\tlocation + filename prefix for usage data (max 116 characters)\n"); + fprintf(stderr, " \"system_prefix\":\tlocation + filename prefix for system events (max 116 characters)\n"); fprintf(stderr, " \"interval\":\t\ttime (in ms) from event and until database is copied (default: 5 sec)\n"); fprintf(stderr, " \"events\":\t\tnumber of events before copying database (default: 10)\n"); fprintf(stderr, " \"session_id\":\t\tpath to session id file\n"); @@ -437,8 +474,8 @@ int32_t md_sqlite_init(void *ptr, json_object* config) struct md_writer_sqlite *mws = ptr; uint32_t node_id = 0, interval = DEFAULT_TIMEOUT, num_events = EVENT_LIMIT; const char *db_filename = NULL, *meta_prefix = NULL, *gps_prefix = NULL, - *monitor_prefix = NULL, *nodeid_file = NULL, *usage_prefix = NULL, - *output_format = NULL; + *monitor_prefix = NULL, *usage_prefix = NULL, + *output_format = NULL, *system_prefix = NULL; json_object* subconfig; if (json_object_object_get_ex(config, "sqlite", &subconfig)) { @@ -448,7 +485,7 @@ int32_t md_sqlite_init(void *ptr, json_object* config) else if (!strcmp(key, "nodeid")) node_id = (uint32_t) json_object_get_int(val); else if (!strcmp(key, "nodeid_file")) - nodeid_file = json_object_get_string(val); + mws->node_id_file = strdup(json_object_get_string(val)); else if (!strcmp(key, "meta_prefix")) meta_prefix = json_object_get_string(val); else if (!strcmp(key, "gps_prefix")) @@ -457,6 +494,8 @@ int32_t md_sqlite_init(void *ptr, json_object* config) monitor_prefix = json_object_get_string(val); else if (!strcmp(key, "usage_prefix")) usage_prefix = json_object_get_string(val); + else if (!strcmp(key, "system_prefix")) + system_prefix = json_object_get_string(val); else if (!strcmp(key, "interval")) interval = ((uint32_t) json_object_get_int(val)) * 1000; else if (!strcmp(key, "events")) @@ -480,7 +519,8 @@ int32_t md_sqlite_init(void *ptr, json_object* config) if ((meta_prefix && strlen(meta_prefix) > 117) || (gps_prefix && strlen(gps_prefix) > 117) || (monitor_prefix && strlen(monitor_prefix) > 117) || - (usage_prefix && strlen(usage_prefix) > 117)) { + (usage_prefix && strlen(usage_prefix) > 117) || + (system_prefix && strlen(system_prefix) > 117)) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "SQLite temp file prefix too long\n"); return RETVAL_FAILURE; } @@ -490,13 +530,6 @@ int32_t md_sqlite_init(void *ptr, json_object* config) return RETVAL_FAILURE; } - if ((meta_prefix && strlen(meta_prefix) > 117) || - (gps_prefix && strlen(gps_prefix) > 117) || - (monitor_prefix && strlen(monitor_prefix) > 117)) { - META_PRINT_SYSLOG(mws->parent, LOG_ERR, "SQLite temp file prefix too long\n"); - return RETVAL_FAILURE; - } - if (!interval || !num_events) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Invalid SQLite interval/number of events\n"); return RETVAL_FAILURE; @@ -520,8 +553,9 @@ int32_t md_sqlite_init(void *ptr, json_object* config) META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Done configuring SQLite handle\n"); - return md_sqlite_configure(mws, db_filename, node_id, nodeid_file, interval, - num_events, meta_prefix, gps_prefix, monitor_prefix, usage_prefix); + return md_sqlite_configure(mws, db_filename, node_id, interval, + num_events, meta_prefix, gps_prefix, monitor_prefix, usage_prefix, + system_prefix); } static uint8_t md_sqlite_check_valid_tstamp(struct md_writer_sqlite *mws) @@ -543,6 +577,8 @@ static uint8_t md_sqlite_check_valid_tstamp(struct md_writer_sqlite *mws) if (md_sqlite_update_timestamp_db(mws, UPDATE_EVENT_TSTAMP, real_boot_time) || md_sqlite_update_timestamp_db(mws, UPDATE_UPDATES_TSTAMP, + real_boot_time) || + md_sqlite_update_timestamp_db(mws, UPDATE_SYSTEM_TSTAMP, real_boot_time)) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Could not update tstamp in database\n"); return RETVAL_FAILURE; @@ -563,7 +599,8 @@ static uint8_t md_sqlite_check_session_id(struct md_writer_sqlite *mws) } if (md_sqlite_update_session_id_db(mws, UPDATE_EVENT_SESSION_ID) || - md_sqlite_update_session_id_db(mws, UPDATE_UPDATES_SESSION_ID)) { + md_sqlite_update_session_id_db(mws, UPDATE_UPDATES_SESSION_ID) || + md_sqlite_update_session_id_db(mws, UPDATE_SYSTEM_SESSION_ID)) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Could not update session id in database\n"); mws->timeout_handle->intvl = DEFAULT_TIMEOUT; mws->session_id = 0; @@ -607,6 +644,15 @@ static void md_sqlite_handle(struct md_writer *writer, struct md_event *event) if (!retval) mws->num_munin_events++; break; + case META_TYPE_SYSTEM: + if (!mws->system_prefix[0]) + return; + + retval = md_inventory_handle_system_event(mws, (md_system_event_t*) event); + + if (!retval) + mws->num_system_events++; + break; default: META_PRINT_SYSLOG(mws->parent, LOG_INFO, "SQLite writer does not support event %u\n", event->md_type); @@ -667,10 +713,12 @@ static void md_sqlite_handle_timeout(void *ptr) if(!mws->node_id) { #ifdef OPENWRT mws->node_id = system_helpers_get_nodeid(); - - if(mws->node_id) - META_PRINT_SYSLOG(mws->parent, LOG_INFO, "Got nodeid %d\n", mws->node_id); +#else + mws->node_id = system_helpers_get_nodeid(mws->node_id_file); #endif + if(mws->node_id) { + META_PRINT_SYSLOG(mws->parent, LOG_INFO, "Got nodeid %d\n", mws->node_id); + } if (!mws->node_id) { META_PRINT_SYSLOG(mws->parent, LOG_INFO, "No node id found\n"); @@ -679,7 +727,8 @@ static void md_sqlite_handle_timeout(void *ptr) } if (md_sqlite_update_nodeid_db(mws, UPDATE_EVENT_ID) || - md_sqlite_update_nodeid_db(mws, UPDATE_UPDATES_ID)) { + md_sqlite_update_nodeid_db(mws, UPDATE_UPDATES_ID) || + md_sqlite_update_nodeid_db(mws, UPDATE_SYSTEM_ID)) { META_PRINT_SYSLOG(mws->parent, LOG_ERR, "Could not update node id in database\n"); mws->timeout_handle->intvl = DEFAULT_TIMEOUT; diff --git a/metadata_writer_sqlite.h b/metadata_writer_sqlite.h index 68a054d..7351085 100644 --- a/metadata_writer_sqlite.h +++ b/metadata_writer_sqlite.h @@ -124,6 +124,15 @@ "TxData INTEGER NOT NULL," \ "PRIMARY KEY(DeviceId,SimCardIccid,SimCardImsi,Timestamp))" +#define CREATE_REBOOT_SQL "CREATE TABLE IF NOT EXISTS RebootEvent(" \ + "NodeId INTEGER NOT NULL," \ + "BootCount INTEGER," \ + "BootMultiplier INTEGER," \ + "Timestamp INTEGER NOT NULL," \ + "Sequence INTEGER NOT NULL," \ + "DeviceId TEXT NOT NULL," \ + "PRIMARY KEY(BootCount,BootMultiplier,Timestamp,Sequence))" + #define INSERT_EVENT "INSERT INTO NetworkEvent(NodeId,SessionId,"\ "SessionIdMultip,Timestamp,Sequence,L3SessionId,"\ "L4SessionId,EventType,EventParam,EventValue,"\ @@ -153,6 +162,10 @@ ",SimCardImsi,Timestamp,RxData,TxData) " \ "VALUES (?,?,?,?,?,?,?,?)" +#define INSERT_REBOOT_EVENT "INSERT INTO RebootEvent(NodeId, BootCount," \ + "BootMultiplier, Timestamp, Sequence, DeviceId)"\ + "VALUES (?,?,?,?,?,?)" + #define SELECT_LAST_UPDATE "SELECT HasIp,Connectivity,ConnectionMode,Quality "\ " FROM NetworkUpdates WHERE "\ "L3SessionId=? AND "\ @@ -187,6 +200,10 @@ "NodeId=? "\ "WHERE NodeId=0" +#define UPDATE_SYSTEM_ID "UPDATE RebootEvent SET " \ + "NodeId=? "\ + "WHERE NodeId=0" + #define UPDATE_EVENT_TSTAMP "UPDATE NetworkEvent SET " \ "Timestamp = Timestamp + ? "\ "WHERE Timestamp < ?" @@ -195,6 +212,10 @@ "Timestamp = Timestamp + ? "\ "WHERE Timestamp < ?" +#define UPDATE_SYSTEM_TSTAMP "UPDATE RebootEvent SET " \ + "Timestamp = Timestamp + ? "\ + "WHERE Timestamp < ?" + #define UPDATE_EVENT_SESSION_ID "UPDATE NetworkEvent SET "\ "SessionId=?,SessionIdMultip=? "\ "WHERE SessionId = 0" @@ -203,6 +224,10 @@ "SessionId=?,SessionIdMultip=? "\ "WHERE SessionId = 0" +#define UPDATE_SYSTEM_SESSION_ID "UPDATE RebootEvent SET "\ + "SessionId=?,SessionIdMultip=? "\ + "WHERE SessionId = 0" + #define DELETE_TABLE "DELETE FROM NetworkEvent" #define DELETE_NW_UPDATE "DELETE FROM NetworkUpdates WHERE Timestamp < ?" @@ -213,6 +238,8 @@ #define DELETE_USAGE_TABLE "DELETE FROM DataUse" +#define DELETE_SYSTEM_TABLE "DELETE FROM RebootEvent" + //This statement is a static version of what the .dump command does. A dynamic //version would query the master table to get tables and then PRAGMA to get //rows. The actualy query is simpler than it looks. It seems SQLite supports @@ -287,6 +314,9 @@ #define DUMP_USAGE_JSON "SELECT * FROM DataUse" +#define DUMP_SYSTEM_JSON "SELECT * FROM RebootEvent" + + struct md_event; struct md_writer; struct backend_timeout_handle; @@ -306,7 +336,10 @@ struct md_writer_sqlite { sqlite3_stmt *insert_usage, *update_usage, *dump_usage, *delete_usage; + sqlite3_stmt *insert_system, *dump_system, *delete_system; + char *session_id_file; + char *node_id_file; const char *last_conn_tstamp_path; uint32_t node_id; @@ -316,6 +349,7 @@ struct md_writer_sqlite { uint32_t num_gps_events; uint32_t num_munin_events; uint32_t num_usage_events; + uint32_t num_system_events; uint8_t timeout_added; uint8_t file_failed; @@ -336,8 +370,10 @@ struct md_writer_sqlite { float gps_speed; struct backend_timeout_handle *timeout_handle; - char meta_prefix[128], gps_prefix[128], monitor_prefix[128], usage_prefix[128]; - size_t meta_prefix_len, gps_prefix_len, monitor_prefix_len, usage_prefix_len; + char meta_prefix[128], gps_prefix[128], monitor_prefix[128], + usage_prefix[128], system_prefix[128]; + size_t meta_prefix_len, gps_prefix_len, monitor_prefix_len, + usage_prefix_len, system_prefix_len; uint8_t api_version; uint8_t delete_conn_update;