diff --git a/inc/common/common.h b/inc/common/common.h index 3dc3bddad114603ae5f025f8adc5dc27726da111..b56af85e040685910831e56c8ce1e5cae54b9b05 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -8,3 +8,5 @@ extern void __not_implemented(const char *func, char *file, int line); #define UNUSED(...) __unused((void *) __VA_ARGS__) void __unused(void *, ...); + +long min_long(long a, long b); diff --git a/inc/lektor/common.h b/inc/lektor/common.h index ec7da1881eff890576009b02b32af5738631f201..28155d1920d67b0d790dea9b595a6f6f9d6087c2 100644 --- a/inc/lektor/common.h +++ b/inc/lektor/common.h @@ -61,38 +61,38 @@ enum mpd_idle_flag { /* Macros */ -#define SQLITE_PREPARE(db, stmt, SQL, goto_label) \ - if (sqlite3_prepare_v2(db, SQL, -1, &(stmt), 0) != SQLITE_OK) { \ - LOG_ERROR_SCT("DB", "Failed to prepare statement: %s", \ - sqlite3_errmsg(db)); \ - goto goto_label; \ +#define SQLITE_PREPARE(db, stmt, SQL, goto_label) \ + if (sqlite3_prepare_v2((sqlite3 *) db, SQL, -1, &(stmt), 0) != SQLITE_OK) { \ + LOG_ERROR_SCT("DB", "Failed to prepare statement: %s", \ + sqlite3_errmsg((sqlite3 *) db)); \ + goto goto_label; \ } -#define SQLITE_EXEC(db, SQL, goto_label) \ - if (sqlite3_exec(db, SQL, NULL, NULL, NULL) != SQLITE_OK) { \ - LOG_ERROR_SCT("DB", "Failed to exec statement: %s", \ - sqlite3_errmsg(db)); \ - goto goto_label; \ +#define SQLITE_EXEC(db, SQL, goto_label) \ + if (sqlite3_exec((sqlite3 *) db, SQL, NULL, NULL, NULL) != SQLITE_OK) { \ + LOG_ERROR_SCT("DB", "Failed to exec statement: %s", \ + sqlite3_errmsg((sqlite3 *) db)); \ + goto goto_label; \ } #define SQLITE_BIND_TEXT(db, stmt, pos, text, error) \ if (sqlite3_bind_text(stmt, pos, text, -1, 0) != SQLITE_OK) { \ LOG_ERROR_SCT("DB", "Failed to bind text %s at pos %d: %s", \ - text, pos, sqlite3_errmsg(db)); \ + text, pos, sqlite3_errmsg((sqlite3 *) db)); \ goto error; \ } #define SQLITE_BIND_INT(db, stmt, pos, integer, error) \ if (sqlite3_bind_int(stmt, pos, integer) != SQLITE_OK) { \ LOG_ERROR_SCT("DB", "Failed to bind int %d at pos %d: %s", \ - integer, pos, sqlite3_errmsg(db)); \ + integer, pos, sqlite3_errmsg((sqlite3 *) db)); \ goto error; \ } #define SQLITE_STEP(db, stmt, code, error) \ if (sqlite3_step(stmt) != code) { \ LOG_ERROR_SCT("DB", "Failed to step and get a row: %s", \ - sqlite3_errmsg(db)); \ + sqlite3_errmsg((sqlite3 *) db)); \ goto error; \ } @@ -101,7 +101,7 @@ enum mpd_idle_flag { #define SQLITE_STEP_OK(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_OK, error) #define SQLITE_DO_ROLLBACK(db) \ - sqlite3_exec(db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); + sqlite3_exec((sqlite3 *) db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); /* Random things */ diff --git a/inc/lektor/database.h b/inc/lektor/database.h index e46f067b94e4a4fc8a12b1a0e956f4056373b24c..e0975dc717b91feaeb7fcaed74f85d66a7a5d3de 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -22,6 +22,9 @@ struct lkt_queue_state { int length; }; +long database_get_timestamp(volatile sqlite3 *db); +void database_stamp(volatile sqlite3 *db); + /* Open correctly a database for lektor. */ bool database_new (sqlite3 **db); bool database_init (const char *dbpath); diff --git a/src/common.c b/src/common.c index b14f8269d36c73ebc8f836e1bedda4a63b94bc56..8bc985b3796f056190ac77a6b007a164afd7a8b0 100644 --- a/src/common.c +++ b/src/common.c @@ -127,3 +127,9 @@ get_stdin_line(const char *prompt, char *buf, size_t len) buf[len - 1] = 0u; return is_utf8(buf); } + +long +min_long(long a, long b) +{ + return a < b ? a : b; +} diff --git a/src/database/open.c b/src/database/open.c index fcfbe69ce11a66dfeee240417cbcb883b9f5c9bb..12c09489da2b72b7c1428b36152d2e44b7dc715c 100644 --- a/src/database/open.c +++ b/src/database/open.c @@ -191,3 +191,25 @@ error: LOG_ERROR_SCT("DB", "Failed to init the 'disk' database, path was '%s'", dbpath); return false; } + +long +database_get_timestamp(volatile sqlite3 *db) +{ + long ret = 0; + static const char *SQL = "SELECT last_update FROM misc WHERE id = 42;"; + sqlite3_stmt *stmt; + SQLITE_PREPARE(db, stmt, SQL, error); + SQLITE_STEP_ROW(db, stmt, error); + ret = sqlite3_column_int(stmt, 0); +error: + sqlite3_finalize(stmt); + return ret; +} + +void +database_stamp(volatile sqlite3 *db) +{ + SQLITE_EXEC(db, "UPDATE misc SET last_update = strftime('%s','now');", error); +error: + return; +} diff --git a/src/net/downloader.c b/src/net/downloader.c index aae9cb97e1ac34825e4ef5dccb5616e09c84fe55..b4d8d328fe3f0dd41142335bc3ca234e7ce0a7a3 100644 --- a/src/net/downloader.c +++ b/src/net/downloader.c @@ -383,7 +383,7 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec int32_t integer, err; struct kara *kara; char url[URL_MAX_LEN]; - long stamp, timestamp; + long filestamp, timestamp; RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING); LOG_INFO_SCT("REPO", "Starting to process json for repo %s", repo->name); @@ -409,13 +409,19 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec kara->filename[PATH_MAX - 1] = 0; LOG_INFO_SCT("REPO", "Crafted filename is '%s'", kara->filename); + /* Timestamp verification */ if (safe_json_get_long(kara_json, "unix_timestamp", ×tamp)) continue; - stamp = get_mtime(kara->filename); - if (stamp > timestamp) { - LOG_INFO_SCT("REPO", "Ignore kara '%ld', last timestamp was %ld, new is %ld", kara->id, stamp, timestamp); + filestamp = get_mtime(kara->filename); + if (database_get_timestamp(db) < filestamp) { + LOG_WARN_SCT("REPO", "Kara file %s is more recent than database timestamp, download it", kara->filename); + goto do_it; + } + if (filestamp > timestamp) { + LOG_INFO_SCT("REPO", "Ignore kara '%ld', last timestamp was %ld, new is %ld", kara->id, filestamp, timestamp); continue; } +do_it: err |= safe_json_get_string(kara_json, "song_name", kara->mdt.song_name, LEKTOR_TAG_MAX); err |= safe_json_get_string(kara_json, "source_name", kara->mdt.source_name, LEKTOR_TAG_MAX); @@ -446,6 +452,8 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec continue; } + database_stamp(db); + LOG_INFO_SCT("REPO", "Added kara %ld from repo %s, filepath is %s", kara->id, repo->name, kara->filename); }