static __tb_inline__ tb_bool_t tb_check_mode(tb_size_t mode) { #ifdef __tb_debug__ if (!(mode & TB_MODE_DEBUG)) { tb_trace_e("libtbox.a has __tb_debug__ but tbox/tbox.h not"); return tb_false; } #else if (mode & TB_MODE_DEBUG) { tb_trace_e("tbox/tbox.h has __tb_debug__ but libtbox.a not"); return tb_false; } #endif #ifdef __tb_small__ if (!(mode & TB_MODE_SMALL)) { tb_trace_e("libtbox.a has __tb_small__ but tbox/tbox.h not"); return tb_false; } #else if (mode & TB_MODE_SMALL) { tb_trace_e("tbox/tbox.h has __tb_small__ but libtbox.a not"); return tb_false; } #endif // ok return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * thread */ static tb_char_t const* tb_demo_gets(tb_char_t* line, tb_size_t maxn) { // check tb_assert_and_check_return_val(line && maxn, tb_null); // done tb_char_t* p = line; tb_char_t* e = line + maxn; while (p < e) { // get character tb_char_t ch = getchar(); if (ch == '\r') getchar(); tb_check_break(ch != '\r' && ch != '\n'); // append digit if (tb_isdigit(ch)) *p++ = ch; else { // trace tb_trace_e("invalid character: %x, please input digit!", ch); } } // end if (p < e) *p = '\0'; // ok? return line; }
static tb_void_t tb_exception_signal_func(tb_int_t sig) { tb_stack_ref_t stack = (tb_stack_ref_t)tb_thread_local_get(&g_exception_local); if (stack && tb_stack_size(stack)) { #if defined(tb_sigsetjmp) && defined(tb_siglongjmp) tb_sigjmpbuf_t* jmpbuf = (tb_sigjmpbuf_t*)tb_stack_top(stack); if (jmpbuf) tb_siglongjmp(*jmpbuf, 1); #else tb_jmpbuf_t* jmpbuf = (tb_jmpbuf_t*)tb_stack_top(stack); if (jmpbuf) tb_longjmp(*jmpbuf, 1); #endif } else { // trace tb_trace_e("exception: no handler for signal: %d", sig); // ignore signal tb_signal(TB_SIGILL, TB_SIG_DFL); tb_signal(TB_SIGFPE, TB_SIG_DFL); tb_signal(TB_SIGBUS, TB_SIG_DFL); tb_signal(TB_SIGSEGV, TB_SIG_DFL); tb_signal(TB_SIGABRT, TB_SIG_DFL); #ifdef TB_CONFIG_LIBC_HAVE_KILL // kill it kill(getpid(), sig); #endif } }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t tb_aicp_walk_wait(tb_pointer_t item, tb_cpointer_t priv) { // check tb_aico_impl_t* aico = (tb_aico_impl_t*)item; tb_assert_and_check_return_val(aico, tb_false); // trace #ifdef __tb_debug__ tb_trace_e("aico[%p]: wait exited failed, type: %lu, handle: %p, state: %s for func: %s, line: %lu, file: %s", aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(tb_atomic_get(&aico->state)), aico->func, aico->line, aico->file); #else tb_trace_e("aico[%p]: wait exited failed, type: %lu, handle: %p, state: %s", aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(tb_atomic_get(&aico->state))); #endif // ok return tb_true; }
tb_pointer_t tb_static_pool_ralloc_(tb_static_pool_ref_t pool, tb_pointer_t data, tb_size_t size __tb_debug_decl__) { // check tb_assert_and_check_return_val(pool && data && size, tb_null); tb_assert_and_check_return_val(size <= TB_POOL_DATA_SIZE_MAXN, tb_null); // ralloc data tb_pointer_t data_new = tb_static_large_pool_ralloc(pool, data, size, tb_null __tb_debug_args__); // failed? dump it #ifdef __tb_debug__ if (!data_new) { // trace tb_trace_e("ralloc(%p, %lu) failed! at %s(): %lu, %s", data, size, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[static_pool]: [error]: "); // abort tb_abort(); } #endif // check tb_assertf_abort(!(((tb_size_t)data_new) & (TB_POOL_DATA_ALIGN - 1)), "ralloc(%lu): unaligned data: %p", size, data); // ok return data_new; }
tb_bool_t tb_static_pool_free_(tb_static_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__) { // check tb_assert_and_check_return_val(pool && data, tb_false); // free data tb_bool_t ok = tb_static_large_pool_free(pool, data __tb_debug_args__); // failed? dump it #ifdef __tb_debug__ if (!ok) { // trace tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[static_pool]: [error]: "); // abort tb_abort(); } #endif // ok return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_bool_t tb_aiop_rtor_epoll_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo) { // check tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor; tb_assert_and_check_return_val(impl && impl->epfd > 0 && aioo && aioo->sock, tb_false); // the code tb_size_t code = aioo->code; // init event struct epoll_event e = {0}; if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) e.events |= EPOLLIN; if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) e.events |= EPOLLOUT; if (code & TB_AIOE_CODE_CLEAR) e.events |= EPOLLET; #ifdef EPOLLONESHOT if (code & TB_AIOE_CODE_ONESHOT) e.events |= EPOLLONESHOT; #endif e.data.u64 = tb_p2u64(aioo); // add aioo if (epoll_ctl(impl->epfd, EPOLL_CTL_ADD, tb_sock2fd(aioo->sock), &e) < 0) { // trace tb_trace_e("addo aioo[%p], code: %lu failed, errno: %d", aioo, code, errno); return tb_false; } // ok return tb_true; }
static tb_void_t gb_device_skia_draw_path(gb_device_impl_t* device, gb_path_ref_t path) { // check gb_skia_device_ref_t impl = (gb_skia_device_ref_t)device; tb_assert_and_check_return(impl && impl->canvas && impl->path && path); // apply matrix gb_device_skia_apply_matrix(impl); // apply paint gb_device_skia_apply_paint(impl); // clear path impl->path->reset(); // init the path fill type tb_size_t rule = gb_paint_fill_rule(impl->base.paint); switch (rule) { case GB_PAINT_FILL_RULE_ODD: impl->path->setFillType(SkPath::kEvenOdd_FillType); break; case GB_PAINT_FILL_RULE_NONZERO: impl->path->setFillType(SkPath::kWinding_FillType); break; default: break; } // done tb_for_all_if (gb_path_item_ref_t, item, path, item) { switch (item->code) { case GB_PATH_CODE_MOVE: impl->path->moveTo(gb_float_to_sk(item->points[0].x), gb_float_to_sk(item->points[0].y)); break; case GB_PATH_CODE_LINE: impl->path->lineTo(gb_float_to_sk(item->points[1].x), gb_float_to_sk(item->points[1].y)); break; case GB_PATH_CODE_QUAD: impl->path->quadTo(gb_float_to_sk(item->points[1].x), gb_float_to_sk(item->points[1].y), gb_float_to_sk(item->points[2].x), gb_float_to_sk(item->points[2].y)); break; case GB_PATH_CODE_CUBIC: impl->path->cubicTo(gb_float_to_sk(item->points[1].x), gb_float_to_sk(item->points[1].y), gb_float_to_sk(item->points[2].x), gb_float_to_sk(item->points[2].y), gb_float_to_sk(item->points[3].x), gb_float_to_sk(item->points[3].y)); break; case GB_PATH_CODE_CLOS: impl->path->close(); break; default: // trace tb_trace_e("invalid code: %lu", item->code); break; } } // draw it impl->canvas->drawPath(*impl->path, *impl->paint); }
static tb_void_t tb_aiop_ptor_exit(tb_aicp_ptor_impl_t* ptor) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; tb_assert_and_check_return(impl); // trace tb_trace_d("exit"); // exit file tb_aicp_file_exit(impl); // exit loop if (impl->loop) { tb_long_t wait = 0; if ((wait = tb_thread_wait(impl->loop, 5000)) <= 0) { // trace tb_trace_e("loop[%p]: wait failed: %ld!", impl->loop, wait); } tb_thread_exit(impl->loop); impl->loop = tb_null; } // exit spak tb_spinlock_enter(&impl->lock); if (impl->spak[0]) tb_queue_exit(impl->spak[0]); if (impl->spak[1]) tb_queue_exit(impl->spak[1]); impl->spak[0] = tb_null; impl->spak[1] = tb_null; tb_spinlock_leave(&impl->lock); // exit aiop if (impl->aiop) tb_aiop_exit(impl->aiop); impl->aiop = tb_null; // exit list if (impl->list) tb_free(impl->list); impl->list = tb_null; // exit wait if (impl->wait) tb_semaphore_exit(impl->wait); impl->wait = tb_null; // exit timer if (impl->timer) tb_timer_exit(impl->timer); impl->timer = tb_null; // exit ltimer if (impl->ltimer) tb_ltimer_exit(impl->ltimer); impl->ltimer = tb_null; // exit lock tb_spinlock_exit(&impl->lock); // exit it tb_free(impl); }
tb_bool_t tb_transfer_pool_exit(tb_transfer_pool_ref_t pool) { // check tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool; tb_assert_and_check_return_val(impl, tb_false); // trace tb_trace_d("exit: .."); // kill it first tb_transfer_pool_kill(pool); // wait all if (tb_transfer_pool_wait_all(pool, 5000) <= 0) { // trace tb_trace_e("exit: wait failed!"); return tb_false; } // enter tb_spinlock_enter(&impl->lock); // check tb_assert(!tb_list_entry_size(&impl->work)); // exit the work list tb_list_entry_exit(&impl->work); // exit the idle list tb_list_entry_exit(&impl->idle); // exit pool if (impl->pool) { // exit all task tb_fixed_pool_walk(impl->pool, tb_transfer_pool_walk_exit, tb_null); // exit it tb_fixed_pool_exit(impl->pool); impl->pool = tb_null; } // leave tb_spinlock_leave(&impl->lock); // exit lock tb_spinlock_exit(&impl->lock); // exit it tb_free(pool); // trace tb_trace_d("exit: ok"); // ok return tb_true; }
tb_bool_t tb_async_transfer_init_istream_from_url(tb_async_transfer_ref_t transfer, tb_char_t const* url) { // check tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer; tb_assert_and_check_return_val(impl && impl->aicp && url, tb_false); // muse be closed tb_assert_and_check_return_val(TB_STATE_CLOSED == tb_atomic_get(&impl->state), tb_false); // check stream type if (impl->istream) { // probe protocol tb_size_t protocol = tb_url_protocol_probe(url); tb_assert_static((tb_size_t)TB_URL_PROTOCOL_FILE == (tb_size_t)TB_STREAM_TYPE_FILE); tb_assert_static((tb_size_t)TB_URL_PROTOCOL_HTTP == (tb_size_t)TB_STREAM_TYPE_HTTP); tb_assert_static((tb_size_t)TB_URL_PROTOCOL_SOCK == (tb_size_t)TB_STREAM_TYPE_SOCK); tb_assert_static((tb_size_t)TB_URL_PROTOCOL_DATA == (tb_size_t)TB_STREAM_TYPE_DATA); // protocol => type tb_size_t type = protocol; if (!type || type > TB_STREAM_TYPE_DATA) { tb_trace_e("unknown stream for url: %s", url); return tb_false; } // exit the previous stream first if be different stream type if (tb_async_stream_type(impl->istream) != type) { if (impl->iowner) tb_async_stream_exit(impl->istream); impl->istream = tb_null; } } // using the previous stream? if (impl->istream) { // ctrl stream if (!tb_async_stream_ctrl(impl->istream, TB_STREAM_CTRL_SET_URL, url)) return tb_false; } else { // init stream impl->istream = tb_async_stream_init_from_url(impl->aicp, url); tb_assert_and_check_return_val(impl->istream, tb_false); // init owner impl->iowner = 1; } // ok return tb_true; }
tb_bool_t tb_small_pool_free_(tb_small_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__) { // check tb_small_pool_impl_t* impl = (tb_small_pool_impl_t*)pool; tb_assert_and_check_return_val(impl && impl->large_pool && data, tb_false); // disable small pool for debug #ifdef TB_SMALL_POOL_DISABLE return tb_large_pool_free(impl->large_pool, data); #endif // done tb_bool_t ok = tb_false; do { // the data head tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_assertf_break(data_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data); // the fixed pool tb_fixed_pool_ref_t fixed_pool = tb_small_pool_find_fixed(impl, data_head->size); tb_assert_and_check_break(fixed_pool); // the data space tb_size_t space = tb_fixed_pool_item_size(fixed_pool); tb_assert_and_check_break(space >= data_head->size); // check underflow tb_assertf_break(space == data_head->size || ((tb_byte_t*)data)[data_head->size] == TB_POOL_DATA_PATCH, "data underflow"); // done ok = tb_fixed_pool_free_(fixed_pool, data __tb_debug_args__); } while (0); // failed? dump it #ifdef __tb_debug__ if (!ok) { // trace tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[small_pool]: [error]: "); // abort tb_abort(); } #endif // ok? return ok; }
tb_bool_t tb_aicp_post_(tb_aicp_ref_t aicp, tb_aice_ref_t aice __tb_debug_decl__) { // check tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; tb_assert_and_check_return_val(impl && impl->ptor && impl->ptor->post, tb_false); tb_assert_and_check_return_val(aice && aice->aico, tb_false); // the aico tb_aico_impl_t* aico = (tb_aico_impl_t*)aice->aico; tb_assert_and_check_return_val(aico, tb_false); // opened or killed or closed? pending it tb_size_t state = tb_atomic_fetch_and_pset(&aico->state, TB_STATE_OPENED, TB_STATE_PENDING); if (state == TB_STATE_OPENED || state == TB_STATE_KILLED) { // save debug info #ifdef __tb_debug__ aico->func = func_; aico->file = file_; aico->line = line_; #endif // post aice return impl->ptor->post(impl->ptor, aice); } // trace #ifdef __tb_debug__ tb_trace_e("post aice[%lu] failed, the aico[%p]: type: %lu, handle: %p, state: %s for func: %s, line: %lu, file: %s", aice->code, aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(state), func_, line_, file_); #else tb_trace_e("post aice[%lu] failed, the aico[%p]: type: %lu, handle: %p, state: %s", aice->code, aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(state)); #endif // abort it tb_assert(0); // post failed return tb_false; }
static tb_bool_t tb_aiop_rtor_epoll_post(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t aioe) { // check tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor; tb_assert_and_check_return_val(impl && impl->epfd > 0 && aioe, tb_false); // the code tb_size_t code = aioe->code; // the priv tb_cpointer_t priv = aioe->priv; // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)aioe->aioo; tb_assert_and_check_return_val(aioo && aioo->sock, tb_false); // init event struct epoll_event e = {0}; if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) e.events |= EPOLLIN; if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) e.events |= EPOLLOUT; if (code & TB_AIOE_CODE_CLEAR) e.events |= EPOLLET; #ifdef EPOLLONESHOT if (code & TB_AIOE_CODE_ONESHOT) e.events |= EPOLLONESHOT; #endif e.data.u64 = tb_p2u64(aioo); // save aioo tb_aioo_impl_t prev = *aioo; aioo->code = code; aioo->priv = priv; // sete if (epoll_ctl(impl->epfd, EPOLL_CTL_MOD, tb_sock2fd(aioo->sock), &e) < 0) { // re-add it #ifndef EPOLLONESHOT if (errno == ENOENT && epoll_ctl(impl->epfd, EPOLL_CTL_ADD, tb_sock2fd(aioo->sock), &e) >= 0) return tb_true; #endif // trace tb_trace_e("post aice code: %lu failed, errno: %d", code, errno); // restore aioo *aioo = prev; return tb_false; } // ok return tb_true; }
/* ////////////////////////////////////////////////////////////////////////////////////// * library implementation */ static tb_handle_t tb_database_sqlite3_library_init(tb_cpointer_t* ppriv) { // init it tb_int_t ok = SQLITE_OK; if ((ok = sqlite3_initialize()) != SQLITE_OK) { // trace tb_trace_e("init: sqlite3 library failed, error: %d", ok); return tb_null; } // ok return ppriv; }
tb_bool_t tb_pool_free_(tb_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__) { // check tb_pool_impl_t* impl = (tb_pool_impl_t*)pool; tb_assert_and_check_return_val(impl, tb_false); // uses allocator? if (impl->allocator) return tb_allocator_free_(impl->allocator, data __tb_debug_args__); // check tb_assert_and_check_return_val(impl->large_pool && impl->small_pool && data, tb_false); // enter tb_spinlock_enter(&impl->lock); // done tb_bool_t ok = tb_false; do { // the data head tb_pool_data_head_t* data_head = &(((tb_pool_data_head_t*)data)[-1]); tb_assertf_break(data_head->debug.magic == TB_POOL_DATA_MAGIC, "free invalid data: %p", data); // free it ok = (data_head->size <= TB_SMALL_POOL_DATA_SIZE_MAXN)? tb_small_pool_free_(impl->small_pool, data __tb_debug_args__) : tb_large_pool_free_(impl->large_pool, data __tb_debug_args__); } while (0); // failed? dump it #ifdef __tb_debug__ if (!ok) { // trace tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[pool]: [error]: "); // abort tb_abort(); } #endif // leave tb_spinlock_leave(&impl->lock); // ok? return ok; }
tb_void_t tb_aiop_delo(tb_aiop_ref_t aiop, tb_aioo_ref_t aioo) { // check tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; tb_assert_and_check_return(impl && impl->rtor && impl->rtor->delo && aioo); // delete aioo from aiop if (!impl->rtor->delo(impl->rtor, (tb_aioo_impl_t*)aioo)) { // trace tb_trace_e("delo: aioo[%p] failed!", aioo); } // exit aioo tb_aiop_aioo_exit(impl, aioo); }
tb_bool_t tb_async_transfer_exit(tb_async_transfer_ref_t transfer) { // chec:w tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer; tb_assert_and_check_return_val(impl, tb_false); // trace tb_trace_d("exit: .."); // kill it first tb_async_transfer_kill(transfer); // try closing it tb_size_t tryn = 30; tb_bool_t ok = tb_false; while (!(ok = tb_async_transfer_clos_try(transfer)) && tryn--) { // wait some time tb_msleep(200); } // close failed? if (!ok) { // trace tb_trace_e("exit: failed!"); return tb_false; } // exit istream if (impl->istream && impl->iowner) tb_async_stream_exit(impl->istream); impl->istream = tb_null; // exit ostream if (impl->ostream && impl->oowner) tb_async_stream_exit(impl->ostream); impl->ostream = tb_null; // exit impl tb_free(impl); // trace tb_trace_d("exit: ok"); // ok return tb_true; }
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_bool_t tb_database_sqlite3_rollback(tb_database_sql_impl_t* database) { // check tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false); // done rollback if (SQLITE_OK != sqlite3_exec(sqlite->database, "rollback;", tb_null, tb_null, tb_null)) { // save state sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); // trace tb_trace_e("rollback: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); return tb_false; } // ok return tb_true; }
static tb_database_sql_statement_ref_t tb_database_sqlite3_statement_init(tb_database_sql_impl_t* database, tb_char_t const* sql) { // check tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); tb_assert_and_check_return_val(sqlite && sqlite->database && sql, tb_null); // init statement sqlite3_stmt* statement = tb_null; if (SQLITE_OK != sqlite3_prepare_v2(sqlite->database, sql, -1, &statement, 0)) { // save state sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); // trace tb_trace_e("statement: init %s failed, error[%d]: %s", sql, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); } // ok? return (tb_database_sql_statement_ref_t)statement; }
tb_void_t tb_static_fixed_pool_dump(tb_static_fixed_pool_ref_t self) { // check tb_static_fixed_pool_t* pool = (tb_static_fixed_pool_t*)self; tb_assert_and_check_return(pool && pool->used_info); // dump tb_size_t index = 0; for (index = 0; index < pool->item_maxn; ++index) { // leak? if (tb_static_fixed_pool_used_bset(pool->used_info, index)) { // the data head tb_pool_data_empty_head_t* data_head = (tb_pool_data_empty_head_t*)(pool->data + index * pool->item_space); // check it tb_static_fixed_pool_check_data(pool, data_head); // the data tb_byte_t const* data = (tb_byte_t const*)data_head + pool->data_head_size; // trace tb_trace_e("leak: %p", data); // dump data tb_pool_data_dump(data, tb_false, "[static_fixed_pool]: [error]: "); } } // trace debug info tb_trace_i("[%lu]: peak_size: %lu, wast_rate: %llu/10000, pred_failed: %lu, item_maxn: %lu, free_count: %lu, malloc_count: %lu" , pool->item_size , pool->peak_size , pool->occupied_size? (((tb_hize_t)pool->occupied_size - pool->real_size) * 10000) / (tb_hize_t)pool->occupied_size : 0 , pool->pred_failed , pool->item_maxn , pool->free_count , pool->malloc_count); }
/* ////////////////////////////////////////////////////////////////////////////////////// * test */ static tb_void_t tb_demo_database_sql_test_done(tb_database_sql_ref_t database, tb_char_t const* sql) { // check tb_assert_and_check_return(database && sql); // done do { // done sql if (!tb_database_sql_done(database, sql)) { // trace tb_trace_e("done %s failed, error: %s", sql, tb_state_cstr(tb_database_sql_state(database))); break ; } // load result // tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_true); tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_false); tb_check_break(result); // trace tb_trace_i("=============================================================================="); tb_trace_i("row: size: %lu", tb_iterator_size(result)); // walk result tb_for_all_if (tb_iterator_ref_t, row, result, row) { // trace tb_tracef_i("[row: %lu, col: size: %lu]: ", row_itor, tb_iterator_size(row)); // walk items tb_for_all_if (tb_database_sql_value_t*, value, row, value) { // trace tb_tracet_i("[%s:%s] ", tb_database_sql_value_name(value), tb_database_sql_value_text(value)); } // trace tb_tracet_i(__tb_newline__); }
static tb_bool_t tb_demo_spider_task_save(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv) { // check tb_demo_spider_task_t* task = (tb_demo_spider_task_t*)priv; tb_assert_and_check_return_val(task && task->spider, tb_false); // percent #ifdef TB_TRACE_DEBUG tb_size_t percent = 0; if (size > 0) percent = (tb_size_t)((offset * 100) / size); else if (state == TB_STATE_OK) percent = 100; // trace tb_trace_d("save[%s]: %llu, rate: %lu bytes/s, percent: %lu%%, state: %s", task->iurl, save, rate, percent, tb_state_cstr(state)); #endif // ok? continue it tb_bool_t ok = tb_false; if (state == TB_STATE_OK) ok = tb_true; // closed? else if (state == TB_STATE_CLOSED && TB_STATE_OK == tb_atomic_get(&task->spider->state)) { // trace tb_trace_i("task: done: %s: ok", task->iurl); // post parser task tb_thread_pool_task_post(tb_thread_pool(), "parser_task", tb_demo_spider_parser_task_done, tb_demo_spider_parser_task_exit, task, tb_false); } // failed or killed? else { // trace tb_trace_e("task: done: %s: %s", task->iurl, tb_state_cstr(state)); // exit task tb_demo_spider_task_exit(task); } // break or continue? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_bool_t tb_aiop_rtor_kqueue_sync(tb_aiop_rtor_impl_t* rtor, struct kevent* evts, tb_size_t evtn) { // check tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor; tb_assert_and_check_return_val(impl && impl->kqfd >= 0, tb_false); tb_assert_and_check_return_val(evts && evtn, tb_false); // change events struct timespec t = {0}; if (kevent(impl->kqfd, evts, evtn, tb_null, 0, &t) < 0) { // trace tb_trace_e("sync failed, errno: %d", errno); // failed return tb_false; } // ok return tb_true; }
tb_bool_t tb_file_exit(tb_file_ref_t file) { // check tb_assert_and_check_return_val(file, tb_false); // trace tb_trace_d("clos: %p", file); // close it tb_bool_t ok = !close(tb_file2fd(file))? tb_true : tb_false; // failed? if (!ok) { // trace tb_trace_e("close: %p failed, errno: %d", file, errno); } // ok? return ok; }
tb_void_t tb_aiop_spak(tb_aiop_ref_t aiop) { // check tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; tb_assert_and_check_return(impl); // spak it if (impl->spak[0]) { // post: 'p' tb_long_t ok = tb_socket_send(impl->spak[0], (tb_byte_t const*)"p", 1); if (ok != 1) { // trace tb_trace_e("spak: failed!"); // abort it tb_assert(0); } } }
tb_pointer_t tb_allocator_ralloc_(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__) { // check tb_assert_and_check_return_val(allocator, tb_null); // enter tb_spinlock_enter(&allocator->lock); // ralloc it tb_pointer_t data_new = tb_null; if (allocator->ralloc) data_new = allocator->ralloc(allocator, data, size __tb_debug_args__); else if (allocator->large_ralloc) data_new = allocator->large_ralloc(allocator, data, size, tb_null __tb_debug_args__); // trace tb_trace_d("ralloc(%p, %lu): %p at %s(): %d, %s", data, size, data_new __tb_debug_args__); // failed? dump it #ifdef __tb_debug__ if (!data_new) { // trace tb_trace_e("ralloc(%p, %lu) failed! at %s(): %lu, %s", data, size, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[large_allocator]: [error]: "); // abort tb_abort(); } #endif // check tb_assertf(!(((tb_size_t)data_new) & (TB_POOL_DATA_ALIGN - 1)), "ralloc(%lu): unaligned data: %p", size, data); // leave tb_spinlock_leave(&allocator->lock); // ok? return data_new; }
static tb_size_t tb_database_sqlite3_result_row_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; tb_assert(result); tb_assert_and_check_return_val(itor < result->count, result->count); // statement result? if (result->statement) { // step statement tb_int_t ok = sqlite3_step(result->statement); // end? if (ok != SQLITE_ROW) { // reset it if (SQLITE_OK != sqlite3_reset(result->statement)) { // the sqlite tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv; if (sqlite) { // save state sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); // trace tb_trace_e("statement: reset failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); } } // tail return result->count; } } // next return itor + 1; }
static tb_bool_t tb_aiop_push_sock(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(impl && aice && aice->aico, tb_false); // the priority tb_size_t priority = tb_aice_impl_priority(aice); tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); // this aico is killed? post to higher priority queue if (tb_aico_impl_is_killed((tb_aico_impl_t*)aice->aico)) priority = 0; // trace tb_trace_d("push: aico: %p, handle: %p, code: %lu, priority: %lu", aice->aico, tb_aico_sock(aice->aico), aice->code, priority); // enter tb_spinlock_enter(&impl->lock); // not full? if (!tb_queue_full(impl->spak[priority])) { // push aice to the spak queue tb_queue_put(impl->spak[priority], aice); // wait ok if be not acpt aice if (aice->code != TB_AICE_CODE_ACPT) ((tb_aiop_aico_t*)aice->aico)->wait_ok = 1; } else { // trace tb_trace_e("push: failed, the spak queue is full!"); } // leave tb_spinlock_leave(&impl->lock); // ok return tb_true; }