struct acceptor * acceptor_create( const char * host, uint16_t port ) { struct acceptor * a = NULL; a = (struct acceptor *)malloc( sizeof(struct acceptor) ); if ( a ) { a->holding = 0; a->socketfd = 0; a->ev_accept = NULL; pthread_mutex_init( &(a->lock), NULL ); a->socketfd = tcp_listen( host, port ); if ( a->socketfd < 0 ) { acceptor_destroy( a ); return NULL; } set_fd_nonblock( a->socketfd ); a->ev_accept = event_create(); if ( a->ev_accept == NULL ) { acceptor_destroy( a ); return NULL; } } return a; }
/** * paxos_learn - Do something useful with the value of a commit. * * Note that we cannot free up the instance or any request associated with * it until a sync. */ int paxos_learn(struct paxos_instance *inst, struct paxos_request *req) { int r = 0; struct paxos_acceptor *acc; // Mark the learn. inst->pi_learned = true; // Act on the decree (e.g., display chat, record acceptor list changes). switch (inst->pi_val.pv_dkind) { case DEC_NULL: break; case DEC_CHAT: // Grab the message sender. acc = acceptor_find(&pax->alist, req->pr_val.pv_reqid.id); assert(acc != NULL); // Invoke client learning callback. state.learn.chat(req->pr_data, req->pr_size, acc->pa_desc, acc->pa_size, pax->client_data); break; case DEC_JOIN: // Check the adefer list to see if we received a hello already for the // newly joined acceptor. acc = acceptor_find(&pax->adefer, inst->pi_hdr.ph_inum); if (acc != NULL) { // We found a deferred hello. To complete the hello, just move our // acceptor over to the alist and increment the live count. LIST_REMOVE(&pax->adefer, acc, pa_le); pax->live_count++; } else { // We have not yet gotten the hello, so create a new acceptor. acc = g_malloc0(sizeof(*acc)); acc->pa_paxid = inst->pi_hdr.ph_inum; } acceptor_insert(&pax->alist, acc); // Copy over the identity information. acc->pa_size = req->pr_size; acc->pa_desc = g_memdup(req->pr_data, req->pr_size); // If we are the proposer, we are responsible for connecting to the new // acceptor, as well as for sending the new acceptor its paxid and other // initial data. if (is_proposer()) { proposer_welcome(acc); } // Invoke client learning callback. state.learn.join(req->pr_data, req->pr_size, acc->pa_desc, acc->pa_size, pax->client_data); break; case DEC_PART: case DEC_KILL: // Grab the acceptor from the alist. acc = acceptor_find(&pax->alist, inst->pi_val.pv_extra); if (acc == NULL) { // It is possible that we may part twice; for instance, if a proposer // issues a part for itself but its departure from the system is // detected by acceptors before the part commit is received. In this // case, just do nothing. break; } // Invoke client learning callback. state.learn.part(acc->pa_desc, acc->pa_size, acc->pa_desc, acc->pa_size, pax->client_data); // If we are being parted, leave the protocol. if (acc->pa_paxid == pax->self_id) { return paxos_end(pax); } // Take the parted acceptor off the list and do accounting if it was // still live. LIST_REMOVE(&pax->alist, acc, pa_le); if (acc->pa_peer != NULL) { pax->live_count--; } // If we just parted our proposer, "elect" a new one. If it's us, send // a prepare. if (acc->pa_paxid == pax->proposer->pa_paxid) { reset_proposer(); if (is_proposer()) { r = proposer_prepare(acc); } } // Free the parted acceptor. acceptor_destroy(acc); break; } return r; }
void evnet_destroyacceptor(void* acceptor) { acceptor_destroy((acceptor_t*)acceptor); }
void echoserver_process_message( int32_t fd, int16_t ev, void * arg ) { struct session * s = (struct session *)arg; if ( ev & EV_READ ) { char buf[16384]; int32_t readn = -1; readn = read( fd, buf, 16384 ); if ( readn <= 0 ) { #if __DEBUG printf( "Client[%ld, %d] is closed, BYTES:%d, TIME:%lld .\n", s->sid, s->fd, s->iobytes, milliseconds() ); #endif //evsets_del( event_get_sets(s->evread), s->evread ); event_destroy( s->evread ); close( s->fd ); free( s ); goto PROCESS_END; } else { #if __DEBUG printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() ); #endif readn = write( fd, buf, readn ); s->iobytes += readn; } #if USE_LIBEVENT { struct timeval tv = {TIMEOUT_MSECS/1000, 0}; event_add( s->evread, &tv ); } #else evsets_add( event_get_sets(s->evread), s->evread, TIMEOUT_MSECS ); #endif } else { #if __DEBUG printf("echoserver_process_message(ev:%d) : TIME:%lld .\n", ev, milliseconds() ); #endif } PROCESS_END : } void accept_new_session( int32_t fd, int16_t ev, void * arg ) { struct iothread * thr = (struct iothread *)arg; struct acceptor * a = thr->core_acceptor; if ( ev & EV_READ ) { // // 接收新连接完毕后 // char srchost[20]; char dsthost[20]; uint16_t dstport = 0; int32_t newfd = tcp_accept( fd, srchost, dsthost, &dstport ); if ( newfd > 0 ) { uint64_t sid = 0; struct session * newsession = NULL; set_fd_nonblock( newfd ); newsession = (struct session *)malloc( sizeof(struct session) ); if ( newsession == NULL ) { printf("Out of memory, allocate for 'newsession' failed .\n"); goto ACCEPT_END; } newsession->evread = event_create(); if ( newsession->evread == NULL ) { printf("Out of memory, allocate for 'newsession->evread' failed .\n"); goto ACCEPT_END; } newsession->iobytes = 0; newsession->fd = newfd; sid = thr->key; sid <<= 32; sid += thr->index++; newsession->sid = sid; #if USE_LIBEVENT { struct timeval tv = {TIMEOUT_MSECS/1000, 0}; event_set( newsession->evread, newsession->fd, EV_READ, echoserver_process_message, newsession ); event_base_set( thr->core_sets, newsession->evread ); event_add( newsession->evread, &tv ); } #else event_set( newsession->evread, newsession->fd, EV_READ ); event_set_callback( newsession->evread, echoserver_process_message, newsession ); evsets_add( thr->core_sets, newsession->evread, TIMEOUT_MSECS ); #endif #if __DEBUG printf( "Thread[%d] accept a new Client[%lld, fd:%d, '%s':%d] .\n", thr->key, newsession->sid, newsession->fd, dsthost, dstport ); #endif } a->holding = 0; pthread_mutex_unlock( &(a->lock) ); } ACCEPT_END : } void trylock_accept_mutex( struct iothread * thr ) { struct acceptor * a = thr->core_acceptor; if ( pthread_mutex_trylock(&(a->lock)) == 0 ) { if ( a->holding == 0 ) { #if USE_LIBEVENT event_set( a->ev_accept, a->socketfd, EV_READ, accept_new_session, thr ); event_base_set( thr->core_sets, a->ev_accept ); event_add( a->ev_accept, 0 ); #else event_set( a->ev_accept, a->socketfd, EV_READ ); event_set_callback( a->ev_accept, accept_new_session, thr ); evsets_add(thr->core_sets, a->ev_accept, 0 ); #endif a->holding = 1; } //pthread_mutex_unlock( &(a->lock) ); } } void acceptor_destroy( struct acceptor * self ) { pthread_mutex_destroy( &(self->lock) ); if ( self->socketfd > 0 ) { close( self->socketfd ); } if ( self->ev_accept != NULL ) { event_destroy( self->ev_accept ); } free( self ); } struct acceptor * acceptor_create( const char * host, uint16_t port ) { struct acceptor * a = NULL; a = (struct acceptor *)malloc( sizeof(struct acceptor) ); if ( a ) { a->holding = 0; a->socketfd = 0; a->ev_accept = NULL; pthread_mutex_init( &(a->lock), NULL ); a->socketfd = tcp_listen( host, port ); if ( a->socketfd < 0 ) { acceptor_destroy( a ); return NULL; } set_fd_nonblock( a->socketfd ); a->ev_accept = event_create(); if ( a->ev_accept == NULL ) { acceptor_destroy( a ); return NULL; } } return a; } void * iothread_main( void * arg ) { struct iothread * thr = (struct iothread *)arg; thr->running = 1; while ( thr->running ) { // // 尝试加锁 // trylock_accept_mutex( thr ); // // 分发IO事件 // evsets_dispatch( thr->core_sets ); } return (void *)0; } struct iothread * iothread_create( uint8_t key, struct acceptor * a ) { pthread_t tid; struct iothread * thr = NULL; thr = (struct iothread *)malloc( sizeof(struct iothread) ); if ( thr ) { thr->key = key; thr->index = 0; thr->core_acceptor = a; thr->core_sets = evsets_create(); if ( thr->core_sets == NULL ) { #if __DEBUG printf( "out of memory, allocate for 'thr->core_sets' failed, Thread[%d] .\n", key ); #endif return NULL; } pthread_create( &tid, NULL, iothread_main, thr ); } return thr; }