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;
}
Ejemplo n.º 2
0
/**
 * 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;
}
Ejemplo n.º 3
0
Archivo: libnet.c Proyecto: luozy/evnet
void evnet_destroyacceptor(void* acceptor)
{
    acceptor_destroy((acceptor_t*)acceptor);
}
Ejemplo n.º 4
0
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;
}