#include #include #include #include sqlite3 *cache_database; static char* cache_get_value(char *key) { sqlite3_stmt *stmt; sqlite3_prepare_v2(cache_database, "SELECT value FROM cache WHERE key=?1;", -1, &stmt, NULL); sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC); char *result = NULL; while(1) { int s; s = sqlite3_step(stmt); if (s == SQLITE_ROW) { const char *found_value = (const char *)sqlite3_column_text(stmt, 0); result = (char*)malloc(sizeof(char) * (strlen(found_value) + 1)); strcpy(result, found_value); } else { if (s == SQLITE_DONE) { break; } else { LOGGER_WARNING("failed selecting %s from cache: %s\n", key, sqlite3_errstr(s)); break; } } } sqlite3_finalize(stmt); return result; } static void cache_insert_value(char *key, char *value) { sqlite3_stmt *stmt; sqlite3_prepare_v2(cache_database, "INSERT INTO cache (key, value, expiration) VALUES (?1, ?2, 0);", -1, &stmt, NULL); sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, value, -1, SQLITE_STATIC); int rc = sqlite3_step(stmt); sqlite3_finalize(stmt); if(rc != SQLITE_DONE) { LOGGER_WARNING("failed to save %s to cache: %s\n", key, sqlite3_errstr(rc)); } } static void cache_invalidate(char *key) { LOGGER_DEBUG("invalidating %s\n", key); sqlite3_stmt *stmt; int rc; sqlite3_prepare_v2(cache_database, "DELETE FROM cache WHERE key=?1;", -1, &stmt, NULL); sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC); rc = sqlite3_step(stmt); sqlite3_finalize(stmt); if(rc != SQLITE_DONE) { LOGGER_WARNING("failed to invalidate %s in cache: %s\n", key, sqlite3_errstr(rc)); } } void cache_init() { int rc = sqlite3_open(":memory:", &cache_database); if(rc) { LOGGER_CRIT("can't open cache database: %s\n", sqlite3_errmsg(cache_database)); exit(1); } char* err_msg; rc = sqlite3_exec(cache_database, (const char *)sql_cache_sql, NULL, NULL, &err_msg); if(rc) { LOGGER_CRIT("couldn't initialize cache (%s)\n", err_msg); exit(1); } LOGGER_DEBUG("cache initalized\n"); } void cache_free() { sqlite3_close(cache_database); } void cache_put_json_schedule(int schedule_id, char *schedule_json) { char key[32]; sprintf(key, "schedule_json:%d", schedule_id); cache_insert_value(key, schedule_json); } char* cache_get_json_schedule(int schedule_id) { char key[32]; sprintf(key, "schedule_json:%d", schedule_id); return cache_get_value(key); } void cache_invalidate_schedule(int schedule_id) { char key[32]; sprintf(key, "schedule_json:%d", schedule_id); cache_invalidate(key); relay_t **relays = relay_get_with_schedule(schedule_id); for(int i = 0; relays[i] != NULL; ++i) { cache_invalidate_relay(relays[i]->id); } relay_free_list(relays); } void cache_put_json_relay(int relay_id, char *relay_json) { char key[32]; sprintf(key, "relay_json:%d", relay_id); cache_insert_value(key, relay_json); } char* cache_get_json_relay(int relay_id) { char key[32]; sprintf(key, "relay_json:%d", relay_id); return cache_get_value(key); } void cache_invalidate_relay(int relay_id) { char key[32]; sprintf(key, "relay_json:%d", relay_id); cache_invalidate(key); relay_t *relay = relay_get_by_id(relay_id); if(relay) { cache_invalidate_controller(relay->controller_id); relay_free(relay); } } void cache_put_json_controller(int controller_id, char *controller_json) { char key[32]; sprintf(key, "controller_json:%d", controller_id); cache_insert_value(key, controller_json); } char* cache_get_json_controller(int controller_id) { char key[32]; sprintf(key, "controller_json:%d", controller_id); return cache_get_value(key); } void cache_invalidate_controller(int controller_id) { char key[32]; sprintf(key, "controller_json:%d", controller_id); cache_invalidate(key); } void cache_invalidate_tagged(int tag_id) { int *schedule_ids = junction_tag_get_schedules_for_tag_id(tag_id); for(int i = 0; schedule_ids[i] != 0; ++i) { cache_invalidate_schedule(schedule_ids[i]); } free(schedule_ids); int *relay_ids = junction_tag_get_relays_for_tag_id(tag_id); for(int i = 0; relay_ids[i] != 0; ++i) { cache_invalidate_relay(relay_ids[i]); } free(relay_ids); }