static GError * __save_service(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, struct meta1_service_url_s *m1url, gboolean force) { gint rc; GError *err = NULL; sqlite3_stmt *stmt = NULL; sqlite3_prepare_debug(rc, sq3->db, force ? "INSERT OR REPLACE INTO services (cid,srvtype,seq,url,args) VALUES (?,?,?,?,?)" : "INSERT INTO services (cid,srvtype,seq,url,args) VALUES (?,?,?,?,?)", -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, m1url->srvtype, -1, NULL); (void) sqlite3_bind_int(stmt, 3, m1url->seq); (void) sqlite3_bind_text(stmt, 4, m1url->host, -1, NULL); (void) sqlite3_bind_text(stmt, 5, m1url->args, -1, NULL); sqlite3_step_debug_until_end(rc, stmt); if (rc != SQLITE_DONE && rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); return err; }
static GError* __count_FK (struct sqlx_sqlite3_s *sq3, struct hc_url_s *url, const char *table, guint *count) { gint rc; sqlite3_stmt *stmt = NULL; gchar sql[sizeof(FMT_COUNT)+32]; g_snprintf (sql, sizeof(sql), FMT_COUNT, table); sqlite3_prepare_debug(rc, sq3->db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); (void) sqlite3_bind_blob(stmt, 1, hc_url_get_id (url), hc_url_get_id_size (url), NULL); guint _count = 0; while (SQLITE_ROW == (rc = sqlite3_step(stmt))) _count += sqlite3_column_int(stmt, 0); GError *err = NULL; if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); if (err) return err; *count = _count; return NULL; }
static GError * __configure_service(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, struct meta1_service_url_s *m1url) { static const char *sql = "UPDATE services SET args = ? " "WHERE cid = ? AND seq = ? AND srvtype = ?"; gint rc; GError *err = NULL; sqlite3_stmt *stmt = NULL; sqlite3_prepare_debug(rc, sq3->db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); else { (void) sqlite3_bind_text(stmt, 1, m1url->args, -1, NULL); (void) sqlite3_bind_blob(stmt, 2, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_int64(stmt, 3, m1url->seq); (void) sqlite3_bind_text(stmt, 4, m1url->srvtype, -1, NULL); sqlite3_step_debug_until_end (rc, stmt); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); if (!err && !sqlite3_changes(sq3->db)) err = NEWERROR(CODE_SRV_NOLINK, "Service not found"); } return err; }
static GError * __del_container_srvtype_properties(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, const char *srvtype) { GError *err = NULL; gint rc; sqlite3_stmt *stmt = NULL; sqlite3_prepare_debug(rc, sq3->db, "DELETE FROM properties WHERE cid = ? AND name LIKE ?", -1, &stmt, NULL); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); else { int len = strlen(srvtype)+10; gchar *tmp_name = g_malloc0(sizeof(gchar)*len); if (tmp_name) { g_snprintf(tmp_name, len, "%s.%%", srvtype); (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, tmp_name, -1, NULL); sqlite3_step_debug_until_end (rc, stmt); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); g_free (tmp_name); } } return err; }
static GError * __replace_property(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, const gchar *name, const gchar *value) { GError *err = NULL; gint rc; sqlite3_stmt *stmt = NULL; EXTRA_ASSERT(name != NULL && *name != '\0'); EXTRA_ASSERT(value != NULL && *value != '\0'); GRID_TRACE("%s(n=%s,v=%s)", __FUNCTION__, name, value); sqlite3_prepare_debug(rc, sq3->db, "REPLACE INTO properties (name,value,cid) VALUES (?,?,?)", -1, &stmt, NULL); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); else { (void) sqlite3_bind_text(stmt, 1, name, -1, NULL); (void) sqlite3_bind_text(stmt, 2, value, -1, NULL); (void) sqlite3_bind_blob(stmt, 3, oio_url_get_id(url), oio_url_get_id_size(url), NULL); sqlite3_step_debug_until_end (rc, stmt); if (rc != SQLITE_DONE && rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); } return err; }
static GError * __get_one_property(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, const gchar *name, GPtrArray *gpa) { GError *err = NULL; sqlite3_stmt *stmt = NULL; int rc; GRID_TRACE("%s(n=%s)", __FUNCTION__, name); sqlite3_prepare_debug(rc, sq3->db, "SELECT name,value FROM properties WHERE cid = ? AND name = ?", -1, &stmt, NULL); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); else { (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, name, -1, NULL); while (SQLITE_ROW == (rc = sqlite3_step(stmt))) { g_ptr_array_add(gpa, item(stmt, 0)); g_ptr_array_add(gpa, item(stmt, 1)); } if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); } return err; }
static GError * __get_container_all_services(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, const char *srvtype, struct meta1_service_url_s ***result) { GError *err = NULL; sqlite3_stmt *stmt = NULL; GPtrArray *gpa; int rc; /* Prepare the statement */ if (srvtype && *srvtype) { sqlite3_prepare_debug(rc, sq3->db, "SELECT seq,srvtype,url,args FROM services WHERE cid = ? AND srvtype = ?", -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, srvtype, -1, NULL); } else { sqlite3_prepare_debug(rc, sq3->db, "SELECT seq,srvtype,url,args FROM services WHERE cid = ?", -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); } /* Run the result */ gpa = g_ptr_array_new(); while (SQLITE_ROW == (rc = sqlite3_step(stmt))) { struct meta1_service_url_s *u; u = g_malloc0(sizeof(struct meta1_service_url_s) + 1 + sqlite3_column_bytes(stmt, 3)); u->seq = sqlite3_column_int(stmt, 0); g_strlcpy(u->srvtype, (gchar*)sqlite3_column_text(stmt, 1), sizeof(u->srvtype)); g_strlcpy(u->host, (gchar*)sqlite3_column_text(stmt, 2), sizeof(u->host)-1); memcpy(u->args, (gchar*)sqlite3_column_text(stmt, 3), sqlite3_column_bytes(stmt, 3)); g_ptr_array_add(gpa, u); } if (rc != SQLITE_DONE && rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); if (err) { gpa_str_free(gpa); return err; } g_ptr_array_add(gpa, NULL); *result = (struct meta1_service_url_s**) g_ptr_array_free(gpa, FALSE); return NULL; }
static GError * __del_container_properties(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, gchar **names) { GError *err = NULL; gchar **p_name; if (!names || !*names) __exec_cid(sq3->db, "DELETE FROM properties WHERE cid = ?", oio_url_get_id(url)); else { for (p_name=names; !err && p_name && *p_name ;p_name++) { sqlite3_stmt *stmt = NULL; gint rc; sqlite3_prepare_debug(rc, sq3->db, "DELETE FROM properties WHERE cid = ? AND name = ?", -1, &stmt, NULL); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); else { (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, *p_name, strlen(*p_name), NULL); sqlite3_step_debug_until_end (rc, stmt); if (rc != SQLITE_DONE) GRID_WARN("SQLite error rc=%d", rc); sqlite3_finalize_debug(rc, stmt); } } } return err; }
static GError * __get_all_services(struct sqlx_sqlite3_s *sq3, struct meta1_service_url_s ***result) { GError *err = NULL; sqlite3_stmt *stmt = NULL; GPtrArray *gpa; int rc; // Prepare the statement sqlite3_prepare_debug(rc, sq3->db, "SELECT DISTINCT srvtype,url FROM services order by srvtype,url", -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); // Run the result gpa = g_ptr_array_new(); while (SQLITE_ROW == (rc = sqlite3_step(stmt))) { struct meta1_service_url_s *u; u = g_malloc0(sizeof(struct meta1_service_url_s) + 1 + sqlite3_column_bytes(stmt, 3)); u->seq = 0; g_strlcpy(u->srvtype, (gchar*)sqlite3_column_text(stmt, 0), sizeof(u->srvtype)); g_strlcpy(u->host, (gchar*)sqlite3_column_text(stmt, 1), sizeof(u->host)-1); u->args[0] = '\0'; g_ptr_array_add(gpa, u); } if (rc != SQLITE_DONE && rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); if (err) { gpa_str_free(gpa); return err; } g_ptr_array_add(gpa, NULL); *result = (struct meta1_service_url_s**) g_ptr_array_free(gpa, FALSE); return NULL; }
static GError * __delete_service(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, const char *srvtype) { gint rc; GError *err = NULL; sqlite3_stmt *stmt = NULL; sqlite3_prepare_debug(rc, sq3->db, "DELETE FROM services WHERE cid = ? AND srvtype = ?", -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, srvtype, -1, NULL); sqlite3_step_debug_until_end (rc, stmt); if (rc != SQLITE_DONE && rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); return err; }
static GError * __del_container_one_service(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, const char *srvtype, gint64 seq) { static const char *sql = "DELETE FROM services WHERE cid = ? AND srvtype = ? AND seq = ?"; sqlite3_stmt *stmt = NULL; GError *err = NULL; int rc; sqlite3_prepare_debug(rc, sq3->db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); else { (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); (void) sqlite3_bind_text(stmt, 2, srvtype, -1, NULL); (void) sqlite3_bind_int64(stmt, 3, seq); sqlite3_step_debug_until_end (rc, stmt); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); } return err; }
static GError * __get_all_container_properties(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, GPtrArray *gpa) { GError *err = NULL; sqlite3_stmt *stmt = NULL; int rc; /* prepare the statement */ sqlite3_prepare_debug(rc, sq3->db, "SELECT name,value FROM properties WHERE cid = ?", -1, &stmt, NULL); if (rc != SQLITE_OK && rc != SQLITE_DONE) err = M1_SQLITE_GERROR(sq3->db, rc); else { (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); while (SQLITE_ROW == (rc = sqlite3_step(stmt))) { g_ptr_array_add(gpa, item(stmt, 0)); g_ptr_array_add(gpa, item(stmt, 1)); } if (rc != SQLITE_DONE && rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); sqlite3_finalize_debug(rc, stmt); } return err; }
GError* _open_and_lock(struct meta1_backend_s *m1, struct oio_url_s *url, enum m1v2_open_type_e how, struct sqlx_sqlite3_s **handle) { EXTRA_ASSERT(m1 != NULL); EXTRA_ASSERT(url != NULL); EXTRA_ASSERT(handle != NULL); GRID_TRACE2("%s(%p,%p,%d,%p)", __FUNCTION__, (void*)m1, oio_url_get (url, OIOURL_HEXID), how, (void*)handle); if (!oio_url_has (url, OIOURL_HEXID)) return NEWERROR (CODE_BAD_REQUEST, "Partial URL (missing HEXID)"); if (!m1b_check_ns_url (m1, url)) return NEWERROR(CODE_NAMESPACE_NOTMANAGED, "Invalid NS"); gchar base[5]; const guint8 *cid = oio_url_get_id(url); g_snprintf(base, sizeof(base), "%02X%02X", cid[0], cid[1]); if (!meta1_prefixes_is_managed(m1->prefixes, cid)) return NEWERROR(CODE_RANGE_NOTFOUND, "prefix [%s] not managed", base); /* Now open/lock the base in a way suitable for our op */ struct sqlx_name_s n = {.base=base, .type=NAME_SRVTYPE_META1, .ns=m1->ns_name}; GError *err = sqlx_repository_open_and_lock(m1->repo, &n, m1_to_sqlx(how), handle, NULL); if (err != NULL) { if (!CODE_IS_REDIRECT(err->code)) g_prefix_error(&err, "Open/Lock error: "); return err; } EXTRA_ASSERT(*handle != NULL); GRID_TRACE("Opened and locked [%s][%s] -> [%s][%s]", base, NAME_SRVTYPE_META1, (*handle)->name.base, (*handle)->name.type); return NULL; } GError* __create_user(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url) { if (!oio_url_has_fq_container (url)) return NEWERROR(CODE_BAD_REQUEST, "Partial URL"); static const gchar *sql = "INSERT INTO users ('cid','account','user') VALUES (?,?,?)"; GError *err = NULL; sqlite3_stmt *stmt = NULL; int rc; EXTRA_ASSERT(sq3 != NULL); EXTRA_ASSERT(sq3->db != NULL); /* Prepare the statement */ sqlite3_prepare_debug(rc, sq3->db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) err = M1_SQLITE_GERROR(sq3->db, rc); else { sqlite3_bind_blob(stmt, 1, oio_url_get_id(url), oio_url_get_id_size(url), NULL); sqlite3_bind_text(stmt, 2, oio_url_get(url, OIOURL_ACCOUNT), -1, NULL); sqlite3_bind_text(stmt, 3, oio_url_get(url, OIOURL_USER), -1, NULL); /* Run the results */ do { rc = sqlite3_step(stmt); } while (rc == SQLITE_ROW); if (rc != SQLITE_OK && rc != SQLITE_DONE) { err = M1_SQLITE_GERROR(sq3->db, rc); if (rc == SQLITE_CONSTRAINT) { g_prefix_error(&err, "Already created? "); err->code = CODE_CONTAINER_EXISTS; } } sqlite3_finalize_debug(rc, stmt); } if (err) GRID_DEBUG("User creation failed : (%d) %s", err->code, err->message); return err; } GError* __info_user(struct sqlx_sqlite3_s *sq3, struct oio_url_s *url, gboolean ac, struct oio_url_s ***result) { GError *err = NULL; sqlite3_stmt *stmt = NULL; GPtrArray *gpa; int rc; gboolean found; EXTRA_ASSERT(sq3 != NULL); EXTRA_ASSERT(sq3->db != NULL); EXTRA_ASSERT(url != NULL); retry: /* Prepare the statement */ sqlite3_prepare_debug(rc, sq3->db, "SELECT account,user FROM users WHERE cid = ?", -1, &stmt, NULL); if (rc != SQLITE_OK) return M1_SQLITE_GERROR(sq3->db, rc); (void) sqlite3_bind_blob(stmt, 1, oio_url_get_id (url), oio_url_get_id_size (url), NULL); /* Run the results */ found = FALSE; gpa = result ? g_ptr_array_new() : NULL; do { if (SQLITE_ROW == (rc = sqlite3_step(stmt))) { found = TRUE; if (!gpa) continue; struct oio_url_s *u = oio_url_empty (); oio_url_set (u, OIOURL_NS, oio_url_get (url, OIOURL_NS)); oio_url_set (u, OIOURL_ACCOUNT, (char*)sqlite3_column_text(stmt, 0)); oio_url_set (u, OIOURL_USER, (char*)sqlite3_column_text(stmt, 1)); oio_url_set (u, OIOURL_HEXID, oio_url_get (url, OIOURL_HEXID)); g_ptr_array_add(gpa, u); } } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE && rc != SQLITE_OK) { err = M1_SQLITE_GERROR(sq3->db, rc); g_prefix_error(&err, "DB error: "); } sqlite3_finalize_debug(rc,stmt); stmt = NULL; if (err) { if (gpa) { g_ptr_array_set_free_func (gpa, (GDestroyNotify)oio_url_clean); g_ptr_array_free (gpa, TRUE); } return err; } if (!found) { if (gpa) g_ptr_array_free (gpa, TRUE); if (ac) { ac = FALSE; /* do not retry */ err = __create_user (sq3, url); if (!err) goto retry; } return NEWERROR(CODE_USER_NOTFOUND, "no such container"); } if (gpa) *result = (struct oio_url_s**) metautils_gpa_to_array(gpa, TRUE); return NULL; }