/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include "metaDef.h" #if !USE_SQLITE_IMPL static void metaSaveSchemaDB(SMeta *pMeta, tb_uid_t uid, STSchema *pSchema); static void metaGetSchemaDBKey(char key[], tb_uid_t uid, int sversion); #define SCHEMA_KEY_LEN (sizeof(tb_uid_t) + sizeof(int)) #define META_OPEN_DB_IMPL(pDB, options, dir, err) \ do { \ pDB = rocksdb_open(options, dir, &err); \ if (pDB == NULL) { \ metaCloseDB(pMeta); \ rocksdb_options_destroy(options); \ return -1; \ } \ } while (0) #define META_CLOSE_DB_IMPL(pDB) \ do { \ if (pDB) { \ rocksdb_close(pDB); \ pDB = NULL; \ } \ } while (0) #endif int metaOpenDB(SMeta *pMeta) { char dir[128]; int rc; char *err = NULL; #if !USE_SQLITE_IMPL rocksdb_options_t *options = rocksdb_options_create(); if (pMeta->pCache) { rocksdb_options_set_row_cache(options, pMeta->pCache); } rocksdb_options_set_create_if_missing(options, 1); pMeta->pDB = (meta_db_t *)calloc(1, sizeof(*(pMeta->pDB))); if (pMeta->pDB == NULL) { // TODO: handle error rocksdb_options_destroy(options); return -1; } // tbDb sprintf(dir, "%s/tb_db", pMeta->path); META_OPEN_DB_IMPL(pMeta->pDB->tbDb, options, dir, err); // nameDb sprintf(dir, "%s/name_db", pMeta->path); META_OPEN_DB_IMPL(pMeta->pDB->nameDb, options, dir, err); // tagDb sprintf(dir, "%s/tag_db", pMeta->path); META_OPEN_DB_IMPL(pMeta->pDB->tagDb, options, dir, err); // schemaDb sprintf(dir, "%s/schema_db", pMeta->path); META_OPEN_DB_IMPL(pMeta->pDB->schemaDb, options, dir, err); // mapDb sprintf(dir, "%s/meta.db", pMeta->path); if (sqlite3_open(dir, &(pMeta->pDB->mapDb)) != SQLITE_OK) { // TODO } // // set read uncommitted sqlite3_exec(pMeta->pDB->mapDb, "PRAGMA read_uncommitted=true;", 0, 0, 0); sqlite3_exec(pMeta->pDB->mapDb, "BEGIN;", 0, 0, 0); rocksdb_options_destroy(options); #else sprintf(dir, "%s/meta.db", pMeta->path); rc = sqlite3_open(dir, &(pMeta->pDB)); if (rc != SQLITE_OK) { // TODO: handle error printf("failed to open meta.db\n"); } // For all tables rc = sqlite3_exec(pMeta->pDB, "CREATE TABLE IF NOT EXISTS tb (" " tbname VARCHAR(256) NOT NULL UNIQUE," " tb_uid INTEGER NOT NULL UNIQUE " ");", NULL, NULL, &err); if (rc != SQLITE_OK) { // TODO: handle error printf("failed to create meta table tb since %s\n", err); } // For super tables rc = sqlite3_exec(pMeta->pDB, "CREATE TABLE IF NOT EXISTS stb (" " tb_uid INTEGER NOT NULL UNIQUE," " tbname VARCHAR(256) NOT NULL UNIQUE," " tb_schema BLOB NOT NULL," " tag_schema BLOB NOT NULL" ");", NULL, NULL, &err); if (rc != SQLITE_OK) { // TODO: handle error printf("failed to create meta table stb since %s\n", err); } // For normal tables rc = sqlite3_exec(pMeta->pDB, "CREATE TABLE IF NOT EXISTS ntb (" " tb_uid INTEGER NOT NULL UNIQUE," " tbname VARCHAR(256) NOT NULL," " tb_schema BLOB NOT NULL" ");", NULL, NULL, &err); if (rc != SQLITE_OK) { // TODO: handle error printf("failed to create meta table ntb since %s\n", err); } sqlite3_exec(pMeta->pDB, "BEGIN;", NULL, NULL, &err); tfree(err); #endif return 0; } void metaCloseDB(SMeta *pMeta) { #if !USE_SQLITE_IMPL if (pMeta->pDB) { if (pMeta->pDB->mapDb) { sqlite3_exec(pMeta->pDB->mapDb, "COMMIT;", 0, 0, 0); sqlite3_close(pMeta->pDB->mapDb); pMeta->pDB->mapDb = NULL; } META_CLOSE_DB_IMPL(pMeta->pDB->schemaDb); META_CLOSE_DB_IMPL(pMeta->pDB->tagDb); META_CLOSE_DB_IMPL(pMeta->pDB->nameDb); META_CLOSE_DB_IMPL(pMeta->pDB->tbDb); free(pMeta->pDB); pMeta->pDB = NULL; } #else if (pMeta->pDB) { sqlite3_exec(pMeta->pDB, "BEGIN;", NULL, NULL, NULL); sqlite3_close(pMeta->pDB); pMeta->pDB = NULL; } // TODO #endif } int metaSaveTableToDB(SMeta *pMeta, const STbCfg *pTbOptions) { #if !USE_SQLITE_IMPL tb_uid_t uid; char * err = NULL; size_t size; char pBuf[1024]; // TODO char sql[128]; rocksdb_writeoptions_t *wopt = rocksdb_writeoptions_create(); // Generate a uid for child and normal table if (pTbOptions->type == META_SUPER_TABLE) { uid = pTbOptions->stbCfg.suid; } else { uid = metaGenerateUid(pMeta); } // Save tbname -> uid to tbnameDB rocksdb_put(pMeta->pDB->nameDb, wopt, pTbOptions->name, strlen(pTbOptions->name), (char *)(&uid), sizeof(uid), &err); rocksdb_writeoptions_disable_WAL(wopt, 1); // Save uid -> tb_obj to tbDB size = metaEncodeTbObjFromTbOptions(pTbOptions, pBuf, 1024); rocksdb_put(pMeta->pDB->tbDb, wopt, (char *)(&uid), sizeof(uid), pBuf, size, &err); switch (pTbOptions->type) { case META_NORMAL_TABLE: // save schemaDB metaSaveSchemaDB(pMeta, uid, pTbOptions->ntbCfg.pSchema); break; case META_SUPER_TABLE: // save schemaDB metaSaveSchemaDB(pMeta, uid, pTbOptions->stbCfg.pSchema); // // save mapDB (really need?) // rocksdb_put(pMeta->pDB->mapDb, wopt, (char *)(&uid), sizeof(uid), "", 0, &err); sprintf(sql, "create table st_%" PRIu64 " (uid BIGINT);", uid); if (sqlite3_exec(pMeta->pDB->mapDb, sql, NULL, NULL, &err) != SQLITE_OK) { // fprintf(stderr,"Failed to create table, since %s\n", err); } break; case META_CHILD_TABLE: // save tagDB rocksdb_put(pMeta->pDB->tagDb, wopt, (char *)(&uid), sizeof(uid), pTbOptions->ctbCfg.pTag, kvRowLen(pTbOptions->ctbCfg.pTag), &err); // save mapDB sprintf(sql, "insert into st_%" PRIu64 " values (%" PRIu64 ");", pTbOptions->ctbCfg.suid, uid); if (sqlite3_exec(pMeta->pDB->mapDb, sql, NULL, NULL, &err) != SQLITE_OK) { fprintf(stderr, "failed to insert data, since %s\n", err); } break; default: ASSERT(0); } rocksdb_writeoptions_destroy(wopt); #else char sql[256]; char *err = NULL; int rc; switch (pTbOptions->type) { case META_SUPER_TABLE: // sprintf(sql, "INSERT INTO tb VALUES (\'%s\', %" PRIu64 // ");" // "INSERT INTO stb VALUES (%" PRIu64 // ", \'%s\', );" // "CREATE TABLE IF NOT EXISTS stb_%" PRIu64 // " (" // " tb_uid INTEGER NOT NULL UNIQUE," // " tbname VARCHAR(256)," // " tag1 INTEGER" // ");" // "CREATE INDEX IF NOT EXISTS stb_%" PRIu64 "_tag1_idx ON stb_1638517480 (tag1);"); rc = sqlite3_exec(pMeta->pDB, sql, NULL, NULL, &err); if (rc != SQLITE_OK) { printf("failed to create normal table since %s\n", err); } break; case META_NORMAL_TABLE: // sprintf(sql, "INSERT INTO tb VALUES (\'%s\', %" PRIu64 // ");" // "INSERT INTO ntb VALUES (%" PRIu64 ", \'%s\', );"); rc = sqlite3_exec(pMeta->pDB, sql, NULL, NULL, &err); if (rc != SQLITE_OK) { printf("failed to create normal table since %s\n", err); } break; case META_CHILD_TABLE: // sprintf(sql, "INSERT INTO tb VALUES (\'%s\', %" PRIu64 // ");" // "INSERT INTO stb_%" PRIu64 " VALUES (%" PRIu64 ", \'%s\', );"); rc = sqlite3_exec(pMeta->pDB, sql, NULL, NULL, &err); if (rc != SQLITE_OK) { printf("failed to create normal table since %s\n", err); } break; default: break; } tfree(err); #endif return 0; } int metaRemoveTableFromDb(SMeta *pMeta, tb_uid_t uid) { /* TODO */ return 0; } /* ------------------------ STATIC METHODS ------------------------ */ #if !USE_SQLITE_IMPL static void metaSaveSchemaDB(SMeta *pMeta, tb_uid_t uid, STSchema *pSchema) { char key[64]; char pBuf[1024]; char * ppBuf = pBuf; size_t vsize; char * err = NULL; rocksdb_writeoptions_t *wopt = rocksdb_writeoptions_create(); rocksdb_writeoptions_disable_WAL(wopt, 1); metaGetSchemaDBKey(key, uid, schemaVersion(pSchema)); vsize = tdEncodeSchema((void **)(&ppBuf), pSchema); rocksdb_put(pMeta->pDB->schemaDb, wopt, key, SCHEMA_KEY_LEN, pBuf, vsize, &err); rocksdb_writeoptions_destroy(wopt); } static void metaGetSchemaDBKey(char *key, tb_uid_t uid, int sversion) { *(tb_uid_t *)key = uid; *(int *)POINTER_SHIFT(key, sizeof(tb_uid_t)) = sversion; } #endif