static tb_bool_t tb_ifaddrs_interface_load(tb_list_ref_t interfaces, tb_long_t sock, tb_long_t request) { // trace tb_trace_d("netlink: load: .."); // send request if (tb_ifaddrs_netlink_socket_send(sock, request) < 0) return tb_false; // make names tb_hash_map_ref_t names = tb_hash_map_init(8, tb_element_size(), tb_element_str(tb_true)); tb_assert_and_check_return_val(names, tb_false); // done tb_long_t ok = -1; while (!(ok = tb_ifaddrs_interface_done(interfaces, names, sock, request))) ; // trace tb_trace_d("netlink: load: %s", ok > 0? "ok" : "no"); // exit names if (names) tb_hash_map_exit(names); names = tb_null; // ok? return ok > 0; }
tb_void_t tb_aico_exit(tb_aico_ref_t aico) { // check tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; tb_assert_and_check_return(impl && aicp_impl && aicp_impl->pool); // wait closing? tb_size_t tryn = 15; while (tb_atomic_get(&impl->state) != TB_STATE_CLOSED && tryn--) { // trace tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: wait: ..", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state))); // wait some time tb_msleep(200); } // check tb_assert_abort(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); tb_check_return(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); // enter tb_spinlock_enter(&aicp_impl->lock); // trace tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: ok", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state))); // free it tb_fixed_pool_free(aicp_impl->pool, aico); // leave tb_spinlock_leave(&aicp_impl->lock); }
static tb_long_t tb_aiop_spak_acpt(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(impl && aice, -1); tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_ACPT, -1); // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; tb_assert_and_check_return_val(aico && aico->base.handle, -1); tb_assert_and_check_return_val(!aico->waiting, -1); // trace tb_trace_d("acpt[%p]: wait: ..", aico); // wait ok? if (tb_aiop_spak_wait(impl, aice)) return 0; // wait failed else aice->state = TB_STATE_FAILED; // trace tb_trace_d("acpt[%p]: wait: failed", aico); // reset wait aico->waiting = 0; aico->aice.code = TB_AICE_CODE_NONE; // ok return 1; }
tb_void_t tb_aico_kill(tb_aico_ref_t aico) { // check tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; tb_assert_and_check_return(impl && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->kilo); // the impl is killed and not worked? tb_check_return(!tb_atomic_get(&aicp_impl->kill) || tb_atomic_get(&aicp_impl->work)); // trace tb_trace_d("kill: aico[%p]: type: %lu, handle: %p: state: %s: ..", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&((tb_aico_impl_t*)aico)->state))); // opened? killed if (TB_STATE_OPENED == tb_atomic_fetch_and_pset(&impl->state, TB_STATE_OPENED, TB_STATE_KILLED)) { // trace tb_trace_d("kill: aico[%p]: type: %lu, handle: %p: ok", aico, tb_aico_type(aico), impl->handle); } // pending? kill it else if (TB_STATE_PENDING == tb_atomic_fetch_and_pset(&impl->state, TB_STATE_PENDING, TB_STATE_KILLING)) { // kill aico aicp_impl->ptor->kilo(aicp_impl->ptor, impl); // trace tb_trace_d("kill: aico[%p]: type: %lu, handle: %p: state: pending: ok", aico, tb_aico_type(aico), impl->handle); } }
static tb_long_t tb_ssl_bio_method_ctrl(BIO* bio, tb_int_t cmd, tb_long_t num, tb_pointer_t ptr) { // check tb_assert_and_check_return_val(bio, -1); // the ssl tb_ssl_t* ssl = (tb_ssl_t*)bio->ptr; tb_assert_and_check_return_val(ssl, -1); // done tb_long_t ok = 0; switch (cmd) { case BIO_CTRL_FLUSH: { // trace tb_trace_d("bio: ctrl: flush"); // ok ok = 1; } break; default: { // trace tb_trace_d("bio: ctrl: unknown: %d", cmd); } break; } // ok? return ok; }
static tb_void_t tb_aiop_ptor_kilo(tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; tb_assert_and_check_return(impl && impl->timer && impl->ltimer && impl->aiop && aico); // trace tb_trace_d("kilo: aico: %p, type: %u: ..", aico, aico->type); // the aiop aico tb_aiop_aico_t* aiop_aico = (tb_aiop_aico_t*)aico; // add timeout task for killing the accept socket if (aico->type == TB_AICO_TYPE_SOCK && aiop_aico->aice.code == TB_AICE_CODE_ACPT) { // add task if (!aiop_aico->task) { aiop_aico->task = tb_ltimer_task_init(impl->ltimer, 10000, tb_false, tb_aiop_spak_wait_timeout, aico); aiop_aico->bltimer = 1; } } // kill the task if (aiop_aico->task) { // trace tb_trace_d("kilo: aico: %p, type: %u, task: %p: ..", aico, aico->type, aiop_aico->task); // kill task if (aiop_aico->bltimer) tb_ltimer_task_kill(impl->ltimer, aiop_aico->task); else tb_timer_task_kill(impl->timer, aiop_aico->task); } // kill sock if (aico->type == TB_AICO_TYPE_SOCK && aico->handle) { // trace tb_trace_d("kilo: aico: %p, type: %u, sock: %p: ..", aico, aico->type, aico->handle); // kill it tb_socket_kill(aico->handle, TB_SOCKET_KILL_RW); } // kill file else if (aico->type == TB_AICO_TYPE_FILE) { // kill it tb_aicp_file_kilo(impl, aico); } /* the aiop will wait long time if the lastest task wait period is too long * so spak the aiop manually for spak the ltimer */ tb_aiop_spak(impl->aiop); // trace tb_trace_d("kilo: aico: %p, type: %u: ok", aico, aico->type); }
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; }
static tb_bool_t tb_aicp_dns_reqt_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_USEND, tb_false); // the aicp tb_aicp_ref_t aicp = (tb_aicp_ref_t)tb_aico_aicp(aice->aico); tb_assert_and_check_return_val(aicp, tb_false); // the impl tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)aice->priv; tb_assert_and_check_return_val(impl && impl->done.func, tb_false); // done tb_bool_t ok = tb_false; if (aice->state == TB_STATE_OK) { // trace tb_trace_d("reqt[%s]: aico: %p, server: %{ipaddr}, real: %lu", impl->host, impl->aico, &aice->u.usend.addr, aice->u.usend.real); // check tb_assert_and_check_return_val(aice->u.usend.real, tb_false); // post resp ok = tb_aico_urecv(aice->aico, impl->data, sizeof(impl->data), tb_aicp_dns_resp_func, (tb_pointer_t)impl); } // timeout or failed? else { // trace tb_trace_d("reqt[%s]: aico: %p, server: %{ipaddr}, state: %s", impl->host, impl->aico, &aice->u.usend.addr, tb_state_cstr(aice->state)); // the next server tb_ipaddr_ref_t server = &impl->list[impl->indx + 1]; if (!tb_ipaddr_is_empty(server)) { // indx++ impl->indx++; // init reqt tb_size_t size = tb_aicp_dns_reqt_init(impl); if (size) { // post reqt ok = tb_aico_usend(aice->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl); } } } // failed? done func if (!ok) impl->done.func((tb_aicp_dns_ref_t)impl, impl->host, tb_null, impl->done.priv); // continue return tb_true; }
static tb_void_t tb_demo_coroutine_client(tb_cpointer_t priv) { // check tb_socket_ref_t sock = (tb_socket_ref_t)priv; tb_assert_and_check_return(sock); // done tb_demo_http_session_t session; do { // init session if (!tb_demo_http_session_init(&session, sock)) break; // read the request header if (!tb_demo_http_session_head_recv(&session)) break; // trace tb_trace_d("path: %s", session.path); // get file or data? tb_char_t const* data = tb_null; if (session.method == TB_HTTP_METHOD_GET) { // only send data? if (g_onlydata) data = g_rootdir; else { // make full path tb_long_t size = tb_snprintf((tb_char_t*)session.data, sizeof(session.data), "%s%s%s", g_rootdir, session.path[0] != '/'? "/" : "", session.path); if (size > 0) session.data[size] = 0; // init file session.file = tb_file_init((tb_char_t*)session.data, TB_FILE_MODE_RO | TB_FILE_MODE_BINARY); // not found? if (!session.file) session.code = TB_HTTP_CODE_NOT_FOUND; } } // send the response if (!tb_demo_http_session_resp_send(&session, data)) break; // exit file if (session.file) tb_file_exit(session.file); session.file = tb_null; // trace tb_trace_d("ok!"); } while (session.keep_alive); // exit session tb_demo_http_session_exit(&session); }
static tb_void_t tb_demo_spider_exit(tb_demo_spider_t* spider) { // check tb_assert_and_check_return(spider); // trace tb_trace_d("exit: .."); // kill it tb_atomic_set(&spider->state, TB_STATE_KILLING); // kill all transfer tasks tb_transfer_pool_kill_all(tb_transfer_pool()); // kill all parser tasks tb_thread_pool_task_kill_all(tb_thread_pool()); // wait all transfer tasks exiting tb_transfer_pool_wait_all(tb_transfer_pool(), -1); // wait all parser tasks exiting tb_thread_pool_task_wait_all(tb_thread_pool(), -1); // enter tb_spinlock_enter(&spider->lock); // exit filter if (spider->filter) tb_bloom_filter_exit(spider->filter); spider->filter = tb_null; // exit pool if (spider->pool) tb_fixed_pool_exit(spider->pool); spider->pool = tb_null; // leave tb_spinlock_leave(&spider->lock); // exit lock tb_spinlock_exit(&spider->lock); // exit home tb_url_exit(&spider->home); // exit option #ifdef TB_CONFIG_MODULE_HAVE_OBJECT if (spider->option) tb_option_exit(spider->option); spider->option = tb_null; #endif // trace tb_trace_d("exit: ok"); }
tb_void_t tb_database_sql_exit(tb_database_sql_ref_t database) { // check tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; tb_assert_and_check_return(impl); // trace tb_trace_d("exit: .."); // exit it if (impl->exit) impl->exit(impl); // trace tb_trace_d("exit: ok"); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t main(tb_int_t argc, tb_char_t const** argv) { // init tbox if (!tb_init(tb_null, tb_null)) return 0; // the itrace.dylib path tb_char_t path[PATH_MAX] = {0}; if (!realpath(argv[2]? argv[2] : "./libitrace.dylib", path)) return -1; // trace tb_trace_d("path: %s, pid: %u", path, it_pid(argv[1])); // wait pid pid_t pid = 0; while (!(pid = it_pid(argv[1]))) tb_msleep(500); // wait some time tb_msleep(1000); // inject it_inject(pid, path); // exit tbox tb_exit(); // ok return 0; }
static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_t* pool, tb_fixed_pool_slot_t* slot) { // check tb_assert_and_check_return(pool && pool->large_allocator && slot); tb_assert_and_check_return(pool->slot_list && pool->slot_count); // trace tb_trace_d("slot[%lu]: exit: size: %lu", pool->item_size, slot->size); // make the iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_iterator_make_for_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count); tb_assert(iterator); // find the slot from the slot list tb_size_t itor = tb_binary_find_all(iterator, (tb_cpointer_t)slot); tb_assert(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]); tb_check_return(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]); // remove the slot if (itor + 1 < pool->slot_count) tb_memmov_(pool->slot_list + itor, pool->slot_list + itor + 1, (pool->slot_count - itor - 1) * sizeof(tb_fixed_pool_slot_t*)); // update the slot count pool->slot_count--; // exit slot tb_allocator_large_free(pool->large_allocator, slot); }
static tb_bool_t tb_demo_file_read_func(tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_READ, tb_false); // the context tb_demo_context_t* context = (tb_demo_context_t*)aice->priv; tb_assert_and_check_return_val(context, tb_false); // ok? if (aice->state == TB_STATE_OK) { // trace tb_trace_d("read[%p]: real: %lu, size: %lu, seek: %llu", aice->aico, aice->u.read.real, aice->u.read.size, aice->u.read.seek); // post send to client if (!tb_aico_send(context->aico[0], aice->u.read.data, aice->u.read.real, tb_demo_sock_send_func, context)) return tb_false; } // closed or failed? else { tb_trace_i("read[%p]: state: %s", aice->aico, tb_state_cstr(aice->state)); tb_demo_context_exit(context); } // ok return tb_true; }
static tb_long_t tb_dns_cache_cler(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(item, -1); // the dns cache address tb_dns_cache_addr_t const* caddr = (tb_dns_cache_addr_t const*)((tb_hash_item_t*)item)->data; tb_assert_and_check_return_val(caddr, -1); // is expired? tb_long_t ok = 1; if (caddr->time < g_cache.expired) { // remove it ok = 0; // trace tb_trace_d("del: %s => %u.%u.%u.%u, time: %u, size: %u", (tb_char_t const*)item->name , caddr->ipv4.u8[0] , caddr->ipv4.u8[1] , caddr->ipv4.u8[2] , caddr->ipv4.u8[3] , caddr->time , tb_hash_size(g_cache.hash)); // update times tb_assert_and_check_return_val(g_cache.times >= caddr->time, -1); g_cache.times -= caddr->time; } // ok? return ok; }
static tb_void_t tb_lo_scheduler_io_events(tb_poller_ref_t poller, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv) { // check tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv; tb_assert(coroutine && poller && sock && priv); // get scheduler tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler; tb_assert(scheduler); // trace tb_trace_d("coroutine(%p): socket: %p, events %lu", coroutine, sock, events); // waiting now? if (coroutine->rs.wait.waiting) { // eof for edge trigger? if (events & TB_POLLER_EVENT_EOF) { // cache this eof as next recv/send event events &= ~TB_POLLER_EVENT_EOF; coroutine->rs.wait.events_cache |= coroutine->rs.wait.events; } // resume the coroutine and pass the events to suspend() tb_lo_scheduler_io_resume(scheduler, coroutine, ((events & TB_POLLER_EVENT_ERROR)? -1 : events)); } // cache this events else coroutine->rs.wait.events_cache = events; }
static tb_bool_t tb_demo_spider_task_ctrl(tb_async_stream_ref_t istream, tb_async_stream_ref_t ostream, 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); tb_assert_and_check_return_val(istream && ostream, tb_false); tb_assert_and_check_return_val(tb_async_stream_type(istream) == TB_STREAM_TYPE_HTTP, tb_false); // the url tb_char_t const* url = tb_null; if (!tb_async_stream_ctrl(istream, TB_STREAM_CTRL_GET_URL, &url)) return tb_false; // trace tb_trace_d("ctrl: %s: ..", url); // set timeout if (!tb_async_stream_ctrl(istream, TB_STREAM_CTRL_SET_TIMEOUT, task->spider->timeout)) return tb_false; #if defined(TB_CONFIG_MODULE_HAVE_ZIP) && defined(TB_CONFIG_THIRD_HAVE_ZLIB) // need gzip if (!tb_async_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "Accept-Encoding", "gzip,deflate")) return tb_false; // auto unzip if (!tb_async_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_AUTO_UNZIP, 1)) return tb_false; #endif // user agent if (!tb_async_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_HEAD, "User-Agent", task->spider->user_agent)) return tb_false; // enable cookies if (!tb_async_stream_ctrl(istream, TB_STREAM_CTRL_HTTP_SET_COOKIES, tb_cookies())) return tb_false; // ok return tb_true; }
static tb_long_t tb_aiop_spak_sendf(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(impl && aice, -1); tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_SENDF, -1); tb_assert_and_check_return_val(aice->u.sendf.file && aice->u.sendf.size, -1); // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; tb_assert_and_check_return_val(aico && aico->base.handle, -1); // try to send it tb_long_t real = 0; tb_hize_t send = 0; tb_hize_t seek = aice->u.sendf.seek; tb_hize_t size = aice->u.sendf.size; tb_handle_t file = aice->u.sendf.file; while (send < size) { // send it real = tb_socket_sendf(aico->base.handle, file, seek + send, size - send); // save send if (real > 0) send += real; else break; } // trace tb_trace_d("sendf[%p]: %llu", aico, send); // no send? if (!send) { // wait it if (!real && !aico->waiting) { // wait ok? if (tb_aiop_spak_wait(impl, aice)) return 0; // wait failed else aice->state = TB_STATE_FAILED; } // closed else aice->state = TB_STATE_CLOSED; } else { // ok or closed? aice->state = TB_STATE_OK; // save the send size aice->u.sendf.real = send; } // reset wait aico->waiting = 0; aico->aice.code = TB_AICE_CODE_NONE; // ok return 1; }
static tb_bool_t tb_async_transfer_done_func(tb_async_transfer_impl_t* impl, tb_size_t state) { // check tb_assert_and_check_return_val(impl && impl->istream && impl->done.func, tb_false); // open failed? closed? if (TB_STATE_CLOSED == tb_atomic_get(&impl->state)) { // done func return impl->done.func(state, 0, 0, 0, 0, impl->done.priv); } // trace tb_trace_d("done: %llu bytes, rate: %lu bytes/s, state: %s", tb_async_stream_offset(impl->istream), impl->done.current_rate, tb_state_cstr(state)); // auto closing it? if (impl->autoclosing) { // killed or failed or closed? close it if ((state != TB_STATE_OK && state != TB_STATE_PAUSED) || (TB_STATE_KILLING == tb_atomic_get(&impl->state))) { // save the closed state impl->done.closed_state = (TB_STATE_KILLING == tb_atomic_get(&impl->state))? TB_STATE_KILLED : state; impl->done.closed_size = tb_async_stream_size(impl->istream); impl->done.closed_offset = tb_async_stream_offset(impl->istream); return tb_async_transfer_clos((tb_async_transfer_ref_t)impl, tb_async_transfer_done_clos_func, impl); } } // done return impl->done.func(state, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), impl->done.saved_size, impl->done.current_rate, impl->done.priv); }
tb_long_t tb_dns_looker_wait(tb_dns_looker_ref_t self, tb_long_t timeout) { // check tb_dns_looker_t* looker = (tb_dns_looker_t*)self; tb_assert_and_check_return_val(looker && looker->sock, -1); // has io event? tb_size_t e = TB_SOCKET_EVENT_NONE; if (!(looker->step & TB_DNS_LOOKER_STEP_NEVT)) { if (!(looker->step & TB_DNS_LOOKER_STEP_REQT)) e = TB_SOCKET_EVENT_SEND; else if (!(looker->step & TB_DNS_LOOKER_STEP_RESP)) e = TB_SOCKET_EVENT_RECV; } // need wait? tb_long_t r = 0; if (e) { // trace tb_trace_d("waiting %p ..", looker->sock); // wait r = tb_socket_wait(looker->sock, e, timeout); // fail or timeout? tb_check_return_val(r > 0, r); } // ok? return r; }
tb_bool_t vm86_parser_get_local_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value, tb_hash_map_ref_t proc_locals) { // check tb_assert(pp && e && value && proc_locals); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // get instruction name tb_char_t name[256] = {0}; if (!vm86_parser_get_variable_name(&p, e, name, sizeof(name))) break; // get value if (tb_hash_map_find(proc_locals, name) != tb_iterator_tail(proc_locals)) *value = (tb_uint32_t)tb_hash_map_get(proc_locals, name); else break; // trace tb_trace_d("local: %s: %u", name, *value); // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }
tb_int_t xm_machine_main(xm_machine_ref_t machine, tb_int_t argc, tb_char_t** argv) { // check xm_machine_impl_t* impl = (xm_machine_impl_t*)machine; tb_assert_and_check_return_val(impl && impl->lua, -1); // save main arguments to the global variable: _ARGV if (!xm_machine_main_save_arguments(impl, argc, argv)) return -1; // get the project directory tb_char_t path[TB_PATH_MAXN] = {0}; if (!xm_machine_main_get_project_directory(impl, path, sizeof(path))) return -1; // get the program directory if (!xm_machine_main_get_program_directory(impl, path, sizeof(path))) return -1; // append the main script path tb_strcat(path, "/core/_xmake_main.lua"); // exists this script? if (!tb_file_info(path, tb_null)) { // error tb_printf("not found main script: %s\n", path); // failed return -1; } // trace tb_trace_d("main: %s", path); // load and execute the main script if (luaL_dofile(impl->lua, path)) { // error tb_printf("error: %s\n", lua_tostring(impl->lua, -1)); // failed return -1; } // set the error function lua_getglobal(impl->lua, "debug"); lua_getfield(impl->lua, -1, "traceback"); // call the main function lua_getglobal(impl->lua, "_xmake_main"); if (lua_pcall(impl->lua, 0, 1, -2)) { // error tb_printf("error: %s\n", lua_tostring(impl->lua, -1)); // failed return -1; } // get the error code return (tb_int_t)lua_tonumber(impl->lua, -1); }
tb_pointer_t tb_allocator_malloc_(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__) { // check tb_assert_and_check_return_val(allocator, tb_null); // enter tb_spinlock_enter(&allocator->lock); // malloc it tb_pointer_t data = tb_null; if (allocator->malloc) data = allocator->malloc(allocator, size __tb_debug_args__); else if (allocator->large_malloc) data = allocator->large_malloc(allocator, size, tb_null __tb_debug_args__); // trace tb_trace_d("malloc(%lu): %p at %s(): %d, %s", size, data __tb_debug_args__); // check tb_assertf(data, "malloc(%lu) failed!", size); tb_assertf(!(((tb_size_t)data) & (TB_POOL_DATA_ALIGN - 1)), "malloc(%lu): unaligned data: %p", size, data); // leave tb_spinlock_leave(&allocator->lock); // ok? return data; }
tb_void_t tb_timer_task_exit(tb_timer_ref_t timer, tb_timer_task_ref_t task) { // check tb_timer_impl_t* impl = (tb_timer_impl_t*)timer; tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)task; tb_assert_and_check_return(impl && impl->pool && task_impl); // trace tb_trace_d("exit: when: %lld, period: %u, refn: %u", task_impl->when, task_impl->period, task_impl->refn); // enter tb_spinlock_enter(&impl->lock); // remove it? if (task_impl->refn > 1) { // refn-- task_impl->refn--; // cancel task task_impl->func = tb_null; task_impl->priv = tb_null; task_impl->repeat = 0; } // remove it from pool directly if the task_impl have been expired else tb_fixed_pool_free(impl->pool, task_impl); // leave tb_spinlock_leave(&impl->lock); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_object_ref_t tb_object_json_reader_func_null(tb_object_json_reader_t* reader, tb_char_t type) { // check tb_assert_and_check_return_val(reader && reader->stream, tb_null); // init data tb_static_string_t data; tb_char_t buff[256]; if (!tb_static_string_init(&data, buff, 256)) return tb_null; // done tb_object_ref_t null = tb_null; do { // append character tb_static_string_chrcat(&data, type); // walk tb_bool_t failed = tb_false; while (!failed && tb_stream_left(reader->stream)) { // need one character tb_byte_t* p = tb_null; if (!tb_stream_need(reader->stream, &p, 1) && p) { failed = tb_true; break; } // the character tb_char_t ch = *p; // append character if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); else break; // skip it tb_stream_skip(reader->stream, 1); } // failed? tb_check_break(!failed); // check tb_assert_and_check_break(tb_static_string_size(&data)); // trace tb_trace_d("null: %s", tb_static_string_cstr(&data)); // null? if (!tb_stricmp(tb_static_string_cstr(&data), "null")) null = tb_object_null_init(); } while (0); // exit data tb_static_string_exit(&data); // ok? return null; }
tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval) { #ifndef TB_CONFIG_MICRO_ENABLE // check tb_assert_and_check_return(scheduler_io && scheduler_io->poller && scheduler_io->scheduler); // get the current coroutine tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); tb_assert(coroutine); // trace tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval); // infinity? if (interval > 0) { // high-precision interval? if (interval % 1000) { // post task to timer tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine); } // low-precision interval? else { // post task to ltimer (faster) tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine); } } #else // not impl tb_trace_noimpl(); #endif }
static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_impl_t* impl, tb_fixed_pool_slot_t* slot) { // check tb_assert_and_check_return(impl && impl->large_pool && slot); tb_assert_and_check_return(impl->slot_list && impl->slot_count); // trace tb_trace_d("slot[%lu]: exit: size: %lu", impl->item_size, slot->size); // init the iterator tb_iterator_t iterator = tb_iterator_init_ptr((tb_pointer_t*)impl->slot_list, impl->slot_count); // find the slot from the slot list tb_size_t itor = tb_binary_find_all(&iterator, (tb_cpointer_t)slot); tb_assert_abort(itor != tb_iterator_tail(&iterator) && itor < impl->slot_count && impl->slot_list[itor]); tb_check_return(itor != tb_iterator_tail(&iterator) && itor < impl->slot_count && impl->slot_list[itor]); // remove the slot if (itor + 1 < impl->slot_count) tb_memmov_(impl->slot_list + itor, impl->slot_list + itor + 1, (impl->slot_count - itor - 1) * sizeof(tb_fixed_pool_slot_t*)); // update the slot count impl->slot_count--; // exit slot tb_large_pool_free(impl->large_pool, slot); }
static tb_long_t tb_dns_looker_resp(tb_dns_looker_impl_t* impl, tb_ipaddr_ref_t addr) { // check tb_check_return_val(!(impl->step & TB_DNS_LOOKER_STEP_RESP), 1); // need wait if no data impl->step &= ~TB_DNS_LOOKER_STEP_NEVT; // recv response data tb_byte_t rpkt[4096]; while (1) { // read data tb_long_t read = tb_socket_urecv(impl->sock, tb_null, rpkt, 4096); //tb_trace_d("read %d", read); tb_assert_and_check_return_val(read >= 0, -1); // no data? if (!read) { // end? read x, read 0 tb_check_break(!tb_static_buffer_size(&impl->rpkt)); // abort? read 0, read 0 tb_check_return_val(!impl->tryn, -1); // tryn++ impl->tryn++; // continue return 0; } else impl->tryn = 0; // copy data tb_static_buffer_memncat(&impl->rpkt, rpkt, read); } // done if (!tb_dns_looker_resp_done(impl, addr)) return -1; // check tb_assert_and_check_return_val(tb_static_string_size(&impl->name) && !tb_ipaddr_ip_is_empty(addr), -1); // save address to cache tb_dns_cache_set(tb_static_string_cstr(&impl->name), addr); // finish it impl->step |= TB_DNS_LOOKER_STEP_RESP; impl->tryn = 0; // reset rpkt impl->size = 0; tb_static_buffer_clear(&impl->rpkt); // ok tb_trace_d("response: ok"); return 1; }
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); }