/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url) { // check tb_assert_and_check_return_val(url, 0); // done tb_size_t score = 0; tb_stream_ref_t stream = tb_null; do { // the url arguments tb_char_t const* args = tb_url_args(url); if (args) { // find the database type tb_char_t const* ptype = tb_stristr(args, "type="); if (ptype && !tb_strnicmp(ptype + 5, "sqlite3", 7)) { // ok score = 100; break; } } // has host or port? no sqlite3 if (tb_url_host(url) || tb_url_port(url)) break; // the database path tb_char_t const* path = tb_url_cstr((tb_url_ref_t)url); tb_assert_and_check_break(path); // is file? if (tb_url_protocol(url) == TB_URL_PROTOCOL_FILE) score += 20; // init stream stream = tb_stream_init_from_url(path); tb_assert_and_check_break(stream); // open stream if (!tb_stream_open(stream)) break; // read head tb_char_t head[16] = {0}; if (!tb_stream_bread(stream, (tb_byte_t*)head, 15)) break; // is sqlite3? if (!tb_stricmp(head, "SQLite format 3")) score = 100; } while (0); // exit stream if (stream) tb_stream_exit(stream); stream = tb_null; // trace tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score); // ok? return score; }
static tb_void_t tb_async_transfer_ostream_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) { // check tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv; tb_assert_and_check_return(stream && impl); // trace tb_trace_d("clos: ostream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state)); // done func tb_async_transfer_clos_func(impl, state); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_void_t tb_async_stream_clos_opening(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) { // check tb_async_stream_impl_t* impl = tb_async_stream_impl(stream); tb_assert_and_check_return(impl); // trace tb_trace_d("clos: opening: %s, state: %s", tb_url_cstr(&impl->url), tb_state_cstr(impl->clos_opening.state)); // closed tb_atomic_set(&impl->istate, TB_STATE_CLOSED); // done func if (impl->clos_opening.func) impl->clos_opening.func(stream, impl->clos_opening.state, impl->clos_opening.priv); }
static tb_bool_t tb_async_transfer_ostream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) { // check tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv; tb_assert_and_check_return_val(stream && impl && impl->open.func, tb_false); // trace tb_trace_d("open: ostream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state)); // done tb_bool_t ok = tb_true; do { // ok? tb_check_break(state == TB_STATE_OK); // reset state state = TB_STATE_UNKNOWN_ERROR; // check tb_assert_and_check_break(impl->istream); // killed? if (TB_STATE_KILLING == tb_atomic_get(&impl->state)) { state = TB_STATE_KILLED; break; } // done func ok = tb_async_transfer_open_func(impl, TB_STATE_OK, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), impl->open.func, impl->open.priv); // ok state = TB_STATE_OK; } while (0); // failed? if (state != TB_STATE_OK) { // done func ok = tb_async_transfer_open_func(impl, state, 0, 0, impl->open.func, impl->open.priv); } // ok return ok; }
static tb_bool_t tb_database_sqlite3_open(tb_database_sql_impl_t* database) { // check tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); tb_assert_and_check_return_val(sqlite, tb_false); // done tb_bool_t ok = tb_false; tb_char_t const* path = tb_null; do { // the database path path = tb_url_cstr(&database->url); tb_assert_and_check_break(path); // load sqlite3 library if (!tb_database_sqlite3_library_load()) break; // open database if (SQLITE_OK != sqlite3_open_v2(path, &sqlite->database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, tb_null) || !sqlite->database) { // error if (sqlite->database) { // save state sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); // trace tb_trace_e("open: %s failed, error[%d]: %s", path, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); } break; } // ok ok = tb_true; } while (0); // trace tb_trace_d("open: %s: %s", path, ok? "ok" : "no"); // ok? return ok; }
static tb_void_t tb_async_transfer_istream_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) { // check tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)priv; tb_assert_and_check_return(stream && impl); // trace tb_trace_d("clos: istream: %s, state: %s", tb_url_cstr(tb_async_stream_url(stream)), tb_state_cstr(state)); // done do { // ok? tb_check_break(state == TB_STATE_OK); // reset state state = TB_STATE_UNKNOWN_ERROR; // clos it if (!tb_async_stream_clos(impl->ostream, tb_async_transfer_ostream_clos_func, impl)) break; // ok state = TB_STATE_OK; } while (0); // failed? if (state != TB_STATE_OK) { // trace tb_trace_e("clos: failed: %s", tb_state_cstr(state)); // done func tb_async_transfer_clos_func(impl, state); } }