diff --git a/inc/lektor/database.h b/inc/lektor/database.h index 0cddeaa1a7b2af6f4ae662664f9f25469c0e276d..c2d090799c38f9184c682abf0a28af80f9d4ec4a 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -22,9 +22,11 @@ struct lkt_queue_state { int length; }; -long database_get_timestamp(volatile sqlite3 *db); -void database_stamp (volatile sqlite3 *db); -void database_updated (volatile sqlite3 *db); +/* Update stuff */ +void database_get_update (volatile sqlite3 *db, long *timestamp, long *job, int *current); +void database_stamp (volatile sqlite3 *db); +void database_updated (volatile sqlite3 *db); +void database_deleted_kara(volatile sqlite3 *db, int **kara_id, size_t *len); /* Open correctly a database for lektor. */ bool database_new (volatile sqlite3 **db); @@ -41,13 +43,13 @@ bool database_queue_set_paused (volatile sqlite3 *db, bool paused); bool database_queue_set_current_index(volatile sqlite3 *db, int idx); bool database_queue_get_current_file (volatile sqlite3 *db, char filepath[PATH_MAX]); -/* Mpv and database synchronisation. */ -bool database_sync_mpv_state(volatile sqlite3 *db, mpv_handle **mpv); +bool database_get_kara_path(volatile sqlite3 *db, int id, char filepath[PATH_MAX]); /* Update the database. */ bool database_update (volatile sqlite3 *db, const char *kara_dir, int check_timestamp); bool database_update_add (volatile sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail); -bool database_update_set_available(volatile sqlite3 *db, uint64_t id); +bool database_update_set_available(volatile sqlite3 *db, int id); +void database_update_del (volatile sqlite3 *db, int id); /* Control the content of the queue. */ bool database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority); @@ -114,6 +116,7 @@ bool database_search_iter(struct lkt_search *item); /* Next and prev operation on the queue. */ bool database_queue_next(volatile sqlite3 *db, char filepath[PATH_MAX]); bool database_queue_prev(volatile sqlite3 *db, char filepath[PATH_MAX]); +bool database_queue_skip_current(volatile sqlite3 *db, char filepath[PATH_MAX]); /* Set a value in the config table */ bool database_config_set (volatile sqlite3 *db, const char *section, const char *key, const char *value); diff --git a/scripts/init.sql b/scripts/init.sql index d4e3e1c3c422e4be0017a0f470a40ef6b6e760b6..285457514f1585114e3412b91a7b73c46e9147fa 100644 --- a/scripts/init.sql +++ b/scripts/init.sql @@ -119,6 +119,18 @@ CREATE TABLE IF NOT EXISTS 'stickers.plt' ) WITHOUT ROWID; +-- Update jobs history +-- Here are stored karas ids present during a certain update job. May be +-- usefull to keep tracks of kara. Now used to handle the 'deleted' case, i.e. +-- when a kara was here, but was deleted on kurisu. + +CREATE TABLE IF NOT EXISTS updates + ( job INTEGER NOT NULL CHECK(job >= 0) + , kara_id INTEGER NOT NULL CHECK(kara_id > 0) + , PRIMARY KEY (job, kara_id) + ) WITHOUT ROWID; + + -- Some useful values: -- last_update is the timestamp of the last time the table of kara has been -- updated. This is so lektor doesn't have to read all kara in the filesystem, @@ -131,6 +143,7 @@ CREATE TABLE IF NOT EXISTS misc ( id INTEGER PRIMARY KEY DEFAULT 42 CHECK(id = 42) , last_update INTEGER , last_end_update INTEGER + , update_job INTEGER NOT NULL CHECK(update_job >= 0) ); -INSERT OR REPLACE INTO misc (id) VALUES (42); +INSERT OR REPLACE INTO misc (id, update_job) VALUES (42, 0); diff --git a/src/commands.c b/src/commands.c index 22863455515b3aa4d4ab01b21448c40cd035f017..f3337062feb3b3712edbe6f2a553996ab9c548c5 100644 --- a/src/commands.c +++ b/src/commands.c @@ -271,20 +271,30 @@ command_crop(volatile sqlite3 *db, mpd_idle_flag *watch_mask_ptr) bool command_delid(volatile sqlite3 *db, struct lkt_win *win, char *id_str, mpd_idle_flag *watch_mask_ptr) { - UNUSED(win); long id; - char *endptr = NULL, err = 0; + char *endptr = NULL, err = 0, filepath[PATH_MAX]; int uri = 0; - *watch_mask_ptr |= MPD_IDLE_PLAYLIST; STRTOL(id, id_str, endptr, err); RETURN_IF(err, "STRTOL failed", false); - /* If one day we allow suppression of the current kara, will need the `win` - pointer to reload the kara in the same position (but the kara won't be - the same). */ database_queue_current_kara(db, NULL, &uri); - RETURN_IF(id == (long) uri, "Can't delete current kara", false); + + if (id == (long) uri) { + if (database_queue_skip_current(db, filepath)) { + if (!win->load_file(win, filepath)) { + LOG_ERROR_SCT("COMMAND", "Failed to skip current kara to delete id %ld", id); + return false; + } + } + + else { + LOG_WARN_SCT("COMMAND", "Failed to skip current kara to delete id %ld, stop playback", id); + win->close(win); + } + } + + *watch_mask_ptr |= MPD_IDLE_PLAYER; return database_queue_del_id(db, id); } diff --git a/src/database/config.c b/src/database/config.c index eb09db8541c459fc983e2f50da364853b18380fd..f4de2a20c6891cf94b65f44f3c53b45f1cfd48b8 100644 --- a/src/database/config.c +++ b/src/database/config.c @@ -134,25 +134,6 @@ error: return ret; } -bool -database_config_queue_default(volatile sqlite3 *db) -{ - static const char *SQL_DEFAULT = - "UPDATE queue_state SET" - " volume = 100," - " paused = 1," - " random = 0," - " repeat = 0," - " single = 0," - " consume = 0," - " current = NULL," - " duration = 0;"; - SQLITE_EXEC(db, SQL_DEFAULT, error); - return true; -error: - return false; -} - bool database_get_config(volatile sqlite3 *db, const char *option, int *value) { diff --git a/src/database/open.c b/src/database/open.c index 9c28886822cbb722d6601585f31646453b383418..cb3cb0b17d30a6cef6fa7bb9dddca9f0afbeb642 100644 --- a/src/database/open.c +++ b/src/database/open.c @@ -189,33 +189,3 @@ 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; -} - -void -database_updated(volatile sqlite3 *db) -{ - SQLITE_EXEC(db, "UPDATE misc SET last_end_update = strftime('%s','now');", error); -error: - return; -} diff --git a/src/database/queue.c b/src/database/queue.c index 8ff68e8410714f2e5dc0c04859ca77b7832760b5..abce4426ed9a77a7d5833570b8a04f71a51a907a 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -7,6 +7,31 @@ #include <stdio.h> #include <string.h> +#define sqlite_just_exec(func, query) \ + bool func (volatile sqlite3 *db) { \ + SQLITE_EXEC(db, "BEGIN TRANSACTION;" #query "COMMIT;", error); \ + return true; \ + error: \ + SQLITE_DO_ROLLBACK(db); \ + return false; \ + } +sqlite_just_exec(database_queue_toggle_pause, "UPDATE queue_state SET paused = 1 - paused;") +sqlite_just_exec(database_queue_crop, "DELETE FROM queue WHERE queue.kara_id <> (SELECT current FROM queue_state LIMIT 1);") +sqlite_just_exec(database_queue_stop, "UPDATE queue_state SET current = NULL;") +sqlite_just_exec(database_queue_clear, "DELETE FROM queue;DELETE FROM sqlite_sequence WHERE name = 'queue';UPDATE queue_state SET current = NULL;") +sqlite_just_exec(database_config_queue_default, "UPDATE queue_state SET volume = 100, paused = 1, random = 0, repeat = 0, single = 0, consume = 0, current = NULL, duration = 0;") +#undef sqlite_just_exec + +bool +database_queue_set_paused(volatile sqlite3 *db, bool paused) +{ + const char *SQL = paused ? "UPDATE queue_state SET paused = 1;" : "UPDATE queue_state SET paused = 0;"; + SQLITE_EXEC(db, SQL, error); + return true; +error: + return false; +} + /* Find in in database/open.c */ extern int is_sql_str_invalid(const char *); @@ -251,17 +276,20 @@ database_queue_add_uri(volatile sqlite3 *db, struct lkt_uri *uri, int priority) bool database_queue_del_id(volatile sqlite3 *db, int id) { - /* FIXME: Can't pop if its the last kara */ -#define POS_OF_ID "(SELECT position FROM queue WHERE kara_id = %d)" static const char *SQL_TEMPLATE = "BEGIN TRANSACTION;" - "WITH before(pos) AS (SELECT position FROM queue JOIN queue_state WHERE position < current ORDER BY position DESC LIMIT 1) " - "UPDATE queue_state SET current = CASE WHEN current IS NULL THEN NULL ELSE (SELECT pos FROM before) END WHERE current > " POS_OF_ID ";" - "UPDATE OR REPLACE queue SET position = position - 1 WHERE position > " POS_OF_ID ";" + "CREATE TEMPORARY TABLE queue_tmp (position INTEGER, kara_id INTEGER, priority INTEGER);" + /* Move the current 'pointer' */ + "UPDATE queue_state SET current = (SELECT NULLIF(COUNT(position), 0) FROM queue JOIN queue_state ON position <= current AND kara_id != %d);" + "DELETE FROM queue WHERE kara_id = %d;" /* Delete any kara with the specified id */ + "INSERT INTO queue_tmp(priority, position, kara_id) SELECT priority, position, kara_id FROM queue ORDER BY position ASC;" + "DELETE FROM queue;" + "INSERT INTO queue(priority, position, kara_id) SELECT priority, ROW_NUMBER() OVER(ORDER BY position ASC), kara_id FROM queue_tmp;" + "UPDATE sqlite_sequence SET seq = (SELECT COUNT(*) FROM queue) WHERE name = 'queue';" /* Update the sqlite_sequence */ + "DROP TABLE queue_tmp;" /* Erase queue_tmp */ "COMMIT;"; -#undef POS_OF_ID char SQL[LKT_MAX_SQLITE_STATEMENT]; - safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE, id, id, id, id); + safe_snprintf(SQL, LKT_MAX_SQLITE_STATEMENT, SQL_TEMPLATE, id, id); SQLITE_EXEC(db, SQL, error); return true; error: @@ -322,13 +350,16 @@ error: } bool -database_queue_toggle_pause(volatile sqlite3 *db) +database_queue_skip_current(volatile sqlite3 *db, char filepath[PATH_MAX]) { - static const char *SQL_STMT = "UPDATE queue_state SET paused = 1 - paused"; - SQLITE_EXEC(db, SQL_STMT, error); - return true; -error: - return false; + if (database_queue_next(db, filepath)) + return true; + else if (database_queue_prev(db, filepath)) + return true; + else { + database_queue_stop(db); + return false; + } } bool @@ -380,33 +411,6 @@ error: return status; } -bool -database_queue_clear(volatile sqlite3 *db) -{ - static const char *SQL_STMT = - "BEGIN TRANSACTION;" - "DELETE FROM queue;" - "DELETE FROM sqlite_sequence WHERE name = 'queue';" - "UPDATE queue_state SET current = NULL;" - "COMMIT;"; - SQLITE_EXEC(db, SQL_STMT, error); - return true; -error: - SQLITE_DO_ROLLBACK(db); - return false; -} - -bool -database_queue_crop(volatile sqlite3 *db) -{ - static const char *SQL_STMT = - "DELETE FROM queue WHERE queue.kara_id <> (SELECT current FROM queue_state LIMIT 1);"; - SQLITE_EXEC(db, SQL_STMT, error); - return true; -error: - return false; -} - bool database_queue_move(volatile sqlite3 *db, int from, int to) { @@ -467,16 +471,6 @@ error: return ret; } -bool -database_queue_stop(volatile sqlite3 *db) -{ - static const char *SQL_STMT = "UPDATE queue_state SET current = NULL;"; - SQLITE_EXEC(db, SQL_STMT, error); - return true; -error: - return false; -} - bool database_queue_set_current_index(volatile sqlite3 *db, int idx) { @@ -514,8 +508,10 @@ database_queue_get_current_file(volatile sqlite3 *db, char filepath[PATH_MAX]) SQLITE_PREPARE(db, stmt, SQL_STMT, error); code = sqlite3_step(stmt); - if (code == SQLITE_ROW) + if (code == SQLITE_ROW) { strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); + filepath[PATH_MAX - 1] = '\0'; + } else { LOG_ERROR_SCT("DB", "Failed to fetch prev kara: %s", sqlite3_errmsg((sqlite3 *) db)); @@ -529,10 +525,16 @@ error: } bool -database_queue_set_paused(volatile sqlite3 *db, bool paused) +database_get_kara_path(volatile sqlite3 *db, int id, char filepath[PATH_MAX]) { - const char *SQL = paused ? "UPDATE queue_state SET paused = 1;" : "UPDATE queue_state SET paused = 0;"; - SQLITE_EXEC(db, SQL, error); + sqlite3_stmt *stmt = NULL; + static const char *SQL = "SELECT file_path FROM kara WHERE id = ?;"; + RETURN_UNLESS(id && db && filepath, "Invalid argument", false); + SQLITE_PREPARE(db, stmt, SQL, error); + SQLITE_BIND_INT(db, stmt, 1, id, error); + SQLITE_STEP_ROW(db, stmt, error); + strncpy(filepath, (const char *) sqlite3_column_text(stmt, 0), PATH_MAX); + filepath[PATH_MAX - 1] = '\0'; return true; error: return false; diff --git a/src/database/update.c b/src/database/update.c index 369df055ec700de599b43b47300194508d5c0f5c..7ff464aa795b96b77fc3bd8d34e054de40049a3c 100644 --- a/src/database/update.c +++ b/src/database/update.c @@ -13,8 +13,25 @@ #include <time.h> #include <linux/limits.h> -static bool -database_add_kara(volatile sqlite3 *db, const char *filename) +static inline bool +__add_kara_to_update_job(volatile sqlite3 *db, size_t id) +{ + static const char *SQL = NULL; + if (id) + SQL = "INSERT INTO updates (job, kara_id) SELECT MAX(update_job), ? FROM misc;"; + else + SQL = "INSERT INTO updates (job, kara_id) SELECT MAX(update_job), last_insert_rowid() FROM misc;"; + sqlite3_stmt *stmt; + SQLITE_PREPARE(db, stmt, SQL, error); + SQLITE_BIND_INT(db, stmt, 1, (int) id, error); + SQLITE_STEP_OK(db, stmt, error); + return true; +error: + return false; +} + +static inline bool +__database_add_kara(volatile sqlite3 *db, const char *filename) { RETURN_UNLESS(db || filename, "Invalid argument", false); static const char *SQL_STMT = @@ -26,7 +43,7 @@ database_add_kara(volatile sqlite3 *db, const char *filename) "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id)" "SELECT ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s','now'), ?, ?"; sqlite3_stmt *stmt = NULL; - long code = SQLITE_OK, status = false, kara_id; + long code = SQLITE_OK, status = false, kara_id = 0; struct kara_metadata data; time_t the_time = time(NULL); struct tm *the_local_time = localtime(&the_time); @@ -42,6 +59,8 @@ database_add_kara(volatile sqlite3 *db, const char *filename) return false; } + SQLITE_EXEC(db, "BEGIN TRANSACTION;", error); + /* Try to find an id in the filename, reuse of variables, it's ugly */ path[PATH_MAX - 1] = '\0'; memcpy(path, filename, (strlen(filename) + 1) * sizeof(char)); @@ -74,34 +93,40 @@ database_add_kara(volatile sqlite3 *db, const char *filename) goto error; } SQLITE_STEP_DONE(db, stmt, error); - status = true; + sqlite3_finalize(stmt); + + if (__add_kara_to_update_job(db, kara_id)) { + SQLITE_EXEC(db, "COMMIT;", error); + return true; + } error: sqlite3_finalize(stmt); + SQLITE_DO_ROLLBACK(db); return status; } bool -database_update_set_available(volatile sqlite3 *db, uint64_t id) +database_update_set_available(volatile sqlite3 *db, int id) { static const char *SQL_STMT = "UPDATE kara SET available = 1 WHERE id = ?;"; sqlite3_stmt *stmt; SQLITE_PREPARE(db, stmt, SQL_STMT, error); - SQLITE_BIND_INT(db, stmt, 1, (int) id, error); + SQLITE_BIND_INT(db, stmt, 1, id, error); if (sqlite3_step(stmt) != SQLITE_DONE) goto error; sqlite3_finalize(stmt); - LOG_INFO_SCT("DB", "Kara %ld is now available", id); + LOG_INFO_SCT("DB", "Kara %d is now available", id); return true; error: sqlite3_finalize(stmt); - LOG_ERROR_SCT("DB", "Failed to set kara %ld available", id); + LOG_ERROR_SCT("DB", "Failed to set kara %d available", id); return false; } bool database_update_add(volatile sqlite3 *db, const char *kara_path, struct kara_metadata *mdt, uint64_t id, bool avail) { - RETURN_UNLESS(db && kara_path && mdt, "Invalid argument", false); + RETURN_UNLESS(db && kara_path && mdt && id, "Invalid argument", false); static const char *SQL_STMT = "INSERT OR REPLACE INTO " "kara (song_name, source_name, category, song_type, language, file_path, is_new, author_name, author_year, song_number, id, available)" @@ -135,7 +160,7 @@ database_update_add(volatile sqlite3 *db, const char *kara_path, struct kara_met } SQLITE_STEP_DONE(db, stmt, error); - ret = true; + ret = __add_kara_to_update_job(db, id); error: sqlite3_finalize(stmt); error_no_sqlite: @@ -148,6 +173,7 @@ database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp) DIR *d; struct dirent *dir; char path[PATH_MAX]; + long db_timestamp = 0; memset(path, 0, PATH_MAX * sizeof(char)); if (!(d = opendir(kara_dir))) { @@ -161,11 +187,12 @@ database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp) strncat(path, dir->d_name, PATH_MAX - 1); if (dir->d_type == DT_REG) { - if (check_timestamp && get_mtime(path) < database_get_timestamp(db)) { + database_get_update(db, &db_timestamp, NULL, NULL); + if (check_timestamp && get_mtime(path) < db_timestamp) { LOG_INFO_SCT("DB", "Skip update of kara '%s' be cause of timestamps", path); continue; } - database_add_kara(db, path); + __database_add_kara(db, path); database_stamp(db); } @@ -180,3 +207,71 @@ database_update(volatile sqlite3 *db, const char *kara_dir, int check_timestamp) closedir(d); return true; } + +void +database_deleted_kara(volatile sqlite3 *db, int **kara_id, size_t *len) +{ + static const char *SQL = + "SELECT kara.id, file_path FROM kara WHERE kara.id NOT IN" + "(SELECT kara_id FROM updates JOIN misc ON job = update_job);"; + sqlite3_stmt *stmt = NULL; + *kara_id = (int *) calloc(LKT_DEFAULT_LIST_SIZE, sizeof(int)); + *len = 0; + RETURN_UNLESS(*kara_id, "Out of memory", NOTHING); + SQLITE_PREPARE(db, stmt, SQL, out); + size_t size = LKT_DEFAULT_LIST_SIZE; + void *new; + + while (sqlite3_step(stmt) == SQLITE_ROW) { + if (size == *len) { + new = realloc((void *) kara_id, (*len) * 2 * sizeof(void *)); + GOTO_UNLESS(new, "Out of memory", out); + size *= 2; + *kara_id = new; + } + (*kara_id)[(*len)++] = sqlite3_column_int(stmt, 0); + } + +out: + return; +} + +void +database_get_update(volatile sqlite3 *db, long *timestamp, long *job, int *current) +{ + static const char *SQL = "SELECT last_update, update_job, last_update > last_end_update FROM misc WHERE id = 42;"; + sqlite3_stmt *stmt; + SQLITE_PREPARE(db, stmt, SQL, error); + SQLITE_STEP_ROW(db, stmt, error); + if (timestamp) + *timestamp = sqlite3_column_int(stmt, 0); + if (job) + *job = sqlite3_column_int(stmt, 1); + if (current) + *current = sqlite3_column_int(stmt, 2); + return; +error: + LOG_WARN_SCT("DB", "Failed to get informations about the last update: %s", sqlite3_errmsg((sqlite3 *) db)); +} + +void +database_update_del(volatile sqlite3 *db, int id) +{ + static const char *SQL = "DELETE FROM kara WHERE id = ?;"; + sqlite3_stmt *stmt = NULL; + SQLITE_PREPARE(db, stmt, SQL, error); + SQLITE_BIND_INT(db, stmt, 1, id, error); + SQLITE_STEP_OK(db, stmt, error); + LOG_WARN_SCT("DB", "Deleted kara with id '%d' from database", id); +error: + return; +} + +#define sqlite_just_exec(func, query) \ + void func (volatile sqlite3 *db) { \ + SQLITE_EXEC(db, #query, error); \ + error: return; \ + } +sqlite_just_exec(database_stamp, "UPDATE misc SET last_update = strftime('%s','now');") +sqlite_just_exec(database_updated, "UPDATE misc SET last_end_update = strftime('%s','now'), update_job = update_job + 1;") +#undef sqlite_just_exec diff --git a/src/module/mpv.c b/src/module/mpv.c index 99826ecdc02b568889cfd5e41b85dd8712e5bd02..492ac110f59a2a7f779bf8bcba5fd7225447707e 100644 --- a/src/module/mpv.c +++ b/src/module/mpv.c @@ -103,12 +103,17 @@ lmpv_load_file(mpv_handle *ctx, const char *file) { RETURN_UNLESS(ctx, "Missing mpv ctx", 1); RETURN_IF(access(file, R_OK), "Failed to read file", 1); - const char *cmd[] = {"loadfile", file, "replace", NULL}; + const char *cmd1[] = { "loadfile", file, "replace", NULL }; + const char *cmd2[] = { "set", "pause", "0", NULL }; int status; - if ((status = mpv_command_async(ctx, 0, cmd)) < 0) { + if ((status = mpv_command_async(ctx, 0, cmd1)) < 0) { LOG_ERROR_SCT("WINDOW", "Failed to add '%s': %s", file, mpv_error_string(status)); return 1; } + if ((status = mpv_command_async(ctx, 0, cmd2)) < 0) { + LOG_ERROR_SCT("WINDOW", "Failed to set state to play: %s", mpv_error_string(status)); + return 1; + } return 0; } diff --git a/src/net/downloader.c b/src/net/downloader.c index a076deef22967bc8079f39795a66b0689b4b90b8..9606701e0e7a89b1bd3f3e15430df3f142864528 100644 --- a/src/net/downloader.c +++ b/src/net/downloader.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <unistd.h> #include <string.h> +#include <strings.h> #include <limits.h> #include <stdlib.h> #include <unistd.h> @@ -324,7 +325,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 filestamp, timestamp; + long filestamp = 0, timestamp = 0, db_timestamp = 0; char mkvpropedit[PATH_MAX]; RETURN_UNLESS(len > 0 && json_object_get_array(json), "Json invalid or array empty", NOTHING); RETURN_UNLESS(database_config_get_text(db, "externals", "mkvpropedit", mkvpropedit, PATH_MAX - 1), @@ -365,12 +366,12 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec if (safe_json_get_long(kara_json, "unix_timestamp", ×tamp)) continue; filestamp = get_mtime(kara.filename); - if (database_get_timestamp(db) >= filestamp && filestamp > timestamp && + database_get_update(db, &db_timestamp, NULL, NULL); + if (db_timestamp >= filestamp && filestamp > timestamp && ! kara_metadata_equals(&kara.mdt, kara.filename)) { LOG_INFO_SCT("REPO", "Ignore kara '%ld' with path '%s'", kara.id, kara.filename); continue; } - LOG_WARN_SCT("REPO", "Download kara '%ld' with path '%s'", kara.id, kara.filename); if (!database_update_add((sqlite3 *) db, kara.filename, &kara.mdt, kara.id, false)) { LOG_ERROR_SCT("REPO", "Could not add unavailable kara %ld to db", kara.id); @@ -399,6 +400,21 @@ __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_objec } } +static inline void +__handle_deleted_kara(volatile sqlite3 *db) +{ + size_t len, i; + int *kara_ids; + char filepath[PATH_MAX]; + database_deleted_kara(db, &kara_ids, &len); + + for (i = 0; i < len; ++i) { + if (!database_get_kara_path(db, kara_ids[i], filepath)) + continue; + database_update_del(db, kara_ids[i]); + } +} + void * __repo_get_all_id_async(void *arg) { @@ -410,6 +426,8 @@ __repo_get_all_id_async(void *arg) __handle_got_json(repo->db, repo, json); LOG_INFO_SCT("REPO", "%s", "Finished to download and insert kara list"); json_object_put(json); + __handle_deleted_kara(repo->db); + LOG_INFO_SCT("REPO", "%s", "Finished to deal with deleted kara"); database_updated(repo->db); return NULL; } diff --git a/src/net/listen.c b/src/net/listen.c index a31deb4425083a4274d3bd33b79f796b34d8f341..01389c300c467881a113920f753388ba11d44bd0 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -378,6 +378,7 @@ handle_disconnected_client(struct lkt_state *srv, size_t c) struct lkt_client *cli = &srv->clients[c - 1]; for (size_t i = 0; i < cli->buffer_out_len; i++) lkt_message_free(cli->buffer_out[i]); + cli->buffer_out_len = 0; } static int