Exemple #1
0
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
    CQ_ITEM *item = cqi_new();
    char buf[1];
    if (item == NULL) {
        close(sfd);
        /* given that malloc failed this may also fail, but let's try */
        fprintf(stderr, "Failed to allocate memory for connection object\n");
        return ;
    }

    int tid = (last_thread + 1) % settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;
    item->mode = queue_new_conn;

    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);
    buf[0] = 'c';
    if (write(thread->notify_send_fd, buf, 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
Exemple #2
0
void dispatch_conn_new_to_thread(int tid, int sfd, enum conn_states init_state,
                                 int event_flags, int read_buffer_size,
                                 enum protocol prot,
                                 enum network_transport transport,
                                 conn_funcs *funcs, void *extra) {
    assert(tid > 0);
    assert(tid < settings.num_threads);

    LIBEVENT_THREAD *thread = threads + tid;

    CQ_ITEM *cq_item = cqi_new();

    cq_item->sfd = sfd;
    cq_item->init_state = init_state;
    cq_item->event_flags = event_flags;
    cq_item->read_buffer_size = read_buffer_size;
    cq_item->protocol = prot;
    cq_item->transport = transport;
    cq_item->funcs = funcs;
    cq_item->extra = extra;

    cq_push(thread->new_conn_queue, cq_item);

    MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);
    if (write(thread->notify_send_fd, "", 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport)
{
    CQ_ITEM *item = cqi_new();
    char buf[1];
    int tid = (last_thread + 1) % g_settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;

    cq_push(thread->new_conn_queue, item);

    buf[0] = 'c';
    if (write(thread->notify_send_fd, buf, 1) != 1)
    {
        log_debug(LOG_ERR, "Writing to thread notify pipe, error:%s\n", strerror(errno));
    }
}
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 *
 * 分发新的连接到线程池中的一个线程中, 其实就是在一个线程的工作队列中加入一个
 * 工作任务, 并通过管道给相应的线程发送信号
 *
 */
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
    // CQ_ITEM connection queue item
    CQ_ITEM *item = cqi_new();
    char buf[1];

    // 线程池中有多个线程, 每个线程都有一个工作队列, 线程所需要做的就是从工作队列中取出工作任务并执行, 只要队列为空线程就可以进入等待状态
    // 计算线程信息下标
    int tid = (last_thread + 1) % settings.num_threads;

    // LIBEVENT_THREAD threads 是一个全局数组变量
    LIBEVENT_THREAD *thread = threads + tid; // 定位到下一个线程信息,通过简单地轮放方式

    last_thread = tid;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;

    // 将工作任务放入对应线程的工作队列中
    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);

    // 有意思, 这里向一个熟睡的线程写了一个字符: char buf[1]
    // 当管道中被写入数据后, libevent 中的注册事件会被触发, thread_libevent_process() 函数会被调用. 因为在 setup_thread() 中线程中管道描述符被设置到 event 中, 并注册到 libevent 中
    buf[0] = 'c';
    if (write(thread->notify_send_fd, buf, 1) != 1) {
        perror("Writing to thread notify pipe");
    }

}
Exemple #5
0
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
    CQ_ITEM *item = cqi_new();
    char buf[1];
    if (item == NULL) {
        close(sfd);
        /* given that malloc failed this may also fail, but let's try */
        fprintf(stderr, "Failed to allocate memory for connection object\n");
        return ;
    }

    int tid = (last_thread + 1) % settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;
#ifdef DUP_AWARE
    fprintf(stderr, "last_thread = %d, tid = %d\n", last_thread, tid);
#endif

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;
    item->priority = -1; // ignored unless DUP_AWARE

#ifdef DUP_AWARE
    if (!IS_UDP(transport)) {

        if (settings.num_threads != NUM_THREADS) {
            fprintf(stderr, "settings.num_threads must be %d for duplicate awareness"
                    "to work in its current implementation. You specified %d "
                    "threads.", NUM_THREADS, settings.num_threads);
            exit(1);
        }

        static int is_priority = NUM_THREADS;

        // The first set of `num_thread` connections will all be primary, while any
        // subsequent will be duplicate.
        item->priority = (is_priority-- > 0) ? PRIMARY : DUPLICATE;
        fprintf(stderr, "<%d item->priority is %s\n", sfd, (item->priority == PRIMARY) ? "PRIMARY" : "DUPLICATE");
    }
#endif

    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);
    buf[0] = 'c';
    if (write(thread->notify_send_fd, buf, 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
Exemple #6
0
void print_levelbylevel(ptr_rbnode root) {
    CircularQueue *cq;
    cq_init(cq, ELEMENT_MAX);

    cq_push(cq, root);
    int depth_cnt = -1;
    while ((depth_cnt = cq->capacity)) {

        while (depth_cnt--) {
            cq_element_t current_node = cq_front(cq);
            cq_pop(cq);
            if (current_node->nil) {
                printf("N ");
            }
            else {
                printf("%d%s ", current_node->val, current_node->color ? "(B)" : "(R)");
                cq_push(cq, current_node->left);
                cq_push(cq, current_node->right);
            }
        }
        printf("\n");
    }
    cq_destroy(cq);
}
Exemple #7
0
static inline int
__op_fetch_disk (uint64_t id, uint64_t offset, struct __arc_object *_obj)
{

    CQ_ITEM *item = cqi_new ();
    item->fops = READ_COMMAND;
    item->offset = offset;
    item->fid = id;
    item->obj = _obj;
//    lfs_printf("readstate =%d",_obj->read_state);
    assert (_obj->read_state == READ_STATE);
/*    
 * cq is aio queue.
 */
    cq_push (RFS_AIOQ, item);
    return 1;
}
Exemple #8
0
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(int sfd, int init_state, int event_flags,
                       int read_buffer_size, int is_udp) {
    CQ_ITEM *item = cqi_new();
    int thread = (last_thread + 1) % settings.num_threads;

    last_thread = thread;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->is_udp = is_udp;

    cq_push(&threads[thread].new_conn_queue, item);
    if (write(threads[thread].notify_send_fd, "", 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(SOCKET sfd, STATE_FUNC init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
    CQ_ITEM *item = cqi_new();
    int tid = (last_thread + 1) % settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;

    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, (uintptr_t)thread->thread_id);
    notify_thread(thread);
}
Exemple #10
0
void dispath_conn(int anewfd,struct sockaddr_in asin)
{ 
// set the new connect item
CQ_ITEM *lpNewItem = calloc(1,sizeof(CQ_ITEM));
if (! lpNewItem) {
     perror("Can't allocate connection item\n");
     exit(1);
  }
  
  lpNewItem->sfd = anewfd;
  strcpy(lpNewItem->szAddr,(char*)inet_ntoa(asin.sin_addr));
  lpNewItem->port = asin.sin_port;


// libev default loop, accept the new connection, round-robin 
// dispath to a work_thread.
  int robin = round_robin%init_count;
  cq_push(work_threads[robin].new_conn_queue,lpNewItem);
  ev_async_send(work_threads[robin].loop, &(work_threads[robin].async_watcher));
  round_robin++;
} 
Exemple #11
0
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
    CQ_ITEM *item = cqi_new();
    int tid = (last_thread + 1) % settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;

    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);
    if (write(thread->notify_send_fd, "", 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
Exemple #12
0
/*
 * Re-dispatches a connection back to the original thread. Can be called from
 * any side thread borrowing a connection.
 */
void redispatch_conn(conn *c) {
    CQ_ITEM *item = cqi_new();
    char buf[1];
    if (item == NULL) {
        /* Can't cleanly redispatch connection. close it forcefully. */
        c->state = conn_closed;
        close(c->sfd);
        return;
    }
    LIBEVENT_THREAD *thread = c->thread;
    item->sfd = c->sfd;
    item->init_state = conn_new_cmd;
    item->c = c;
    item->mode = queue_redispatch;

    cq_push(thread->new_conn_queue, item);

    buf[0] = 'c';
    if (write(thread->notify_send_fd, buf, 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
Exemple #13
0
//将主线程的连接分发给worker线程
void dispatch_conn_new(int sfd, enum conn_states init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
	//创建CQ_ITEM对象,封装了client_fd以及一些client连接信息
	CQ_ITEM *item = cqi_new();
    char buf[1];
    if (item == NULL) {
        close(sfd);
        /* given that malloc failed this may also fail, but let's try */
        fprintf(stderr, "Failed to allocate memory for connection object\n");
        return ;
    }

	//通过轮询的方式选择worker线程
    int tid = (last_thread + 1) % settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;

	//初始化CQ_ITEM对象
    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;

	//将CQ_ITEM放入所选择的worker线程的CQ_ITEM队列中
    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, thread->thread_id);
    buf[0] = 'c';
	//主线程向所选择的worker线程的管道中写入一个'c'字符,
	//由于worker线程会监听管道的receive_fd, 于是会收到事件通知
	//触发worker线程的事件处理函数thread_libevent_process
    if (write(thread->notify_send_fd, buf, 1) != 1) {
        perror("Writing to thread notify pipe");
    }
}
Exemple #14
0
static int __op_fetch (struct __arc_object *e)
{
    uint64_t offset, id;
    struct object *obj = __arc_list_entry (e, struct object, entry);
    obj->obj_data = cache_alloc_shm (lfs_n.lfs_cache);

    offset = obj->offset;
    id = obj->id;
#ifdef LFS_DEBUG
    lfs_printf ("\n2:cache_alloc obj=%p,id=%" PRIu64 ",offset=%" PRIu64 "",
		&obj->entry, id, offset);
#endif
    CQ_ITEM *item = cqi_new ();
    item->fops = READ_COMMAND;
    item->offset = offset;
    item->fid = id;
    item->obj = e;
    lfs_printf (" 2ci fetch begin id=%d\n", id);
    if (id < 0 || id > lfs_n.max_files)
	return -1;
    cq_push (RFS_AIOQ, item);
    return 0;
}
Exemple #15
0
/*
 * Dispatches a new connection to another thread. This is only ever called
 * from the main thread, either during initialization (for UDP) or because
 * of an incoming connection.
 */
void dispatch_conn_new(int sfd, STATE_FUNC init_state, int event_flags,
                       int read_buffer_size, enum network_transport transport) {
    CQ_ITEM *item = cqi_new();
    int tid = (last_thread + 1) % settings.num_threads;

    LIBEVENT_THREAD *thread = threads + tid;

    last_thread = tid;

    item->sfd = sfd;
    item->init_state = init_state;
    item->event_flags = event_flags;
    item->read_buffer_size = read_buffer_size;
    item->transport = transport;

    cq_push(thread->new_conn_queue, item);

    MEMCACHED_CONN_DISPATCH(sfd, (uintptr_t)thread->thread_id);
    if (write(thread->notify_send_fd, "", 1) != 1) {
        mc_logger->log(EXTENSION_LOG_WARNING, NULL,
                "Writing to thread notify pipe: %s", strerror(errno));
    }
}
Exemple #16
0
void dispatch_conn_new(int fd, char key, void *arg) {

    if ('k' == key) {

        for (int i = 0; i < num_threads; i++) {
            LIBEVENT_THREAD *thread = threads + i;
            char buf[1];
            buf[0] = key;
            if (write(thread->notify_send_fd, buf, 1) != 1) {
                merror("writing to thread notify pipe failed!");
            }
        }
    } else {
        CQ_ITEM *item = cqi_new();
        if (NULL == item) {
            merror("cqi_new failed!");
            return;
        }

        char buf[1];
        int tid = (last_thread + 1) % num_threads;

        LIBEVENT_THREAD *thread = threads + tid;

        last_thread = tid;

        item->fd = fd;
        item->data = arg;

        cq_push(thread->new_conn_queue, item);

        buf[0] = key;
        if (write(thread->notify_send_fd, buf, 1) != 1) {
            merror("writing to thread notify pipe failed!");
        }
    }
}