static pse_op_error_t sqlite_update_node(sqlite3_stmt* stat, const uint8_t* blob, uint32_t blob_size, uint32_t id)
{
    pse_op_error_t ret = OP_SUCCESS;
    int rc;

    rc = sqlite3_bind_blob(stat, 1, blob, blob_size, NULL); 
    EXIT_IFNOT_SQLITE_OK(rc, error)

    rc = sqlite3_bind_int(stat, 2, id);
    EXIT_IFNOT_SQLITE_OK(rc, error)

    rc = sqlite3_step(stat); 
    if(rc != SQLITE_DONE)
    {
        ret = OP_ERROR_SQLITE_INTERNAL;
        goto error;
    }

    rc = sqlite3_clear_bindings(stat);
    EXIT_IFNOT_SQLITE_OK(rc, error)

    rc = sqlite3_reset(stat);
    EXIT_IFNOT_SQLITE_OK(rc, error)

    return OP_SUCCESS;

error:
    return ret;
}
pse_op_error_t sqlite_write_db(pse_vmc_hash_tree_cache_t* cache,
                               uint8_t is_for_update_flag,
                               op_leafnode_flag_t* op_flag_info)
{
    PROFILE_START("sqlite_write_db");

    int rc;
    pse_op_error_t ret = OP_SUCCESS;
    sqlite3_stmt* stat = NULL;
    sqlite3       *db = NULL;
    char          sql_sentence[512] = {0};
    int refid = 0;

    if( !cache)
    {
        PROFILE_END("sqlite_write_db");
        return OP_ERROR_INVALID_PARAMETER;
    }

    if(is_for_update_flag && !op_flag_info)
    {
        PROFILE_END("sqlite_write_db");
        return OP_ERROR_INVALID_PARAMETER;
    }

    // Backup DB first
    ret = backup_vmc_db_file();
    if(OP_SUCCESS != ret)
    {
        pse_vmc_db_state = PSE_VMC_DB_STATE_DOWN;
        PROFILE_END("sqlite_write_db");
        return ret;
    }

    ret = sqlite_open_db(&db);
    if(OP_SUCCESS != ret)
    {
        pse_vmc_db_state = PSE_VMC_DB_STATE_DOWN;
        PROFILE_END("sqlite_write_db");
        return ret;
    }

    rc = sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
    EXIT_IFNOT_SQLITE_OK(rc, error)

    if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "update HASH_TREE_NODE_TABLE set node_content=? where ID=?") < 0)
    {
        ret = OP_ERROR_INTERNAL;
        goto error;
    }

    rc = sqlite3_prepare_v2(db, sql_sentence, -1, &stat, 0);
    EXIT_IFNOT_SQLITE_OK(rc, error)

    // update internal nodes
    for (uint32_t index = 0; index < INIT_INTERNAL_NODE_NR; index++)
    {
        // update ancestors
        if ((ret = sqlite_update_node(stat, 
            (uint8_t*)&cache->ancestors[index].internal, 
            INTERNAL_NODE_SIZE, 
            cache->ancestors[index].node_id)) != OP_SUCCESS)
            goto error;

        // update brothers of ancestors
        if ((ret = sqlite_update_node(stat, 
            (uint8_t*)&cache->brother_of_ancestors[index].internal, 
            INTERNAL_NODE_SIZE, 
            cache->brother_of_ancestors[index].node_id)) != OP_SUCCESS)
            goto error;
    }

    // update leaf and its brother
    if ((ret = sqlite_update_node(stat, 
        (uint8_t*)&cache->self.leaf, 
        LEAF_NODE_SIZE, 
        cache->self.node_id)) != OP_SUCCESS)
        goto error;
    if ((ret = sqlite_update_node(stat, 
        (uint8_t*)&cache->brother.leaf, 
        LEAF_NODE_SIZE, 
        cache->brother.node_id)) != OP_SUCCESS)
        goto error;

    if(is_for_update_flag)
    {
        // update USED flag and QUOTA record
        char mrsigner[65] = {0};
        // convert mr_signer to hex string
        for(uint32_t i=0; i < sizeof(sgx_measurement_t); i++)
        {
            char tmp[3];
            if(_snprintf_s(tmp, sizeof(tmp), "%02x", ((uint8_t*)(&op_flag_info->mr_signer))[i]) < 0)
            {
                ret = OP_ERROR_INTERNAL;
                goto error;
            }

            if(0 != strncat_s(mrsigner, sizeof(mrsigner), tmp, sizeof(tmp)))
            {
                ret = OP_ERROR_INTERNAL;
                goto error;
            }
        }

        switch(op_flag_info->op_type)
        {
            case CLR_LEAFNODE_FLAG:
                // read REFID saved in HASH_TREE_NODE_TABLE before deleting the record.
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "select REFID from HASH_TREE_NODE_TABLE where ID=%d;", cache->self.node_id) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }
                ret = sqlite_query_int_value(db, sql_sentence, &refid);
                if(OP_SUCCESS != ret && OP_ERROR_SQLITE_NOT_FOUND != ret)
                {
                    goto error;
                }
                // clear REFID and USED flag
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "update HASH_TREE_NODE_TABLE set USED=0 and REFID=0 where ID=%d;", cache->self.node_id) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }
                rc = sqlite3_exec(db, sql_sentence, NULL, NULL, NULL);
                if(SQLITE_OK != rc)
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                if(1 != sqlite3_changes(db))
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }

                // update QUOTA, counter--;
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "update VMC_QUOTA_TABLE set COUNTER=COUNTER-1 where ID=%d and COUNTER>0;", refid) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }
                rc = sqlite3_exec(db, sql_sentence, NULL, NULL, NULL);
                if(SQLITE_OK != rc)
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                if(1 != sqlite3_changes(db))
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                break;
            case SET_LEAFNODE_FLAG:
                // update QUOTA, counter++;
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "update VMC_QUOTA_TABLE set COUNTER=COUNTER+1 where MRSIGNER='%s';", mrsigner) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }
			    rc = sqlite3_exec(db, sql_sentence, NULL, NULL, NULL);
                if(SQLITE_OK != rc)
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                rc = sqlite3_changes(db);
                if(0 == rc)
                {
                    // the mrsigner isn't in quota table yet, so insert it.
                    if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "insert into VMC_QUOTA_TABLE(MRSIGNER,COUNTER) values('%s', 1);", mrsigner) < 0)
                    {
                        ret = OP_ERROR_INTERNAL;
                        goto error;
                    }
                    rc = sqlite3_exec(db, sql_sentence, NULL, NULL, NULL);
                    if(SQLITE_OK != rc)
                    {
                        ret = OP_ERROR_SQLITE_INTERNAL;
                        goto error;
                    }
                    if(1 != sqlite3_changes(db))
                    {
                        ret = OP_ERROR_SQLITE_INTERNAL;
                        goto error;
                    }
                }
                else if(1 == rc)
                {
                    // the mrsigner has been in quota table
                }
                else
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                // read refid
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "select ID from VMC_QUOTA_TABLE where MRSIGNER='%s';", mrsigner) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }

                ret = sqlite_query_int_value(db, sql_sentence, &refid);
                if(OP_SUCCESS != ret && OP_ERROR_SQLITE_NOT_FOUND != ret)
                {
                    goto error;
                }

                // Update HASH_TREE_NODE_TABLE
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "update HASH_TREE_NODE_TABLE set USED=1 where ID=%d;", cache->self.node_id) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }
                rc = sqlite3_exec(db, sql_sentence, NULL, NULL, NULL);
                if(SQLITE_OK != rc)
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                if(1 != sqlite3_changes(db))
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                if (_snprintf_s(sql_sentence, sizeof(sql_sentence), "update HASH_TREE_NODE_TABLE set REFID=%d where ID=%d;", refid, cache->self.node_id) < 0)
                {
                    ret = OP_ERROR_INTERNAL;
                    goto error;
                }
                rc = sqlite3_exec(db, sql_sentence, NULL, NULL, NULL);
                if(SQLITE_OK != rc)
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                if(1 != sqlite3_changes(db))
                {
                    ret = OP_ERROR_SQLITE_INTERNAL;
                    goto error;
                }
                break;

            default:
                ret = OP_ERROR_INVALID_PARAMETER;
                goto error;
        }
    }

    rc = sqlite3_exec(db, "END TRANSACTION;", NULL, NULL, NULL);
    EXIT_IFNOT_SQLITE_OK(rc, error)

    sqlite3_finalize(stat);
    sqlite3_close_v2(db);

    PROFILE_END("sqlite_write_db");

    return OP_SUCCESS;

error:
    assert(db != NULL);
    sqlite3_finalize(stat);
    sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
    sqlite3_close_v2(db);

    PROFILE_END("sqlite_write_db");
    return ret;
}
示例#3
0
文件: main.cpp 项目: 01org/linux-sgx
int sqlite_generate_prebuild_db()
{
    sqlite3* db = NULL;
    int      rc;
    char*    errmsg = NULL;
    int      node_type;
    int      start_id, end_id;
    sqlite3_stmt* stat = NULL;
    char     sql_sentence[512] = {0};
    uint8_t* ptr_buf = NULL;
    uint32_t bufflen;
    uint8_t* ptr_precalc_node_buff = NULL;
    int      layer;

    bufflen = (INIT_MAX_HASH_TREE_LAYER-2)*sizeof(hash_tree_internal_node_t) + 
              sizeof(hash_tree_leaf_node_t);

    ptr_precalc_node_buff = (uint8_t*)malloc(bufflen);
    if(NULL == ptr_precalc_node_buff)
    {
        return -1;
    }

    memset(ptr_precalc_node_buff, 0, bufflen);

    hash_tree_internal_node_t* internal_node = (hash_tree_internal_node_t*)ptr_precalc_node_buff;
    for(int index=INIT_MAX_HASH_TREE_LAYER-3; index>=0; index--)
    {
        if(memcpy_s(internal_node->hash, 
                    sizeof(internal_node->hash), 
                    &(internal_node_hash_value_table[index][0]), 
                    HASH_VALUE_SIZE))
        {
            free(ptr_precalc_node_buff);
            return -1;
        }
        internal_node++;
    }

    if(gDb)
    {
        db = gDb;
    }
    else
    {
        rc = sqlite3_open(SQLITE_DB_FILE_NAME, &gDb);
        if( SQLITE_OK != rc )
        {
            free(ptr_precalc_node_buff);
            return rc;
        }
		db = gDb;
    }

    rc = sqlite3_exec( db, 
                       "create table VMC_QUOTA_TABLE( ID integer primary key AUTOINCREMENT, MRSIGNER char(64), COUNTER integer)", 
                       NULL,
                       NULL,
                       &errmsg );
    EXIT_IFNOT_SQLITE_OK(rc)

    rc = sqlite3_exec( db, 
                       "create table HASH_TREE_NODE_TABLE( ID integer primary key, node_content blob, USED integer, REFID integer NULL REFERENCES VMC_QUOTA_TABLE(ID))", 
                       NULL,
                       NULL,
                       &errmsg );
    EXIT_IFNOT_SQLITE_OK(rc)

    rc = sqlite3_exec( db, 
                       "create table BACKUP_TABLE( ID integer primary key, node_content blob, USED integer, REFID integer)", 
                       NULL,
                       NULL,
                       &errmsg );
    EXIT_IFNOT_SQLITE_OK(rc)

    // all nodes in the same layer have the same precalculated value
    // the merkel hash tree has 12 layers including root layer

    rc = sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
    EXIT_IFNOT_SQLITE_OK(rc)

    sprintf(sql_sentence, "insert into HASH_TREE_NODE_TABLE( ID, node_content, USED, REFID) values( ?, ?, 0, NULL)");

    rc = sqlite3_prepare_v2(db, 
                         sql_sentence, 
                         -1, 
                         &stat, 
                         0);
    EXIT_IFNOT_SQLITE_OK(rc)

    layer = INIT_MAX_HASH_TREE_LAYER - 1;
    do{
        if(INIT_MAX_HASH_TREE_LAYER - 1 == layer)
        {
            node_type = HASH_TREE_NODE_TYPE_LEAF;
        }
        else
        {
            node_type = HASH_TREE_NODE_TYPE_INTERNAL;
        }

        start_id = (int)pow((double)2,layer);
        end_id = (int)pow((double)2,layer+1) - 1;

        for(int id = start_id; id <= end_id; id++)
        {
            rc =sqlite3_bind_int(stat, 1, id);
            EXIT_IFNOT_SQLITE_OK(rc)

            switch(node_type)
            {
                case HASH_TREE_NODE_TYPE_INTERNAL:
                    ptr_buf = ptr_precalc_node_buff;
                    rc = sqlite3_bind_blob(stat,
                                           2,
                                           (hash_tree_internal_node_t*)ptr_buf + layer - 1,
                                           sizeof(hash_tree_internal_node_t),
                                           NULL
                                           );
                    break;
                case HASH_TREE_NODE_TYPE_LEAF:
                    rc = sqlite3_bind_blob(stat,
                                           2,
                                           ptr_precalc_node_buff + (INIT_MAX_HASH_TREE_LAYER-2)*sizeof(hash_tree_internal_node_t),
                                           sizeof(hash_tree_leaf_node_t),
                                           NULL
                                           );

                    break;
                default:
                    goto error;
            }
            EXIT_IFNOT_SQLITE_OK(rc)

            rc = sqlite3_step(stat);
            if(rc != SQLITE_DONE)
            {
                goto error;
            }

            rc = sqlite3_clear_bindings(stat);
            EXIT_IFNOT_SQLITE_OK(rc)

            rc = sqlite3_reset(stat);
            EXIT_IFNOT_SQLITE_OK(rc)
        }
        layer--;
        if(layer&0x1)
            sqlite3_sleep(1);
    }while(layer>0);

    rc = sqlite3_exec(db, "END TRANSACTION;", NULL, NULL, NULL);
    EXIT_IFNOT_SQLITE_OK(rc)

    rc = sqlite3_finalize(stat);
    EXIT_IFNOT_SQLITE_OK(rc)

    stat = NULL;

    sqlite3_close_v2(db);
    gDb = NULL;

    free(ptr_precalc_node_buff);
    
    return 0;
error:
    free(ptr_precalc_node_buff);
    if(db)
    {
        sqlite3_finalize(stat);
        sqlite3_exec(db, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
        sqlite3_close_v2(db);
        gDb = NULL;
    }
    return -1;
}