예제 #1
0
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;
}
예제 #2
0
파일: aico.c 프로젝트: 1060460048/tbox
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);
}
예제 #3
0
파일: aicp_aiop.c 프로젝트: ZuckerB/tbox
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;
}
예제 #4
0
파일: aico.c 프로젝트: 1060460048/tbox
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);
    }
}
예제 #5
0
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;
}
예제 #6
0
파일: aicp_aiop.c 프로젝트: RockyShi/tbox
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);
}
예제 #7
0
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;
}
예제 #8
0
파일: dns.c 프로젝트: AlexShiLucky/tbox
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;
}
예제 #9
0
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);
}
예제 #10
0
파일: spider.c 프로젝트: ahnan4arch/tbox
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");
}
예제 #11
0
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");
}
예제 #12
0
파일: itracer.c 프로젝트: LiJingBiao/itrace
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
예제 #13
0
파일: fixed_pool.c 프로젝트: siwuxian/xmake
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);
}
예제 #14
0
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;
}
예제 #15
0
파일: cache.c 프로젝트: DonkeyWs/tbox
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;
}
예제 #16
0
파일: scheduler_io.c 프로젝트: waruqi/tbox
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;
}
예제 #17
0
파일: spider.c 프로젝트: ahnan4arch/tbox
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;
}
예제 #18
0
파일: aicp_aiop.c 프로젝트: ZuckerB/tbox
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;
}
예제 #19
0
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);
}
예제 #20
0
파일: looker.c 프로젝트: waruqi/tbox
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;
}
예제 #21
0
파일: parser.c 프로젝트: waruqi/vm86
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;
}
예제 #22
0
파일: sqlite3.c 프로젝트: ljx0305/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
예제 #23
0
파일: machine.c 프로젝트: KISSMonX/xmake
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);
}
예제 #24
0
파일: allocator.c 프로젝트: siwuxian/xmake
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;
}
예제 #25
0
파일: timer.c 프로젝트: 1060460048/tbox
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);
}
예제 #26
0
파일: json.c 프로젝트: luxuan/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
예제 #27
0
파일: scheduler_io.c 프로젝트: waruqi/tbox
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
}
예제 #28
0
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);
}
예제 #29
0
파일: looker.c 프로젝트: luxuan/tbox
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;
}
예제 #30
0
파일: aicp_aiop.c 프로젝트: RockyShi/tbox
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);
}