Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 25e81392efede46b15cb371e7ceff378196eda29
  • master par défaut protégée
  • rust-playlist-sync
  • rust
  • fix-qt-deprecated-qvariant-type
  • fix-mpris-qtwindow-race-condition
  • rust-appimage-wayland
  • windows-build-rebased
  • v2.5 protégée
  • v2.4 protégée
  • v2.3-1 protégée
  • v2.3 protégée
  • v2.2 protégée
  • v2.1 protégée
  • v2.0 protégée
  • v1.8-3 protégée
  • v1.8-2 protégée
  • v1.8-1 protégée
  • v1.8 protégée
  • v1.7 protégée
  • v1.6 protégée
  • v1.5 protégée
  • v1.4 protégée
  • v1.3 protégée
  • v1.2 protégée
  • v1.1 protégée
  • v1.0 protégée
27 résultats

open.c

Blame
  • open.c 7,18 Kio
    #define _POSIX_C_SOURCE 200809L
    
    #include <common/common.h>
    #include <lektor/database.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <strings.h>
    
    /* Some notes:
       - There's one and only row.
       - `paused` 0 = play, 1 = paused
       - `random` whether the queue is played randomly
       - `repeat` whether the queue loops
       - `single` whether only one kara loops
       - `current` the position in the queue of the kara being played
       - `elapsed` the number of seconds from the beginning of the current kara
       - `duration` the total duration of the playing kara
       This schema is used to initialize the in-memory database. */
    static const char *const SQL_MEM_SCHEM =
        "CREATE TABLE IF NOT EXISTS queue_state"
        "  ( id         INTEGER PRIMARY KEY DEFAULT 42 CHECK(id = 42)"
        "  , volume     INTEGER NOT NULL DEFAULT 100 CHECK(0 <= volume AND volume <= 100)"
        "  , paused     INTEGER NOT NULL DEFAULT 1"
        "  , random     INTEGER NOT NULL DEFAULT 0"
        "  , repeat     INTEGER NOT NULL DEFAULT 0"
        "  , single     INTEGER NOT NULL DEFAULT 0"
        "  , consume    INTEGER NOT NULL DEFAULT 0"
        "  , current    INTEGER CHECK(current > 0)"
        "  , duration   INTEGER CHECK(duration >= 0)"
        "  , elapsed    INTEGER CHECK(elapsed >= 0)"
        "  );\n"
        "INSERT INTO queue_state (id) VALUES (42);\n"
        "CREATE TABLE IF NOT EXISTS config"
        "  ( section    TEXT NOT NULL"
        "  , key        TEXT NOT NULL"
        "  , value      TEXT"
        "  , PRIMARY KEY (section, key)"
        "  ) WITHOUT ROWID;\n";
    
    /* Should be, defined scripts_init_sql and its length scripts_init_sql_len */
    extern unsigned char ___scripts_init_sql[];
    extern int ___scripts_init_sql_len;
    
    #define INVALID_CHARS_DBPATH    ":?!'\""
    #define HEAP_LIMIT_SOFT         100 * 1024 * 1024
    #define HEAP_LIMIT_HARD         150 * 1024 * 1024
    
    int
    is_sql_str_invalid(const char *str)
    {
        size_t len = strlen(str);
        return strcspn(str, INVALID_CHARS_DBPATH) != len;
    }
    
    bool
    database_new(volatile sqlite3 **db)
    {
        static int flags = SQLITE_OPEN_READWRITE    |   /* Open in RW mode              */
                           SQLITE_OPEN_SHAREDCACHE  |   /* hHared cache for databases   */
                           SQLITE_OPEN_NOFOLLOW     |   /* Don't follow symlinks        */
                           SQLITE_OPEN_FULLMUTEX;       /* Serialized                   */
        RETURN_IF(SQLITE_OK != sqlite3_enable_shared_cache(1), "Failed to enable shared cache", false);
        RETURN_IF(sqlite3_soft_heap_limit64(HEAP_LIMIT_SOFT) < 0, "Failed to set soft heap limit", false);
        RETURN_IF(sqlite3_hard_heap_limit64(HEAP_LIMIT_HARD) < 0, "Failed to set soft heap limit", false);
        RETURN_IF(SQLITE_OK != sqlite3_open_v2(":memory:", (sqlite3 **) db, flags, NULL), "Failed to open :memory:", false);
        SQLITE_EXEC(*db, SQL_MEM_SCHEM, err_not_init);
        return true;
    err_not_init:
        *db = NULL;
        return false;
    }
    
    static inline bool
    __attach(volatile sqlite3 *db, const char *name, const char *path)
    {
        static const char SQL_ATTACH_TEMPLATE[] = "ATTACH '%s' AS '%s';";
        char SQL_ATTACH[LKT_MAX_SQLITE_STATEMENT];
        bool ret = false;
    
        safe_snprintf(SQL_ATTACH, LKT_MAX_SQLITE_STATEMENT, SQL_ATTACH_TEMPLATE, path, name);
        SQLITE_EXEC(db, SQL_ATTACH, err_no_attach);
        LOG_INFO_SCT("DB", "Attached database '%s' with path '%s'", name, path);
        ret = true;
    err_no_attach:
        return ret;
    }
    
    static inline bool
    __detach(volatile sqlite3 *db, const char *name)
    {
        static const char SQL_DETACH_TEMPLATE[] = "DETACH '%s';\n";
        char SQL_DETACH[LKT_MAX_SQLITE_STATEMENT];
        bool ret = false;
    
        safe_snprintf(SQL_DETACH, LKT_MAX_SQLITE_STATEMENT, SQL_DETACH_TEMPLATE, name);
        SQLITE_EXEC(db, SQL_DETACH, err_no_detach);
        LOG_INFO_SCT("DB", "Detached database '%s'", name);
        ret = true;
    err_no_detach:
        return ret;
    }
    
    static inline bool
    __is_attached(volatile sqlite3 *db, const char *name)
    {
        static const char *SQL_STMT = "SELECT name FROM pragma_database_list WHERE name = ?;\n";
        sqlite3_stmt *stmt = 0;
        bool ret = false;
    
        SQLITE_PREPARE(db, stmt, SQL_STMT, error);
        SQLITE_BIND_TEXT(db, stmt, 1, name, error);
        SQLITE_STEP_ROW(db, stmt, error);
        ret = true;
    error:
        sqlite3_finalize(stmt);
        return ret;
    }
    
    bool
    database_open(volatile sqlite3 *db, const char *dbpath)
    {
        if (is_sql_str_invalid(dbpath)) {
            LOG_ERROR("The database path '%s' is invalid", dbpath);
            return false;
        }
        return __attach(db, PROTECTED_DATABASE, dbpath);
    }
    
    bool
    database_attach(volatile sqlite3 *db, const char *name, const char *dbpath)
    {
        RETURN_UNLESS(strcasecmp(PROTECTED_DATABASE, name), " The database "PROTECTED_DATABASE
                      " is protected, can't attach a database with the same name", false);
    
        if (is_sql_str_invalid(name)) {
            LOG_ERROR("The database name '%s' is invalid", name);
            return false;
        }
    
        if (__is_attached(db, name)) {
            LOG_ERROR("The database '%s' is already attached", name);
            return false;
        }
    
        if (!__attach(db, name, dbpath)) {
            LOG_ERROR_SCT("DB", "Failed to attach database named '%s' with path '%s'", name, dbpath);
            return false;
        }
    
        LOG_INFO_SCT("DB", "Database '%s' attached", name);
        return true;
    }
    
    bool
    database_detach(volatile sqlite3 *db, const char *name)
    {
        RETURN_UNLESS(strcasecmp(PROTECTED_DATABASE, name), " The database "PROTECTED_DATABASE
                      " is protected, can't detach it", false);
    
        if (is_sql_str_invalid(name)) {
            LOG_ERROR("The database name '%s' is invalid", name);
            return false;
        }
    
        if (!__is_attached(db, name)) {
            LOG_ERROR("The database '%s' is not attached", name);
            return false;
        }
    
        if (!__detach(db, name)) {
            LOG_ERROR_SCT("DB", "Failed to detach database named %s", name);
            return false;
        }
    
        LOG_INFO_SCT("DB", "Database '%s' detached", name);
        return true;
    }
    
    bool
    database_init(const char *dbpath)
    {
        sqlite3 *db;
        GOTO_IF(SQLITE_OK != sqlite3_open(dbpath, &db), "Failed to open the database", error);
        SQLITE_EXEC(db, (const char *) ___scripts_init_sql, error);
        LOG_INFO_SCT("DB", "Initialized the 'disk' database successfully, path was '%s'", dbpath);
        return true;
    error:
        LOG_ERROR_SCT("DB", "Failed to init the 'disk' database, path was '%s'", dbpath);
        return false;
    }
    
    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_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'), update_job = update_job + 1;", error);
    error:
        return;
    }