Пример #1
0
static stKVDatabaseConf *constructFromString(const char *xmlString) {
    stHash *hash = hackParseXmlString(xmlString);
    stKVDatabaseConf *databaseConf = NULL;
    const char *type = getXmlValueRequired(hash, "conf_type");
    const char *dbTag = getXmlValueRequired(hash, "db_tag");
    if (!stString_eq(type, dbTag)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "Database XML tag \"%s\" did not match st_kv_database_conf type attribute", dbTag, type);
    }
    if (stString_eq(type, "tokyo_cabinet")) {
        databaseConf = stKVDatabaseConf_constructTokyoCabinet(getXmlValueRequired(hash, "database_dir"));
    } else if (stString_eq(type, "kyoto_tycoon")) {
        databaseConf = stKVDatabaseConf_constructKyotoTycoon(getXmlValueRequired(hash, "host"), 
                                                        getXmlPort(hash), 
                                                        getXmlTimeout(hash), 
                                                        getXMLMaxKTRecordSize(hash),
                                                        getXMLMaxKTBulkSetSize(hash),
                                                        getXMLMaxKTBulkSetNumRecords(hash),
                                                        getXmlValueRequired(hash, "database_dir"),
                                                        stHash_search(hash, "database_name"));
    } else if (stString_eq(type, "mysql")) {
        databaseConf = stKVDatabaseConf_constructMySql(getXmlValueRequired(hash, "host"), getXmlPort(hash),
                                                       getXmlValueRequired(hash, "user"), getXmlValueRequired(hash, "password"),
                                                       getXmlValueRequired(hash, "database_name"), getXmlValueRequired(hash, "table_name"));
    } else {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "invalid database type \"%s\"", type);
    }
    stHash_destruct(hash);
    return databaseConf;
}
Пример #2
0
/* Parse XML string into a hash.  This parses all attributes of all tags
 * into values.  st_kv_database_conf type is stored as conf_type,
 * database tag is stores as db_tag.  This does minimal error checking
 * and is really lame.
 */
static stHash *hackParseXmlString(const char *xmlString) {
    stHash *hash = stHash_construct3(stHash_stringKey, stHash_stringEqualKey, free, free);
    char *toReplace[5] = { "</", "<", "/>", ">", "=" };
    char *cA = stString_replace(xmlString, toReplace[0], " "), *cA2;
    for (int64_t i = 1; i < 5; i++) {
        cA2 = stString_replace(cA, toReplace[i], " ");
        free(cA);
        cA = cA2;
    }
    getExpectedToken(&cA2, "st_kv_database_conf");
    stHash_insert(hash, stString_copy("conf_type"), getKeyValue(&cA2, "type"));
    stHash_insert(hash, stString_copy("db_tag"), getNextToken(&cA2));

    char *key;
    while (((key = getNextToken(&cA2)) != NULL) && !stString_eq(key, "st_kv_database_conf")) {
        char *value = getNextToken(&cA2);
        if (value == NULL) {
            stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "failed to to get value for key \"%s\"", key);
        }
        if (stHash_search(hash, key) != NULL) {
            stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "got a duplicate entry in the database conf string \"%s\"", key);
        }
        stHash_insert(hash, key, value);
    }
    if(!stString_eq(key, "st_kv_database_conf")) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "got an unexpected final entry \"%s\"", key);
    }
    free(key);
    free(cA);
    return hash;
}
Пример #3
0
static void stSet_verifySetsHaveSameFunctions(stSet *set1, stSet *set2) {
    if (!stSet_hashersEqual(set1, set2)) {
        stThrowNew(SET_EXCEPTION_ID, "Comparator functions are not equal for "
                   "two sets.");
    }
    if (!stSet_equalitiesEqual(set1, set2)) {
        stThrowNew(SET_EXCEPTION_ID, "Hash functions are not equal for "
                   "two sets.");
    }
}
Пример #4
0
static const char *getXmlValueRequired(stHash *hash, const char *key) {
    const char *value = stHash_search(hash, (char*)key);
    if (value == NULL) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "did not find a \"%s\" value in the database XML string", key);
    }
    return value;
}
Пример #5
0
stSortedSetIterator *stSortedSet_getIteratorFrom(stSortedSet *items, void *item) {
    stSortedSetIterator *iterator = stSortedSet_getIterator(items);
    if(avl_t_find(&iterator->traverser, items->sortedSet, item) == NULL) {
        stThrowNew(SORTED_SET_EXCEPTION_ID, "Tried to create an iterator with an item that is not in the list of items");
    }
    stSortedSet_getPrevious(iterator);
    return iterator;
}
Пример #6
0
stKVDatabaseConf *stKVDatabaseConf_constructMySql(const char *host, unsigned port, const char *user, const char *password,
                                                  const char *databaseName, const char *tableName) {
#ifndef HAVE_MYSQL
    stThrowNew(ST_KV_DATABASE_EXCEPTION_ID,
            "requested MySQL database, however sonlib is not compiled with MySql support");
#endif
    return constructSql(stKVDatabaseTypeMySql, host, port, user, password, databaseName, tableName);
}
Пример #7
0
static void removeRecord(stKVDatabase *database, int64_t key) {
    MySqlDb *dbImpl = database->dbImpl;
    sqlExec(dbImpl, "delete from %s where id=%lld", dbImpl->table, (long long)key);
    my_ulonglong numRows = mysql_affected_rows(dbImpl->conn);
    if (numRows == 0) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "remove of non-existent key %lld", (long long)key);
    } 
}
Пример #8
0
static void getExpectedToken(char **tokenStream, const char *expected) {
    char *cA = getNextToken(tokenStream);
    if (!stString_eq(cA, expected)) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID,
                   "BUG: expected the token: %s in database XML string, but I got: %s from the stream %s",
                   expected, cA, *tokenStream);
    }
    free(cA);
}
Пример #9
0
/* immediate execution of a statement that doesn't return results, formatting
 * arguments into query */
static void sqlExec(MySqlDb *dbImpl, char *query, ...) {
    va_list args;
    va_start(args, query);
    MYSQL_RES *rs = queryStartv(dbImpl, query, args);
    va_end(args);
    if (queryNext(dbImpl, rs) != NULL) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "SQL command should not have returned a result: \"%s\"", query);
    }
    queryEnd(dbImpl, rs);
}
Пример #10
0
static void *getPartialRecord(stKVDatabase *database, int64_t key, int64_t zeroBasedByteOffset, int64_t sizeInBytes, int64_t recordSize) {
    MySqlDb *dbImpl = database->dbImpl;
    MYSQL_RES *rs = queryStart(dbImpl, "select substring(data, %lld, %lld) from %s where id=%lld", (long long)zeroBasedByteOffset+1, (long long)sizeInBytes, dbImpl->table, (long long)key);
    char **row = queryNext(dbImpl, rs);
    void *data = NULL;
    int64_t readLen = 0;
    if (row != NULL) {
        readLen = queryLength(dbImpl, rs);
        data = stSafeCCopyMem(row[0], readLen);
    }
    queryEnd(dbImpl, rs);
    if (readLen != sizeInBytes) {
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "partial read of key %lld, expected %lld bytes got %lld bytes", (long long)key, (long long)sizeInBytes, (long long)readLen);
    }
    return data;
}
Пример #11
0
stSortedSet *stSortedSet_getDifference(stSortedSet *sortedSet1, stSortedSet *sortedSet2) {
    if(!stSortedSet_comparatorsEqual(sortedSet1, sortedSet2)) {
        stThrowNew(SORTED_SET_EXCEPTION_ID, "Comparators are not equal for creating the sorted set difference");
    }
    stSortedSet *sortedSet3 = stSortedSet_construct3(stSortedSet_getComparator(sortedSet1)->compareFn, NULL);

    //Add those from sortedSet1 only if they are not in sortedSet2
    stSortedSetIterator *it= stSortedSet_getIterator(sortedSet1);
    void *o;
    while((o = stSortedSet_getNext(it)) != NULL) {
        if(stSortedSet_search(sortedSet2, o) == NULL) {
            stSortedSet_insert(sortedSet3, o);
        }
    }
    stSortedSet_destructIterator(it);

    return sortedSet3;
}
Пример #12
0
static void cactusDisk_loadFromBinaryRepresentation(void **binaryString, CactusDisk *cactusDisk, stKVDatabaseConf *conf) {
    cactusDisk->sequencesReadFileHandle = NULL;
    cactusDisk->sequencesWriteFileHandle = NULL; //I think these lines are not needed.
    cactusDisk->sequencesFileName = NULL;
    cactusDisk->absSequencesFileName = NULL;
    assert(binaryRepresentation_peekNextElementType(*binaryString) == CODE_CACTUS_DISK);
    binaryRepresentation_popNextElementType(binaryString);
    cactusDisk->storeSequencesInAFile = binaryRepresentation_getBool(binaryString);
    if (cactusDisk->storeSequencesInAFile) {
        cactusDisk->sequencesFileName = binaryRepresentation_getString(binaryString);
        if (stKVDatabaseConf_getDir(conf) == NULL) {
            stThrowNew(CACTUS_DISK_EXCEPTION_ID,
                    "The database conf does not contain a directory in which the sequence file is to be found!\n");
        }
        cactusDisk->absSequencesFileName = stString_print("%s/%s", stKVDatabaseConf_getDir(conf),
                cactusDisk->sequencesFileName);
    }
    assert(binaryRepresentation_peekNextElementType(*binaryString) == CODE_CACTUS_DISK);
    binaryRepresentation_popNextElementType(binaryString);
}
Пример #13
0
stSortedSet *stSortedSet_getUnion(stSortedSet *sortedSet1, stSortedSet *sortedSet2) {
    if(!stSortedSet_comparatorsEqual(sortedSet1, sortedSet2)) {
        stThrowNew(SORTED_SET_EXCEPTION_ID, "Comparators are not equal for creating the union of two sorted sets");
    }
    stSortedSet *sortedSet3 = stSortedSet_construct3(stSortedSet_getComparator(sortedSet1)->compareFn, NULL);

    //Add those from sortedSet1
    stSortedSetIterator *it= stSortedSet_getIterator(sortedSet1);
    void *o;
    while((o = stSortedSet_getNext(it)) != NULL) {
        stSortedSet_insert(sortedSet3, o);
    }
    stSortedSet_destructIterator(it);

    //Add those from sortedSet2
    it= stSortedSet_getIterator(sortedSet2);
    while((o = stSortedSet_getNext(it)) != NULL) {
        stSortedSet_insert(sortedSet3, o);
    }
    stSortedSet_destructIterator(it);

    return sortedSet3;
}
Пример #14
0
/* connect to a database server */
static MySqlDb *connect(stKVDatabaseConf *conf) {
    MySqlDb *dbImpl = stSafeCCalloc(sizeof(MySqlDb));
    if ((dbImpl->conn = mysql_init(NULL)) == NULL) {
        disconnect(dbImpl);
        stThrowNew(ST_KV_DATABASE_EXCEPTION_ID, "mysql_init failed");
    }
    if (mysql_real_connect(dbImpl->conn, stKVDatabaseConf_getHost(conf), stKVDatabaseConf_getUser(conf), stKVDatabaseConf_getPassword(conf), stKVDatabaseConf_getDatabaseName(conf), stKVDatabaseConf_getPort(conf), NULL, 0) == NULL) {
        stExcept *ex = createMySqlExcept(dbImpl, "failed to connect to MySql database: %s on %s as user %s",
                                         stKVDatabaseConf_getDatabaseName(conf), stKVDatabaseConf_getHost(conf), stKVDatabaseConf_getUser(conf));
        disconnect(dbImpl);
        stThrow(ex);
    }
    dbImpl->table = stString_copy(stKVDatabaseConf_getTableName(conf));

    // disable report of notes, so only warnings and errors come back
    sqlExec(dbImpl, "set sql_notes=0");

    // set max sizes of an sql statment to 1G.  This must also be specified
    // for the server by adding "max_allowed_packet = 1G" to the [mysqld]
    // section of my.cnf
    sqlExec(dbImpl, "set global max_allowed_packet=1073741824");

    // set the idle timeout to a week
    int waitTimeout = 7 * 24 * 60 * 60;  // 1 week
    sqlExec(dbImpl, "set wait_timeout=%d", waitTimeout);

    // set the read timeout to an hour
    int readTimeout = 60 * 60;  // 1 hour
    sqlExec(dbImpl, "set net_read_timeout=%d", readTimeout);

    // NOTE: commit will not return an error, this does row-level locking on
    // the select done before the update
    sqlExec(dbImpl, "set autocommit = 0;");
    sqlExec(dbImpl, "set session transaction isolation level serializable;");
    return dbImpl;
}
Пример #15
0
static void thrower2() {
    stThrowNew(ERR2, "error in %s", "thrower2");
}
Пример #16
0
/* check if the sorted set is in a state that it can be modified */
static void checkModifiable(stSortedSet *sortedSet) {
    if (sortedSet->numberOfLiveIterators > 0) {
        //assert(0);
        stThrowNew(SORTED_SET_EXCEPTION_ID, "attempt to modify an stSortedSet while iterators are active");
    }
}
Пример #17
0
static CactusDisk *cactusDisk_constructPrivate(stKVDatabaseConf *conf, bool create, const char *sequencesFileName) {
    //sequencesFileName = NULL; //Disable the ability to store the sequences on disk.
    CactusDisk *cactusDisk = st_calloc(1, sizeof(CactusDisk));

    //construct lists of in memory objects
    cactusDisk->metaSequences = stSortedSet_construct3(cactusDisk_constructMetaSequencesP, NULL);
    cactusDisk->flowers = stSortedSet_construct3(cactusDisk_constructFlowersP, NULL);
    cactusDisk->flowerNamesMarkedForDeletion = stSortedSet_construct3((int (*)(const void *, const void *)) strcmp,
            free);
    cactusDisk->updateRequests = stList_construct3(0, (void (*)(void *)) stKVDatabaseBulkRequest_destruct);

    //Now open the database
    cactusDisk->database = stKVDatabase_construct(conf, create);
    cactusDisk->cache = stCache_construct();
    cactusDisk->stringCache = stCache_construct();

    //initialise the unique ids.
    int64_t seed = (clock() << 24) | (time(NULL) << 16) | (getpid() & 65535); //Likely to be unique
    st_logDebug("The cactus disk is seeding the random number generator with the value %" PRIi64 "\n", seed);
    st_randomSeed(seed);
    cactusDisk->uniqueNumber = 0;
    cactusDisk->maxUniqueNumber = 0;

    //Now load any stuff..
    if (containsRecord(cactusDisk, CACTUS_DISK_PARAMETER_KEY)) {
        if (create) {
            stThrowNew(CACTUS_DISK_EXCEPTION_ID, "Tried to create a cactus disk, but the cactus disk already exists");
        }
        if (sequencesFileName != NULL) {
            stThrowNew(CACTUS_DISK_EXCEPTION_ID,
                    "A sequences file name is specified, but the cactus disk is not being created");
        }
        void *record = getRecord(cactusDisk, CACTUS_DISK_PARAMETER_KEY, "cactus_disk parameters");
        void *record2 = record;
        cactusDisk_loadFromBinaryRepresentation(&record, cactusDisk, conf);
        free(record2);
    } else {
        assert(create);
        if (sequencesFileName == NULL) {
            cactusDisk->storeSequencesInAFile = 0;
            cactusDisk->sequencesFileName = NULL;
            cactusDisk->sequencesReadFileHandle = NULL;
            cactusDisk->sequencesWriteFileHandle = NULL;
            cactusDisk->absSequencesFileName = NULL;
        } else {
            if (stKVDatabaseConf_getDir(conf) == NULL) {
                stThrowNew(CACTUS_DISK_EXCEPTION_ID,
                        "The database conf does not contain a directory in which the sequence file is to be found!\n");
            }
            cactusDisk->storeSequencesInAFile = 1;
            cactusDisk->sequencesFileName = stString_copy(sequencesFileName);
            cactusDisk->absSequencesFileName = stString_print("%s/%s", stKVDatabaseConf_getDir(conf),
                    cactusDisk->sequencesFileName);
            //Make sure the file exists
            cactusDisk->sequencesReadFileHandle = fopen(cactusDisk->absSequencesFileName, "w");
            assert(cactusDisk->sequencesReadFileHandle != NULL);
            fclose(cactusDisk->sequencesReadFileHandle); //Flush it first time.
            cactusDisk->sequencesReadFileHandle = NULL;
            cactusDisk->sequencesWriteFileHandle = NULL;
        }
    }

    return cactusDisk;
}