/** helper **/ bool TcpListener::_listen(const int domain, struct sockaddr* addr, const int addr_len){ // close old _close_sock(); // new m_sock =::socket(domain, SOCK_STREAM, 0); if(m_sock == INVALID_FD){ ERROR("network listen error, %s", get_last_error_desc()); return false; } // set opt const int sock_flag =1; if(0 != ::setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &sock_flag, sizeof(sock_flag))){ ERROR("network listen error, %s", get_last_error_desc()); return false; } // bind if(0 != ::bind(m_sock, addr, addr_len)){ ERROR("network listen error, %s", get_last_error_desc()); return false; } // listen const int result =::listen(m_sock, BACKLOG); if(0 == result){ return true; } else{ ERROR("network listen error, %s", get_last_error_desc()); _close_sock(); return false; } }
int64_t write_bytes(const char* path, Bytes* content){ if(!path || !content) return -1; if(FILE* fp =fopen(path, "wb")){ char* ptr =content->c_str(); size_t cursor =0; const size_t s =(size_t)content->size(); while(cursor < s){ const size_t n =fwrite(ptr+cursor, 1, s-cursor, fp); if(n > 0){ cursor +=n; } else if(n == 0){ if(ferror(fp)){ return -1; } if(feof(fp)){ return cursor; } } else{ ERROR("fail to write %s, %s", path, get_last_error_desc()); fclose(fp); return -1; } } fclose(fp); ASSERT(cursor == s); return cursor; } else{ ERROR("fail to open %s, %s", path, get_last_error_desc()); return -1; } }
/** private **/ void Logger::_open_file(){ // check if(!m_szName || m_szName->empty()) return; OPH(); const time_t now =stable_time(); if(m_file){ if(ferror(m_file) || ((int64_t)now - m_file_open_time) > m_file_life_time){ fclose(m_file); m_file =0; } } if(m_file) return; // prepare time tm tmp; const tm* t =localtime_r(&now, &tmp); if(!t){ printf("fail to call localtime_r, %s\n", get_last_error_desc()); return; } // open String* path =String::Format("../log/%s_%04d%02d%02d%02d", m_szName->c_str(), t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour); m_file =fopen(path->c_str(), "a"); if(m_file){ m_file_open_time =now; } else{ printf("fail to open %s, %s\n", path->c_str(), get_last_error_desc()); } }
/*** CharsetConvert ***/ Bytes* CharsetConvert::Convert(const char* src, const char* from_code, const char* to_code){ // open iconv_t ic =iconv_open(to_code, from_code); if((iconv_t)-1 == ic){ ERROR("fail to %s, %s", __FUNCTION__, get_last_error_desc()); return 0; } // conv Bytes* bs =SafeNew<Bytes>(); char buf[64] ={0}; size_t os =64; char* ob =0; size_t is =strlen(src); char* ib =const_cast< char* >(src); while(is > 0){ os =64; ob =buf; const int err =iconv(ic, &ib, &is, &ob, &os); if(err == -1){ if(get_last_error() != E2BIG){ ERROR("fail to %s, %s", __FUNCTION__, get_last_error_desc()); iconv_close(ic); return 0; } } bs->write(buf, ob-buf); } // close iconv_close(ic); return bs; }
/** read write bytes **/ Bytes* read_bytes(const char* path){ if(!path) return 0; if(FILE* fp =fopen(path, "rb")){ if(0 != fseek(fp, 0, SEEK_END)){ ERROR("fail read %s, %s", path, get_last_error_desc()); fclose(fp); return 0; } const int64_t s =ftell(fp); if(s == -1){ ERROR("fail read %s, %s", path, get_last_error_desc()); fclose(fp); return 0; } if(0 != fseek(fp, 0, SEEK_SET)){ ERROR("fail read %s, %s", path, get_last_error_desc()); fclose(fp); return 0; } Bytes* content =SafeNew<Bytes>(); content->resize(s); char* ptr =content->c_str(); size_t cursor =0; while(cursor < (size_t)s){ const size_t n =fread(ptr+cursor, 1, (size_t)s-cursor, fp); if(n > 0){ cursor +=n; } else if(n == 0){ if(ferror(fp)){ return 0; } if(feof(fp)){ return content; } } else{ ERROR("fail read %s, %s", path, get_last_error_desc()); fclose(fp); return 0; } } fclose(fp); ASSERT(cursor == (size_t)s); return content; } else{ ERROR("fail to open %s, %s", path, get_last_error_desc()); return 0; } }
bool Coroutine::_yield(Object* yield_param, const int64_t status){ // assigin pointer by hand if(m_yield_param != yield_param){ if(yield_param){ yield_param->retain(); } if(m_yield_param){ m_yield_param->release(); } m_yield_param =yield_param; } // set status m_status =status; g_running =0; #ifndef VALGRIND_CHECK_ENABLE // store stack char tricky =0; m_stack_size =m_coroutine_pool->getMainStackHighAddr() - &tricky + STACK_PROTECT_SIZE; if(m_stack_size > m_coroutine_pool->getMainStackSize()){ FATAL("stack penetrate, stack size is %lld", m_stack_size); } m_stack =reinterpret_cast< char* >(REALLOCATE(m_stack, m_stack_size)); memcpy(m_stack, m_coroutine_pool->getMainStackHighAddr() - m_stack_size, m_stack_size); #endif // swap context if(0 != swapcontext(&m_ctx, m_coroutine_pool->getMainContext())){ FATAL("fail to %s, %s", get_last_error_desc()); } return true; }
int64_t Coroutine::_resume(Object* param){ #ifdef VALGRIND_CHECK_ENABLE if(m_stack == 0){ m_stack =reinterpret_cast< char* >(ALLOCATE(CoroutinePool::MAIN_STACK_SIZE)); m_stack_size =CoroutinePool::MAIN_STACK_SIZE; if(0 != getcontext(&m_ctx)){ FATAL("fail to %s, %s", get_last_error_desc()); return -ErrorCode::SYSTEM_ERROR; } m_ctx.uc_stack.ss_sp =m_stack; m_ctx.uc_stack.ss_size =m_stack_size; m_ctx.uc_stack.ss_flags =0; m_ctx.uc_link =m_coroutine_pool->getMainContext(); makecontext(&m_ctx, (void(*)())(_entry), 0); _valgrind_register(); } #else if(m_stack == 0){ if(0 != getcontext(&m_ctx)){ FATAL("fail to %s, %s", get_last_error_desc()); return -ErrorCode::SYSTEM_ERROR; } m_stack_size =0; m_ctx.uc_stack.ss_sp =m_coroutine_pool->getMainStack(); m_ctx.uc_stack.ss_size =m_coroutine_pool->getMainStackSize(); m_ctx.uc_stack.ss_flags =0; m_ctx.uc_link =m_coroutine_pool->getMainContext(); makecontext(&m_ctx, (void(*)())(_entry), 0); } else{ memcpy(m_coroutine_pool->getMainStackHighAddr() - m_stack_size, m_stack, m_stack_size); } #endif // set status m_status =STATUS_RUNNING; g_running =this; ASSIGN_POINTER(m_resume_param, param); // swap context if(0 != swapcontext(m_coroutine_pool->getMainContext(), &m_ctx)){ FATAL("fail to %s, %s", get_last_error_desc()); return -ErrorCode::SYSTEM_ERROR; } return m_status; }
void delete_fd_from_epoll(int epollfd, int fd) { if(0 != epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, 0)) { if(get_last_error() == ENOENT) { return; } else { ERROR("fail to call epoll_ctl EPOLL_CTL_DEL, %s", get_last_error_desc()); } } }
bool modify_fd_in_epoll(int epollfd, int fd, int events, void* context) { struct epoll_event evt; memset(&evt, 0, sizeof(evt)); evt.events =events; evt.data.ptr =context; if(0 != epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &evt)) { if(get_last_error() != ENOENT) { ERROR("fail to call epoll_ctl EPOLL_CTL_ADD, %s", get_last_error_desc()); } return false; } return true; }
int64_t write_string(const char* path, String* content){ if(!path || !content) return -1; if(FILE* fp =fopen(path, "w")){ const size_t s =(size_t)content->size(); const char* ptr =content->c_str(); size_t cursor =0; while(cursor < s){ const size_t n =fwrite(ptr+cursor, 1, s-cursor, fp); if(n < 0){ ERROR("fail to write %s, %s", path, get_last_error_desc()); fclose(fp); return -1; } cursor +=n; } fclose(fp); ASSERT(cursor == s); return cursor; } else{ ERROR("fail to open %s, %s", path, get_last_error_desc()); return -1; } }
bool add_fd_to_epoll(int epollfd, int fd, int events, void* context) { struct epoll_event evt; memset(&evt, 0, sizeof(evt)); evt.events =events; evt.data.ptr =context; if(0 != epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &evt)) { if(get_last_error() == EEXIST) { return modify_fd_in_epoll(epollfd, fd, events, context); } else { ERROR("fail to call epoll_ctl EPOLL_CTL_ADD, %s", get_last_error_desc()); return false; } } return true; }
void BytesChannel::_read_event_fd(){ uint64_t count =0; while(1){ if(::read(m_event_fd, &count, sizeof(count)) == sizeof(count)){ break; } const int errnum = get_last_error(); if(errnum == EINTR){ continue; } else if(errnum==EAGAIN || errnum==EWOULDBLOCK){ continue; } else{ ERROR("call %s failed, WTF:errno %d, %s", __FUNCTION__, errnum, get_last_error_desc()); break; } } }
bool BytesChannel::signal(){ // signal uint64_t count =1; while(1){ if(::write(m_event_fd, &count, sizeof(count)) == sizeof(count)){ return true; } const int errnum = get_last_error(); if(errnum == EINTR){ continue; } else if(errnum==EAGAIN || errnum==EWOULDBLOCK){ continue; } else{ ERROR("call %s failed, WTF:errno %d, %s", __FUNCTION__, errnum, get_last_error_desc()); return false; } } }
bool TcpListener::onEvent(const fd_t fd, const uint64_t events){ struct sockaddr_in client_addr; socklen_t addr_len =0; const int client_fd =::accept(m_sock, (struct sockaddr*)&client_addr, &addr_len); if(client_fd != INVALID_FD){ TcpConnection* conn =create_connection(); const char* client_host =::inet_ntoa(client_addr.sin_addr); const int32_t client_port =client_addr.sin_port; conn->attach(client_fd, client_host, client_port); // deliver return Network::Deliver(conn, m_deliver_begin, m_deliver_range); } else{ const int errcode =get_last_error(); if(errcode==EINTR || errcode==EAGAIN || errcode==EWOULDBLOCK){ return true; } else{ WARN("TcpListener accept failed, %s", get_last_error_desc()); return true; } } }