void SQLitePersistedObjectSet::initDB() {
    SQLiteDBPtr db = SQLite::getSingleton().open(mDBFilename);
    sqlite3_busy_timeout(db->db(), 1000);

    // Create the table for this object if it doesn't exist yet
    String table_create = "CREATE TABLE IF NOT EXISTS ";
    table_create += "\"" TABLE_NAME "\"";
    table_create += "(object TEXT PRIMARY KEY, script_type TEXT, script_args TEXT, script_contents TEXT)";

    int rc;
    char* remain;
    sqlite3_stmt* table_create_stmt;

    mDB = db;
    bool success = true;

    rc = sqlite3_prepare_v2(db->db(), table_create.c_str(), -1, &table_create_stmt, (const char**)&remain);
    success = success && !checkSQLiteError(rc, "Error preparing table create statement");

    rc = sqlite3_step(table_create_stmt);
    success = success && !checkSQLiteError(rc, "Error executing table create statement");
    rc = sqlite3_finalize(table_create_stmt);
    success = success && !checkSQLiteError(rc, "Error finalizing table create statement");

    if (!success)
        mDB.reset();
}
template <class WriteSet> SQLiteObjectStorage::Error SQLiteObjectStorage::applyWriteSet(const SQLiteDBPtr& db, const WriteSet& ws, int retries) {
    int num_writes=ws.writes_size();
    for (int ws_it=0;ws_it<num_writes;++ws_it) {

        String object_hex = getTableName(ws.writes(ws_it));
        String key_name = getKeyName(ws.writes(ws_it));

        int rc;
        char* remain;

        // Insert or replace the value

        String value_insert = "INSERT OR REPLACE INTO ";
        if (!ws.writes(ws_it).has_data()) {
             value_insert = "DELETE FROM ";
        }
        value_insert += "\"" TABLE_NAME "\"";
        if (!ws.writes(ws_it).has_data()) {
            value_insert+= " WHERE object = x\'" + object_hex + "\' AND key = ?";
        }else {
        //if (ws.writes(ws_it).has_data()) {
            value_insert += " (object, key, value) VALUES(x\'" + object_hex + "\', ?, ?)";
            //}
        }
        sqlite3_stmt* value_insert_stmt;

        rc = sqlite3_prepare_v2(db->db(), value_insert.c_str(), -1, &value_insert_stmt, (const char**)&remain);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing value insert statement");

        rc = sqlite3_bind_text(value_insert_stmt, 1, key_name.data(), (int)key_name.size(), SQLITE_TRANSIENT);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error binding key name to value insert statement");
        if (rc==SQLITE_OK) {
            if (ws.writes(ws_it).has_data()) {
                rc = sqlite3_bind_blob(value_insert_stmt, 2, ws.writes(ws_it).data().data(), (int)ws.writes(ws_it).data().size(), SQLITE_TRANSIENT);
                SQLite::check_sql_error(db->db(), rc, NULL, "Error binding value to value insert statement");
            }
        }

        int step_rc = sqlite3_step(value_insert_stmt);
        if (step_rc != SQLITE_OK && step_rc != SQLITE_DONE)
            sqlite3_reset(value_insert_stmt); // allow this to be cleaned up

        rc = sqlite3_finalize(value_insert_stmt);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing value insert statement");
        if (step_rc == SQLITE_BUSY || step_rc == SQLITE_LOCKED)
            return DatabaseLocked;

    }

    return None;
}
示例#3
0
void SQLiteObjectFactory::generate() {
    SQLiteDBPtr db = SQLite::getSingleton().open(mDBFilename);
    sqlite3_busy_timeout(db->db(), 1000);


    String value_query = "SELECT object, script_type, script_args, script_contents FROM ";
    value_query += "\"" TABLE_NAME "\"";
    int rc;
    char* remain;
    sqlite3_stmt* value_query_stmt;
    rc = sqlite3_prepare_v2(db->db(), value_query.c_str(), -1, &value_query_stmt, (const char**)&remain);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing value query statement");
    if (rc==SQLITE_OK) {
        int step_rc = sqlite3_step(value_query_stmt);
        while(step_rc == SQLITE_ROW) {
            String object_str(
                (const char*)sqlite3_column_text(value_query_stmt, 0),
                sqlite3_column_bytes(value_query_stmt, 0)
            );
            String script_type(
                (const char*)sqlite3_column_text(value_query_stmt, 1),
                sqlite3_column_bytes(value_query_stmt, 1)
            );
            String script_args(
                (const char*)sqlite3_column_text(value_query_stmt, 2),
                sqlite3_column_bytes(value_query_stmt, 2)
            );
            String script_contents(
                (const char*)sqlite3_column_text(value_query_stmt, 3),
                sqlite3_column_bytes(value_query_stmt, 3)
            );

            HostedObjectPtr obj = mOH->createObject(
                                      UUID(object_str, UUID::HexString()),
                                      script_type, script_args, script_contents
                                  );

            step_rc = sqlite3_step(value_query_stmt);
        }
        if (step_rc != SQLITE_DONE) {
            // reset the statement so it'll clean up properly
            rc = sqlite3_reset(value_query_stmt);
            SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing value query statement");
        }
    }

    rc = sqlite3_finalize(value_query_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing value query statement");
}
void SQLiteObjectStorage::rollbackTransaction(const SQLiteDBPtr& db) {
    String rollback = "ROLLBACK TRANSACTION";

    int rc;
    char* remain;
    sqlite3_stmt* rollback_stmt;

    rc = sqlite3_prepare_v2(db->db(), rollback.c_str(), -1, &rollback_stmt, (const char**)&remain);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing rollback transaction statement");

    rc = sqlite3_step(rollback_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error executing rollback statement");
    rc = sqlite3_finalize(rollback_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing rollback statement");
}
/*
void SQLiteObjectStorage::handleResult(const EventPtr& evt) const {
    SQLiteObjectStorageResultEventPtr revt = DowncastEvent<SQLiteObjectStorageResultEvent>(evt);

    revt->callback()(revt->error());
}
*/
void SQLiteObjectStorage::beginTransaction(const SQLiteDBPtr& db) {
    String begin = "BEGIN DEFERRED TRANSACTION";

    int rc;
    char* remain;
    sqlite3_stmt* begin_stmt;

    rc = sqlite3_prepare_v2(db->db(), begin.c_str(), -1, &begin_stmt, (const char**)&remain);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing begin transaction statement");

    rc = sqlite3_step(begin_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error executing begin statement");
    rc = sqlite3_finalize(begin_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing begin statement");
}
SQLiteObjectStorage::SQLiteObjectStorage(bool transactional, const String& pl)
 : mTransactional(transactional),
   mDBName(),
   mRetries(5),
   mBusyTimeout(1000)
{
    OptionValue*databaseFile;
    OptionValue*workQueueInstance;
    unsigned char * epoch=NULL;
    static AtomicValue<int> counter(0);
    int handle_offset=counter++;
    InitializeClassOptions("sqlite",epoch+handle_offset,
                           databaseFile=new OptionValue("databasefile","",OptionValueType<String>(),"Sets the database to be used for storage"),
                           workQueueInstance=new OptionValue("workqueue","0",OptionValueType<void*>(),"Sets the work queue to be used for disk reads to a common work queue"),NULL);
    (mOptions=OptionSet::getOptions("sqlite",epoch+handle_offset))->parse(pl);

    mDiskWorkQueue=(Task::WorkQueue*)workQueueInstance->as<void*>();
    mWorkQueueThread=NULL;
    if(mDiskWorkQueue==NULL) {
        mDiskWorkQueue=&_mLocalWorkQueue;
        mWorkQueueThread=mDiskWorkQueue->createWorkerThreads(1);
    }

    mDBName = databaseFile->as<String>();
    assert( !mDBName.empty() );

    SQLiteDBPtr db = SQLite::getSingleton().open(mDBName);
    sqlite3_busy_timeout(db->db(), mBusyTimeout);

    // Create the table for this object if it doesn't exist yet
    String table_create = "CREATE TABLE IF NOT EXISTS ";
    table_create += "\"" TABLE_NAME "\"";
    table_create += "(object TEXT, key TEXT, value TEXT, PRIMARY KEY(object, key))";

    int rc;
    char* remain;
    sqlite3_stmt* table_create_stmt;

    rc = sqlite3_prepare_v2(db->db(), table_create.c_str(), -1, &table_create_stmt, (const char**)&remain);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing table create statement");

    rc = sqlite3_step(table_create_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error executing table create statement");
    rc = sqlite3_finalize(table_create_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing table create statement");

    mDB = db;
}
bool SQLiteObjectStorage::commitTransaction(const SQLiteDBPtr& db) {
    String commit = "COMMIT TRANSACTION";

    int rc;
    char* remain;
    sqlite3_stmt* commit_stmt;

    rc = sqlite3_prepare_v2(db->db(), commit.c_str(), -1, &commit_stmt, (const char**)&remain);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing commit transaction statement");

    rc = sqlite3_step(commit_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error executing commit statement");
    rc = sqlite3_finalize(commit_stmt);
    SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing commit statement");

    return true;
}
template <class CompareSet> SQLiteObjectStorage::Error SQLiteObjectStorage::checkCompareSet(const SQLiteDBPtr& db, const CompareSet& cs) {
    int num_compares=cs.compares_size();
    for (int cs_it=0;cs_it<num_compares;++cs_it) {

        String object_hex = getTableName(cs.compares(cs_it));
        String key_name = getKeyName(cs.compares(cs_it));

        String value_query = "SELECT value FROM ";
        value_query += "\"" TABLE_NAME "\"";
        value_query += " WHERE object == x\'" + object_hex + "\' AND key == ?";

        int rc;
        char* remain;
        sqlite3_stmt* value_query_stmt;

        rc = sqlite3_prepare_v2(db->db(), value_query.c_str(), -1, &value_query_stmt, (const char**)&remain);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing value query statement");

        rc = sqlite3_bind_text(value_query_stmt, 1, key_name.data(), (int)key_name.size(), SQLITE_TRANSIENT);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error binding key name to value query statement");

        int step_rc = sqlite3_step(value_query_stmt);
        bool passed_test = true;

        if (step_rc == SQLITE_ROW) {
            const char *data=(const char*)sqlite3_column_text(value_query_stmt, 0);
            size_t size=sqlite3_column_bytes(value_query_stmt, 0);
            if(cs.compares(cs_it).has_data()==false) {
                passed_test=false; 
            } else if (cs.compares(cs_it).has_comparator()==false) {
                if (cs.compares(cs_it).data().length() != size) passed_test = false;
                else if (0!=memcmp(cs.compares(cs_it).data().data(), data, size)) passed_test = false;
            }else {
                switch (cs.compares(cs_it).comparator()) {
                  case Protocol::CompareElement::EQUAL:
                    if (cs.compares(cs_it).data().length() != size) passed_test = false;
                    else if (0!=memcmp(cs.compares(cs_it).data().data(), data, size)) passed_test = false;
                    break;
                  case Protocol::CompareElement::NEQUAL:
                    if (cs.compares(cs_it).data().length() == size
                        && 0==memcmp(cs.compares(cs_it).data().data(), data, size)) 
                        passed_test = false;
                    break;
                  default:
                    passed_test=false;
                    break;
                }
            }
        }
        else {
            sqlite3_reset(value_query_stmt); // allow proper clean up
        }

        rc = sqlite3_finalize(value_query_stmt);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing value query statement");

        if (step_rc == SQLITE_BUSY || step_rc == SQLITE_LOCKED)
            return DatabaseLocked;

        if (step_rc == SQLITE_DONE)
            return KeyMissing;

        if (!passed_test)
            return ComparisonFailed;

    }

    return None;
}
template <class ReadSet> SQLiteObjectStorage::Error SQLiteObjectStorage::applyReadSet(const SQLiteDBPtr& db, const ReadSet& rs, Protocol::Response&retval) {

    int num_reads=rs.reads_size();
    retval.clear_reads();
    while (retval.reads_size()<num_reads)
        retval.add_reads();
    SQLiteObjectStorage::Error databaseError=None;
    for (int rs_it=0;rs_it<num_reads;++rs_it) {
        String object_hex = getTableName(rs.reads(rs_it));
        String key_name = getKeyName(rs.reads(rs_it));

        String value_query = "SELECT value FROM ";
        value_query += "\"" TABLE_NAME "\"";
        value_query += " WHERE object == x\'" + object_hex + "\' AND key == ?";
        int rc;
        char* remain;
        sqlite3_stmt* value_query_stmt;
        bool newStep=true;
        bool locked=false;
        rc = sqlite3_prepare_v2(db->db(), value_query.c_str(), -1, &value_query_stmt, (const char**)&remain);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error preparing value query statement");
        if (rc==SQLITE_OK) {
            rc = sqlite3_bind_text(value_query_stmt, 1, key_name.data(), (int)key_name.size(), SQLITE_TRANSIENT);
            SQLite::check_sql_error(db->db(), rc, NULL, "Error binding key name to value query statement");
            if (rc==SQLITE_OK) {
                int step_rc = sqlite3_step(value_query_stmt);
                while(step_rc == SQLITE_ROW) {
                    newStep=false;
                    retval.reads(rs_it).set_data((const char*)sqlite3_column_text(value_query_stmt, 0),sqlite3_column_bytes(value_query_stmt, 0));
                    step_rc = sqlite3_step(value_query_stmt);
                }
                if (step_rc != SQLITE_DONE) {
                    // reset the statement so it'll clean up properly
                    rc = sqlite3_reset(value_query_stmt);
                    SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing value query statement");
                    if (rc==SQLITE_LOCKED||rc==SQLITE_BUSY)
                        locked=true;
                }         
                
            }
        }
        rc = sqlite3_finalize(value_query_stmt);
        SQLite::check_sql_error(db->db(), rc, NULL, "Error finalizing value query statement");
        if (locked||rc == SQLITE_LOCKED||rc==SQLITE_BUSY) {
            retval.clear_reads();
            return DatabaseLocked;
        }

        if (newStep) {
            retval.reads(rs_it).clear_data();
            retval.reads(rs_it).set_return_status(Protocol::StorageElement::KEY_MISSING);
        }
        if(rs.reads(rs_it).has_index()) {
            retval.reads(rs_it).set_index(rs.reads(rs_it).index());
        }
    }
    if (rs.has_options()&&(rs.options()&Protocol::ReadWriteSet::RETURN_READ_NAMES)!=0) {
        // make sure read set is clear before each attempt
        mergeKeysFromStorageSet( retval, rs );
    }
    return databaseError;
}