Compare commits

...

2 Commits

Author SHA1 Message Date
Mingkai Dong 691265ada7 [style] Update code format with clang-format 2023-06-15 19:53:53 +08:00
Mingkai Dong c724b65c08 [feat] Add virtualstorage and sqlite tpcc
The code is from Sipeng Zhang
2023-06-14 23:13:43 +08:00
38 changed files with 229488 additions and 0 deletions

View File

@ -0,0 +1,13 @@
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
src = ['sqlite3.c']
src += ['dbhelper.c']
# The set of source files associated with this SConscript file.
path = [cwd]
group = DefineGroup('sqlite', src, depend = ['RT_USING_SDIO'], CPPPATH = path)
Return('group')

View File

@ -0,0 +1,615 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-06 lizhen9880 first version
*/
#include <stdio.h>
#include <string.h>
#include <rtthread.h>
#include <ctype.h>
#include "dbhelper.h"
#define DBG_ENABLE
#define DBG_SECTION_NAME "app.dbhelper"
#define DBG_LEVEL DBG_INFO
#define DBG_COLOR
#include <rtdbg.h>
#if PKG_SQLITE_DB_NAME_MAX_LEN < 8
#error "the database name length is too short"
#endif
#define DEFAULT_DB_NAME "/rt.db"
static rt_mutex_t db_mutex_lock = RT_NULL;
static char db_name[PKG_SQLITE_DB_NAME_MAX_LEN + 1] = DEFAULT_DB_NAME;
/**
* This function will initialize SQLite3 create a mutex as a lock.
*/
int db_helper_init(void)
{
sqlite3_initialize();
if (db_mutex_lock == RT_NULL)
{
db_mutex_lock = rt_mutex_create("dbmtx", RT_IPC_FLAG_FIFO);
}
if (db_mutex_lock == RT_NULL)
{
LOG_E("rt_mutex_create dbmtx failed!\n");
return -RT_ERROR;
}
return RT_EOK;
}
INIT_APP_EXPORT(db_helper_init);
/**
* This function will create a database.
*
* @param sqlstr should be a SQL CREATE TABLE statements.
* @return the result of sql execution.
*/
int db_create_database(const char *sqlstr)
{
return db_nonquery_operator(sqlstr, 0, 0);
}
static int db_bind_by_var(sqlite3_stmt *stmt, const char *fmt, va_list args)
{
int len, npara = 1;
int ret = SQLITE_OK;
if (fmt == NULL)
{
return ret;
}
for (; *fmt; ++fmt)
{
if (*fmt != '%')
{
continue;
}
++fmt;
/* get length */
len = 0;
while (isdigit(*fmt))
{
len = len * 10 + (*fmt - '0');
++fmt;
}
switch (*fmt)
{
case 'd':
ret = sqlite3_bind_int(stmt, npara, va_arg(args, int));
break;
case 'f':
ret = sqlite3_bind_double(stmt, npara, va_arg(args, double));
break;
case 's':
{
char *str = va_arg(args, char *);
ret = sqlite3_bind_text(stmt, npara, str, strlen(str), NULL);
}
break;
case 'x':
{
char *pdata;
pdata = va_arg(args, char *);
ret = sqlite3_bind_blob(stmt, npara, pdata, len, NULL);
}
break;
default:
ret = SQLITE_ERROR;
break;
}
++npara;
if (ret)
return ret;
}
return ret;
}
/**
* This function will be used for the SELECT operating.The additional arguments
* following format are formatted and inserted in the resulting string replacing
* their respective specifiers.
*
* @param sql the SQL statements.
* @param create the callback function supported by user.
* create@param stmt the SQL statement after preparing.
* create@param arg the input parameter from 'db_query_by_varpara' arg.
* create@return rule:SQLITE_OK:success,others:fail
* @param arg the parameter for the callback "create".
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return =SQLITE_OK:success, others:fail.
*/
int db_query_by_varpara(const char *sql, int (*create)(sqlite3_stmt *stmt, void *arg), void *arg, const char *fmt, ...)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if (sql == NULL)
{
return SQLITE_ERROR;
}
// rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
LOG_E("open database failed,rc=%d", rc);
// rt_mutex_release(db_mutex_lock);
return rc;
}
rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
LOG_E("database prepare fail,rc=%d", rc);
goto __db_exec_fail;
}
if (fmt)
{
va_list args;
va_start(args, fmt);
rc = db_bind_by_var(stmt, fmt, args);
va_end(args);
if (rc)
{
LOG_E("database bind fail,rc=%d", rc);
goto __db_exec_fail;
}
}
if (create)
{
rc = (*create)(stmt, arg);
}
else
{
rc = (sqlite3_step(stmt), 0);
}
sqlite3_finalize(stmt);
goto __db_exec_ok;
__db_exec_fail:
LOG_E("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
// rt_mutex_release(db_mutex_lock);
return rc;
}
/**
* This function will be used for the operating that is not SELECT.It support executing multiple
* SQL statements.
*
* @param sqlstr the SQL statements strings.if there are more than one
* statements in the sqlstr to execute,separate them by a semicolon(;).
* @param bind the callback function supported by user.bind data and call the sqlite3_step function.
* bind@param stmt the SQL statement after preparing.
* bind@param index the index of SQL statements strings.
* bind@param param the parameter from 'db_nonquery_operator' arg.
* bind@return SQLITE_OK or SQLITE_DONE:success,others:fail
* @param param the parameter for the callback "bind".
* @return =SQLITE_OK:success, others:fail.
*/
int db_nonquery_operator(const char *sqlstr, int (*bind)(sqlite3_stmt *stmt, int index, void *param), void *param)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
int index = 0, offset = 0, n = 0;
if (sqlstr == NULL)
{
return SQLITE_ERROR;
}
// rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
LOG_E("open database failed,rc=%d", rc);
// rt_mutex_release(db_mutex_lock);
return rc;
}
rc = sqlite3_exec(db, "begin transaction", 0, 0, NULL);
if (rc != SQLITE_OK)
{
LOG_E("begin transaction:ret=%d", rc);
goto __db_begin_fail;
}
char sql[DB_SQL_MAX_LEN];
while (sqlstr[index] != 0)
{
offset = 0;
do
{
if (offset >= DB_SQL_MAX_LEN)
{
LOG_E("sql is too long,(%d)", offset);
rc = SQLITE_ERROR;
goto __db_exec_fail;
}
if ((sqlstr[index] != ';') && (sqlstr[index] != 0))
{
sql[offset++] = sqlstr[index++];
}
else
{
sql[offset] = '\0';
if (sqlstr[index] == ';')
{
index++;
}
n++;
break;
}
} while (1);
rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
LOG_E("prepare error,rc=%d", rc);
goto __db_exec_fail;
}
if (bind)
{
rc = (*bind)(stmt, n, param);
}
else
{
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
{
LOG_E("bind failed");
goto __db_exec_fail;
}
}
rc = sqlite3_exec(db, "commit transaction", 0, 0, NULL);
if (rc)
{
LOG_E("commit transaction:%d", rc);
goto __db_exec_fail;
}
goto __db_exec_ok;
__db_exec_fail:
if (sqlite3_exec(db, "rollback transaction", 0, 0, NULL))
{
LOG_E("rollback transaction error");
}
__db_begin_fail:
LOG_E("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
// rt_mutex_release(db_mutex_lock);
return rc;
}
/**
* This function will be used for the operating that is not SELECT.The additional
* arguments following format are formatted and inserted in the resulting string
* replacing their respective specifiers.
*
* @param sql the SQL statement.
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return =SQLITE_OK:success, others:fail.
*/
int db_nonquery_by_varpara(const char *sql, const char *fmt, ...)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if (sql == NULL)
{
return SQLITE_ERROR;
}
// rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
LOG_E("open database failed,rc=%d\n", rc);
// rt_mutex_release(db_mutex_lock);
return rc;
}
LOG_D("sql:%s", sql);
rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK)
{
LOG_E("prepare error,rc=%d", rc);
goto __db_exec_fail;
}
if (fmt)
{
va_list args;
va_start(args, fmt);
rc = db_bind_by_var(stmt, fmt, args);
va_end(args);
if (rc)
{
goto __db_exec_fail;
}
}
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
{
LOG_E("bind error,rc=%d", rc);
goto __db_exec_fail;
}
rc = SQLITE_OK;
goto __db_exec_ok;
__db_exec_fail:
LOG_E("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
// rt_mutex_release(db_mutex_lock);
return rc;
}
/**
* This function will be used for the transaction that is not SELECT.
*
* @param exec_sqls the callback function of executing SQL statements.
* exec_sqls@param db the database connection handle
* exec_sqls@param arg the input parameter from 'db_nonquery_transaction' function parameter 'arg'.
* exec_sqls@return =SQLITE_OK or =SQLITE_DONE:success,others:fail
* @param arg the parameter for the callback "exec_sqls".
* @return =SQLITE_OK:success, others:fail.
*/
int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db, void *arg), void *arg)
{
sqlite3 *db = NULL;
// rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
int rc = sqlite3_open(db_name, &db);
if (rc != SQLITE_OK)
{
LOG_E("open database failed,rc=%d", rc);
// rt_mutex_release(db_mutex_lock);
return rc;
}
rc = sqlite3_exec(db, "begin transaction", 0, 0, NULL);
if (rc != SQLITE_OK)
{
LOG_E("begin transaction:%d", rc);
goto __db_begin_fail;
}
if (exec_sqls)
{
rc = (*exec_sqls)(db, arg);
}
else
{
rc = SQLITE_ERROR;
}
if ((rc != SQLITE_OK) && (rc != SQLITE_DONE))
{
LOG_E("prepare error,rc=%d", rc);
goto __db_exec_fail;
}
rc = sqlite3_exec(db, "commit transaction", 0, 0, NULL);
if (rc)
{
LOG_E("commit transaction:%d", rc);
goto __db_exec_fail;
}
goto __db_exec_ok;
__db_exec_fail:
if (sqlite3_exec(db, "rollback transaction", 0, 0, NULL))
{
LOG_E("rollback transaction:error");
}
__db_begin_fail:
LOG_E("db operator failed,rc=%d", rc);
__db_exec_ok:
sqlite3_close(db);
// rt_mutex_release(db_mutex_lock);
return rc;
}
static int db_get_count(sqlite3_stmt *stmt, void *arg)
{
int ret, *count = arg;
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
return SQLITE_EMPTY;
}
*count = db_stmt_get_int(stmt, 0);
return SQLITE_OK;
}
/**
* This function will return the number of records returned by a select query.
* This function only gets the 1st row of the 1st column.
*
* @param sql the SQL statement SELECT COUNT() FROM .
* @return >=0:the count ,<0: fail.
*/
int db_query_count_result(const char *sql)
{
int ret, count = 0;
ret = db_query_by_varpara(sql, db_get_count, &count, NULL);
if (ret == SQLITE_OK)
{
return count;
}
return -RT_ERROR;
}
/**
* This function will get the blob from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return >=0:the result length ,<0: fail.
*/
int db_stmt_get_blob(sqlite3_stmt *stmt, int index, unsigned char *out)
{
const char *pdata = sqlite3_column_blob(stmt, index);
int len = sqlite3_column_bytes(stmt, index);
if (pdata)
{
memcpy(out, pdata, len);
return len;
}
return -RT_ERROR;
}
/**
* This function will get the text from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return >=0:the result length ,<0: fail.
*/
int db_stmt_get_text(sqlite3_stmt *stmt, int index, char *out)
{
const unsigned char *pdata = sqlite3_column_text(stmt, index);
if (pdata)
{
int len = strlen((char *)pdata);
strncpy(out, (char *)pdata, len);
return len;
}
return -RT_ERROR;
}
/**
* This function will get a integer from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
int db_stmt_get_int(sqlite3_stmt *stmt, int index)
{
return sqlite3_column_int(stmt, index);
}
/**
* This function will get a double precision value from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
double db_stmt_get_double(sqlite3_stmt *stmt, int index)
{
return sqlite3_column_double(stmt, index);
}
/**
* This function will check a table exist or not by table name.
*
* @param tbl_name the table name.
* @return >0:existed; ==0:not existed; <0:ERROR
*/
int db_table_is_exist(const char *tbl_name)
{
char sqlstr[DB_SQL_MAX_LEN];
int cnt = 0;
if (tbl_name == RT_NULL)
{
return -RT_ERROR;
}
rt_snprintf(sqlstr, DB_SQL_MAX_LEN, "select count(*) from sqlite_master where type = 'table' and name = '%s';", tbl_name);
cnt = db_query_count_result(sqlstr);
if (cnt > 0)
{
return cnt;
}
return -RT_ERROR;
}
/**
* This function will connect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_connect(char *name)
{
int32_t len = 0;
// rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
len = rt_strnlen(name, PKG_SQLITE_DB_NAME_MAX_LEN + 1);
if (len >= PKG_SQLITE_DB_NAME_MAX_LEN + 1)
{
LOG_E("the database name '(%s)' lengh is too long(max:%d).", name, PKG_SQLITE_DB_NAME_MAX_LEN);
// rt_mutex_release(db_mutex_lock);
return -RT_ERROR;
}
rt_strncpy(db_name, name, len);
db_name[len] = '\0';
return RT_EOK;
}
/**
* This function will disconnect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_disconnect(char *name)
{
int32_t len = 0;
// rt_mutex_release(db_mutex_lock);
rt_strncpy(db_name, DEFAULT_DB_NAME, strlen(DEFAULT_DB_NAME));
db_name[len] = '\0';
return RT_EOK;
}
/**
* This function will connect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_set_name(char *name)
{
int32_t len = 0;
// rt_mutex_take(db_mutex_lock, RT_WAITING_FOREVER);
len = rt_strnlen(name, PKG_SQLITE_DB_NAME_MAX_LEN + 1);
if (len >= PKG_SQLITE_DB_NAME_MAX_LEN + 1)
{
LOG_E("the database name '(%s)' lengh is too long(max:%d).", name, PKG_SQLITE_DB_NAME_MAX_LEN);
// rt_mutex_release(db_mutex_lock);
return -RT_ERROR;
}
rt_strncpy(db_name, name, len);
db_name[len] = '\0';
// rt_mutex_release(db_mutex_lock);
return RT_EOK;
}
/**
* This function will get the current DB filename
*
* @return the current DB filename
*
*/
char *db_get_name(void)
{
static char name[PKG_SQLITE_DB_NAME_MAX_LEN + 1];
size_t len = rt_strlen(db_name);
rt_strncpy(name, db_name, len);
name[len] = '\0';
return name;
}

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-06 lizhen9880 first version
*/
#ifndef __DBHELPER_H__
#define __DBHELPER_H__
#include <sqlite3.h>
#include <rtthread.h>
#define DB_SQL_MAX_LEN 1024
#define PKG_SQLITE_DB_NAME_MAX_LEN 1023
int db_helper_init(void);
int db_create_database(const char *sqlstr);
/**
* This function will be used for the operating that is not SELECT.It support executing multiple
* SQL statements.
*
* @param sqlstr the SQL statements strings.if there are more than one
* statements in the sqlstr to execute,separate them by a semicolon(;).
* @param bind the callback function supported by user.bind data and call the sqlite3_step function.
* @param param the parameter for the callback "bind".
* @return success or fail.
*/
int db_nonquery_operator(const char *sqlstr, int (*bind)(sqlite3_stmt *, int index, void *arg), void *param);
/**
* This function will be used for the operating that is not SELECT.The additional
* arguments following format are formatted and inserted in the resulting string
* replacing their respective specifiers.
*
* @param sql the SQL statement.
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return success or fail.
*/
int db_nonquery_by_varpara(const char *sql, const char *fmt, ...);
/**
* This function will be used for the transaction that is not SELECT.
*
* @param exec_sqls the callback function of executing SQL statements.
* @param arg the parameter for the callback "exec_sqls".
* @return success or fail.
*/
int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db, void *arg), void *arg);
/**
* This function will be used for the SELECT operating.The additional arguments
* following format are formatted and inserted in the resulting string replacing
* their respective specifiers.
*
* @param sql the SQL statements.
* @param create the callback function supported by user.
* @param arg the parameter for the callback "create".
* @param fmt the args format.such as %s string,%d int.
* @param ... the additional arguments
* @return success or fail.
*/
int db_query_by_varpara(const char *sql, int (*create)(sqlite3_stmt *stmt, void *arg), void *arg, const char *fmt, ...);
/**
* This function will return the number of records returned by a select query.
* This function only gets the 1st row of the 1st column.
*
* @param sql the SQL statement SELECT COUNT() FROM .
* @return the count or fail.
*/
int db_query_count_result(const char *sql);
/**
* This function will get the blob from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return the result length or fail.
*/
int db_stmt_get_blob(sqlite3_stmt *stmt, int index, unsigned char *out);
/**
* This function will get the text from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @param out the output buffer.the result will put in this buffer.
* @return the result length or fail.
*/
int db_stmt_get_text(sqlite3_stmt *stmt, int index, char *out);
/**
* This function will get a integer from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
int db_stmt_get_int(sqlite3_stmt *stmt, int index);
/**
* This function will get a double precision value from the "index" colum.
*
* @param stmt the SQL statement returned by the function sqlite3_step().
* @param index the colum index.the first colum's index value is 0.
* @return the result.
*/
double db_stmt_get_double(sqlite3_stmt *stmt, int index);
/**
* This function will check a table exist or not by table name.
*
* @param tbl_name the table name.
* @return >0:existed; ==0:not existed; <0:ERROR
*/
int db_table_is_exist(const char *tbl_name);
/**
* This function will connect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_connect(char *name);
/**
* This function will disconnect DB
*
* @param name the DB filename.
* @return RT_EOK:success
* -RT_ERROR:the input name is too long
*/
int db_disconnect(char *name);
/**
* This function will get the current DB filename
*
* @return the current DB filename
*
*/
char *db_get_name(void);
#endif

View File

@ -0,0 +1,467 @@
static int _rtthread_io_read(sqlite3_file *file_id, void *pbuf, int cnt, sqlite3_int64 offset)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
sqlite3_int64 new_offset;
int r_cnt;
assert(file_id);
assert(offset >= 0);
assert(cnt > 0);
new_offset = lseek(file->fd, offset, SEEK_SET);
if (new_offset != offset)
{
return SQLITE_IOERR_READ;
}
do {
r_cnt = read(file->fd, pbuf, cnt);
if (r_cnt == cnt)
{
break;
}
if (r_cnt < 0)
{
if (errno != EINTR)
{
return SQLITE_IOERR_READ;
}
r_cnt = 1;
continue;
}
else if (r_cnt > 0)
{
cnt -= r_cnt;
pbuf = (void*)(r_cnt + (char*)pbuf);
}
} while (r_cnt > 0);
if (r_cnt != cnt)
{
memset(&((char*)pbuf)[r_cnt], 0, cnt - r_cnt);
return SQLITE_IOERR_SHORT_READ;
}
return SQLITE_OK;
}
static int _rtthread_io_write(sqlite3_file* file_id, const void *pbuf, int cnt, sqlite3_int64 offset)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
sqlite3_int64 new_offset;
int w_cnt;
assert(file_id);
assert(cnt > 0);
new_offset = lseek(file->fd, offset, SEEK_SET);
if (new_offset != offset)
{
return SQLITE_IOERR_WRITE;
}
do {
w_cnt = write(file->fd, pbuf, cnt);
if (w_cnt == cnt)
{
break;
}
if (w_cnt < 0)
{
if (errno != EINTR)
{
return SQLITE_IOERR_WRITE;
}
w_cnt = 1;
continue;
}
else if (w_cnt > 0)
{
cnt -= w_cnt;
pbuf = (void*)(w_cnt + (char*)pbuf);
}
} while (w_cnt > 0);
if (w_cnt != cnt)
{
return SQLITE_FULL;
}
return SQLITE_OK;
}
static int _rtthread_io_truncate(sqlite3_file* file_id, sqlite3_int64 size)
{
return SQLITE_IOERR_TRUNCATE;
}
static int _rtthread_io_sync(sqlite3_file* file_id, int flags)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
assert((flags & 0x0F) == SQLITE_SYNC_NORMAL
|| (flags & 0x0F) == SQLITE_SYNC_FULL);
fsync(file->fd);
return SQLITE_OK;
}
static int _rtthread_io_file_size(sqlite3_file* file_id, sqlite3_int64 *psize)
{
int rc;
struct stat buf;
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
assert(file_id);
rc = fstat(file->fd, &buf);
if (rc != 0)
{
return SQLITE_IOERR_FSTAT;
}
*psize = buf.st_size;
/* When opening a zero-size database, the findInodeInfo() procedure
** writes a single byte into that file in order to work around a bug
** in the OS-X msdos filesystem. In order to avoid problems with upper
** layers, we need to report this file size as zero even though it is
** really 1. Ticket #3260.
*/
if (*psize == 1) *psize = 0;
return SQLITE_OK;
}
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero. The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int _rtthread_io_check_reserved_lock(sqlite3_file *file_id, int *pResOut)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
rt_sem_t psem = &file->sem;
int reserved = 0;
/* Check if a thread in this process holds such a lock */
if (file->eFileLock > SHARED_LOCK)
{
reserved = 1;
}
/* Otherwise see if some other process holds it. */
if (!reserved)
{
if (rt_sem_trytake(psem) != RT_EOK)
{
/* someone else has the lock when we are in NO_LOCK */
reserved = (file->eFileLock < SHARED_LOCK);
}
else
{
/* we could have it if we want it */
rt_sem_release(psem);
}
}
*pResOut = reserved;
return SQLITE_OK;
}
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
**
** (1) SHARED_LOCK
** (2) RESERVED_LOCK
** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between. The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal. The following chart shows the allowed
** transitions and the inserted intermediate states:
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
** lock states in the sqlite3_file structure, but all locks SHARED or
** above are really EXCLUSIVE locks and exclude all other processes from
** access the file.
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int _rtthread_io_lock(sqlite3_file *file_id, int eFileLock)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
rt_sem_t psem = &file->sem;
int rc = SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (file->eFileLock > NO_LOCK)
{
file->eFileLock = eFileLock;
rc = SQLITE_OK;
goto sem_end_lock;
}
/* lock semaphore now but bail out when already locked. */
if (rt_sem_trytake(psem) != RT_EOK)
{
rc = SQLITE_BUSY;
goto sem_end_lock;
}
/* got it, set the type and return ok */
file->eFileLock = eFileLock;
sem_end_lock:
return rc;
}
/*
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int _rtthread_io_unlock(sqlite3_file *file_id, int eFileLock)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
rt_sem_t psem = &file->sem;
assert(eFileLock <= SHARED_LOCK);
/* no-op if possible */
if (file->eFileLock == eFileLock)
{
return SQLITE_OK;
}
/* shared can just be set because we always have an exclusive */
if (eFileLock == SHARED_LOCK)
{
file->eFileLock = SHARED_LOCK;
return SQLITE_OK;
}
/* no, really unlock. */
rt_sem_release(psem);
file->eFileLock = NO_LOCK;
return SQLITE_OK;
}
static int _rtthread_io_close(sqlite3_file *file_id)
{
int rc = 0;
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
if (file->fd >= 0)
{
_rtthread_io_unlock(file_id, NO_LOCK);
rt_sem_detach(&file->sem);
rc = close(file->fd);
file->fd = -1;
}
return rc;
}
static int _rtthread_fcntl_size_hint(sqlite3_file *file_id, i64 nByte)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
if (file->szChunk > 0)
{
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
if (fstat(file->fd, &buf))
{
return SQLITE_IOERR_FSTAT;
}
nSize = ((nByte + file->szChunk - 1) / file->szChunk) * file->szChunk;
if (nSize > (i64)buf.st_size)
{
/* If the OS does not have posix_fallocate(), fake it. Write a
** single byte to the last byte in each block that falls entirely
** within the extended region. Then, if required, a single byte
** at offset (nSize-1), to set the size of the file correctly.
** This is a similar technique to that used by glibc on systems
** that do not have a real fallocate() call.
*/
int nBlk = 512; /* File-system block size */
int nWrite = 0; /* Number of bytes written by seekAndWrite */
i64 iWrite; /* Next offset to write to */
iWrite = (buf.st_size / nBlk) * nBlk + nBlk - 1;
assert(iWrite >= buf.st_size);
assert(((iWrite + 1) % nBlk) == 0);
for (/*no-op*/; iWrite < nSize + nBlk - 1; iWrite += nBlk)
{
if (iWrite >= nSize)
{
iWrite = nSize - 1;
}
nWrite = _rtthread_io_write(file_id, "", 1, iWrite);
if (nWrite != 1)
{
return SQLITE_IOERR_WRITE;
}
}
}
}
return SQLITE_OK;
}
/*
** Information and control of an open file handle.
*/
static int _rtthread_io_file_ctrl(sqlite3_file *file_id, int op, void *pArg)
{
RTTHREAD_SQLITE_FILE_T *file = (RTTHREAD_SQLITE_FILE_T*)file_id;
switch( op )
{
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = file->eFileLock;
return SQLITE_OK;
}
case SQLITE_LAST_ERRNO: {
*(int*)pArg = 0;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
file->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
int rc;
rc = _rtthread_fcntl_size_hint(file_id, *(i64 *)pArg);
return rc;
}
case SQLITE_FCNTL_PERSIST_WAL: {
return SQLITE_OK;
}
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
return SQLITE_OK;
}
case SQLITE_FCNTL_VFSNAME: {
*(char**)pArg = sqlite3_mprintf("%s", file->pvfs->zName);
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = sqlite3_malloc(file->pvfs->mxPathname );
if( zTFile )
{
_rtthread_get_temp_name(file->pvfs->mxPathname, zTFile);
*(char**)pArg = zTFile;
}
return SQLITE_OK;
}
}
return SQLITE_NOTFOUND;
}
static int _rtthread_io_sector_size(sqlite3_file *file_id)
{
return SQLITE_DEFAULT_SECTOR_SIZE;
}
static int _rtthread_io_device_characteristics(sqlite3_file *file_id)
{
return 0;
}
/*
** If possible, return a pointer to a mapping of file fd starting at offset
** iOff. The mapping must be valid for at least nAmt bytes.
**
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
** If this function does return a pointer, the caller must eventually
** release the reference by calling unixUnfetch().
*/
static int _rtthread_io_fetch(sqlite3_file *file_id, i64 iOff, int nAmt, void **pp)
{
*pp = 0;
return SQLITE_OK;
}
/*
** If the third argument is non-NULL, then this function releases a
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
** argument that was passed to the unixFetch() invocation.
**
** Or, if the third argument is NULL, then this function is being called
** to inform the VFS layer that, according to POSIX, any existing mapping
** may now be invalid and should be unmapped.
*/
static int _rtthread_io_unfetch(sqlite3_file *fd, i64 iOff, void *p)
{
return SQLITE_OK;
}
static const sqlite3_io_methods _rtthread_io_method = {
3,
_rtthread_io_close,
_rtthread_io_read,
_rtthread_io_write,
_rtthread_io_truncate,
_rtthread_io_sync,
_rtthread_io_file_size,
_rtthread_io_lock,
_rtthread_io_unlock,
_rtthread_io_check_reserved_lock,
_rtthread_io_file_ctrl,
_rtthread_io_sector_size,
_rtthread_io_device_characteristics,
0,
0,
0,
0,
_rtthread_io_fetch,
_rtthread_io_unfetch
};

View File

@ -0,0 +1,235 @@
#if defined(SQLITE_MUTEX_RTTHREAD)
/*
* rt-thread mutex
*/
struct sqlite3_mutex {
struct rt_mutex mutex; /* Mutex controlling the lock */
int id; /* Mutex type */
};
SQLITE_PRIVATE void sqlite3MemoryBarrier(void)
{
}
/*
** Initialize and deinitialize the mutex subsystem.
The argument to sqlite3_mutex_alloc() must one of these integer constants:
SQLITE_MUTEX_FAST
SQLITE_MUTEX_RECURSIVE
SQLITE_MUTEX_STATIC_MASTER
SQLITE_MUTEX_STATIC_MEM
SQLITE_MUTEX_STATIC_OPEN
SQLITE_MUTEX_STATIC_PRNG
SQLITE_MUTEX_STATIC_LRU
SQLITE_MUTEX_STATIC_PMEM
SQLITE_MUTEX_STATIC_APP1
SQLITE_MUTEX_STATIC_APP2
SQLITE_MUTEX_STATIC_APP3
SQLITE_MUTEX_STATIC_VFS1
SQLITE_MUTEX_STATIC_VFS2
SQLITE_MUTEX_STATIC_VFS3
The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
cause sqlite3_mutex_alloc() to create a new mutex. The new mutex is recursive
when SQLITE_MUTEX_RECURSIVE is used but not necessarily so when SQLITE_MUTEX_FAST
is used. The mutex implementation does not need to make a distinction between
SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does not want to.
SQLite will only request a recursive mutex in cases where it really needs one.
If a faster non-recursive mutex implementation is available on the host platform,
the mutex subsystem might return such a mutex in response to SQLITE_MUTEX_FAST.
The other allowed parameters to sqlite3_mutex_alloc()
(anything other than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
a pointer to a static preexisting mutex. Nine static mutexes are used by the
current version of SQLite. Future versions of SQLite may add additional static
mutexes. Static mutexes are for internal use by SQLite only. Applications that
use SQLite mutexes should use only the dynamic mutexes returned by SQLITE_MUTEX_FAST
or SQLITE_MUTEX_RECURSIVE.
Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST or SQLITE_MUTEX_RECURSIVE)
is used then sqlite3_mutex_alloc() returns a different mutex on every call.
For the static mutex types, the same mutex is returned on every call that has the same type number.
*/
static sqlite3_mutex _static_mutex[12];
static int _rtthread_mtx_init(void)
{
printf("%s %d\n",__func__,__LINE__);
int i;
rt_err_t err;
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
{
err = rt_mutex_init(&_static_mutex[i].mutex, "sqlmtx", RT_IPC_FLAG_PRIO);
if (err != RT_EOK)
{
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
static int _rtthread_mtx_end(void)
{
printf("%s %d\n",__func__,__LINE__);
int i;
rt_err_t err;
for (i = 0; i < sizeof(_static_mutex) / sizeof(_static_mutex[0]); i++)
{
err = rt_mutex_detach(&_static_mutex[i].mutex);
_static_mutex[i].mutex.owner = 0;
_static_mutex[i].mutex.hold = 0;
if (err != RT_EOK)
{
return SQLITE_ERROR;
}
}
return SQLITE_OK;
}
static sqlite3_mutex * _rtthread_mtx_alloc(int id)
{
printf("%s %d\n",__func__,__LINE__);
sqlite3_mutex *p = NULL;
switch (id)
{
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE:
p = sqlite3Malloc(sizeof(sqlite3_mutex));
if (p != NULL)
{
rt_mutex_init(&p->mutex, "sqlmtx", RT_IPC_FLAG_PRIO);
p->id = id;
}
break;
default:
assert(id - 2 >= 0);
assert(id - 2 < ArraySize(_static_mutex) );
p = &_static_mutex[id - 2];
p->id = id;
break;
}
return p;
}
static void _rtthread_mtx_free(sqlite3_mutex * p)
{
printf("%s %d\n",__func__,__LINE__);
assert(p != 0);
rt_mutex_detach(&p->mutex);
switch (p->id)
{
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE:
sqlite3_free(p);
break;
default:
break;
}
}
static void _rtthread_mtx_enter(sqlite3_mutex *p)
{
printf("%s %d\n",__func__,__LINE__);
assert(p != 0);
// rt_mutex_take(&p->mutex, RT_WAITING_FOREVER);
}
static int _rtthread_mtx_try(sqlite3_mutex *p)
{
printf("%s %d\n",__func__,__LINE__);
assert(p != 0);
// if (rt_mutex_take(&p->mutex, RT_WAITING_NO) != RT_EOK)
// {
// return SQLITE_BUSY;
// }
return SQLITE_OK;
}
static void _rtthread_mtx_leave(sqlite3_mutex *p)
{
printf("%s %d\n",__func__,__LINE__);
assert(p != 0);
// rt_mutex_release(&p->mutex);
}
#ifdef SQLITE_DEBUG
/*
If the argument to sqlite3_mutex_held() is a NULL pointer then the routine
should return 1. This seems counter-intuitive since clearly the mutex cannot
be held if it does not exist. But the reason the mutex does not exist is
because the build is not using mutexes. And we do not want the assert()
containing the call to sqlite3_mutex_held() to fail, so a non-zero return
is the appropriate thing to do. The sqlite3_mutex_notheld() interface should
also return 1 when given a NULL pointer.
*/
static int _rtthread_mtx_held(sqlite3_mutex *p)
{
if (p != 0)
{
if ((rt_thread_self() == p->mutex.owner) && (p->mutex.hold > 0))
{
return 1;
}
return 0;
}
return 1;
}
static int _rtthread_mtx_noheld(sqlite3_mutex *p)
{
if (_rtthread_mtx_held(p))
{
return 0;
}
return 1;
}
#endif /* SQLITE_DEBUG */
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void)
{
static const sqlite3_mutex_methods sMutex = {
_rtthread_mtx_init,
_rtthread_mtx_end,
_rtthread_mtx_alloc,
_rtthread_mtx_free,
_rtthread_mtx_enter,
_rtthread_mtx_try,
_rtthread_mtx_leave,
#ifdef SQLITE_DEBUG
_rtthread_mtx_held,
_rtthread_mtx_noheld
#else
0,
0
#endif
};
return &sMutex;
}
#endif /* SQLITE_MUTEX_RTTHREAD */

View File

@ -0,0 +1,655 @@
#ifdef SQLITE_OS_RTTHREAD
#ifndef SQLITE_OMIT_LOAD_EXTENSION
#error "rt-thread not support load extension, compile with SQLITE_OMIT_LOAD_EXTENSION."
#endif
#define RTTHREAD_MAX_PATHNAME 256
#include <dfs_posix.h>
/*
** Define various macros that are missing from some systems.
*/
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifdef SQLITE_DISABLE_LFS
# undef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifndef O_NOFOLLOW
# define O_NOFOLLOW 0
#endif
#ifndef O_BINARY
# define O_BINARY 0
#endif
#ifndef RT_USING_NEWLIB
#ifndef EINTR
#define EINTR 4 /* Interrupted system call */
#endif
#ifndef ENOLCK
#define ENOLCK 46 /* No record locks available */
#endif
#ifndef EACCES
#define EACCES 13 /* Permission denied */
#endif
#ifndef EPERM
#define EPERM 1 /* Operation not permitted */
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT 145 /* Connection timed out */
#endif
#ifndef ENOTCONN
#define ENOTCONN 134 /* Transport endpoint is not connected */
#endif
#if defined(__GNUC__) || defined(__ADSPBLACKFIN__)
int _gettimeofday(struct timeval *tp, void *ignore) __attribute__((weak));
int _gettimeofday(struct timeval *tp, void *ignore)
#elif defined(__CC_ARM)
__weak int _gettimeofday(struct timeval *tp, void *ignore)
#elif defined(__IAR_SYSTEMS_ICC__)
#if __VER__ > 540
__weak
#endif
int _gettimeofday(struct timeval *tp, void *ignore)
#else
int _gettimeofday(struct timeval *tp, void *ignore)
#endif
{
return 0;
}
#endif /* RT_USING_NEWLIB */
static int _Access(const char *pathname, int mode)
{
int fd;
fd = open(pathname, O_RDONLY, mode);
if (fd >= 0)
{
close(fd);
return 0;
}
return -1;
}
#define _RTTHREAD_LOG_ERROR(a,b,c) _rtthread_log_error_at_line(a,b,c,__LINE__)
static int _rtthread_log_error_at_line(
int errcode, /* SQLite error code */
const char *zFunc, /* Name of OS function that failed */
const char *zPath, /* File path associated with error */
int iLine /* Source line number where error occurred */
)
{
char *zErr; /* Message from strerror() or equivalent */
int iErrno = errno; /* Saved syscall error number */
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
** the strerror() function to obtain the human-readable error message
** equivalent to errno. Otherwise, use strerror_r().
*/
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
char aErr[80];
memset(aErr, 0, sizeof(aErr));
zErr = aErr;
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
** assume that the system provides the GNU version of strerror_r() that
** returns a pointer to a buffer containing the error message. That pointer
** may point to aErr[], or it may point to some static storage somewhere.
** Otherwise, assume that the system provides the POSIX version of
** strerror_r(), which always writes an error message into aErr[].
**
** If the code incorrectly assumes that it is the POSIX version that is
** available, the error message will often be an empty string. Not a
** huge problem. Incorrectly concluding that the GNU version is available
** could lead to a segfault though.
*/
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
zErr =
#endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
#elif SQLITE_THREADSAFE
/* This is a threadsafe build, but strerror_r() is not available. */
zErr = "";
#else
/* Non-threadsafe build, use strerror(). */
zErr = strerror(iErrno);
#endif
if( zPath==0 )
zPath = "";
sqlite3_log(errcode, "os_rtthread.c:%d: (%d) %s(%s) - %s",
iLine, iErrno, zFunc, zPath, zErr);
return errcode;
}
typedef struct
{
sqlite3_io_methods const *pMethod;
sqlite3_vfs *pvfs;
int fd;
int eFileLock;
int szChunk;
struct rt_semaphore sem;
} RTTHREAD_SQLITE_FILE_T;
static const char* _rtthread_temp_file_dir(void)
{
const char *azDirs[] = {
0,
"/sql",
"/sql/tmp"
"/tmp",
0 /* List terminator */
};
unsigned int i;
struct stat buf;
const char *zDir = 0;
azDirs[0] = sqlite3_temp_directory;
for (i = 0; i < sizeof(azDirs) / sizeof(azDirs[0]); zDir = azDirs[i++])
{
if( zDir == 0 ) continue;
if( stat(zDir, &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
break;
}
return zDir;
}
/*
** Create a temporary file name in zBuf. zBuf must be allocated
** by the calling process and must be big enough to hold at least
** pVfs->mxPathname bytes.
*/
static int _rtthread_get_temp_name(int nBuf, char *zBuf)
{
const unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
unsigned int i, j;
const char *zDir;
zDir = _rtthread_temp_file_dir();
if (zDir == 0)
{
zDir = ".";
}
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
if ((strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf)
{
return SQLITE_ERROR;
}
do {
sqlite3_snprintf(nBuf-18, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
j = (int)strlen(zBuf);
sqlite3_randomness(15, &zBuf[j]);
for (i = 0; i < 15; i++, j++)
{
zBuf[j] = (char)zChars[((unsigned char)zBuf[j]) % (sizeof(zChars) - 1)];
}
zBuf[j] = 0;
zBuf[j + 1] = 0;
} while (_Access(zBuf, 0) == 0);
return SQLITE_OK;
}
#include "rtthread_io_methods.c"
/*
** Invoke open(). Do so multiple times, until it either succeeds or
** fails for some reason other than EINTR.
**
** If the file creation mode "m" is 0 then set it to the default for
** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
** 0644) as modified by the system umask. If m is not 0, then
** make the file creation mode be exactly m ignoring the umask.
**
** The m parameter will be non-zero only when creating -wal, -journal,
** and -shm files. We want those files to have *exactly* the same
** permissions as their original database, unadulterated by the umask.
** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
** transaction crashes and leaves behind hot journals, then any
** process that is able to write to the database will also be able to
** recover the hot journals.
*/
static int _rtthread_fs_open(const char *file_path, int f, mode_t m)
{
int fd = -1;
while (fd < 0)
{
#if defined(O_CLOEXEC)
fd = open(file_path, f | O_CLOEXEC, m);
#else
fd = open(file_path, f, m);
#endif
if (fd < 0)
{
if (errno == EINTR)
continue;
break;
}
}
return fd;
}
static int _rtthread_vfs_open(sqlite3_vfs *pvfs, const char *file_path, sqlite3_file *file_id, int flags, int *pOutFlags)
{
RTTHREAD_SQLITE_FILE_T *p;
int fd;
int eType = flags & 0xFFFFFF00; /* Type of file to open */
int rc = SQLITE_OK; /* Function Return Code */
int openFlags = 0;
mode_t openMode = 0;
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
int isReadonly = (flags & SQLITE_OPEN_READONLY);
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
char zTmpname[RTTHREAD_MAX_PATHNAME + 2];
p = (RTTHREAD_SQLITE_FILE_T*)file_id;
/* Check the following statements are true:
**
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
** (b) if CREATE is set, then READWRITE must also be set, and
** (c) if EXCLUSIVE is set, then CREATE must also be set.
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
*/
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
assert(isCreate==0 || isReadWrite);
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
/* The main DB, main journal, WAL file and master journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
assert( (!isDelete && file_path) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
** sqlite3_uri_parameter(). */
assert((eType != SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || file_path[strlen(file_path) + 1] == 0);
memset(p, 0, sizeof(RTTHREAD_SQLITE_FILE_T));
if (!file_path)
{
rc = _rtthread_get_temp_name(RTTHREAD_MAX_PATHNAME + 2, zTmpname);
if (rc != SQLITE_OK )
{
return rc;
}
file_path = zTmpname;
/* Generated temporary filenames are always double-zero terminated
** for use by sqlite3_uri_parameter(). */
assert(file_path[strlen(file_path) + 1] == 0);
}
/* Determine the value of the flags parameter passed to POSIX function
** open(). These must be calculated even if open() is not called, as
** they may be stored as part of the file handle and used by the
** 'conch file' locking functions later on. */
if (isReadonly) openFlags |= O_RDONLY;
if (isReadWrite) openFlags |= O_RDWR;
if (isCreate) openFlags |= O_CREAT;
if (isExclusive) openFlags |= (O_EXCL | O_NOFOLLOW);
openFlags |= (O_LARGEFILE | O_BINARY);
fd = _rtthread_fs_open(file_path, openFlags, openMode);
if (fd < 0 && (errno != -EISDIR) && isReadWrite && !isExclusive)
{
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR | O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
fd = _rtthread_fs_open(file_path, openFlags, openMode);
}
if (fd < 0)
{
rc = _RTTHREAD_LOG_ERROR(SQLITE_CANTOPEN_BKPT, "open", file_path);
return rc;
}
if (pOutFlags)
{
*pOutFlags = flags;
}
if (isDelete)
{
unlink(file_path);
}
p->fd = fd;
p->pMethod = &_rtthread_io_method;
p->eFileLock = NO_LOCK;
p->szChunk = 0;
p->pvfs = pvfs;
rt_sem_init(&p->sem, "vfssem", 1, RT_IPC_FLAG_PRIO);
return rc;
}
int _rtthread_vfs_delete(sqlite3_vfs* pvfs, const char *file_path, int syncDir)
{
int rc = SQLITE_OK;
if (unlink(file_path) == (-1))
{
if (errno == -ENOENT)
{
rc = SQLITE_IOERR_DELETE_NOENT;
}
else
{
rc = _RTTHREAD_LOG_ERROR(SQLITE_IOERR_DELETE, "unlink", file_path);
}
return rc;
}
// sync dir: open dir -> fsync -> close
if ((syncDir & 1) != 0)
{
int ii;
int fd = -1;
char zDirname[RTTHREAD_MAX_PATHNAME + 1];
sqlite3_snprintf(RTTHREAD_MAX_PATHNAME, zDirname, "%s", file_path);
for (ii=(int)strlen(zDirname); ii > 1 && zDirname[ii] != '/'; ii--);
if (ii > 0)
{
zDirname[ii] = '\0';
fd = _rtthread_fs_open(zDirname, O_RDONLY | O_BINARY, 0);
}
if (fd >= 0)
{
if (fsync(fd))
{
rc = _RTTHREAD_LOG_ERROR(SQLITE_IOERR_DIR_FSYNC, "fsync", file_path);
}
close(fd);
}
rc = SQLITE_OK;
}
return rc;
}
static int _rtthread_vfs_access(sqlite3_vfs* pvfs, const char *file_path, int flags, int *pResOut)
{
int amode = 0;
#ifndef F_OK
# define F_OK 0
#endif
#ifndef R_OK
# define R_OK 4
#endif
#ifndef W_OK
# define W_OK 2
#endif
switch (flags)
{
case SQLITE_ACCESS_EXISTS:
amode = F_OK;
break;
case SQLITE_ACCESS_READWRITE:
amode = W_OK | R_OK;
break;
case SQLITE_ACCESS_READ:
amode = R_OK;
break;
default:
_RTTHREAD_LOG_ERROR(flags, "access", file_path);
return -1;
}
*pResOut = (_Access(file_path, amode) == 0);
if (flags == SQLITE_ACCESS_EXISTS && *pResOut)
{
struct stat buf;
if (0 == stat(file_path, &buf) && (buf.st_size == 0))
{
*pResOut = 0;
}
}
return SQLITE_OK;
}
static int _rtthread_vfs_fullpathname(sqlite3_vfs* pvfs, const char *file_path, int nOut, char *zOut)
{
assert(pvfs->mxPathname == RTTHREAD_MAX_PATHNAME);
zOut[nOut - 1] = '\0';
if (file_path[0] == '/')
{
sqlite3_snprintf(nOut, zOut, "%s", file_path);
}
else
{
int nCwd;
if (getcwd(zOut, nOut - 1) == 0)
{
return _RTTHREAD_LOG_ERROR(SQLITE_CANTOPEN_BKPT, "getcwd", file_path);
}
nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut - nCwd, &zOut[nCwd], "/%s", file_path);
}
return SQLITE_OK;
}
static int _rtthread_vfs_randomness(sqlite3_vfs* pvfs, int nByte, char *zOut)
{
assert((size_t)nByte >= (sizeof(time_t) + sizeof(int)));
memset(zOut, 0, nByte);
{
int i;
char tick8, tick16;
tick8 = (char)rt_tick_get();
tick16 = (char)(rt_tick_get() >> 8);
for (i = 0; i < nByte; i++)
{
zOut[i] = (char)(i ^ tick8 ^ tick16);
tick8 = zOut[i];
tick16 = ~(tick8 ^ tick16);
}
}
return nByte;
}
static int _rtthread_vfs_sleep(sqlite3_vfs* pvfs, int microseconds)
{
int millisecond = (microseconds + 999) / 1000;
rt_thread_delay(rt_tick_from_millisecond(millisecond));
return millisecond * 1000;
}
static int _rtthread_vfs_current_time_int64(sqlite3_vfs*, sqlite3_int64*);
static int _rtthread_vfs_current_time(sqlite3_vfs* pvfs, double* pnow)
{
sqlite3_int64 i = 0;
int rc;
rc = _rtthread_vfs_current_time_int64(0, &i);
*pnow = i / 86400000.0;
return rc;
}
static int _rtthread_vfs_get_last_error(sqlite3_vfs* pvfs, int nBuf, char *zBuf)
{
return 0;
}
static int _rtthread_vfs_current_time_int64(sqlite3_vfs* pvfs, sqlite3_int64*pnow)
{
#ifndef NO_GETTOD
#define NO_GETTOD 1
#endif
static const sqlite3_int64 rtthreadEpoch = 24405875 * (sqlite3_int64)8640000;
int rc = SQLITE_OK;
#if defined(NO_GETTOD)
time_t t;
time(&t);
*pnow = ((sqlite3_int64)t) * 1000 + rtthreadEpoch;
#else
struct timeval sNow;
if (gettimeofday(&sNow, 0) == 0)
{
*pnow = rtthreadEpoch + 1000 * (sqlite3_int64)sNow.tv_sec + sNow.tv_usec / 1000;
}
else
{
rc = SQLITE_ERROR;
}
#endif
#ifdef SQLITE_TEST
if( sqlite3_current_time )
{
*pnow = 1000 * (sqlite3_int64)sqlite3_current_time + rtthreadEpoch;
}
#endif
return rc;
}
static int _rtthread_vfs_set_system_call(sqlite3_vfs* pvfs, const char *file_path, sqlite3_syscall_ptr pfn)
{
return SQLITE_NOTFOUND;
}
static sqlite3_syscall_ptr _rtthread_vfs_get_system_call(sqlite3_vfs* pvfs, const char *file_path)
{
return 0;
}
static const char* _rtthread_vfs_next_system_call(sqlite3_vfs *pvfs, const char *file_path)
{
return 0;
}
/*
** Initialize and deinitialize the operating system interface.
*/
SQLITE_API int sqlite3_os_init(void)
{
static sqlite3_vfs _rtthread_vfs = {
3, /* iVersion */
sizeof(RTTHREAD_SQLITE_FILE_T), /* szOsFile */
RTTHREAD_MAX_PATHNAME, /* mxPathname */
0, /* pNext */
"rt-thread", /* zName */
0, /* pAppData */
_rtthread_vfs_open, /* xOpen */
_rtthread_vfs_delete, /* xDelete */
_rtthread_vfs_access, /* xAccess */
_rtthread_vfs_fullpathname, /* xFullPathname */
0, /* xDlOpen */
0, /* xDlError */
0, /* xDlSym */
0, /* xDlClose */
_rtthread_vfs_randomness, /* xRandomness */
_rtthread_vfs_sleep, /* xSleep */
_rtthread_vfs_current_time, /* xCurrentTime */
_rtthread_vfs_get_last_error, /* xGetLastError */
_rtthread_vfs_current_time_int64, /* xCurrentTimeInt64 */
_rtthread_vfs_set_system_call, /* xSetSystemCall */
_rtthread_vfs_get_system_call, /* xGetSystemCall */
_rtthread_vfs_next_system_call, /* xNextSystemCall */
};
printf("vfs register begin\n");
sqlite3_vfs_register(&_rtthread_vfs, 1);
return SQLITE_OK;
}
SQLITE_API int sqlite3_os_end(void)
{
return SQLITE_OK;
}
#endif /* SQLITE_OS_RTTHREAD */

7516
components/sqlite3/shell.c Normal file

File diff suppressed because it is too large Load Diff

202967
components/sqlite3/sqlite3.c Normal file

File diff suppressed because it is too large Load Diff

10500
components/sqlite3/sqlite3.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,564 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(sqlite3*);
const char *(*db_filename)(sqlite3*,const char*);
int (*db_readonly)(sqlite3*,const char*);
int (*db_release_memory)(sqlite3*);
const char *(*errstr)(int);
int (*stmt_busy)(sqlite3_stmt*);
int (*stmt_readonly)(sqlite3_stmt*);
int (*stricmp)(const char*,const char*);
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*vsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(sqlite3_value*);
void (*result_subtype)(sqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(sqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(sqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
sqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/*
** The following macros redefine the API routines so that they are
** redirected through the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
#define sqlite3_result_error_code sqlite3_api->result_error_code
#define sqlite3_test_control sqlite3_api->test_control
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2 sqlite3_api->close_v2
#define sqlite3_db_filename sqlite3_api->db_filename
#define sqlite3_db_readonly sqlite3_api->db_readonly
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
#define sqlite3_errstr sqlite3_api->errstr
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
#define sqlite3_stricmp sqlite3_api->stricmp
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype sqlite3_api->value_subtype
#define sqlite3_result_subtype sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64 sqlite3_api->status64
#define sqlite3_strlike sqlite3_api->strlike
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* SQLITE3EXT_H */

View File

@ -0,0 +1,47 @@
#ifndef _SQLITE_CONFIG_RTTHREAD_H_
#define _SQLITE_CONFIG_RTTHREAD_H_
/*
* SQLite compile macro
*/
#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
#define SQLITE_MINIMUM_FILE_DESCRIPTOR 0
#endif
#define SQLITE_OMIT_LOAD_EXTENSION 0
#define SQLITE_OMIT_WAL 1
// #define SQLITE_OMIT_AUTOINIT 1
#ifndef SQLITE_RTTHREAD_NO_WIDE
#define SQLITE_RTTHREAD_NO_WIDE 1
#endif
#ifndef SQLITE_TEMP_STORE
#define SQLITE_TEMP_STORE 1
#endif
#ifndef SQLITE_THREADSAFE
#define SQLITE_THREADSAFE 0
#endif
// #ifdef SQLITE_THREADSAFE
// #undef SQLITE_THREADSAFE
// #endif
#ifndef HAVE_READLINE
#define HAVE_READLINE 0
#endif
#ifndef NDEBUG
#define NDEBUG
#endif
#ifndef SQLITE_OS_OTHER
#define SQLITE_OS_OTHER 1
#endif
#ifndef SQLITE_OS_RTTHREAD
#define SQLITE_OS_RTTHREAD 1
#endif
#endif

View File

@ -0,0 +1,12 @@
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
src = Glob("*.c")
# The set of source files associated with this SConscript file.
path = [cwd]
group = DefineGroup('sqlite', src, depend = ['RT_USING_SDIO'], CPPPATH = path)
Return('group')

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 peterfan Add copyright header.
*/
#include <rthw.h>
#include <stdint.h>
#include <stdbool.h>
/*
* override gcc builtin atomic function for std::atomic<int64_t>, std::atomic<uint64_t>
* @see https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
*/
uint64_t __atomic_load_8(volatile void *ptr, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
register rt_base_t level;
uint64_t tmp;
level = rt_hw_interrupt_disable();
tmp = *val_ptr;
rt_hw_interrupt_enable(level);
return tmp;
}
void __atomic_store_8(volatile void *ptr, uint64_t val, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
register rt_base_t level;
level = rt_hw_interrupt_disable();
*val_ptr = val;
rt_hw_interrupt_enable(level);
}
uint64_t __atomic_exchange_8(volatile void *ptr, uint64_t val, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
register rt_base_t level;
uint64_t tmp;
level = rt_hw_interrupt_disable();
tmp = *val_ptr;
*val_ptr = val;
rt_hw_interrupt_enable(level);
return tmp;
}
bool __atomic_compare_exchange_8(volatile void *ptr, volatile void *expected, uint64_t desired, bool weak, int success_memorder, int failure_memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
volatile uint64_t *expected_ptr = (volatile uint64_t *)expected;
register rt_base_t level;
bool exchanged;
level = rt_hw_interrupt_disable();
if (*val_ptr == *expected_ptr)
{
*val_ptr = desired;
exchanged = true;
}
else
{
*expected_ptr = *val_ptr;
exchanged = false;
}
rt_hw_interrupt_enable(level);
return exchanged;
}
#define __atomic_fetch_op_8(OPNAME, OP) \
uint64_t __atomic_fetch_##OPNAME##_8(volatile void *ptr, uint64_t val, int memorder) {\
volatile uint64_t* val_ptr = (volatile uint64_t*)ptr;\
register rt_base_t level;\
uint64_t tmp;\
level = rt_hw_interrupt_disable();\
tmp = *val_ptr;\
*val_ptr OP##= val;\
rt_hw_interrupt_enable(level);\
return tmp;\
}
__atomic_fetch_op_8(add, +)
__atomic_fetch_op_8(sub, -)
__atomic_fetch_op_8( and, &)
__atomic_fetch_op_8( or, |)
__atomic_fetch_op_8(xor, ^)

View File

@ -0,0 +1,192 @@
/*
* -*-C-*-
* delivery.pc
* corresponds to A.4 in appendix A
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>
#include "spt_proc.h"
#include "tpc.h"
extern sqlite3 **ctx;
extern sqlite3_stmt ***stmt;
#define NNULL ((void *)0)
int delivery( int t_num,
int w_id_arg,
int o_carrier_id_arg
)
{
int ret;
int w_id = w_id_arg;
int o_carrier_id = o_carrier_id_arg;
int d_id;
int c_id;
int no_o_id;
float ol_total;
char datetime[81];
int proceed = 0;
sqlite3_stmt *sqlite_stmt;
int num_cols;
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerr;*/
gettimestamp(datetime, STRFTIME_FORMAT, TIMESTAMP_LEN);
/* For each district in warehouse */
/* printf("W: %d\n", w_id); */
for (d_id = 1; d_id <= DIST_PER_WARE; d_id++) {
proceed = 1;
/*EXEC_SQL SELECT COALESCE(MIN(no_o_id),0) INTO :no_o_id
FROM new_orders
WHERE no_d_id = :d_id AND no_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][25];
sqlite3_bind_int64(sqlite_stmt, 1, d_id);
sqlite3_bind_int64(sqlite_stmt, 2, w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
no_o_id = sqlite3_column_int64(sqlite_stmt, 0);
}
sqlite3_reset(sqlite_stmt);
if(no_o_id == 0) continue;
proceed = 2;
/*EXEC_SQL DELETE FROM new_orders WHERE no_o_id = :no_o_id AND no_d_id = :d_id
AND no_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][26];
sqlite3_bind_int64(sqlite_stmt, 1, no_o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
proceed = 3;
/*EXEC_SQL SELECT o_c_id INTO :c_id FROM orders
WHERE o_id = :no_o_id AND o_d_id = :d_id
AND o_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][27];
sqlite3_bind_int64(sqlite_stmt, 1, no_o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
c_id = sqlite3_column_int64(sqlite_stmt, 0);
}
sqlite3_reset(sqlite_stmt);
proceed = 4;
/*EXEC_SQL UPDATE orders SET o_carrier_id = :o_carrier_id
WHERE o_id = :no_o_id AND o_d_id = :d_id AND
o_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][28];
sqlite3_bind_int64(sqlite_stmt, 1, o_carrier_id);
sqlite3_bind_int64(sqlite_stmt, 2, no_o_id);
sqlite3_bind_int64(sqlite_stmt, 3, d_id);
sqlite3_bind_int64(sqlite_stmt, 4, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
proceed = 5;
/*EXEC_SQL UPDATE order_line
SET ol_delivery_d = :datetime
WHERE ol_o_id = :no_o_id AND ol_d_id = :d_id AND
ol_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][29];
sqlite3_bind_text(sqlite_stmt, 1, datetime, -1, SQLITE_STATIC);
sqlite3_bind_int64(sqlite_stmt, 2, no_o_id);
sqlite3_bind_int64(sqlite_stmt, 3, d_id);
sqlite3_bind_int64(sqlite_stmt, 4, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
proceed = 6;
/*EXEC_SQL SELECT SUM(ol_amount) INTO :ol_total
FROM order_line
WHERE ol_o_id = :no_o_id AND ol_d_id = :d_id
AND ol_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][30];
sqlite3_bind_int64(sqlite_stmt, 1, no_o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
ol_total = sqlite3_column_double(sqlite_stmt, 0);
}
sqlite3_reset(sqlite_stmt);
proceed = 7;
/*EXEC_SQL UPDATE customer SET c_balance = c_balance + :ol_total ,
c_delivery_cnt = c_delivery_cnt + 1
WHERE c_id = :c_id AND c_d_id = :d_id AND
c_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][31];
sqlite3_bind_double(sqlite_stmt, 1, ol_total);
sqlite3_bind_int64(sqlite_stmt, 2, c_id);
sqlite3_bind_int64(sqlite_stmt, 3, d_id);
sqlite3_bind_int64(sqlite_stmt, 4, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
/*EXEC_SQL COMMIT WORK;*/
//if( sqlite3_exec(ctx[t_num], "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
/* printf("D: %d, O: %d, time: %d\n", d_id, o_id, tad); */
}
/*EXEC_SQL COMMIT WORK;*/
return (1);
sqlerr:
fprintf(stderr, "delivery %d:%d\n",t_num,proceed);
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],mysql_stmt);
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerrerr;*/
/*EXEC_SQL ROLLBACK WORK;*/
sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL);
sqlerrerr:
return (0);
}

View File

@ -0,0 +1,500 @@
/*
* driver.c
* driver for the tpcc transactions
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/times.h>
#include <time.h>
#include "tpc.h" /* prototypes for misc. functions */
#include "trans_if.h" /* prototypes for transacation interface calls */
#include "sequence.h"
#include "rthist.h"
#include "sb_percentile.h"
#include <sqlite3.h>
static int other_ware (int home_ware);
static int do_neword (int t_num);
static int do_payment (int t_num);
static int do_ordstat (int t_num);
static int do_delivery (int t_num);
static int do_slev (int t_num);
extern sqlite3 **ctx;
extern int num_ware;
extern int num_conn;
extern int activate_transaction;
extern int counting_on;
extern int time_start;
extern int time_end;
extern int num_trans;
extern int num_node;
extern int time_count;
extern FILE *freport_file;
extern int success[];
extern int late[];
extern int retry[];
extern int failure[];
extern int* success2[];
extern int* late2[];
extern int* retry2[];
extern int* failure2[];
extern double max_rt[];
extern double total_rt[];
extern int rt_limit[];
extern long clk_tck;
extern sb_percentile_t local_percentile;
#define MAX_RETRY 2000
int driver (int t_num)
{
int i, j;
instrumentation_type neword_time, payment_time, ordstat_time, delivery_time, slev_time;
/* Actually, WaitTimes are needed... */
//for (i = 0; i < num_trans; i++) {
switch(seq_get()){
case 0:
START_TIMING(neword_t, neword_time);
do_neword(t_num);
END_TIMING(neword_t, neword_time);
break;
case 1:
START_TIMING(payment_t, payment_time);
do_payment(t_num);
END_TIMING(payment_t, payment_time);
break;
case 2:
START_TIMING(ordstat_t, ordstat_time);
do_ordstat(t_num);
END_TIMING(ordstat_t, ordstat_time);
break;
case 3:
START_TIMING(delivery_t, delivery_time);
do_delivery(t_num);
END_TIMING(delivery_t, delivery_time);
break;
case 4:
START_TIMING(slev_t, slev_time);
do_slev(t_num);
END_TIMING(slev_t, slev_time);
break;
default:
printf("Error - Unknown sequence.\n");
}
//PRINT_TIME();
//num_trans++;
//}
return(0);
}
/*
* prepare data and execute the new order transaction for one order
* officially, this is supposed to be simulated terminal I/O
*/
static int do_neword (int t_num)
{
int c_num;
int i,ret;
clock_t clk1,clk2;
double rt;
struct timespec tbuf1;
struct timespec tbuf2;
int w_id, d_id, c_id, ol_cnt;
int all_local = 1;
int notfound = MAXITEMS+1; /* valid item ids are numbered consecutively
[1..MAXITEMS] */
int rbk;
int itemid[MAX_NUM_ITEMS];
int supware[MAX_NUM_ITEMS];
int qty[MAX_NUM_ITEMS];
if(num_node==0){
w_id = RandomNumber(1, num_ware);
}else{
c_num = ((num_node * t_num)/num_conn); /* drop moduls */
w_id = RandomNumber(1 + (num_ware * c_num)/num_node,
(num_ware * (c_num + 1))/num_node);
}
d_id = RandomNumber(1, DIST_PER_WARE);
c_id = NURand(1023, 1, CUST_PER_DIST);
ol_cnt = RandomNumber(5, 15);
rbk = RandomNumber(1, 100);
for (i = 0; i < ol_cnt; i++) {
itemid[i] = NURand(8191, 1, MAXITEMS);
if ((i == ol_cnt - 1) && (rbk == 1)) {
itemid[i] = notfound;
}
if (RandomNumber(1, 100) != 1) {
supware[i] = w_id;
}
else {
supware[i] = other_ware(w_id);
all_local = 0;
}
qty[i] = RandomNumber(1, 10);
}
clk1 = clock_gettime(CLOCK_MONOTONIC, &tbuf1 );
for (i = 0; i < MAX_RETRY; i++) {
// printf("try times:%d",i);
ret = neword(t_num, w_id, d_id, c_id, ol_cnt, all_local, itemid, supware, qty);
clk2 = clock_gettime(CLOCK_MONOTONIC, &tbuf2 );
if(ret){
rt = (double)(tbuf2.tv_sec * 1000.0 + tbuf2.tv_nsec/1000000.0-tbuf1.tv_sec * 1000.0 - tbuf1.tv_nsec/1000000.0);
//printf("NOT : %.3f\n", rt);
if(rt > max_rt[0])
max_rt[0]=rt;
total_rt[0] += rt;
sb_percentile_update(&local_percentile, rt);
hist_inc(0, rt);
if(counting_on){
if( rt < rt_limit[0]){
success[0]++;
success2[0][t_num]++;
}else{
late[0]++;
late2[0][t_num]++;
}
}
return (1); /* end */
}else{
if(counting_on){
retry[0]++;
retry2[0][t_num]++;
}
}
}
if(counting_on){
retry[0]--;
retry2[0][t_num]--;
failure[0]++;
failure2[0][t_num]++;
}
return (0);
}
/*
* produce the id of a valid warehouse other than home_ware
* (assuming there is one)
*/
static int other_ware (int home_ware)
{
int tmp;
if (num_ware == 1) return home_ware;
while ((tmp = RandomNumber(1, num_ware)) == home_ware);
return tmp;
}
/*
* prepare data and execute payment transaction
*/
static int do_payment (int t_num)
{
int c_num;
int byname,i,ret;
clock_t clk1,clk2;
double rt;
struct timespec tbuf1;
struct timespec tbuf2;
int w_id, d_id, c_w_id, c_d_id, c_id, h_amount;
char c_last[17];
if(num_node==0){
w_id = RandomNumber(1, num_ware);
}else{
c_num = ((num_node * t_num)/num_conn); /* drop moduls */
w_id = RandomNumber(1 + (num_ware * c_num)/num_node,
(num_ware * (c_num + 1))/num_node);
}
d_id = RandomNumber(1, DIST_PER_WARE);
c_id = NURand(1023, 1, CUST_PER_DIST);
Lastname(NURand(255,0,999), c_last);
h_amount = RandomNumber(1,5000);
if (RandomNumber(1, 100) <= 60) {
byname = 1; /* select by last name */
}else{
byname = 0; /* select by customer id */
}
if (RandomNumber(1, 100) <= 85) {
c_w_id = w_id;
c_d_id = d_id;
}else{
c_w_id = other_ware(w_id);
c_d_id = RandomNumber(1, DIST_PER_WARE);
}
clk1 = clock_gettime(CLOCK_MONOTONIC, &tbuf1 );
for (i = 0; i < MAX_RETRY; i++) {
ret = payment(t_num, w_id, d_id, byname, c_w_id, c_d_id, c_id, c_last, h_amount);
clk2 = clock_gettime(CLOCK_MONOTONIC, &tbuf2 );
if(ret){
rt = (double)(tbuf2.tv_sec * 1000.0 + tbuf2.tv_nsec/1000000.0-tbuf1.tv_sec * 1000.0 - tbuf1.tv_nsec/1000000.0);
if(rt > max_rt[1])
max_rt[1]=rt;
total_rt[1] += rt;
hist_inc(1, rt);
if(counting_on){
if( rt < rt_limit[1]){
success[1]++;
success2[1][t_num]++;
}else{
late[1]++;
late2[1][t_num]++;
}
}
return (1); /* end */
}else{
if(counting_on){
retry[1]++;
retry2[1][t_num]++;
}
}
}
if(counting_on){
retry[1]--;
retry2[1][t_num]--;
failure[1]++;
failure2[1][t_num]++;
}
return (0);
}
/*
* prepare data and execute order status transaction
*/
static int do_ordstat (int t_num)
{
int c_num;
int byname,i,ret;
clock_t clk1,clk2;
double rt;
struct timespec tbuf1;
struct timespec tbuf2;
int w_id, d_id, c_id;
char c_last[16];
if(num_node==0){
w_id = RandomNumber(1, num_ware);
}else{
c_num = ((num_node * t_num)/num_conn); /* drop moduls */
w_id = RandomNumber(1 + (num_ware * c_num)/num_node,
(num_ware * (c_num + 1))/num_node);
}
d_id = RandomNumber(1, DIST_PER_WARE);
c_id = NURand(1023, 1, CUST_PER_DIST);
Lastname(NURand(255,0,999), c_last);
if (RandomNumber(1, 100) <= 60) {
byname = 1; /* select by last name */
}else{
byname = 0; /* select by customer id */
}
clk1 = clock_gettime(CLOCK_MONOTONIC, &tbuf1 );
for (i = 0; i < MAX_RETRY; i++) {
ret = ordstat(t_num, w_id, d_id, byname, c_id, c_last);
clk2 = clock_gettime(CLOCK_MONOTONIC, &tbuf2 );
if(ret){
rt = (double)(tbuf2.tv_sec * 1000.0 + tbuf2.tv_nsec/1000000.0-tbuf1.tv_sec * 1000.0 - tbuf1.tv_nsec/1000000.0);
if(rt > max_rt[2])
max_rt[2]=rt;
total_rt[2] += rt;
hist_inc(2, rt);
if(counting_on){
if( rt < rt_limit[2]){
success[2]++;
success2[2][t_num]++;
}else{
late[2]++;
late2[2][t_num]++;
}
}
return (1); /* end */
}else{
if(counting_on){
retry[2]++;
retry2[2][t_num]++;
}
}
}
if(counting_on){
retry[2]--;
retry2[2][t_num]--;
failure[2]++;
failure2[2][t_num]++;
}
return (0);
}
/*
* execute delivery transaction
*/
static int do_delivery (int t_num)
{
int c_num;
int i,ret;
clock_t clk1,clk2;
double rt;
struct timespec tbuf1;
struct timespec tbuf2;
int w_id, o_carrier_id;
if(num_node==0){
w_id = RandomNumber(1, num_ware);
}else{
c_num = ((num_node * t_num)/num_conn); /* drop moduls */
w_id = RandomNumber(1 + (num_ware * c_num)/num_node,
(num_ware * (c_num + 1))/num_node);
}
o_carrier_id = RandomNumber(1, 10);
clk1 = clock_gettime(CLOCK_MONOTONIC, &tbuf1 );
for (i = 0; i < MAX_RETRY; i++) {
ret = delivery(t_num, w_id, o_carrier_id);
clk2 = clock_gettime(CLOCK_MONOTONIC, &tbuf2 );
if(ret){
rt = (double)(tbuf2.tv_sec * 1000.0 + tbuf2.tv_nsec/1000000.0-tbuf1.tv_sec * 1000.0 - tbuf1.tv_nsec/1000000.0);
if(rt > max_rt[3])
max_rt[3]=rt;
total_rt[3] += rt;
hist_inc(3, rt );
if(counting_on){
if( rt < rt_limit[3]){
success[3]++;
success2[3][t_num]++;
}else{
late[3]++;
late2[3][t_num]++;
}
}
return (1); /* end */
}else{
if(counting_on){
retry[3]++;
retry2[3][t_num]++;
}
}
}
if(counting_on){
retry[3]--;
retry2[3][t_num]--;
failure[3]++;
failure2[3][t_num]++;
}
return (0);
}
/*
* prepare data and execute the stock level transaction
*/
static int do_slev (int t_num)
{
int c_num;
int i,ret;
clock_t clk1,clk2;
double rt;
struct timespec tbuf1;
struct timespec tbuf2;
int w_id, d_id, level;
if(num_node==0){
w_id = RandomNumber(1, num_ware);
}else{
c_num = ((num_node * t_num)/num_conn); /* drop moduls */
w_id = RandomNumber(1 + (num_ware * c_num)/num_node,
(num_ware * (c_num + 1))/num_node);
}
d_id = RandomNumber(1, DIST_PER_WARE);
level = RandomNumber(10, 20);
clk1 = clock_gettime(CLOCK_MONOTONIC, &tbuf1 );
for (i = 0; i < MAX_RETRY; i++) {
ret = slev(t_num, w_id, d_id, level);
clk2 = clock_gettime(CLOCK_MONOTONIC, &tbuf2 );
if(ret){
rt = (double)(tbuf2.tv_sec * 1000.0 + tbuf2.tv_nsec/1000000.0-tbuf1.tv_sec * 1000.0 - tbuf1.tv_nsec/1000000.0);
if(rt > max_rt[4])
max_rt[4]=rt;
total_rt[4] += rt;
hist_inc(4, rt );
if(counting_on){
if( rt < rt_limit[4]){
success[4]++;
success2[4][t_num]++;
}else{
late[4]++;
late2[4][t_num]++;
}
}
return (1); /* end */
}else{
if(counting_on){
retry[4]++;
retry2[4][t_num]++;
}
}
}
if(counting_on){
retry[4]--;
retry2[4][t_num]--;
failure[4]++;
failure2[4][t_num]++;
}
return (0);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,426 @@
/*
* -*-C-*-
* neword.pc
* corresponds to A.1 in appendix A
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sqlite3.h>
#include "spt_proc.h"
#include "tpc.h"
#define pick_dist_info(ol_dist_info,ol_supply_w_id) \
switch(ol_supply_w_id) { \
case 1: strncpy(ol_dist_info, s_dist_01, 25); break; \
case 2: strncpy(ol_dist_info, s_dist_02, 25); break; \
case 3: strncpy(ol_dist_info, s_dist_03, 25); break; \
case 4: strncpy(ol_dist_info, s_dist_04, 25); break; \
case 5: strncpy(ol_dist_info, s_dist_05, 25); break; \
case 6: strncpy(ol_dist_info, s_dist_06, 25); break; \
case 7: strncpy(ol_dist_info, s_dist_07, 25); break; \
case 8: strncpy(ol_dist_info, s_dist_08, 25); break; \
case 9: strncpy(ol_dist_info, s_dist_09, 25); break; \
case 10: strncpy(ol_dist_info, s_dist_10, 25); break; \
}
extern sqlite3 **ctx;
extern sqlite3_stmt ***stmt;
#define NNULL ((void *)0)
/*
* the new order transaction
*/
int neword( int t_num,
int w_id_arg, /* warehouse id */
int d_id_arg, /* district id */
int c_id_arg, /* customer id */
int o_ol_cnt_arg, /* number of items */
int o_all_local_arg, /* are all order lines local */
int itemid[], /* ids of items to be ordered */
int supware[], /* warehouses supplying items */
int qty[] /* quantity of each item */
)
{
int ret;
int w_id = w_id_arg;
int d_id = d_id_arg;
int c_id = c_id_arg;
int o_ol_cnt = o_ol_cnt_arg;
int o_all_local = o_all_local_arg;
float c_discount;
char c_last[17];
char c_credit[3];
float w_tax;
int d_next_o_id;
float d_tax;
char datetime[81];
int o_id;
char i_name[25];
float i_price;
char i_data[51];
int ol_i_id;
int s_quantity;
char s_data[51];
char s_dist_01[25];
char s_dist_02[25];
char s_dist_03[25];
char s_dist_04[25];
char s_dist_05[25];
char s_dist_06[25];
char s_dist_07[25];
char s_dist_08[25];
char s_dist_09[25];
char s_dist_10[25];
char ol_dist_info[25];
int ol_supply_w_id;
float ol_amount;
int ol_number;
int ol_quantity;
char iname[MAX_NUM_ITEMS][MAX_ITEM_LEN];
char bg[MAX_NUM_ITEMS];
float amt[MAX_NUM_ITEMS];
float price[MAX_NUM_ITEMS];
int stock[MAX_NUM_ITEMS];
float total = 0.0;
int min_num;
int i,j,tmp,swp;
int ol_num_seq[MAX_NUM_ITEMS];
int proceed = 0;
struct timespec tbuf1,tbuf_start;
clock_t clk1,clk_start;
sqlite3_stmt* sqlite_stmt;
int num_cols;
/* EXEC SQL WHENEVER NOT FOUND GOTO sqlerr;*/
/* EXEC SQL WHENEVER SQLERROR GOTO sqlerr;*/
/*EXEC SQL CONTEXT USE :ctx[t_num];*/
gettimestamp(datetime, STRFTIME_FORMAT, TIMESTAMP_LEN);
clk_start = clock_gettime(CLOCK_REALTIME, &tbuf_start );
proceed = 1;
/*EXEC_SQL SELECT c_discount, c_last, c_credit, w_tax
INTO :c_discount, :c_last, :c_credit, :w_tax
FROM customer, warehouse
WHERE w_id = :w_id
AND c_w_id = w_id
AND c_d_id = :d_id
AND c_id = :c_id;*/
sqlite_stmt = stmt[t_num][0];
sqlite3_bind_int64(sqlite_stmt, 1, w_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, c_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 4) goto sqlerr;
c_discount = sqlite3_column_double(sqlite_stmt, 0);
strcpy(c_last, sqlite3_column_text(sqlite_stmt, 1));
strcpy(c_credit, sqlite3_column_text(sqlite_stmt, 2));
w_tax = sqlite3_column_double(sqlite_stmt, 3);
}
sqlite3_reset(sqlite_stmt);
#ifdef DEBUG
printf("n %d\n",proceed);
#endif
proceed = 2;
/*EXEC_SQL SELECT d_next_o_id, d_tax INTO :d_next_o_id, :d_tax
FROM district
WHERE d_id = :d_id
AND d_w_id = :w_id
FOR UPDATE;*/
sqlite_stmt = stmt[t_num][1];
sqlite3_bind_int64(sqlite_stmt, 1, d_id);
sqlite3_bind_int64(sqlite_stmt, 2, w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 2) goto sqlerr;
d_next_o_id = sqlite3_column_int64(sqlite_stmt, 0);
d_tax = sqlite3_column_double(sqlite_stmt, 1);
}
sqlite3_reset(sqlite_stmt);
proceed = 3;
/*EXEC_SQL UPDATE district SET d_next_o_id = :d_next_o_id + 1
WHERE d_id = :d_id
AND d_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][2];
sqlite3_bind_int64(sqlite_stmt, 1, d_next_o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
o_id = d_next_o_id;
#ifdef DEBUG
printf("n %d\n",proceed);
#endif
proceed = 4;
/*EXEC_SQL INSERT INTO orders (o_id, o_d_id, o_w_id, o_c_id,
o_entry_d, o_ol_cnt, o_all_local)
VALUES(:o_id, :d_id, :w_id, :c_id,
:datetime,
:o_ol_cnt, :o_all_local);*/
sqlite_stmt = stmt[t_num][3];
// printf("prepared params oid:%d,did:%d,wid:%d",o_id,d_id,w_id);
sqlite3_bind_int64(sqlite_stmt, 1, o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
sqlite3_bind_int64(sqlite_stmt, 4, c_id);
sqlite3_bind_text(sqlite_stmt, 5, datetime, -1, SQLITE_STATIC);
sqlite3_bind_int64(sqlite_stmt, 6, o_ol_cnt);
sqlite3_bind_int64(sqlite_stmt, 7, o_all_local);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
#ifdef DEBUG
printf("n %d\n",proceed);
#endif
proceed = 5;
/* EXEC_SQL INSERT INTO new_orders (no_o_id, no_d_id, no_w_id)
VALUES (:o_id,:d_id,:w_id); */
sqlite_stmt = stmt[t_num][4];
sqlite3_bind_int64(sqlite_stmt, 1, o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
/* sort orders to avoid DeadLock */
for (i = 0; i < o_ol_cnt; i++) {
ol_num_seq[i]=i;
}
for (i = 0; i < (o_ol_cnt - 1); i++) {
tmp = (MAXITEMS + 1) * supware[ol_num_seq[i]] + itemid[ol_num_seq[i]];
min_num = i;
for ( j = i+1; j < o_ol_cnt; j++) {
if ( (MAXITEMS + 1) * supware[ol_num_seq[j]] + itemid[ol_num_seq[j]] < tmp ){
tmp = (MAXITEMS + 1) * supware[ol_num_seq[j]] + itemid[ol_num_seq[j]];
min_num = j;
}
}
if ( min_num != i ){
swp = ol_num_seq[min_num];
ol_num_seq[min_num] = ol_num_seq[i];
ol_num_seq[i] = swp;
}
}
for (ol_number = 1; ol_number <= o_ol_cnt; ol_number++) {
ol_supply_w_id = supware[ol_num_seq[ol_number - 1]];
ol_i_id = itemid[ol_num_seq[ol_number - 1]];
ol_quantity = qty[ol_num_seq[ol_number - 1]];
/* EXEC SQL WHENEVER NOT FOUND GOTO invaliditem; */
proceed = 6;
/*EXEC_SQL SELECT i_price, i_name, i_data
INTO :i_price, :i_name, :i_data
FROM item
WHERE i_id = :ol_i_id;*/
sqlite_stmt = stmt[t_num][5];
sqlite3_bind_int64(sqlite_stmt, 1, ol_i_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 3) goto sqlerr;
i_price = sqlite3_column_double(sqlite_stmt, 0);
strcpy(i_name, sqlite3_column_text(sqlite_stmt, 1));
strcpy(i_data, sqlite3_column_text(sqlite_stmt, 2));
}
sqlite3_reset(sqlite_stmt);
price[ol_num_seq[ol_number - 1]] = i_price;
strncpy(iname[ol_num_seq[ol_number - 1]], i_name, 25);
/* EXEC SQL WHENEVER NOT FOUND GOTO sqlerr; */
#ifdef DEBUG
printf("n %d\n",proceed);
#endif
proceed = 7;
/*EXEC_SQL SELECT s_quantity, s_data, s_dist_01, s_dist_02,
s_dist_03, s_dist_04, s_dist_05, s_dist_06,
s_dist_07, s_dist_08, s_dist_09, s_dist_10
INTO :s_quantity, :s_data, :s_dist_01, :s_dist_02,
:s_dist_03, :s_dist_04, :s_dist_05, :s_dist_06,
:s_dist_07, :s_dist_08, :s_dist_09, :s_dist_10
FROM stock
WHERE s_i_id = :ol_i_id
AND s_w_id = :ol_supply_w_id
FOR UPDATE;*/
sqlite_stmt = stmt[t_num][6];
sqlite3_bind_int64(sqlite_stmt, 1, ol_i_id);
sqlite3_bind_int64(sqlite_stmt, 2, ol_supply_w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 12) goto sqlerr;
s_quantity = sqlite3_column_int64(sqlite_stmt, 0);
strcpy(s_data, sqlite3_column_text(sqlite_stmt, 1));
strcpy(s_dist_01, sqlite3_column_text(sqlite_stmt, 2));
strcpy(s_dist_02, sqlite3_column_text(sqlite_stmt, 3));
strcpy(s_dist_03, sqlite3_column_text(sqlite_stmt, 4));
strcpy(s_dist_04, sqlite3_column_text(sqlite_stmt, 5));
strcpy(s_dist_05, sqlite3_column_text(sqlite_stmt, 6));
strcpy(s_dist_06, sqlite3_column_text(sqlite_stmt, 7));
strcpy(s_dist_07, sqlite3_column_text(sqlite_stmt, 8));
strcpy(s_dist_08, sqlite3_column_text(sqlite_stmt, 9));
strcpy(s_dist_09, sqlite3_column_text(sqlite_stmt, 10));
strcpy(s_dist_10, sqlite3_column_text(sqlite_stmt, 11));
}
sqlite3_reset(sqlite_stmt);
pick_dist_info(ol_dist_info, d_id); /* pick correct
* s_dist_xx */
stock[ol_num_seq[ol_number - 1]] = s_quantity;
if ((strstr(i_data, "original") != NULL) &&
(strstr(s_data, "original") != NULL))
bg[ol_num_seq[ol_number - 1]] = 'B';
else
bg[ol_num_seq[ol_number - 1]] = 'G';
if (s_quantity > ol_quantity)
s_quantity = s_quantity - ol_quantity;
else
s_quantity = s_quantity - ol_quantity + 91;
#ifdef DEBUG
printf("n %d\n",proceed);
#endif
proceed = 8;
/*EXEC_SQL UPDATE stock SET s_quantity = :s_quantity
WHERE s_i_id = :ol_i_id
AND s_w_id = :ol_supply_w_id;*/
sqlite_stmt = stmt[t_num][7];
sqlite3_bind_int64(sqlite_stmt, 1, s_quantity);
sqlite3_bind_int64(sqlite_stmt, 2, ol_i_id);
sqlite3_bind_int64(sqlite_stmt, 3, ol_supply_w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
ol_amount = ol_quantity * i_price * (1 + w_tax + d_tax) * (1 - c_discount);
amt[ol_num_seq[ol_number - 1]] = ol_amount;
total += ol_amount;
#ifdef DEBUG
printf("n %d\n",proceed);
#endif
proceed = 9;
/*EXEC_SQL INSERT INTO order_line (ol_o_id, ol_d_id, ol_w_id,
ol_number, ol_i_id,
ol_supply_w_id, ol_quantity,
ol_amount, ol_dist_info)
VALUES (:o_id, :d_id, :w_id, :ol_number, :ol_i_id,
:ol_supply_w_id, :ol_quantity, :ol_amount,
:ol_dist_info);*/
sqlite_stmt = stmt[t_num][8];
sqlite3_bind_int64(sqlite_stmt, 1, o_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
sqlite3_bind_int64(sqlite_stmt, 3, w_id);
sqlite3_bind_int64(sqlite_stmt, 4, ol_number);
sqlite3_bind_int64(sqlite_stmt, 5, ol_i_id);
sqlite3_bind_int64(sqlite_stmt, 6, ol_supply_w_id);
sqlite3_bind_int64(sqlite_stmt, 7, ol_amount);
sqlite3_bind_double(sqlite_stmt, 8, ol_supply_w_id);
sqlite3_bind_text(sqlite_stmt, 9, ol_dist_info, -1, SQLITE_STATIC);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
} /* End Order Lines */
#ifdef DEBUG
printf("insert 3\n");
fflush(stdout);
#endif
/*EXEC_SQL COMMIT WORK;*/
//if( sqlite3_exec(ctx[t_num], "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
clk1 = clock_gettime(CLOCK_REALTIME, &tbuf1 );
return (1);
invaliditem:
/*EXEC_SQL ROLLBACK WORK;*/
if( sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
/* printf("Item number is not valid\n"); */
return (1); /* OK? */
sqlerr:
fprintf(stderr,"neword %d:%d\n",t_num,proceed);
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],mysql_stmt);
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerrerr;*/
/*EXEC_SQL ROLLBACK WORK;*/
sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL);
sqlerrerr:
return (0);
}

View File

@ -0,0 +1,255 @@
/*
* -*-C-*-
* ordstat.pc
* corresponds to A.3 in appendix A
*/
#include <string.h>
#include <stdio.h>
#include <sqlite3.h>
#include "spt_proc.h"
#include "tpc.h"
extern sqlite3 **ctx;
extern sqlite3_stmt ***stmt;
/*
* the order status transaction
*/
int ordstat( int t_num,
int w_id_arg, /* warehouse id */
int d_id_arg, /* district id */
int byname, /* select by c_id or c_last? */
int c_id_arg, /* customer id */
char c_last_arg[] /* customer last name, format? */
)
{
int ret;
int w_id = w_id_arg;
int d_id = d_id_arg;
int c_id = c_id_arg;
int c_d_id = d_id;
int c_w_id = w_id;
char c_first[17];
char c_middle[3];
char c_last[17];
float c_balance;
int o_id;
char o_entry_d[25];
int o_carrier_id;
int ol_i_id;
int ol_supply_w_id;
int ol_quantity;
float ol_amount;
char ol_delivery_d[25];
int namecnt;
int n;
int proceed = 0;
sqlite3_stmt *sqlite_stmt;
int num_cols;
int bytes;
/*EXEC SQL WHENEVER NOT FOUND GOTO sqlerr;*/
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerr;*/
if (byname) {
strcpy(c_last, c_last_arg);
proceed = 1;
/*EXEC_SQL SELECT count(c_id)
INTO :namecnt
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_last = :c_last;*/
sqlite_stmt = stmt[t_num][20];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_text(sqlite_stmt, 3, c_last, -1, SQLITE_STATIC);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
namecnt = sqlite3_column_int64(sqlite_stmt, 0);
}
sqlite3_reset(sqlite_stmt);
proceed = 2;
/*EXEC_SQL DECLARE c_byname_o CURSOR FOR
SELECT c_balance, c_first, c_middle, c_last
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_last = :c_last
ORDER BY c_first;
proceed = 3;
EXEC_SQL OPEN c_byname_o;*/
sqlite_stmt = stmt[t_num][21];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_text(sqlite_stmt, 3, c_last, -1, SQLITE_STATIC);
if (namecnt % 2)
namecnt++; /* Locate midpoint customer; */
for (n = 0; n < namecnt / 2; n++) {
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 4) goto sqlerr;
c_balance = sqlite3_column_double(sqlite_stmt, 0);
strcpy(c_first, sqlite3_column_text(sqlite_stmt, 1));
strcpy(c_middle, sqlite3_column_text(sqlite_stmt, 2));
strcpy(c_last, sqlite3_column_text(sqlite_stmt, 3));
}
}
sqlite3_reset(sqlite_stmt);
proceed = 5;
/*EXEC_SQL CLOSE c_byname_o;*/
} else { /* by number */
proceed = 6;
/*EXEC_SQL SELECT c_balance, c_first, c_middle, c_last
INTO :c_balance, :c_first, :c_middle, :c_last
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_id = :c_id;*/
sqlite_stmt = stmt[t_num][22];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_text(sqlite_stmt, 3, c_last, -1, SQLITE_STATIC);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 4) goto sqlerr;
c_balance = sqlite3_column_double(sqlite_stmt, 0);
strcpy(c_first, sqlite3_column_text(sqlite_stmt, 1));
strcpy(c_middle, sqlite3_column_text(sqlite_stmt, 2));
strcpy(c_last, sqlite3_column_text(sqlite_stmt, 3));
}
sqlite3_reset(sqlite_stmt);
}
/* find the most recent order for this customer */
proceed = 7;
/*EXEC_SQL SELECT o_id, o_entry_d, COALESCE(o_carrier_id,0)
INTO :o_id, :o_entry_d, :o_carrier_id
FROM orders
WHERE o_w_id = :c_w_id
AND o_d_id = :c_d_id
AND o_c_id = :c_id
AND o_id = (SELECT MAX(o_id)
FROM orders
WHERE o_w_id = :c_w_id
AND o_d_id = :c_d_id
AND o_c_id = :c_id);*/
sqlite_stmt = stmt[t_num][23];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 3, c_id);
sqlite3_bind_int64(sqlite_stmt, 4, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 5, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 6, c_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 3) goto sqlerr;
o_id = sqlite3_column_int64(sqlite_stmt, 0);
strcpy(o_entry_d, sqlite3_column_text(sqlite_stmt, 1));
o_carrier_id = sqlite3_column_int64(sqlite_stmt, 2);
}
/* find all the items in this order */
sqlite3_reset(sqlite_stmt);
proceed = 8;
/*EXEC_SQL DECLARE c_items CURSOR FOR
SELECT ol_i_id, ol_supply_w_id, ol_quantity, ol_amount,
ol_delivery_d
FROM order_line
WHERE ol_w_id = :c_w_id
AND ol_d_id = :c_d_id
AND ol_o_id = :o_id;*/
sqlite_stmt = stmt[t_num][24];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 3, o_id);
for(;;) {
ret = sqlite3_step(sqlite_stmt);
if (ret == SQLITE_DONE)
break;
if (ret == SQLITE_ROW) {
proceed = 10;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 5) goto sqlerr;
ol_i_id = sqlite3_column_int64(sqlite_stmt, 0);
ol_supply_w_id = sqlite3_column_int64(sqlite_stmt, 1);
ol_quantity = sqlite3_column_int64(sqlite_stmt, 2);
ol_amount = sqlite3_column_double(sqlite_stmt, 3);
bytes = sqlite3_column_bytes(sqlite_stmt, 4);
if (bytes)
strcpy(ol_delivery_d, sqlite3_column_text(sqlite_stmt, 4));
}
else
goto sqlerr;
}
sqlite3_reset(sqlite_stmt);
/*proceed = 9;
EXEC_SQL OPEN c_items;
EXEC SQL WHENEVER NOT FOUND GOTO done;*/
done:
/*EXEC_SQL CLOSE c_items;*/
/*EXEC_SQL COMMIT WORK;*/
//if( sqlite3_exec(ctx[t_num], "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
return (1);
sqlerr:
fprintf(stderr, "ordstat %d:%d\n",t_num,proceed);
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],mysql_stmt);
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerrerr;*/
/*EXEC_SQL ROLLBACK WORK;*/
sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL);
sqlerrerr:
return (0);
}

View File

@ -0,0 +1,403 @@
/*
* -*-C-*-
* payment.pc
* corresponds to A.2 in appendix A
*/
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <sqlite3.h>
#include "spt_proc.h"
#include "tpc.h"
extern sqlite3 **ctx;
extern sqlite3_stmt ***stmt;
#define NNULL ((void *)0)
/*
* the payment transaction
*/
int payment( int t_num,
int w_id_arg, /* warehouse id */
int d_id_arg, /* district id */
int byname, /* select by c_id or c_last? */
int c_w_id_arg,
int c_d_id_arg,
int c_id_arg, /* customer id */
char c_last_arg[], /* customer last name */
float h_amount_arg /* payment amount */
)
{
int ret;
int w_id = w_id_arg;
int d_id = d_id_arg;
int c_id = c_id_arg;
char w_name[11];
char w_street_1[21];
char w_street_2[21];
char w_city[21];
char w_state[3];
char w_zip[10];
int c_d_id = c_d_id_arg;
int c_w_id = c_w_id_arg;
char c_first[17];
char c_middle[3];
char c_last[17];
char c_street_1[21];
char c_street_2[21];
char c_city[21];
char c_state[3];
char c_zip[10];
char c_phone[17];
char c_since[20];
char c_credit[4];
int c_credit_lim;
float c_discount;
float c_balance;
char c_data[502];
char c_new_data[502];
float h_amount = h_amount_arg;
char h_data[26];
char d_name[11];
char d_street_1[21];
char d_street_2[21];
char d_city[21];
char d_state[3];
char d_zip[10];
int namecnt;
char datetime[81];
int n;
int proceed = 0;
int bytes;
sqlite3_stmt *sqlite_stmt;
int num_cols;
/* EXEC SQL WHENEVER NOT FOUND GOTO sqlerr; */
/* EXEC SQL WHENEVER SQLERROR GOTO sqlerr; */
gettimestamp(datetime, STRFTIME_FORMAT, TIMESTAMP_LEN);
proceed = 1;
/*EXEC_SQL UPDATE warehouse SET w_ytd = w_ytd + :h_amount
WHERE w_id =:w_id;*/
sqlite_stmt = stmt[t_num][9];
sqlite3_bind_double(sqlite_stmt, 1, h_amount);
sqlite3_bind_int64(sqlite_stmt, 2, w_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
proceed = 2;
/*EXEC_SQL SELECT w_street_1, w_street_2, w_city, w_state, w_zip,
w_name
INTO :w_street_1, :w_street_2, :w_city, :w_state,
:w_zip, :w_name
FROM warehouse
WHERE w_id = :w_id;*/
sqlite_stmt = stmt[t_num][10];
sqlite3_bind_int64(sqlite_stmt, 1, w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 6) goto sqlerr;
strcpy(w_street_1, sqlite3_column_text(sqlite_stmt, 0));
strcpy(w_street_2, sqlite3_column_text(sqlite_stmt, 1));
strcpy(w_city, sqlite3_column_text(sqlite_stmt, 2));
strcpy(w_state, sqlite3_column_text(sqlite_stmt, 3));
strcpy(w_zip, sqlite3_column_text(sqlite_stmt, 4));
strcpy(w_name, sqlite3_column_text(sqlite_stmt, 5));
}
sqlite3_reset(sqlite_stmt);
proceed = 3;
/*EXEC_SQL UPDATE district SET d_ytd = d_ytd + :h_amount
WHERE d_w_id = :w_id
AND d_id = :d_id;*/
sqlite_stmt = stmt[t_num][11];
sqlite3_bind_double(sqlite_stmt, 1, h_amount);
sqlite3_bind_int64(sqlite_stmt, 2, w_id);
sqlite3_bind_int64(sqlite_stmt, 3, d_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
proceed = 4;
/*EXEC_SQL SELECT d_street_1, d_street_2, d_city, d_state, d_zip,
d_name
INTO :d_street_1, :d_street_2, :d_city, :d_state,
:d_zip, :d_name
FROM district
WHERE d_w_id = :w_id
AND d_id = :d_id;*/
sqlite_stmt = stmt[t_num][12];
sqlite3_bind_int64(sqlite_stmt, 1, w_id);
sqlite3_bind_int64(sqlite_stmt, 2, d_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 6) goto sqlerr;
strcpy(d_street_1, sqlite3_column_text(sqlite_stmt, 0));
strcpy(d_street_2, sqlite3_column_text(sqlite_stmt, 1));
strcpy(d_city, sqlite3_column_text(sqlite_stmt, 2));
strcpy(d_state, sqlite3_column_text(sqlite_stmt, 3));
strcpy(d_zip, sqlite3_column_text(sqlite_stmt, 4));
strcpy(d_name, sqlite3_column_text(sqlite_stmt, 5));
}
sqlite3_reset(sqlite_stmt);
if (byname) {
strcpy(c_last, c_last_arg);
proceed = 5;
/*EXEC_SQL SELECT count(c_id)
INTO :namecnt
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_last = :c_last;*/
sqlite_stmt = stmt[t_num][13];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_text(sqlite_stmt, 3, c_last, -1, SQLITE_STATIC);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
namecnt = sqlite3_column_int64(sqlite_stmt, 0);
}
sqlite3_reset(sqlite_stmt);
/*EXEC_SQL DECLARE c_byname_p CURSOR FOR
SELECT c_id
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_last = :c_last
ORDER BY c_first;
EXEC_SQL OPEN c_byname_p;*/
sqlite_stmt = stmt[t_num][14];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_text(sqlite_stmt, 3, c_last, -1, SQLITE_STATIC);
if (namecnt % 2)
namecnt++;
for (n = 0; n < namecnt / 2; n++) {
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
c_id = sqlite3_column_int64(sqlite_stmt, 0);
}
}
sqlite3_reset(sqlite_stmt);
}
proceed = 6;
/*EXEC_SQL SELECT c_first, c_middle, c_last, c_street_1,
c_street_2, c_city, c_state, c_zip, c_phone,
c_credit, c_credit_lim, c_discount, c_balance,
c_since
INTO :c_first, :c_middle, :c_last, :c_street_1,
:c_street_2, :c_city, :c_state, :c_zip, :c_phone,
:c_credit, :c_credit_lim, :c_discount, :c_balance,
:c_since
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_id = :c_id
FOR UPDATE;*/
sqlite_stmt = stmt[t_num][15];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 3, c_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 14) goto sqlerr;
strcpy(c_first, sqlite3_column_text(sqlite_stmt, 0));
strcpy(c_middle, sqlite3_column_text(sqlite_stmt, 1));
strcpy(c_last, sqlite3_column_text(sqlite_stmt, 2));
strcpy(c_street_1, sqlite3_column_text(sqlite_stmt, 3));
strcpy(c_street_2, sqlite3_column_text(sqlite_stmt, 4));
strcpy(c_city, sqlite3_column_text(sqlite_stmt, 5));
strcpy(c_state, sqlite3_column_text(sqlite_stmt, 6));
strcpy(c_zip, sqlite3_column_text(sqlite_stmt, 7));
strcpy(c_phone, sqlite3_column_text(sqlite_stmt, 8));
strcpy(c_credit, sqlite3_column_text(sqlite_stmt, 9));
c_credit_lim = sqlite3_column_int64(sqlite_stmt, 10);
c_discount = sqlite3_column_double(sqlite_stmt, 11);
c_balance = sqlite3_column_double(sqlite_stmt, 12);
strcpy(c_since, sqlite3_column_text(sqlite_stmt, 13));
}
sqlite3_reset(sqlite_stmt);
c_balance = c_balance - h_amount;
c_credit[2] = '\0';
if (strstr(c_credit, "BC")) {
proceed = 7;
/*EXEC_SQL SELECT c_data
INTO :c_data
FROM customer
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_id = :c_id; */
sqlite_stmt = stmt[t_num][16];
sqlite3_bind_int64(sqlite_stmt, 1, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 3, c_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
strcpy(c_data, sqlite3_column_text(sqlite_stmt, 0));
}
sqlite3_reset(sqlite_stmt);
sprintf(c_new_data,
"| %4d %2d %4d %2d %4d $%7.2f %12c %24c",
c_id, c_d_id, c_w_id, d_id,
w_id, h_amount,
datetime, c_data);
strncat(c_new_data, c_data,
500 - strlen(c_new_data));
c_new_data[500] = '\0';
proceed = 8;
/*EXEC_SQL UPDATE customer
SET c_balance = :c_balance, c_data = :c_new_data
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_id = :c_id;*/
sqlite_stmt = stmt[t_num][17];
sqlite3_bind_double(sqlite_stmt, 1, c_balance);
sqlite3_bind_text(sqlite_stmt, 2, c_data, -1, SQLITE_STATIC);
sqlite3_bind_int64(sqlite_stmt, 3, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 4, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 5, c_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
} else {
proceed = 9;
/*EXEC_SQL UPDATE customer
SET c_balance = :c_balance
WHERE c_w_id = :c_w_id
AND c_d_id = :c_d_id
AND c_id = :c_id;*/
sqlite_stmt = stmt[t_num][18];
sqlite3_bind_double(sqlite_stmt, 1, c_balance);
sqlite3_bind_int64(sqlite_stmt, 2, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 3, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 4, c_id);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
}
strncpy(h_data, w_name, 10);
h_data[10] = '\0';
strncat(h_data, d_name, 10);
h_data[20] = ' ';
h_data[21] = ' ';
h_data[22] = ' ';
h_data[23] = ' ';
h_data[24] = '\0';
proceed = 10;
/*EXEC_SQL INSERT INTO history(h_c_d_id, h_c_w_id, h_c_id, h_d_id,
h_w_id, h_date, h_amount, h_data)
VALUES(:c_d_id, :c_w_id, :c_id, :d_id,
:w_id,
:datetime,
:h_amount, :h_data);*/
sqlite_stmt = stmt[t_num][19];
sqlite3_bind_int64(sqlite_stmt, 1, c_d_id);
sqlite3_bind_int64(sqlite_stmt, 2, c_w_id);
sqlite3_bind_int64(sqlite_stmt, 3, c_id);
sqlite3_bind_int64(sqlite_stmt, 4, d_id);
sqlite3_bind_int64(sqlite_stmt, 5, w_id);
sqlite3_bind_text(sqlite_stmt, 6, datetime, -1, SQLITE_STATIC);
sqlite3_bind_double(sqlite_stmt, 7, h_amount);
sqlite3_bind_text(sqlite_stmt, 8, h_data, -1, SQLITE_STATIC);
if (sqlite3_step(sqlite_stmt) != SQLITE_DONE) goto sqlerr;
sqlite3_reset(sqlite_stmt);
/*EXEC_SQL COMMIT WORK;*/
//if( sqlite3_exec(ctx[t_num], "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
return (1);
sqlerr:
fprintf(stderr, "payment %d:%d\n",t_num,proceed);
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],mysql_stmt);
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerrerr;*/
/*EXEC_SQL ROLLBACK WORK;*/
sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL);
sqlerrerr:
return (0);
}

View File

@ -0,0 +1,153 @@
/*
* rthist.c
* RT-histgram
*/
#include <stdio.h>
#include <sys/time.h>
#define MAXREC 20
#define REC_PER_SEC 1000
extern double max_rt[];
extern double cur_max_rt[];
// int total_hist[5][MAXREC * REC_PER_SEC];
// int cur_hist[5][MAXREC * REC_PER_SEC];
int **total_hist=NULL;
int ** cur_hist=NULL;
/* initialize */
void hist_init()
{
//
if (total_hist==NULL||cur_hist==NULL){
total_hist=malloc(20);
cur_hist=malloc(20);
for (int i=0;i<5;i++){
total_hist[i]=malloc(20000*4);
cur_hist[i]=malloc(20000*4);
}
}
//
int i,j;
for( i=0; i<5; i++){
for( j=0; j<(MAXREC * REC_PER_SEC); j++){
total_hist[i][j] = cur_hist[i][j] = 0;
}
}
}
/* incliment matched one */
void hist_inc( int transaction, double rtclk )
{
int i;
i = ( rtclk * (double)REC_PER_SEC );
if(i >= (MAXREC * REC_PER_SEC)){
i = (MAXREC * REC_PER_SEC) - 1;
}
if (rtclk > cur_max_rt[transaction]) cur_max_rt[transaction] = rtclk;
++cur_hist[transaction][i];
//printf("In: %.3f, trx: %d, Added %d\n", rtclk, transaction, i);
}
/* check point, add on total histgram, return 90% line */
double hist_ckp( int transaction )
{
int i;
int total,tmp,line,line_set;
total = tmp = line_set = 0;
line = MAXREC * REC_PER_SEC;
for( i=0; i<(MAXREC * REC_PER_SEC); i++){
total += cur_hist[transaction][i];
//total += i;
}
for( i=0; i<(MAXREC * REC_PER_SEC); i++){
tmp += cur_hist[transaction][i];
//tmp += i;
total_hist[transaction][i] += cur_hist[transaction][i];
cur_hist[transaction][i] = 0;
if (( tmp >= (total*99/100) ) && (line_set ==0)){
line = i;
line_set=1;
}
}
//printf("CKP: trx: %d line: %d total: %d tmp: %d ret: %.3f\n", transaction, line, total, tmp,(double)(line)/(double)(REC_PER_SEC));
return ( (double)(line)/(double)(REC_PER_SEC) );
}
void hist_report()
{
int i,j;
int total[5],tmp[5],line[5];
for( j=0; j<5; j++){
total[j] = tmp[j] = 0;
line[j] = MAXREC * REC_PER_SEC;
for( i=0; i<(MAXREC * REC_PER_SEC); i++){
total[j] += total_hist[j][i];
}
for( i=(MAXREC * REC_PER_SEC)-1; i >= 0 ; i--){
tmp[j] += total_hist[j][i];
if( (tmp[j] * 10) <= total[j] ){
line[j] = i;
}
}
}
printf("\n<RT Histogram>\n");
for( j=0; j<5; j++){
switch(j){
case 0:
printf("\n1.New-Order\n\n");
break;
case 1:
printf("\n2.Payment\n\n");
break;
case 2:
printf("\n3.Order-Status\n\n");
break;
case 3:
printf("\n4.Delivery\n\n");
break;
case 4:
printf("\n5.Stock-Level\n\n");
}
for( i=0; (i<(MAXREC * REC_PER_SEC))&&(i <= line[j]*4); i++){
printf("%3.2f, %6d\n",(double)(i+1)/(double)(REC_PER_SEC),total_hist[j][i]);
}
printf("\n");
}
printf("\n<90th Percentile RT (MaxRT)>\n");
for( j=0; j<5; j++){
switch(j){
case 0:
printf(" New-Order : ");
break;
case 1:
printf(" Payment : ");
break;
case 2:
printf("Order-Status : ");
break;
case 3:
printf(" Delivery : ");
break;
case 4:
printf(" Stock-Level : ");
}
printf("%3.2f (%.2f)\n",(double)(line[j])/(double)(REC_PER_SEC),max_rt[j]);
}
}

View File

@ -0,0 +1,8 @@
/*
* rthist.h
*/
void hist_init();
void hist_inc( int transaction, double rtclk );
double hist_ckp( int transaction );
void hist_report();

View File

@ -0,0 +1,119 @@
/* Copyright (C) 2011 Alexey Kopytov.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef _WIN32
#include "sb_win.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <pthread.h>
#include "sb_percentile.h"
int sb_percentile_init(sb_percentile_t *percentile,
unsigned int size, double range_min, double range_max)
{
percentile->values = (unsigned long long *)
calloc(size, sizeof(unsigned long long));
percentile->tmp = (unsigned long long *)
calloc(size, sizeof(unsigned long long));
if (percentile->values == NULL || percentile->tmp == NULL)
{
//log_text(LOG_FATAL, "Cannot allocate values array, size = %u", size);
return 1;
}
percentile->range_deduct = log(range_min);
percentile->range_mult = (size - 1) / (log(range_max) -
percentile->range_deduct);
percentile->range_min = range_min;
percentile->range_max = range_max;
percentile->size = size;
percentile->total = 0;
pthread_mutex_init(&percentile->mutex, NULL);
return 0;
}
void sb_percentile_update(sb_percentile_t *percentile, double value)
{
unsigned int n;
if (value < percentile->range_min)
value= percentile->range_min;
else if (value > percentile->range_max)
value= percentile->range_max;
n = floor((log(value) - percentile->range_deduct) * percentile->range_mult
+ 0.5);
pthread_mutex_lock(&percentile->mutex);
percentile->total++;
percentile->values[n]++;
pthread_mutex_unlock(&percentile->mutex);
}
double sb_percentile_calculate(sb_percentile_t *percentile, double percent)
{
unsigned long long ncur, nmax;
unsigned int i;
pthread_mutex_lock(&percentile->mutex);
if (percentile->total == 0)
{
pthread_mutex_unlock(&percentile->mutex);
return 0.0;
}
memcpy(percentile->tmp, percentile->values,
percentile->size * sizeof(unsigned long long));
nmax = floor(percentile->total * percent / 100 + 0.5);
pthread_mutex_unlock(&percentile->mutex);
ncur = percentile->tmp[0];
for (i = 1; i < percentile->size; i++)
{
ncur += percentile->tmp[i];
if (ncur >= nmax)
break;
}
return exp((i) / percentile->range_mult + percentile->range_deduct);
}
void sb_percentile_reset(sb_percentile_t *percentile)
{
pthread_mutex_lock(&percentile->mutex);
percentile->total = 0;
memset(percentile->values, 0, percentile->size * sizeof(unsigned long long));
pthread_mutex_unlock(&percentile->mutex);
}
void sb_percentile_done(sb_percentile_t *percentile)
{
pthread_mutex_destroy(&percentile->mutex);
free(percentile->values);
free(percentile->tmp);
}

View File

@ -0,0 +1,50 @@
/* Copyright (C) 2011 Alexey Kopytov.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SB_PERCENTILE_H
#define SB_PERCENTILE_H
#include "timers.h"
# include <pthread.h>
typedef struct {
unsigned long long *values;
unsigned long long *tmp;
unsigned long long total;
unsigned int size;
double range_min;
double range_max;
double range_deduct;
double range_mult;
pthread_mutex_t mutex;
} sb_percentile_t;
int sb_percentile_init(sb_percentile_t *percentile,
unsigned int size, double range_min, double range_max);
void sb_percentile_update(sb_percentile_t *percentile, double value);
double sb_percentile_calculate(sb_percentile_t *percentile, double percent);
void sb_percentile_reset(sb_percentile_t *percentile);
void sb_percentile_done(sb_percentile_t *percentile);
#endif

View File

@ -0,0 +1,81 @@
/*
* sequence.c
* manage sequence shared by threads
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
/* weight */
static int no;
static int py;
static int os;
static int dl;
static int sl;
static int total;
static pthread_mutex_t mutex;
static int *seq;
static int next_num;
static void shuffle()
{
int i,j,rnd,tmp;
for( i=0, j=0; i < no ; i++, j++ ){
seq[j]=0;
}
for( i=0; i < py ; i++, j++){
seq[j]=1;
}
for( i=0; i < os ; i++, j++){
seq[j]=2;
}
for( i=0; i < dl ; i++, j++){
seq[j]=3;
}
for( i=0; i < sl ; i++, j++){
seq[j]=4;
}
for( i=0, j = total - 1; j>0; i++, j--){
rnd = rand()%(j+1);
tmp = seq[rnd+i];
seq[rnd+i] = seq[i];
seq[i] = tmp;
}
}
void seq_init( int n, int p, int o, int d, int s )
{
pthread_mutex_init( &mutex, NULL );
no = n;
py = p;
os = o;
dl = d;
sl = s;
total = n + p + o + d + s;
seq = malloc( sizeof(int) * total );
shuffle();
next_num = 0;
}
int seq_get()
{
int retval;
pthread_mutex_lock( &mutex );
if(next_num >= total){
shuffle();
next_num = 0;
}
retval = seq[next_num];
++next_num;
pthread_mutex_unlock( &mutex );
return(retval);
}

View File

@ -0,0 +1,6 @@
/*
* sequence.h
*/
void seq_init( int n, int p, int o, int d, int s );
int seq_get();

View File

@ -0,0 +1,142 @@
/*
* -*-C-*-
* slev.pc
* corresponds to A.5 in appendix A
*/
#include <string.h>
#include <stdio.h>
#include <sqlite3.h>
#include "spt_proc.h"
#include "tpc.h"
extern sqlite3 **ctx;
extern sqlite3_stmt ***stmt;
/*
* the stock level transaction
*/
int slev( int t_num,
int w_id_arg, /* warehouse id */
int d_id_arg, /* district id */
int level_arg /* stock level */
)
{
int ret;
int w_id = w_id_arg;
int d_id = d_id_arg;
int level = level_arg;
int d_next_o_id;
int i_count;
int ol_i_id;
sqlite3_stmt *sqlite_stmt;
sqlite3_stmt *sqlite_stmt2;
int num_cols;
/*EXEC SQL WHENEVER NOT FOUND GOTO sqlerr;*/
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerr;*/
/* find the next order id */
#ifdef DEBUG
printf("select 1\n");
#endif
/*EXEC_SQL SELECT d_next_o_id
INTO :d_next_o_id
FROM district
WHERE d_id = :d_id
AND d_w_id = :w_id;*/
sqlite_stmt = stmt[t_num][32];
sqlite3_bind_int64(sqlite_stmt, 1, d_id);
sqlite3_bind_int64(sqlite_stmt, 2, w_id);
ret = sqlite3_step(sqlite_stmt);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
d_next_o_id = sqlite3_column_int64(sqlite_stmt, 0);
}
sqlite3_reset(sqlite_stmt);
/* find the most recent 20 orders for this district */
/*EXEC_SQL DECLARE ord_line CURSOR FOR
SELECT DISTINCT ol_i_id
FROM order_line
WHERE ol_w_id = :w_id
AND ol_d_id = :d_id
AND ol_o_id < :d_next_o_id
AND ol_o_id >= (:d_next_o_id - 20);
EXEC_SQL OPEN ord_line;
EXEC SQL WHENEVER NOT FOUND GOTO done;*/
sqlite_stmt = stmt[t_num][33];
sqlite3_bind_int64(sqlite_stmt, 1, d_id);
sqlite3_bind_int64(sqlite_stmt, 2, w_id);
sqlite3_bind_int64(sqlite_stmt, 3, d_next_o_id);
sqlite3_bind_int64(sqlite_stmt, 4, d_next_o_id);
while (sqlite3_step(sqlite_stmt) != SQLITE_DONE) {
num_cols = sqlite3_column_count(sqlite_stmt);
if (num_cols != 1) goto sqlerr;
ol_i_id = sqlite3_column_int64(sqlite_stmt, 0);
/*EXEC_SQL SELECT count(*) INTO :i_count
FROM stock
WHERE s_w_id = :w_id
AND s_i_id = :ol_i_id
AND s_quantity < :level;*/
sqlite_stmt2 = stmt[t_num][34];
sqlite3_bind_int64(sqlite_stmt, 1, w_id);
sqlite3_bind_int64(sqlite_stmt, 2, ol_i_id);
sqlite3_bind_int64(sqlite_stmt, 3, level);
ret = sqlite3_step(sqlite_stmt2);
if (ret != SQLITE_DONE) {
if (ret != SQLITE_ROW) goto sqlerr;
num_cols = sqlite3_column_count(sqlite_stmt2);
if (num_cols != 1) goto sqlerr;
i_count = sqlite3_column_int64(sqlite_stmt2, 0);
}
sqlite3_reset(sqlite_stmt2);
}
sqlite3_reset(sqlite_stmt);
done:
/*EXEC_SQL CLOSE ord_line;*/
/*EXEC_SQL COMMIT WORK;*/
//if( sqlite3_exec(ctx[t_num], "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
return (1);
sqlerr:
fprintf(stderr,"slev\n");
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],mysql_stmt);
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerrerr;*/
/*EXEC_SQL ROLLBACK WORK;*/
sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL);
return (0);
sqlerr2:
fprintf(stderr,"slev\n");
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],mysql_stmt2);
/*EXEC SQL WHENEVER SQLERROR GOTO sqlerrerr;*/
/*EXEC_SQL ROLLBACK WORK;*/
//mysql_stmt_free_result(mysql_stmt);
//mysql_rollback(ctx[t_num]);
sqlite3_exec(ctx[t_num], "ROLLBACK;", NULL, NULL, NULL);
return (0);
}

View File

@ -0,0 +1,30 @@
/*
* spt_proc.pc
* support routines for the proc tpcc implementation
*/
#include <sqlite3.h>
#include <stdio.h>
/*
* report error
*/
int error(
sqlite3 *sqlite,
sqlite3_stmt *sqlite_stmt
)
{
/*
if(mysql_stmt) {
printf("\n%d, %s, %s", mysql_stmt_errno(mysql_stmt),
mysql_stmt_sqlstate(mysql_stmt), mysql_stmt_error(mysql_stmt) );
}
*/
if(sqlite){
printf("%s: error!\n", __func__);
}
return (0);
}

View File

@ -0,0 +1,5 @@
int error(sqlite3 *sqlite, sqlite3_stmt *sqlite_stmt);
#define TIMESTAMP_LEN 80
#define STRFTIME_FORMAT "%Y-%m-%d %H:%M:%S"

View File

@ -0,0 +1,814 @@
/*
* main.pc
* driver for the tpcc transactions
*/
#include <rtdevice.h>
#include <rtthread.h>
#include <board.h>
#include <sys/signal.h>
// #include "support.h"
// #include "rthist.h"
// #include "sb_percentile.h"
// #include "sequence.h"
// #include "spt_proc.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <pthread.h>
#include <fcntl.h>
#include <time.h>
#include <sqlite3.h>
#include "tpc.h"
#include "trans_if.h"
#include "spt_proc.h"
#include "sequence.h"
#include "rthist.h"
#include "sb_percentile.h"
/* Global SQL Variables */
sqlite3 **ctx;
sqlite3_stmt ***stmt;
#define DB_STRING_MAX 128
#define MAX_CLUSTER_SIZE 128
int num_ware;
int num_conn;
int lampup_time;
int measure_time;
int num_node; /* number of servers that consists of cluster i.e. RAC (0:normal mode)*/
#define NUM_NODE_MAX 8
char node_string[NUM_NODE_MAX][DB_STRING_MAX];
int time_count;
int PRINT_INTERVAL=10;
int multi_schema = 0;
int multi_schema_offset = 0;
int success[5];
int late[5];
int retry[5];
int failure[5];
int* success2[5];
int* late2[5];
int* retry2[5];
int* failure2[5];
int success2_sum[5];
int late2_sum[5];
int retry2_sum[5];
int failure2_sum[5];
int prev_s[5];
int prev_l[5];
double max_rt[5];
double total_rt[5];
double cur_max_rt[5];
double prev_total_rt[5];
#define RTIME_NEWORD 5
#define RTIME_PAYMENT 5
#define RTIME_ORDSTAT 5
#define RTIME_DELIVERY 80
#define RTIME_SLEV 20
int rt_limit[5] = {
RTIME_NEWORD,
RTIME_PAYMENT,
RTIME_ORDSTAT,
RTIME_DELIVERY,
RTIME_SLEV
};
sb_percentile_t local_percentile;
int activate_transaction;
double time_taken;
clock_t time_start;
clock_t time_end;
int counting_on;
int num_trans=5000;
long clk_tck;
// int is_local = 0; /* "1" mean local */
int valuable_flg = 0; /* "1" mean valuable ratio */
// extern const char* db_path = "tpcc.db";
extern const char * db_path;
extern int is_local;
typedef struct
{
int number;
} thread_arg;
int thread_main(thread_arg*);
void alarm_handler(int signum);
void alarm_dummy();
void start( )
{
int i, k, t_num, arg_offset, c;
long j;
float f;
pthread_t *t;
thread_arg *thd_arg;
timer_t timer;
// struct itimerval itval;
// struct sigaction sigact;
int fd, seed;
printf("CHECKING IF SQLITE IS THREADSAFE: RETURN VALUE = %d\n", sqlite3_threadsafe());
// sqlite3_vfs_register(sqlite3_vfs_find("unix-none"), 1);
sqlite3_initialize();
printf("***************************************\n");
printf("*** ###easy### TPC-C Load Generator ***\n");
printf("***************************************\n");
/* initialize */
hist_init();
activate_transaction = 1;
counting_on = 1;
for ( i=0; i<5; i++ ){
success[i]=0;
late[i]=0;
retry[i]=0;
failure[i]=0;
prev_s[i]=0;
prev_l[i]=0;
prev_total_rt[i] = 0.0;
max_rt[i]=0.0;
total_rt[i]=0.0;
}
/* dummy initialize*/
num_ware = 3;
num_conn = 1;
lampup_time = 10;
measure_time = 20;
/* number of node (default 0) */
num_node = 0;
arg_offset = 0;
// clk_tck = sysconf(_SC_CLK_TCK);
clk_tck = 1000;
/* Parse args */
// while ( (c = getopt(argc, argv, "w:c:r:l:i:m:o:t:d:0:1:2:3:4:")) != -1) {
// switch (c) {
// case 'w':
// printf ("option w with value '%s'\n", optarg);
// num_ware = atoi(optarg);
// break;
// case 'c':
// printf ("option c with value '%s'\n", optarg);
// num_conn = atoi(optarg);
// break;
// case 'r':
// printf ("option r with value '%s'\n", optarg);
// lampup_time = atoi(optarg);
// break;
// case 'l':
// printf ("option l with value '%s'\n", optarg);
// measure_time = atoi(optarg);
// break;
// case 'm':
// printf ("option m (multiple schemas) with value '%s'\n", optarg);
// multi_schema = atoi(optarg);
// break;
// case 'o':
// printf ("option o (multiple schemas offset) with value '%s'\n", optarg);
// multi_schema_offset = atoi(optarg);
// break;
// case 't':
// printf ("option t (number of transactions) with value '%s'\n", optarg);
// num_trans = atoi(optarg);
// break;
// case 'i':
// printf ("option i with value '%s'\n", optarg);
// PRINT_INTERVAL = atoi(optarg);
// break;
// case 'd':
// printf ("option d with value '%s'\n", optarg);
// db_path = optarg;
// break;
// case '0':
// printf ("option 0 (response time limit for transaction 0) '%s'\n", optarg);
// rt_limit[0] = atoi(optarg);
// break;
// case '1':
// printf ("option 1 (response time limit for transaction 1) '%s'\n", optarg);
// rt_limit[1] = atoi(optarg);
// break;
// case '2':
// printf ("option 2 (response time limit for transaction 2) '%s'\n", optarg);
// rt_limit[2] = atoi(optarg);
// break;
// case '3':
// printf ("option 3 (response time limit for transaction 3) '%s'\n", optarg);
// rt_limit[3] = atoi(optarg);
// break;
// case '4':
// printf ("option 4 (response time limit for transaction 4) '%s'\n", optarg);
// rt_limit[4] = atoi(optarg);
// break;
// case '?':
// printf("Usage: tpcc_start -w warehouses -c connections -r warmup_time -l running_time -i report_interval\n");
// exit(0);
// default:
// printf ("?? getopt returned character code 0%o ??\n", c);
// }
// }
// if (optind < argc) {
// printf ("non-option ARGV-elements: ");
// while (optind < argc)
// printf ("%s ", argv[optind++]);
// printf ("\n");
// }
/*
if ((num_node == 0)&&(argc == 14)) {
valuable_flg = 1;
}
if ((num_node == 0)&&(valuable_flg == 0)&&(argc != 9)) {
fprintf(stderr, "\n usage: tpcc_start [server] [DB] [user] [pass] [warehouse] [connection] [rampup] [measure]\n");
exit(1);
}
if ( strlen(argv[1]) >= DB_STRING_MAX ) {
fprintf(stderr, "\n server phrase is too long\n");
exit(1);
}
if ( strlen(argv[2]) >= DB_STRING_MAX ) {
fprintf(stderr, "\n DBname phrase is too long\n");
exit(1);
}
if ( strlen(argv[3]) >= DB_STRING_MAX ) {
fprintf(stderr, "\n user phrase is too long\n");
exit(1);
}
if ( strlen(argv[4]) >= DB_STRING_MAX ) {
fprintf(stderr, "\n pass phrase is too long\n");
exit(1);
}
if ((num_ware = atoi(argv[5 + arg_offset])) <= 0) {
fprintf(stderr, "\n expecting positive number of warehouses\n");
exit(1);
}
if ((num_conn = atoi(argv[6 + arg_offset])) <= 0) {
fprintf(stderr, "\n expecting positive number of connections\n");
exit(1);
}
if ((lampup_time = atoi(argv[7 + arg_offset])) < 0) {
fprintf(stderr, "\n expecting positive number of lampup_time [sec]\n");
exit(1);
}
if ((measure_time = atoi(argv[8 + arg_offset])) < 0) {
fprintf(stderr, "\n expecting positive number of measure_time [sec]\n");
exit(1);
}
if (parse_host_get_port(&port, argv[1]) < 0) {
fprintf(stderr, "cannot prase the host: %s\n", argv[1]);
exit(1);
}
strcpy( db_string, argv[2] );
strcpy( db_user, argv[3] );
strcpy( db_password, argv[4] );
*/
// if(valuable_flg==1){
// if( (atoi(argv[9 + arg_offset]) < 0)||(atoi(argv[10 + arg_offset]) < 0)||(atoi(argv[11 + arg_offset]) < 0)
// ||(atoi(argv[12 + arg_offset]) < 0)||(atoi(argv[13 + arg_offset]) < 0) ) {
// fprintf(stderr, "\n expecting positive number of ratio parameters\n");
// exit(1);
// }
// }
if( num_node > 0 ){
if( num_ware % num_node != 0 ){
fprintf(stderr, "\n [warehouse] value must be devided by [num_node].\n");
}
if( num_conn % num_node != 0 ){
fprintf(stderr, "\n [connection] value must be devided by [num_node].\n");
}
}
printf("<Parameters>\n");
printf(" [warehouse]: %d\n", num_ware);
printf(" [connection]: %d\n", num_conn);
printf(" [rampup]: %d (sec.)\n", lampup_time);
printf(" [measure]: %d (sec.)\n", measure_time);
// if(valuable_flg==1){
// printf(" [ratio]: %d:%d:%d:%d:%d\n", atoi(argv[9 + arg_offset]), atoi(argv[10 + arg_offset]),
// atoi(argv[11 + arg_offset]), atoi(argv[12 + arg_offset]), atoi(argv[13 + arg_offset]) );
// }
/* alarm initialize */
time_count = 0;
// itval.it_interval.tv_sec = PRINT_INTERVAL;
// itval.it_interval.tv_usec = 0;
// itval.it_value.tv_sec = PRINT_INTERVAL;
// itval.it_value.tv_usec = 0;
// sigact.sa_handler = alarm_handler;
// sigact.sa_flags = 0;
// sigemptyset(&sigact.sa_mask);
/* setup handler&timer */
// if( sigaction( SIGALRM, &sigact, NULL ) == -1 ) {
// fprintf(stderr, "error in sigaction()\n");
//
// }
// fd = open("/dev/urandom", O_RDONLY);
// if (fd == -1) {
// fd = open("/dev/random", O_RDONLY);
// if (fd == -1) {
struct timeval tv;
gettimeofday(&tv, NULL);
seed = (tv.tv_sec ^ tv.tv_usec) * tv.tv_sec * tv.tv_usec ^ tv.tv_sec;
// }else{
// read(fd, &seed, sizeof(seed));
// close(fd);
// }
// }else{
// read(fd, &seed, sizeof(seed));
// close(fd);
// }
SetSeed(seed);
if(valuable_flg==0){
seq_init(10,10,1,1,1); /* normal ratio */
}else{
// seq_init( atoi(argv[9 + arg_offset]), atoi(argv[10 + arg_offset]), atoi(argv[11 + arg_offset]),
// atoi(argv[12 + arg_offset]), atoi(argv[13 + arg_offset]) );
}
/* set up each counter */
for ( i=0; i<5; i++ ){
success2[i] = malloc( sizeof(int) * num_conn );
late2[i] = malloc( sizeof(int) * num_conn );
retry2[i] = malloc( sizeof(int) * num_conn );
failure2[i] = malloc( sizeof(int) * num_conn );
for ( k=0; k<num_conn; k++ ){
success2[i][k] = 0;
late2[i][k] = 0;
retry2[i][k] = 0;
failure2[i][k] = 0;
}
}
if (sb_percentile_init(&local_percentile, 100000, 1.0, 1e13))
return NULL;
/* set up threads */
t = malloc( sizeof(pthread_t) * num_conn );
if ( t == NULL ){
fprintf(stderr, "error at malloc(pthread_t)\n");
}
thd_arg = malloc( sizeof(thread_arg) * num_conn );
if( thd_arg == NULL ){
fprintf(stderr, "error at malloc(thread_arg)\n");
}
ctx = malloc( sizeof(sqlite3 *) * num_conn );
stmt = malloc( sizeof(sqlite3_stmt **) * num_conn );
for( i=0; i < num_conn; i++ ){
stmt[i] = malloc( sizeof(sqlite3_stmt *) * 40 );
}
if ( ctx == NULL ){
fprintf(stderr, "error at malloc(sql_context)\n");
}
/* EXEC SQL WHENEVER SQLERROR GOTO sqlerr; */
for( t_num=0; t_num < num_conn; t_num++ ){
thd_arg[t_num].number= t_num;
pthread_create( &t[t_num], NULL, (void *)thread_main, (void *)&(thd_arg[t_num]) );
}
printf("\nRAMP-UP TIME.(%d sec.)\n",lampup_time);
fflush(stdout);
sleep(lampup_time);
printf("\nMEASURING START.\n\n");
fflush(stdout);
/* sleep(measure_time); */
/* start timer */
// #ifndef _SLEEP_ONLY_
// if( setitimer(0, &itval, NULL) == -1 ) {
// fprintf(stderr, "error in setitimer()\n");
// }
// #endif
counting_on = 1;
/* wait signal */
/*
for(i = 0; i < (measure_time / PRINT_INTERVAL); i++ ) {
//while (activate_transaction) {
#ifndef _SLEEP_ONLY_
pause();
#else
sleep(PRINT_INTERVAL);
alarm_dummy();
#endif
}
*/
counting_on = 0;
// #ifndef _SLEEP_ONLY_
// /* stop timer */
// itval.it_interval.tv_sec = 0;
// itval.it_interval.tv_usec = 0;
// itval.it_value.tv_sec = 0;
// itval.it_value.tv_usec = 0;
// if( setitimer(0, &itval, NULL) == -1 ) {
// fprintf(stderr, "error in setitimer()\n");
// }
// #endif
printf("\nSTOPPING THREADS");
activate_transaction = 0;
/* wait threads' ending and close connections*/
for( i=0; i < num_conn; i++ ){
pthread_join( t[i], NULL );
}
printf("\n");
free(ctx);
for( i=0; i < num_conn; i++ ){
free(stmt[i]);
}
free(stmt);
free(t);
free(thd_arg);
//hist_report();
printf("\n<Raw Results>\n");
for ( i=0; i<5; i++ ){
printf(" [%d] sc:%d lt:%d rt:%d fl:%d avg_rt: %.1f (%d)\n",
i, success[i], late[i], retry[i], failure[i],
total_rt[i] / (success[i] + late[i]), rt_limit[i]);
}
printf(" in %d sec.\n", (measure_time / PRINT_INTERVAL) * PRINT_INTERVAL);
printf("\n<Raw Results2(sum ver.)>\n");
for( i=0; i<5; i++ ){
success2_sum[i] = 0;
late2_sum[i] = 0;
retry2_sum[i] = 0;
failure2_sum[i] = 0;
for( k=0; k<num_conn; k++ ){
success2_sum[i] += success2[i][k];
late2_sum[i] += late2[i][k];
retry2_sum[i] += retry2[i][k];
failure2_sum[i] += failure2[i][k];
}
}
for ( i=0; i<5; i++ ){
printf(" [%d] sc:%d lt:%d rt:%d fl:%d \n", i, success2_sum[i], late2_sum[i], retry2_sum[i], failure2_sum[i]);
}
printf("\n<Constraint Check> (all must be [OK])\n [transaction percentage]\n");
for ( i=0, j=0; i<5; i++ ){
j += (success[i] + late[i]);
}
f = 100.0 * (float)(success[1] + late[1])/(float)j;
printf(" Payment: %3.2f%% (>=43.0%%)",f);
if ( f >= 43.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)(success[2] + late[2])/(float)j;
printf(" Order-Status: %3.2f%% (>= 4.0%%)",f);
if ( f >= 4.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)(success[3] + late[3])/(float)j;
printf(" Delivery: %3.2f%% (>= 4.0%%)",f);
if ( f >= 4.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)(success[4] + late[4])/(float)j;
printf(" Stock-Level: %3.2f%% (>= 4.0%%)",f);
if ( f >= 4.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
printf(" [response time (at least 90%% passed)]\n");
f = 100.0 * (float)success[0]/(float)(success[0] + late[0]);
printf(" New-Order: %3.2f%% ",f);
if ( f >= 90.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)success[1]/(float)(success[1] + late[1]);
printf(" Payment: %3.2f%% ",f);
if ( f >= 90.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)success[2]/(float)(success[2] + late[2]);
printf(" Order-Status: %3.2f%% ",f);
if ( f >= 90.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)success[3]/(float)(success[3] + late[3]);
printf(" Delivery: %3.2f%% ",f);
if ( f >= 90.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
f = 100.0 * (float)success[4]/(float)(success[4] + late[4]);
printf(" Stock-Level: %3.2f%% ",f);
if ( f >= 90.0 ){
printf(" [OK]\n");
}else{
printf(" [NG] *\n");
}
printf("\n<TpmC>\n");
f = (float)(success[0] + late[0]) * 60.0
/ (float)((measure_time / PRINT_INTERVAL) * PRINT_INTERVAL);
printf(" %.3f TpmC\n",f);
printf("\nTime taken\n");
time_taken = ((double) (time_end - time_start)) / CLOCKS_PER_SEC;
printf(" %.3f seconds\n", time_taken);
sqlerr:
fprintf(stdout, "error at main\n");
error(ctx[i],0);
}
MSH_CMD_EXPORT(start, start tpcc test);
void alarm_handler(int signum)
{
int i;
int s[5],l[5];
double rt90[5];
double trt[5];
double percentile_val;
double percentile_val99;
for( i=0; i<5; i++ ){
s[i] = success[i];
l[i] = late[i];
trt[i] = total_rt[i];
//rt90[i] = hist_ckp(i);
}
time_count += PRINT_INTERVAL;
percentile_val = sb_percentile_calculate(&local_percentile, 95);
percentile_val99 = sb_percentile_calculate(&local_percentile, 99);
sb_percentile_reset(&local_percentile);
// printf("%4d, %d:%.3f|%.3f(%.3f), %d:%.3f|%.3f(%.3f), %d:%.3f|%.3f(%.3f), %d:%.3f|%.3f(%.3f), %d:%.3f|%.3f(%.3f)\n",
printf("%4d, trx: %d, 95%: %.3f, 99%: %.3f, max_rt: %.3f, %d|%.3f, %d|%.3f, %d|%.3f, %d|%.3f\n",
time_count,
( s[0] + l[0] - prev_s[0] - prev_l[0] ), percentile_val,percentile_val99,
(double)cur_max_rt[0],
( s[1] + l[1] - prev_s[1] - prev_l[1] ),
(double)cur_max_rt[1],
( s[2] + l[2] - prev_s[2] - prev_l[2] ),
(double)cur_max_rt[2],
( s[3] + l[3] - prev_s[3] - prev_l[3] ),
(double)cur_max_rt[3],
( s[4] + l[4] - prev_s[4] - prev_l[4] ),
(double)cur_max_rt[4]
);
fflush(stdout);
for( i=0; i<5; i++ ){
prev_s[i] = s[i];
prev_l[i] = l[i];
prev_total_rt[i] = trt[i];
cur_max_rt[i]=0.0;
}
}
void alarm_dummy()
{
int i;
int s[5],l[5];
float rt90[5];
for( i=0; i<5; i++ ){
s[i] = success[i];
l[i] = late[i];
rt90[i] = hist_ckp(i);
}
time_count += PRINT_INTERVAL;
printf("%4d, %d(%d):%.2f, %d(%d):%.2f, %d(%d):%.2f, %d(%d):%.2f, %d(%d):%.2f\n",
time_count,
( s[0] + l[0] - prev_s[0] - prev_l[0] ),
( l[0] - prev_l[0] ),
rt90[0],
( s[1] + l[1] - prev_s[1] - prev_l[1] ),
( l[1] - prev_l[1] ),
rt90[1],
( s[2] + l[2] - prev_s[2] - prev_l[2] ),
( l[2] - prev_l[2] ),
rt90[2],
( s[3] + l[3] - prev_s[3] - prev_l[3] ),
( l[3] - prev_l[3] ),
rt90[3],
( s[4] + l[4] - prev_s[4] - prev_l[4] ),
( l[4] - prev_l[4] ),
rt90[4]
);
fflush(stdout);
for( i=0; i<5; i++ ){
prev_s[i] = s[i];
prev_l[i] = l[i];
}
}
int thread_main (thread_arg* arg)
{
int t_num= arg->number;
int r,i;
sqlite3* sqlite3_db = NULL;
/* EXEC SQL WHENEVER SQLERROR GOTO sqlerr;*/
// printf("Using schema: %s\n", db_string_full);
/* exec sql connect :connect_string; */
printf("%s: opening db, thread id = %lu\n", __func__, pthread_self());
sqlite3_open(db_path, &sqlite3_db);
printf("%s: opened db, thread id = %lu\n", __func__, pthread_self());
sqlite3_exec(sqlite3_db, "PRAGMA journal_mode = OFF;", 0, 0, 0);
if(!sqlite3_db) {
goto sqlerr;
}
ctx[t_num] = sqlite3_db;
printf("go prepare here\n");
/* Prepare ALL of SQLs */
if( sqlite3_prepare_v2(sqlite3_db, "SELECT c_discount, c_last, c_credit, w_tax FROM customer, warehouse WHERE w_id = ? AND c_w_id = w_id AND c_d_id = ? AND c_id = ?", -1, &stmt[t_num][0], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT d_next_o_id, d_tax FROM district WHERE d_id = ? AND d_w_id = ?", -1, &stmt[t_num][1], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE district SET d_next_o_id = ? + 1 WHERE d_id = ? AND d_w_id = ?", -1, &stmt[t_num][2], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "INSERT INTO orders (o_id, o_d_id, o_w_id, o_c_id, o_entry_d, o_ol_cnt, o_all_local) VALUES(?, ?, ?, ?, ?, ?, ?)", -1, &stmt[t_num][3], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "INSERT INTO new_orders (no_o_id, no_d_id, no_w_id) VALUES (?,?,?)", -1, &stmt[t_num][4], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT i_price, i_name, i_data FROM item WHERE i_id = ?", -1, &stmt[t_num][5], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT s_quantity, s_data, s_dist_01, s_dist_02, s_dist_03, s_dist_04, s_dist_05, s_dist_06, s_dist_07, s_dist_08, s_dist_09, s_dist_10 FROM stock WHERE s_i_id = ? AND s_w_id = ?", -1, &stmt[t_num][6], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE stock SET s_quantity = ? WHERE s_i_id = ? AND s_w_id = ?", -1, &stmt[t_num][7], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "INSERT INTO order_line (ol_o_id, ol_d_id, ol_w_id, ol_number, ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_dist_info) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", -1, &stmt[t_num][8], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE warehouse SET w_ytd = w_ytd + ? WHERE w_id = ?", -1, &stmt[t_num][9], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT w_street_1, w_street_2, w_city, w_state, w_zip, w_name FROM warehouse WHERE w_id = ?", -1, &stmt[t_num][10], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE district SET d_ytd = d_ytd + ? WHERE d_w_id = ? AND d_id = ?", -1, &stmt[t_num][11], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT d_street_1, d_street_2, d_city, d_state, d_zip, d_name FROM district WHERE d_w_id = ? AND d_id = ?", -1, &stmt[t_num][12], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT count(c_id) FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_last = ?", -1, &stmt[t_num][13], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT c_id FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_last = ? ORDER BY c_first", -1, &stmt[t_num][14], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city, c_state, c_zip, c_phone, c_credit, c_credit_lim, c_discount, c_balance, c_since FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_id = ?", -1, &stmt[t_num][15], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT c_data FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_id = ?", -1, &stmt[t_num][16], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE customer SET c_balance = ?, c_data = ? WHERE c_w_id = ? AND c_d_id = ? AND c_id = ?", -1, &stmt[t_num][17], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE customer SET c_balance = ? WHERE c_w_id = ? AND c_d_id = ? AND c_id = ?", -1, &stmt[t_num][18], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "INSERT INTO history(h_c_d_id, h_c_w_id, h_c_id, h_d_id, h_w_id, h_date, h_amount, h_data) VALUES(?, ?, ?, ?, ?, ?, ?, ?)", -1, &stmt[t_num][19], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT count(c_id) FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_last = ?", -1, &stmt[t_num][20], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT c_balance, c_first, c_middle, c_last FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_last = ? ORDER BY c_first", -1, &stmt[t_num][21], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT c_balance, c_first, c_middle, c_last FROM customer WHERE c_w_id = ? AND c_d_id = ? AND c_id = ?", -1, &stmt[t_num][22], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT o_id, o_entry_d, COALESCE(o_carrier_id,0) FROM orders WHERE o_w_id = ? AND o_d_id = ? AND o_c_id = ? AND o_id = (SELECT MAX(o_id) FROM orders WHERE o_w_id = ? AND o_d_id = ? AND o_c_id = ?)", -1, &stmt[t_num][23], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT ol_i_id, ol_supply_w_id, ol_quantity, ol_amount, ol_delivery_d FROM order_line WHERE ol_w_id = ? AND ol_d_id = ? AND ol_o_id = ?", -1, &stmt[t_num][24], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT COALESCE(MIN(no_o_id),0) FROM new_orders WHERE no_d_id = ? AND no_w_id = ?", -1, &stmt[t_num][25], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "DELETE FROM new_orders WHERE no_o_id = ? AND no_d_id = ? AND no_w_id = ?", -1, &stmt[t_num][26], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT o_c_id FROM orders WHERE o_id = ? AND o_d_id = ? AND o_w_id = ?", -1, &stmt[t_num][27], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE orders SET o_carrier_id = ? WHERE o_id = ? AND o_d_id = ? AND o_w_id = ?", -1, &stmt[t_num][28], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE order_line SET ol_delivery_d = ? WHERE ol_o_id = ? AND ol_d_id = ? AND ol_w_id = ?", -1, &stmt[t_num][29], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT SUM(ol_amount) FROM order_line WHERE ol_o_id = ? AND ol_d_id = ? AND ol_w_id = ?", -1, &stmt[t_num][30], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "UPDATE customer SET c_balance = c_balance + ? , c_delivery_cnt = c_delivery_cnt + 1 WHERE c_id = ? AND c_d_id = ? AND c_w_id = ?", -1, &stmt[t_num][31], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT d_next_o_id FROM district WHERE d_id = ? AND d_w_id = ?", -1, &stmt[t_num][32], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT DISTINCT ol_i_id FROM order_line WHERE ol_w_id = ? AND ol_d_id = ? AND ol_o_id < ? AND ol_o_id >= (? - 20)", -1, &stmt[t_num][33], NULL) != SQLITE_OK) goto sqlerr;
if( sqlite3_prepare_v2(sqlite3_db, "SELECT count(*) FROM stock WHERE s_w_id = ? AND s_i_id = ? AND s_quantity < ?", -1, &stmt[t_num][34], NULL) != SQLITE_OK) goto sqlerr;
INITIALIZE_TIMERS();
time_start = clock();
for (i = 0; i < num_trans; i++) {
printf("trans num:%d\n",i);
if( sqlite3_exec(ctx[t_num], "BEGIN TRANSACTION;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
r = driver(t_num);
/* EXEC SQL COMMIT WORK; */
if( sqlite3_exec(ctx[t_num], "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) goto sqlerr;
}
PRINT_TIME();
time_end = clock();
for(i=0;i<40;i++){
sqlite3_reset(stmt[t_num][i]);
}
/* EXEC SQL DISCONNECT; */
sqlite3_close(ctx[t_num]);
printf(".");
fflush(stdout);
return(r);
sqlerr:
fprintf(stdout, "error at thread_main\n");
printf("%s: error: %s\n", __func__, sqlite3_errmsg(ctx[t_num]));
//error(ctx[t_num],0);
return(0);
}

View File

@ -0,0 +1,185 @@
/*
* support.c
* routines needed for the tpcc loading and transaction programs
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "tpc.h"
// static int nums[CUST_PER_DIST];
static int *nums=NULL;
static int perm_count;
void SetSeed (int seed)
{
srand(seed);
}
/*
* return number uniformly distributed b/w min and max, inclusive
*/
int RandomNumber (int min, int max)
{ int rd=rand();
// printf("randnumber %d\n",rd);
return min + (rd % ((max - min) + 1));
}
/*
* non uniform random -- see p. 15
*
* the constant C depends on which value of A is passed, but the same
* value of C should be used for all calls with the same value of
* A. however, we know in advance which values of A will be used.
*/
int NURand (unsigned A, unsigned x, unsigned y)
{
static int first = 1;
unsigned C, C_255, C_1023, C_8191;
if (first) {
C_255 = RandomNumber(0, 255);
C_1023 = RandomNumber(0, 1023);
C_8191 = RandomNumber(0, 8191);
first = 0;
}
switch (A) {
case 255: C = C_255; break;
case 1023: C = C_1023; break;
case 8191: C = C_8191; break;
default:
fprintf(stderr,
"NURand: unexpected value (%d) of A used\n",
A);
abort();
}
return (int)
(((RandomNumber(0, A) | RandomNumber(x, y)) + C) % (y-x+1)) + x;
}
/*
* p. 54
*
* make a ``random a-string'': a string of random alphanumeric
* characters of a random length of minimum x, maximum y, and
* mean (y+x)/2
*/
int MakeAlphaString (int x, int y, char str[])
{
static char *alphanum = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int arrmax = 61; /* index of last array element */
register int i, len;
len = RandomNumber(x, y);
for (i = 0; i < len; i++)
str[i] = alphanum[RandomNumber(0, arrmax)];
return len;
}
/*
* like MakeAlphaString, only numeric characters only
*/
int MakeNumberString (int x, int y, char str[])
{
static char *numeric = "0123456789";
int arrmax = 9;
register int i, len;
len = RandomNumber(x, y);
for (i = 0; i < len; i++)
str[i] = numeric[RandomNumber(0, arrmax)];
return len;
}
/*
* turn system time into database format
* the format argument should be a strftime() format string that produces
* a datetime string acceptable to the database
*/
void gettimestamp (char str[], char *format, size_t len)
{
time_t t;
struct tm *datetime;
t = time(NULL);
datetime = localtime(&t);
if ( !strftime(str, len, format, datetime) ) {
fprintf(stderr, "error writing timestamp to string\n");
abort();
}
}
/*
* permute the list of customer ids for the order table
*/
void InitPermutation (void)
{
if (nums==NULL){
nums=malloc(3000*4);
}
int *cur;
int i,j;
perm_count = 0;
/* initialize with consecutive values [1..ORD_PER_DIST] */
for (i = 0, cur = nums; i < ORD_PER_DIST; i++, cur++) {
*cur = i + 1;
}
/* now, shuffle */
for (i = 0; i < ORD_PER_DIST-1; i++) {
j = (int)RandomNumber(i+1, ORD_PER_DIST-1);
swap_int(nums[i], nums[j]);
}
}
int GetPermutation (void)
{
if (nums==NULL){
nums=malloc(3000*4);
}
if ( perm_count >= ORD_PER_DIST ) {
fprintf(stderr, "GetPermutation: past end of list!\n");
abort();
}
return nums[perm_count++];
}
/*==================================================================+
| ROUTINE NAME
| Lastname
| DESCRIPTION
| TPC-C Lastname Function.
| ARGUMENTS
| num - non-uniform random number
| name - last name string
+==================================================================*/
void Lastname(num, name)
int num;
char *name;
{
static char *n[] =
{"BAR", "OUGHT", "ABLE", "PRI", "PRES",
"ESE", "ANTI", "CALLY", "ATION", "EING"};
strcpy(name,n[num/100]);
strcat(name,n[(num/10)%10]);
strcat(name,n[num%10]);
return;
}

View File

@ -0,0 +1,3 @@
#include "timers.h"
atomic_uint_least64_t Instrustats[INSTRUMENT_NUM];

View File

@ -0,0 +1,97 @@
#ifndef _SQLITE_SRC_TIMERS_H_
#define _SQLITE_SRC_TIMERS_H_
#include <sys/time.h>
#include <string.h>
#include <time.h>
#include <stdatomic.h>
enum instrumentation_vars {
open_t,
close_t,
pread_t,
pwrite_t,
read_t,
write_t,
seek_t,
fsync_t,
unlink_t,
bg_thread_t,
memcpy_to_pmem_t,
fsync_noop_t,
neword_t,
payment_t,
ordstat_t,
delivery_t,
slev_t,
INSTRUMENT_NUM,
};
extern atomic_uint_least64_t Instrustats[INSTRUMENT_NUM];
static const char *Instruprint[INSTRUMENT_NUM] =
{
"open",
"close",
"pread",
"pwrite",
"read",
"write",
"seek",
"fsync",
"unlink",
"bg_thread",
"memcpy_to_pmem",
"fsync_noop",
"neword",
"payment",
"ordstat",
"delivery",
"slev",
};
typedef struct timespec instrumentation_type;
#define INSTRUMENT_CALLS 1
#define INITIALIZE_TIMERS() \
{ \
int i; \
for (i = 0; i < INSTRUMENT_NUM; i++) \
Instrustats[i] = 0; \
} \
#if INSTRUMENT_CALLS
#define START_TIMING(name, start) \
{ \
clock_gettime(CLOCK_MONOTONIC, &start); \
}
#define END_TIMING(name, start) \
{ \
instrumentation_type end; \
clock_gettime(CLOCK_MONOTONIC, &end); \
__atomic_fetch_add(&Instrustats[name], (end.tv_sec - start.tv_sec) * 1000000000 + (end.tv_nsec - start.tv_nsec), __ATOMIC_SEQ_CST); \
}
#define PRINT_TIME() \
{ \
int i; \
printf("\n ----------------------\n"); \
for(i=0; i<INSTRUMENT_NUM; i++) \
if (Instrustats[i] > 0) \
printf("%s: timing = %lu nanoseconds\n", \
Instruprint[i], Instrustats[i]); \
}
#else
#define START_TIMING(name, start) {(void)(start);}
#define END_TIMING(name, start) {(void)(start);}
#define PRINT_TIME() {(void)(Instrustats[0]);}
#endif
#endif

View File

@ -0,0 +1,101 @@
/*
* tpc.h
* definitions for tpcc loading program && transactions
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* correct values
*/
// #define MAXITEMS 10000 //100000
// #define CUST_PER_DIST 3000
// #define DIST_PER_WARE 10
// #define ORD_PER_DIST 3000
/*
*/
#define MAXITEMS 1000
#define CUST_PER_DIST 30
#define DIST_PER_WARE 3
#define ORD_PER_DIST 30
/* definitions for new order transaction */
#define MAX_NUM_ITEMS 15
#define MAX_ITEM_LEN 24
#define swap_int(a,b) {int tmp; tmp=a; a=b; b=tmp;}
/*
* hack MakeAddress() into a macro so that we can pass Oracle
* VARCHARs instead of char *s
*/
#define MakeAddressMacro(str1,str2,city,state,zip) \
{int tmp; \
tmp = MakeAlphaString(10,20,str1.arr); \
str1.len = tmp; \
tmp = MakeAlphaString(10,20,str2.arr); \
str2.len = tmp; \
tmp = MakeAlphaString(10,20,city.arr); \
city.len = tmp; \
tmp = MakeAlphaString(2,2,state.arr); \
state.len = tmp; \
tmp = MakeNumberString(9,9,zip.arr); \
zip.len = tmp;}
/*
* while we're at it, wrap MakeAlphaString() and MakeNumberString()
* in a similar way
*/
#define MakeAlphaStringMacro(x,y,str) \
{int tmp; tmp = MakeAlphaString(x,y,str.arr); str.len = tmp;}
#define MakeNumberStringMacro(x,y,str) \
{int tmp; tmp = MakeNumberString(x,y,str.arr); str.len = tmp;}
/*
* likewise, for Lastname()
* counts on Lastname() producing null-terminated strings
*/
#define LastnameMacro(num,str) \
{Lastname(num, str.arr); str.len = strlen(str.arr);}
extern long count_ware;
/* Functions */
void LoadItems();
void LoadWare();
void LoadCust();
void LoadOrd();
void LoadNewOrd();
int Stock();
int District();
void Customer();
void Orders();
void New_Orders();
void MakeAddress();
void Error();
#ifdef __STDC__
void SetSeed (int seed);
int RandomNumber (int min, int max);
int NURand (unsigned A, unsigned x, unsigned y);
int MakeAlphaString (int x, int y, char str[]);
int MakeNumberString (int x, int y, char str[]);
void gettimestamp (char str[], char *format, size_t n);
void InitPermutation (void);
int GetPermutation (void);
void Lastname(int num, char* name);
#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,25 @@
/*
* trans_if.h
*
* prototypes for the transaction interface calls
*/
#ifdef __cplusplus
extern "C" {
#endif
int driver (int t_num);
int neword (int t_num, int w_id_arg, int d_id_arg, int c_id_arg,
int o_ol_cnt_arg, int o_all_local_arg, int itemid[],
int supware[], int qty[]);
int payment (int t_num, int w_id_arg, int d_id_arg, int byname,
int c_w_id_arg, int c_d_id_arg,
int c_id_arg, char c_last_arg[], float h_amount_arg);
int ordstat (int t_num, int w_id, int d_id, int byname, int c_id,
char c_last[]);
int slev (int t_num, int w_id, int d_id, int level);
int delivery (int t_num, int w_id_arg, int o_carrier_id_arg);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,14 @@
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
src = Split("""
virtualstorage.c
""")
# The set of source files associated with this SConscript file.
path = [cwd]
group = DefineGroup('Virtualstorage', src, depend = ['RT_USING_SDIO'], CPPPATH = path)
Return('group')

View File

@ -0,0 +1,676 @@
#include <rtthread.h>
// #include <time.h>
#include "virtualstorage.h"
#include <dfs_fs.h>
// #include "../dfs/filesystems/elmfat/ff.h"
static struct virtual_storage_device *virtual_dev = RT_NULL;
void register_virtual_device()
{
virtual_dev = rt_calloc(1, sizeof(struct virtual_storage_device));
virtual_dev->virtual_storage_size = Max_storage_size;
virtual_dev->components_size = 0;
virtual_dev->dev.user_data = virtual_dev;
virtual_dev->register_components = rt_vs_register_components;
// set geometry
virtual_dev->geometry.bytes_per_sector = Virtual_sector_size;
virtual_dev->geometry.sector_count = 12500000;
virtual_dev->geometry.block_size = 512;
//
// bind function
virtual_dev->dev.init = rt_vs_init;
virtual_dev->dev.close = rt_vs_close;
virtual_dev->dev.open = rt_vs_open;
virtual_dev->dev.control = rt_vs_control;
virtual_dev->dev.read = rt_vs_read;
virtual_dev->dev.write = rt_vs_write;
rt_device_register(&virtual_dev->dev, "virtual_storage",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE |
RT_DEVICE_FLAG_STANDALONE);
//
// u_int part_size=(virtual_dev->geometry.sector_count)/Virtual_disk_Num;
// for (int i=0;i<Virtual_disk_Num;i++){
// struct virtual_disk * vd;
// vd=rt_calloc(1,sizeof(struct virtual_disk));
// vd->geometry.block_size=512;
// vd->geometry.bytes_per_sector=512;
// vd->geometry.sector_count=part_size;
// vd->v_sec_offset=i*part_size;
// vd->dev.user_data=vd;
// vd->vs_pointer=&(virtual_dev->dev);
// vd->dev.init=rt_vd_init;
// vd->dev.close=rt_vd_close;
// vd->dev.open=rt_vd_open;
// vd->dev.control=rt_vd_control;
// vd->dev.read=rt_vd_read;
// vd->dev.write=rt_vd_write;
// char dname[4];
// rt_snprintf(dname, 4, "vd%d", i);
// rt_device_register(&vd->dev, dname,
// RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE |
// RT_DEVICE_FLAG_STANDALONE);
// }
//
// rt_device_register(&virtual_dev->dev, "virtual_storage",
// RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE |
// RT_DEVICE_FLAG_STANDALONE);
}
INIT_PREV_EXPORT(register_virtual_device);
static rt_err_t rt_vs_register_components(rt_device_t dev, const char *name,
rt_uint16_t flags, enum dev_type tp)
{
struct rt_device_blk_geometry geometry;
rt_memset(&geometry, 0, sizeof(geometry));
dev->control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
if (geometry.sector_count > 3097152)
return RT_EOK;
//
dev->flag = flags;
int o_size = virtual_dev->components_size;
virtual_dev->components_size += 1;
virtual_dev->sub_dev[o_size].dev = dev;
virtual_dev->sub_dev[o_size].type = tp;
virtual_dev->sub_dev[o_size].index = void_index;
// show subdev info
// struct rt_device_blk_geometry geometry;
// rt_memset(&geometry, 0, sizeof(geometry));
// dev->control(dev,RT_DEVICE_CTRL_BLK_GETGEOME,&geometry);
virtual_dev->sub_dev[o_size].geometry = geometry;
rt_kprintf(
"subdev %s register success blk size:%d,bytes_per_sec:%d,sec_count:%d ",
name, geometry.block_size, geometry.bytes_per_sector,
geometry.sector_count);
// if o_size==0, initiate the mapping
return RT_EOK;
}
void vs_refresh_primary()
{
struct virtual_storage_device *v_dev = virtual_dev;
u_int block_size = 1024;
if (v_dev == NULL)
return;
BYTE *buf = rt_malloc(512 * block_size);
memset(buf, 0, 512 * block_size);
for (u_int i = 0; i < v_dev->components_size; i++) {
DWORD identifier, index, next_allocated;
rt_device_t tmp = v_dev->sub_dev[i].dev;
if (v_dev->sub_dev[i].index == primary_index) {
DWORD allocate_table_offset = (v_dev->virtual_storage_size) * 16 * 1024;
v_dev->sub_dev[i].next_allocated_sec_idx =
start_sector + 1 + allocate_table_offset;
st_dword(buf, Magic_identity_number);
st_dword(buf + 4, primary_index);
st_dword(buf + 8, v_dev->sub_dev[i].next_allocated_sec_idx);
if (v_dev->sub_dev[i].dev->write(v_dev->sub_dev[i].dev, start_sector, buf,
1) != 1) {
rt_kprintf("refresh primary boot record failed!\n");
return;
}
u_int upper = start_sector + 1 + allocate_table_offset;
memset(buf, 0, 512 * block_size);
rt_device_t bs = v_dev->sub_dev[i].dev;
for (u_int j = start_sector + 1;
j < start_sector + 1 + allocate_table_offset; j += block_size) {
if (bs->write(bs, j, buf, block_size) != block_size) {
rt_kprintf("refresh mapping area failed! sec num is %d\n", j);
return;
} else {
rt_kprintf("refresh in progress sec num is %d\n", j);
}
}
rt_kprintf("refresh success\n");
}
}
rt_free(buf);
}
MSH_CMD_EXPORT(vs_refresh_primary, refresh primary disk);
static rt_err_t vs_init()
{
struct virtual_storage_device *v_dev = virtual_dev;
u_int primary = 0;
BYTE *buf = rt_malloc(4096);
DWORD max_index = 0;
for (u_int i = 0; i < v_dev->components_size; i++) {
DWORD identifier, index, next_allocated;
rt_device_t tmp = v_dev->sub_dev[i].dev;
tmp->read(tmp, start_sector, buf, 1);
identifier = ld_dword(buf);
if (identifier != Magic_identity_number) {
// err
continue;
}
index = ld_dword(buf + 4);
v_dev->sub_dev[i].index = index;
max_index = max_index > index ? max_index : index;
next_allocated = ld_dword(buf + 8);
v_dev->sub_dev[i].next_allocated_sec_idx = next_allocated;
if (index == primary_index) {
primary = 1;
rt_kprintf("primary disk found!");
}
// init geometry TODO?
}
for (u_int i = 0; i < v_dev->components_size; i++) {
if (!primary) {
if (v_dev->sub_dev[i].index != void_index)
continue;
rt_kprintf("init primary disk\n");
v_dev->sub_dev[i].index = primary_index;
primary = 1;
DWORD allocate_table_offset = (v_dev->virtual_storage_size) * 16 * 1024;
v_dev->sub_dev[i].next_allocated_sec_idx =
start_sector + 1 + allocate_table_offset;
st_dword(buf, Magic_identity_number);
st_dword(buf + 4, primary_index);
st_dword(buf + 8, v_dev->sub_dev[i].next_allocated_sec_idx);
// TODO:check return status and debug;
v_dev->sub_dev[i].dev->write(v_dev->sub_dev[i].dev, start_sector, buf, 1);
// break;
} else {
if (v_dev->sub_dev[i].index != void_index)
continue;
rt_kprintf("init sub disk\n");
v_dev->sub_dev[i].index = max_index + 1;
max_index += 1;
v_dev->sub_dev[i].next_allocated_sec_idx = start_sector + 1;
st_dword(buf, Magic_identity_number);
st_dword(buf + 4, v_dev->sub_dev[i].index);
st_dword(buf + 8, v_dev->sub_dev[i].next_allocated_sec_idx);
// TODO:check return status and debug;
v_dev->sub_dev[i].dev->write(v_dev->sub_dev[i].dev, start_sector, buf, 1);
}
}
rt_free(buf);
return RT_EOK;
}
MSH_CMD_EXPORT(vs_init, init vs system);
static rt_err_t rt_vs_init(rt_device_t dev) { return RT_EOK; }
static rt_err_t rt_vs_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_vs_close(rt_device_t dev) { return RT_EOK; }
static rt_err_t rt_vs_control(rt_device_t dev, int cmd, void *args)
{
// rt_kprintf("rt_vs_control invoked\n");
struct virtual_storage_device *v_dev =
(struct virtual_storage_device *)(dev->user_data);
switch (cmd) {
case RT_DEVICE_CTRL_BLK_GETGEOME:
rt_memcpy(args, &v_dev->geometry, sizeof(struct rt_device_blk_geometry));
break;
default:
break;
}
return RT_EOK;
}
struct operation_pair allocate_sec_num(struct virtual_storage_device *dev,
u_int flag)
{
struct operation_pair ret;
for (u_int i = 0; i < dev->components_size; i++) {
// if (dev->sub_dev[i].index==primary_index){
// ret.idx=primary_index;
// ret.real_sec_number=dev->sub_dev[i].next_allocated_sec_idx;
// dev->sub_dev[i].next_allocated_sec_idx++;
// //TODO:ADD bound check;
// return ret;
// }
if ((dev->sub_dev[i].next_allocated_sec_idx + 1) <
(dev->sub_dev[i].geometry.sector_count)) {
ret.idx = dev->sub_dev[i].index;
ret.real_sec_number = dev->sub_dev[i].next_allocated_sec_idx;
dev->sub_dev[i].next_allocated_sec_idx++;
// TODO:ADD bound check;
return ret;
}
}
rt_kprintf("allocate failed! no available disk!\n");
}
struct seg allocate_seg(struct virtual_storage_device *dev, u_int size)
{
struct seg ret;
for (u_int i = 0; i < dev->components_size; i++) {
if ((dev->sub_dev[i].next_allocated_sec_idx + size) <
(dev->sub_dev[i].geometry.sector_count)) {
ret.devid = dev->sub_dev[i].index;
ret.start = dev->sub_dev[i].next_allocated_sec_idx;
dev->sub_dev[i].next_allocated_sec_idx += size;
return ret;
}
}
rt_kprintf("allocate failed! no available disk!\n");
}
// flag == 0 means read, 1 means write
struct operation_pair get_mapping(struct virtual_storage_device *dev,
rt_off_t pos, u_int size, u_int flag)
{
struct operation_pair ret;
struct operation_pair allocate;
BYTE *buf = rt_malloc(512);
for (u_int i = 0; i < dev->components_size; i++) {
if (dev->sub_dev[i].index == primary_index) {
u_int r = pos % 128;
u_int q = (pos - r) / 128;
r *= 4;
if (dev->sub_dev[i].dev->read(dev->sub_dev[i].dev, start_sector + q + 1,
buf, 1) != 1) {
rt_kprintf("map read err\n");
};
DWORD true_sec_number = ld_dword(buf + r);
// TODO:init to zero
if (true_sec_number == 0) {
// rt_kprintf("mapping not found in primary\n");
if (flag == 1) {
//存储idx并写入磁盘
allocate = allocate_sec_num(dev, 0);
DWORD mask = allocate.idx << 28;
true_sec_number = allocate.real_sec_number | mask;
st_dword(buf + r, true_sec_number);
// TODO:fix 写入主盘
if (dev->sub_dev[i].dev->write(dev->sub_dev[i].dev,
start_sector + q + 1, buf, 1) != 1) {
rt_kprintf("map write err\n");
} else {
// rt_kprintf("map set pos:%d\n",pos);
}
} else {
// report err
rt_kprintf("Err:attempt to read unmapping area pos :%d\n", pos);
}
} else {
// rt_kprintf("mapping found in primary\n");
}
DWORD idx = true_sec_number & index_mask;
idx = idx >> 28;
DWORD sec_num = true_sec_number & secnum_mask;
ret.idx = idx;
ret.real_sec_number = sec_num;
}
}
rt_free(buf);
return ret;
}
struct operation_seg get_seg_mapping(struct virtual_storage_device *dev,
rt_off_t pos, u_int size, u_int flag)
{
struct operation_seg ret;
ret.seg_num = 0;
struct operation_seg allocate;
rt_off_t init_pos = pos;
rt_off_t end_pos = pos + size;
struct buffer_wrapper wrap;
wrap.buf = rt_malloc(512);
wrap.offset = 0;
u_int seg_num = 0;
for (u_int i = 0; i < dev->components_size; i++) {
if (dev->sub_dev[i].index == primary_index) {
struct seg current_seg;
current_seg.size = 0;
while (pos < end_pos) {
u_int r = pos % 128;
u_int q = ((pos - r) / 128) + 1;
r *= 4;
if (q != wrap.offset) {
if (dev->sub_dev[i].dev->read(dev->sub_dev[i].dev, start_sector + q,
wrap.buf, 1) != 1) {
rt_kprintf("map read err\n");
};
wrap.offset = q;
}
DWORD true_sec_number;
true_sec_number = ld_dword(wrap.buf + r);
if (true_sec_number == 0) {
if (current_seg.size == 0) {
current_seg.size++;
current_seg.if_blank = 1;
current_seg.v_start = pos;
} else {
if (current_seg.if_blank == 1) {
current_seg.size++;
} else {
ret.segs[seg_num] = current_seg;
seg_num++;
ret.seg_num++;
current_seg.size = 1;
current_seg.if_blank = 1;
current_seg.v_start = pos;
}
}
} else {
if (current_seg.size == 0) {
current_seg.size++;
current_seg.if_blank = 0;
current_seg.v_start = pos;
DWORD idx = true_sec_number & index_mask;
idx = idx >> 28;
DWORD sec_num = true_sec_number & secnum_mask;
current_seg.devid = idx;
current_seg.start = sec_num;
} else {
if (current_seg.if_blank == 1) {
ret.segs[seg_num] = current_seg;
struct seg alloc_seg = allocate_seg(dev, current_seg.size);
ret.segs[seg_num].devid = alloc_seg.devid;
ret.segs[seg_num].start = alloc_seg.start;
seg_num++;
ret.seg_num++;
DWORD idx = true_sec_number & index_mask;
idx = idx >> 28;
DWORD sec_num = true_sec_number & secnum_mask;
current_seg.size = 1;
current_seg.if_blank = 0;
current_seg.v_start = pos;
current_seg.devid = idx;
current_seg.start = sec_num;
} else if (current_seg.if_blank == 0) {
DWORD idx = true_sec_number & index_mask;
idx = idx >> 28;
DWORD sec_num = true_sec_number & secnum_mask;
if (current_seg.devid == idx &&
(sec_num == (current_seg.start + current_seg.size))) {
current_seg.size++;
} else {
ret.segs[seg_num] = current_seg;
seg_num++;
ret.seg_num++;
current_seg.size = 1;
current_seg.if_blank = 0;
current_seg.v_start = pos;
current_seg.devid = idx;
current_seg.start = sec_num;
}
}
}
}
pos++;
}
ret.segs[seg_num] = current_seg;
if (current_seg.if_blank) {
struct seg alloc_seg = allocate_seg(dev, current_seg.size);
ret.segs[seg_num].devid = alloc_seg.devid;
ret.segs[seg_num].start = alloc_seg.start;
}
seg_num++;
ret.seg_num++;
current_seg.size = 0;
u_int cnt = 0;
for (int a = 0; a < ret.seg_num; a++) {
if (ret.segs[a].if_blank) {
u_int v_pos = ret.segs[a].v_start;
while (cnt < ret.segs[a].size) {
u_int r = v_pos % 128;
u_int q = ((v_pos - r) / 128) + 1;
r *= 4;
DWORD mask = ret.segs[a].devid << 28;
DWORD true_sec_number = (ret.segs[a].start + cnt) | mask;
if (q != wrap.offset) {
if (dev->sub_dev[i].dev->write(dev->sub_dev[i].dev,
start_sector + wrap.offset,
wrap.buf, 1) != 1) {
rt_kprintf("map set err\n");
};
if (dev->sub_dev[i].dev->read(dev->sub_dev[i].dev,
start_sector + q, wrap.buf,
1) != 1) {
rt_kprintf("map read err\n");
};
wrap.offset = q;
}
st_dword(wrap.buf + r, true_sec_number);
if (cnt == ret.segs[a].size - 1) {
if (dev->sub_dev[i].dev->write(dev->sub_dev[i].dev,
start_sector + wrap.offset,
wrap.buf, 1) != 1) {
rt_kprintf("map set err\n");
};
}
cnt++;
v_pos++;
}
}
}
// TODO:init to zero
// if (true_sec_number==0){
// // rt_kprintf("mapping not found in primary\n");
// if (flag==1){
// //存储idx并写入磁盘
// allocate= allocate_sec_num(dev,0);
// DWORD mask = allocate.idx << 28;
// true_sec_number = allocate.real_sec_number | mask;
// st_dword(buf+r,true_sec_number);
// //TODO:fix 写入主盘
// if
// (dev->sub_dev[i].dev->write(dev->sub_dev[i].dev,start_sector+q+1,buf,1)!=1){
// rt_kprintf("map write err\n");
// }else{
// // rt_kprintf("map set pos:%d\n",pos);
// }
// } else{
// //report err
// rt_kprintf("Err:attempt to read unmapping area pos :%d\n",pos);
// }
// } else{
// // rt_kprintf("mapping found in primary\n");
// }
// DWORD idx=true_sec_number&index_mask;
// idx=idx>>28;
// DWORD sec_num=true_sec_number&secnum_mask;
// ret.idx=idx;
// ret.real_sec_number=sec_num;
}
}
rt_free(wrap.buf);
return ret;
}
static rt_size_t rt_vs_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
{
struct virtual_storage_device *v_dev =
(struct virtual_storage_device *)(dev->user_data);
rt_size_t remainsize = size; // sec count
rt_off_t init_pos = pos;
u_int cnt = 0;
if (remainsize < 640000) {
struct operation_seg seg = get_seg_mapping(v_dev, pos, size, 0);
for (int j = 0; j < seg.seg_num; j++) {
struct seg current_seg = seg.segs[j];
for (u_int k = 0; k < v_dev->components_size; k++) {
if (v_dev->sub_dev[k].index == current_seg.devid) {
if (v_dev->sub_dev[k].dev->read(
v_dev->sub_dev[k].dev, current_seg.start,
(char *)buffer + cnt, current_seg.size) != current_seg.size) {
rt_kprintf("read failed,v sec:%d,seg start:%d,true idx:%d", pos,
current_seg.start, current_seg.devid);
} else {
cnt += 512 * current_seg.size;
break;
}
}
}
// rt_kprintf("read invalid disk idx,v sec:%d,seg start:%d,true
// idx:%d",pos,current_seg.start,current_seg.devid);
}
return size;
} else {
rt_kprintf("attempt to read toomuch blocks\n");
for (;; remainsize -= 1, cnt += 512, pos += 1) {
if (remainsize == 0)
return size;
struct operation_pair pr = get_mapping(v_dev, pos, size, 0);
// rt_kprintf("rt_vs_read invoked v_pos :%d,pr.secnum:%d
// pr.idx=%d\n",pos,pr.real_sec_number,pr.idx);
for (u_int i = 0; i < v_dev->components_size; i++) {
if (v_dev->sub_dev[i].index == pr.idx) {
if (v_dev->sub_dev[i].dev->read(v_dev->sub_dev[i].dev,
pr.real_sec_number,
(char *)buffer + cnt, 1) != 1) {
rt_kprintf("read failed,v sec:%d,true sec:%d,true idx:%d", pos,
pr.real_sec_number, pr.idx);
} else {
break;
}
}
}
// printf("invalid sec_num and pr in read\n");
// return 0;
}
}
// err invalid sec_num
}
static rt_size_t rt_vs_write(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
{
struct virtual_storage_device *v_dev =
(struct virtual_storage_device *)(dev->user_data);
rt_size_t remainsize = size; // sec count
rt_off_t init_pos = pos;
u_int cnt = 0;
if (remainsize < 640000) {
struct operation_seg seg = get_seg_mapping(v_dev, pos, size, 1);
for (int j = 0; j < seg.seg_num; j++) {
struct seg current_seg = seg.segs[j];
for (u_int k = 0; k < v_dev->components_size; k++) {
if (v_dev->sub_dev[k].index == current_seg.devid) {
if (v_dev->sub_dev[k].dev->write(
v_dev->sub_dev[k].dev, current_seg.start,
(char *)buffer + cnt, current_seg.size) != current_seg.size) {
rt_kprintf("write failed,v sec:%d,seg start:%d,true idx:%d", pos,
current_seg.start, current_seg.devid);
} else {
cnt += 512 * current_seg.size;
break;
}
}
}
// rt_kprintf("write invalid disk idx,v sec:%d,seg start:%d,true
// idx:%d",pos,current_seg.start,current_seg.devid);
}
return size;
} else {
rt_kprintf("attempt to read toomuch blocks\n");
for (;; remainsize -= 1, cnt += 512, pos += 1) {
if (remainsize == 0)
return size;
struct operation_pair pr = get_mapping(v_dev, pos, size, 1);
// rt_kprintf("rt_vs_write invoked v_pos :%d,pr.secnum:%d
// pr.idx=%d\n",pos,pr.real_sec_number,pr.idx);
for (u_int i = 0; i < v_dev->components_size; i++) {
if (v_dev->sub_dev[i].index == pr.idx) {
if (v_dev->sub_dev[i].dev->write(v_dev->sub_dev[i].dev,
pr.real_sec_number,
(char *)buffer + cnt, 1) != 1) {
rt_kprintf("write failed,v sec:%d,true sec:%d,true idx:%d", pos,
pr.real_sec_number, pr.idx);
} else {
break;
}
}
}
// printf("invalid sec_num and pr in write\n");
// return 0;
}
}
}
static WORD ld_word(const BYTE *ptr) /* Load a 2-byte little-endian word */
{
WORD rv;
rv = ptr[1];
rv = rv << 8 | ptr[0];
return rv;
}
static DWORD ld_dword(const BYTE *ptr) /* Load a 4-byte little-endian word */
{
DWORD rv;
rv = ptr[3];
rv = rv << 8 | ptr[2];
rv = rv << 8 | ptr[1];
rv = rv << 8 | ptr[0];
return rv;
}
static void st_word(BYTE *ptr,
WORD val) /* Store a 2-byte word in little-endian */
{
*ptr++ = (BYTE)val;
val >>= 8;
*ptr++ = (BYTE)val;
}
static void st_dword(BYTE *ptr,
DWORD val) /* Store a 4-byte word in little-endian */
{
*ptr++ = (BYTE)val;
val >>= 8;
*ptr++ = (BYTE)val;
val >>= 8;
*ptr++ = (BYTE)val;
val >>= 8;
*ptr++ = (BYTE)val;
}
static rt_err_t rt_vd_init(rt_device_t dev) { return RT_EOK; }
static rt_err_t rt_vd_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_vd_close(rt_device_t dev) { return RT_EOK; }
static rt_err_t rt_vd_control(rt_device_t dev, int cmd, void *args)
{
struct virtual_disk *vd = (struct virtual_disk *)(dev->user_data);
switch (cmd) {
case RT_DEVICE_CTRL_BLK_GETGEOME:
rt_memcpy(args, &vd->geometry, sizeof(struct rt_device_blk_geometry));
break;
default:
break;
}
return RT_EOK;
}
static rt_size_t rt_vd_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
{
struct virtual_disk *vd = (struct virtual_disk *)(dev->user_data);
struct virtual_storage_device *vss =
(struct virtual_storage_device *)(vd->vs_pointer->user_data);
return vss->dev.read(&(vss->dev), pos + vd->v_sec_offset, buffer, size);
}
static rt_size_t rt_vd_write(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
{
struct virtual_disk *vd = (struct virtual_disk *)(dev->user_data);
struct virtual_storage_device *vss =
(struct virtual_storage_device *)(vd->vs_pointer->user_data);
return vss->dev.write(&(vss->dev), pos + vd->v_sec_offset, buffer, size);
}

View File

@ -0,0 +1,102 @@
#ifndef __VIRTUALSTORAGE_H__
#define __VIRTUALSTORAGE_H__
#define Virtual_sector_size 512
#define Max_storage_size 7
#define start_sector 63UL
#define primary_index 0
#define void_index 0xFFFFFFFF
#define index_mask 0xF0000000
#define secnum_mask 0x0FFFFFFF
#define Virtual_disk_Num 2
#define Magic_identity_number 0xABCDEF98
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
typedef unsigned char BYTE; /* char must be 8-bit */
typedef unsigned int u_int;
typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
// typedef unsigned char BYTE;
enum dev_type { sd, udisk };
struct v_device_components {
struct rt_device *dev;
enum dev_type type;
DWORD index;
struct rt_device_blk_geometry geometry;
DWORD next_allocated_sec_idx;
};
struct operation_pair {
DWORD idx;
DWORD real_sec_number;
};
struct buffer_wrapper {
BYTE *buf;
u_int offset;
};
struct seg {
u_int start;
u_int v_start;
u_int size;
u_int devid;
u_int if_blank;
};
struct operation_seg {
struct seg segs[64];
u_int seg_num;
};
struct virtual_disk {
struct rt_device dev;
u_int v_sec_offset;
struct rt_device_blk_geometry geometry;
rt_device_t vs_pointer;
};
struct virtual_storage_device {
rt_list_t list;
u_int virtual_storage_size;
struct rt_device dev;
struct v_device_components
sub_dev[10]; // all suboardinate device,maybe udisk,sd card
int components_size;
struct rt_device_blk_geometry geometry;
rt_err_t (*register_components)(rt_device_t dev, const char *name,
rt_uint16_t flags, enum dev_type tp);
// partition info
// u_int primary_index;
// u_int sub_index[10];
};
static rt_err_t rt_vs_register_components(rt_device_t dev, const char *name,
rt_uint16_t flags, enum dev_type tp);
static rt_err_t rt_vs_init(rt_device_t dev);
static rt_err_t rt_vs_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t rt_vs_close(rt_device_t dev);
static rt_err_t rt_vs_control(rt_device_t dev, int cmd, void *args);
static rt_size_t rt_vs_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size);
static rt_size_t rt_vs_write(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size);
static void st_dword(BYTE *ptr, DWORD val);
static void st_word(BYTE *ptr, WORD val);
static DWORD ld_dword(const BYTE *ptr);
static WORD ld_word(const BYTE *ptr);
static rt_err_t rt_vd_init(rt_device_t dev);
static rt_err_t rt_vd_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t rt_vd_close(rt_device_t dev);
static rt_err_t rt_vd_control(rt_device_t dev, int cmd, void *args);
static rt_size_t rt_vd_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size);
static rt_size_t rt_vd_write(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size);
#endif

View File

@ -20,6 +20,8 @@
#include <rtdevice.h> /* for wqueue_init */
#endif /* RT_USING_POSIX */
#include "../components/virtualstorage/virtualstorage.h"
#ifdef RT_USING_DEVICE
#ifdef RT_USING_DEVICE_OPS
@ -59,6 +61,24 @@ rt_err_t rt_device_register(rt_device_t dev,
if (rt_device_find(name) != RT_NULL)
return -RT_ERROR;
//
rt_device_t ptr=rt_device_find("virtual_storage");
if (ptr!=RT_NULL)
{
if (strstr(name,"sd")!=RT_NULL){
struct virtual_storage_device * dev_ptr=(struct virtual_storage_device *)(ptr->user_data);
dev_ptr->register_components(dev,name,flags,sd);
return RT_EOK;
}else if (strstr(name,"udisk")!=RT_NULL){
struct virtual_storage_device * dev_ptr=(struct virtual_storage_device *)(ptr->user_data);
dev_ptr->register_components(dev,name,flags,udisk);
return RT_EOK;
}
}
//
rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
dev->flag = flags;
dev->ref_count = 0;