A tool for adding anime to your anidb list.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
5.8KB

  1. #include <stddef.h>
  2. #include <sqlite3.h>
  3. #include "cache.h"
  4. #include "config.h"
  5. #include "uio.h"
  6. #include "ed2k.h"
  7. #include "util.h"
  8. #define sqlite_bind_goto(smt, name, type, ...) { \
  9. int sb_idx = sqlite3_bind_parameter_index(smt, name); \
  10. if (sb_idx == 0) { \
  11. uio_error("Cannot get named parameter for var: %s", name); \
  12. err = ERR_CACHE_SQLITE; \
  13. goto fail; \
  14. } \
  15. int sb_sret = sqlite3_bind_##type(smt, sb_idx, __VA_ARGS__); \
  16. if (sb_sret != SQLITE_OK) {\
  17. uio_error("Cannot bind to statement: %s", sqlite3_errmsg(cache_db));\
  18. err = ERR_CACHE_SQLITE;\
  19. goto fail;\
  20. } \
  21. }
  22. static sqlite3 *cache_db = NULL;
  23. static const char sql_create_table[] = "CREATE TABLE IF NOT EXISTS mylist ("
  24. "lid INTEGER NOT NULL PRIMARY KEY,"
  25. "fname TEXT NOT NULL,"
  26. "fsize INTEGER NOT NULL,"
  27. "ed2k TEXT NOT NULL,"
  28. "UNIQUE (fname, fsize) )";
  29. static const char sql_mylist_add[] = "INSERT INTO mylist "
  30. "(lid, fname, fsize, ed2k) VALUES "
  31. //"(?, ?, ?, ?)";
  32. "(:lid, :fname, :fsize, :ed2k)";
  33. static const char sql_mylist_get[] = "SELECT * FROM mylist WHERE "
  34. "fsize=:fsize AND fname=:fname";
  35. #if 0
  36. static const char sql_has_tables[] = "SELECT 1 FROM sqlite_master "
  37. "WHERE type='table' AND tbl_name='mylist'";
  38. /* Return 0 if false, 1 if true, and -1 if error */
  39. static int cache_has_tables()
  40. {
  41. sqlite3_smt smt;
  42. int sret;
  43. sret = sqlite3_prepare_v2(cache_db, sql_has_tables,
  44. sizeof(sql_has_tables), &smt, NULL);
  45. if (sret != SQLITE_OK) {
  46. uio_error("Cannot prepare statement: %s", sqlite3_errmsg(cache_db));
  47. return -1;
  48. }
  49. sqlite3_step(&smt);
  50. // ehh fuck this, lets just use if not exists
  51. sret = sqlite3_finalize(&smt);
  52. if (sret != SQLITE_OK)
  53. uio_debug("sql3_finalize failed: %s", sqlite3_errmsg(cache_db));
  54. }
  55. #endif
  56. /*
  57. * Create database table(s)
  58. */
  59. static enum error cache_init_table()
  60. {
  61. sqlite3_stmt *smt;
  62. int sret;
  63. enum error err = NOERR;
  64. sret = sqlite3_prepare_v2(cache_db, sql_create_table,
  65. sizeof(sql_create_table), &smt, NULL);
  66. if (sret != SQLITE_OK) {
  67. uio_error("Cannot prepare statement: %s", sqlite3_errmsg(cache_db));
  68. return ERR_CACHE_SQLITE;
  69. }
  70. sret = sqlite3_step(smt);
  71. if (sret != SQLITE_DONE) {
  72. uio_error("sql3_step is not done: %s", sqlite3_errmsg(cache_db));
  73. err = ERR_CACHE_SQLITE;
  74. }
  75. sret = sqlite3_finalize(smt);
  76. if (sret != SQLITE_OK)
  77. uio_debug("sql3_finalize failed: %s", sqlite3_errmsg(cache_db));
  78. return err;
  79. }
  80. enum error cache_init()
  81. {
  82. char **db_path;
  83. enum error err;
  84. int sret;
  85. err = config_get("cachedb", (void**)&db_path);
  86. if (err != NOERR) {
  87. uio_error("Cannot get cache db path from args");
  88. return err;
  89. }
  90. uio_debug("Opening cache db: '%s'", *db_path);
  91. sret = sqlite3_open(*db_path, &cache_db);
  92. if (sret != SQLITE_OK) {
  93. uio_error("Cannot create sqlite3 database: %s", sqlite3_errstr(sret));
  94. sqlite3_close(cache_db); /* Even if arg is NULL, it's A'OK */
  95. return ERR_CACHE_SQLITE;
  96. }
  97. sqlite3_extended_result_codes(cache_db, 1);
  98. err = cache_init_table();
  99. if (err != NOERR)
  100. goto fail;
  101. return NOERR;
  102. fail:
  103. cache_free();
  104. return err;
  105. }
  106. void cache_free()
  107. {
  108. sqlite3_close(cache_db);
  109. uio_debug("Closed cache db");
  110. }
  111. enum error cache_add(uint64_t lid, const char *fname,
  112. uint64_t fsize, const uint8_t *ed2k)
  113. {
  114. char ed2k_str[ED2K_HASH_SIZE * 2 + 1];
  115. sqlite3_stmt *smt;
  116. int sret;
  117. enum error err = NOERR;
  118. sret = sqlite3_prepare_v2(cache_db, sql_mylist_add,
  119. sizeof(sql_mylist_add), &smt, NULL);
  120. if (sret != SQLITE_OK) {
  121. uio_error("Cannot prepare statement: %s", sqlite3_errmsg(cache_db));
  122. return ERR_CACHE_SQLITE;
  123. }
  124. util_byte2hex(ed2k, ED2K_HASH_SIZE, false, ed2k_str);
  125. sqlite_bind_goto(smt, ":lid", int64, lid);
  126. sqlite_bind_goto(smt, ":fname", text, fname, -1, SQLITE_STATIC);
  127. sqlite_bind_goto(smt, ":fsize", int64, fsize);
  128. sqlite_bind_goto(smt, ":ed2k", text, ed2k_str, -1, SQLITE_STATIC);
  129. sret = sqlite3_step(smt);
  130. if (sret != SQLITE_DONE) {
  131. if (sret == SQLITE_CONSTRAINT_PRIMARYKEY) {
  132. uio_debug("Attempted to add duplicate entry!");
  133. err = ERR_CACHE_EXISTS;
  134. } else if (sret == SQLITE_CONSTRAINT_UNIQUE) {
  135. uio_debug("An entry with the same name and size already exists!");
  136. err = ERR_CACHE_NON_UNIQUE;
  137. } else {
  138. uio_error("error after sql3_step: %s %d", sqlite3_errmsg(cache_db), sret);
  139. err = ERR_CACHE_SQLITE;
  140. }
  141. }
  142. fail:
  143. sqlite3_finalize(smt);
  144. return err;
  145. }
  146. enum error cache_get(const char *fname, uint64_t fsize,
  147. struct cache_entry *out_ce)
  148. {
  149. sqlite3_stmt *smt;
  150. int sret;
  151. enum error err = NOERR;
  152. sret = sqlite3_prepare_v2(cache_db, sql_mylist_get,
  153. sizeof(sql_mylist_get), &smt, NULL);
  154. if (sret != SQLITE_OK) {
  155. uio_error("Cannot prepare statement: %s", sqlite3_errmsg(cache_db));
  156. return ERR_CACHE_SQLITE;
  157. }
  158. sqlite_bind_goto(smt, ":fname", text, fname, -1, SQLITE_STATIC);
  159. sqlite_bind_goto(smt, ":fsize", int64, fsize);
  160. sret = sqlite3_step(smt);
  161. if (sret == SQLITE_DONE) {
  162. uio_debug("Cache entry with size (%lu) and name (%s) not found", fsize, fname);
  163. err = ERR_CACHE_NO_EXISTS;
  164. } else if (sret == SQLITE_ROW) {
  165. uio_debug("Found Cache entry with size (%lu) and name (%s)", fsize, fname);
  166. } else {
  167. uio_error("sqlite_step failed: %s", sqlite3_errmsg(cache_db));
  168. err = ERR_CACHE_SQLITE;
  169. }
  170. fail:
  171. sqlite3_finalize(smt);
  172. return err;
  173. }