Memcached源码拆分:Libevent_Thread

http://www.cnblogs.com/aga-j/archive/2011/11/04/2230603.html

WorkerThreads.cpp
复制代码
  1 /*
  2 #include"libevent_thread.h"
  3 #include<event.h>
  4 #include<pthread.h>
  5 #include"conn.h"
  6 #include"cq.h"
  7 #include<unistd.h>
  8 #include<string.h>
  9 */
 10 #include"WorkerThreads.h"
 11 #include<stdio.h>
 12 
 13 /*
 14     WorkerThreads::WorkerThreads(int threadCount=1):nthreads(threadCount),threads(NULL)
 15     {
 16         init_count=0;
 17         pthread_mutex_init(&init_lock,NULL);
 18         pthread_cond_init(&init_cond,NULL);
 19     }
 20 */
 21 
 22     void WorkerThreads::initiate()
 23     {
 24         int i;
 25 
 26         threads=(LIBEVENT_THREAD*)calloc(nthreads,sizeof(LIBEVENT_THREAD));        //LIBEVENT_THREAD,加入libevent元素的thread结构 “数组”
 27         if(!threads)
 28         {
 29             perror("can't allocate thread des");
 30             exit(1);
 31         }
 32 
 33         for(i=0;i<nthreads;i++)                                                    //设置thread和thread中的libevent所需属性
 34         {
 35             int fds[2];
 36             if(pipe(fds))                                                        //thread和主线程的通信pipe
 37             {
 38                 perror("can't create notify pipe");
 39                 exit(1);
 40             }
 41 
 42             threads[i].notify_receive_fd=fds[0];
 43             threads[i].notify_send_fd=fds[1];
 44 
 45             setup_event_thread(&threads[i]);                                    //设置thread和thread中的libevent所需属性
 46         }
 47 
 48         for(i=0;i<nthreads;i++)
 49         {
 50             create_worker(worker_libevent,&threads[i]);                            //启动thread
 51         }
 52 
 53         pthread_mutex_lock(&init_lock);
 54         while( init_count < nthreads)
 55         {
 56             pthread_cond_wait(&init_cond,&init_lock);
 57         }
 58         pthread_mutex_unlock(&init_lock);
 59 
 60         printf("finish\n");
 61     }
 62 
 63     void WorkerThreads::setup_event_thread(LIBEVENT_THREAD *me)
 64     {
 65         me->base=event_init();//every thread has its own event_base
 66         
 67 //2.0 has event_config
 68         /*
 69         struct event_config *cfg=event_config_new();
 70         event_config_avoid_method(cfg,"epoll");
 71         me->base=event_base_new_with_config(cfg);
 72         event_config_free(cfg);
 73 */
 74         //in order to use libevent on file,use this method
 75 
 76         if(!me->base)
 77         {
 78             fprintf(stderr,"can't allocate event base\n");
 79             exit(1);
 80         }
 81 
 82         event_set(&me->notify_event,me->notify_receive_fd,                        //设置 监听事件 和 处理函数
 83             EV_READ|EV_PERSIST, thread_libevent_process,me);    
 84         event_base_set(me->base,&me->notify_event);
 85 
 86         if(event_add(&me->notify_event,0)==-1)
 87         {
 88             fprintf(stderr,"can't monitor libevent notify pipe\n");
 89             exit(1);
 90         }
 91 
 92         //why initiate conn_queue here?
 93         me->new_conn_queue=(conn_queue*)malloc(sizeof(struct conn_queue));        //内部的conn_queue
 94         if(me->new_conn_queue==NULL)
 95         {
 96             perror("Failed to allocate memory for connection queue");
 97             exit(EXIT_FAILURE);
 98         }
 99 
100         cq_init(me->new_conn_queue);
101     }
102     
103     void thread_libevent_process(int fd,short which,void *arg)                    //处理函数,即当主线程通知workerThread时,主线程会插入一个item到某个thread的queue中,queue是一个工具类
104 //workerThread将item pop出来并封装为conn,封装期间就建立了和item所指向的对象的联系,也使用libevent完成
105     {
106         LIBEVENT_THREAD *me=(LIBEVENT_THREAD*)arg;
107         CQ_ITEM *item;
108 
109         char buf[1];
110 
111         if(read(fd,buf,1)!=1)
112             fprintf(stderr,"can't read from libevent pipe\n");
113 
114         item=cq_pop(me->new_conn_queue);
115         printf("item fd is:%d\n",item->sfd);
116         if(NULL!=item)
117         {
118             conn *c= conn_new (item->sfd,item->init_state,item->event_flags,
119                 item->read_buffer_size,item->transport,me->base);
120     
121             if(NULL==c)
122             {
123                 if( IS_UDP(item->transport))
124                 {
125                     fprintf(stderr,"can't listen for events on UDP\n");
126                     exit(1);
127                 }
128                 else
129                 {
130                     fprintf(stderr,"can't listen for events on fd %d\n",item->sfd);
131                     close(item->sfd);
132                 }
133             }
134             else
135             {
136                 c->thread=me;
137                 //test
138                 write(item->read_buffer_size,"a",1);
139             }
140             cqi_free(item);
141         }
142 
143     }
144     
145     void WorkerThreads::create_worker(void *(*func)(void*),void *arg)
146     {
147         pthread_t thread;
148         pthread_attr_t attr;
149         int ret;
150 
151         pthread_attr_init(&attr);
152 
153         if((ret=pthread_create(&thread,&attr,func,arg))!=0)                
154         {
155             fprintf(stderr,"can't create thread: %s\n",strerror(ret));
156             exit(1);
157         }
158     }
159     
160     void* worker_libevent(void *arg)
161     {
162         LIBEVENT_THREAD *me = (LIBEVENT_THREAD*)arg;
163         pthread_mutex_lock(&init_lock);
164         init_count++;
165         pthread_cond_signal(&init_cond);
166         pthread_mutex_unlock(&init_lock);
167 
168         event_base_loop(me->base,0);
169         return NULL;
170     }
171 
172     
173 
174     
复制代码
conn.cpp
复制代码
  1 //#include<pthread.h>
  2 //#include<event.h>
  3 #include"conn.h"
  4 
  5 #include<unistd.h>
  6 
  7 static pthread_mutex_t conn_lock=PTHREAD_MUTEX_INITIALIZER;
  8 static int freecurr;
  9 static int freetotal;
 10 
 11 
 12 
 13 static conn **freeconns;
 14 
 15 //static                    //why can not use static 
 16 void conn_init(void) {                                                        //每个Worker的
 17     freetotal = 200;
 18     freecurr = 0;
 19     if ((freeconns =(conn**)calloc(freetotal, sizeof(conn *))) == NULL) {
 20         fprintf(stderr, "Failed to allocate connection structures\n");
 21     }
 22     return;
 23 }
 24 
 25 conn *conn_new(const int sfd,enum conn_states init_state,const int event_flags,
 26                const int read_buffer_size,enum network_transport transport,
 27 struct event_base *base)
 28 {
 29     conn *c=conn_from_freelist();
 30     if(NULL==c)
 31     {
 32         if(!(c=(conn*)calloc(1,sizeof(conn))))
 33         {
 34             fprintf(stderr,"calloc()\n");
 35             return NULL;
 36         }
 37         //initiate c
 38 /*
 39 {
 40     MEMCACHED_CONN_CREATE(c);
 41 
 42         c->rbuf = c->wbuf = 0;
 43         c->ilist = 0;
 44         c->suffixlist = 0;
 45         c->iov = 0;
 46         c->msglist = 0;
 47         c->hdrbuf = 0;
 48 
 49         c->rsize = read_buffer_size;
 50         c->wsize = DATA_BUFFER_SIZE;
 51         c->isize = ITEM_LIST_INITIAL;
 52         c->suffixsize = SUFFIX_LIST_INITIAL;
 53         c->iovsize = IOV_LIST_INITIAL;
 54         c->msgsize = MSG_LIST_INITIAL;
 55         c->hdrsize = 0;
 56 
 57         c->rbuf = (char *)malloc((size_t)c->rsize);
 58         c->wbuf = (char *)malloc((size_t)c->wsize);
 59         c->ilist = (item **)malloc(sizeof(item *) * c->isize);
 60         c->suffixlist = (char **)malloc(sizeof(char *) * c->suffixsize);
 61         c->iov = (struct iovec *)malloc(sizeof(struct iovec) * c->iovsize);
 62         c->msglist = (struct msghdr *)malloc(sizeof(struct msghdr) * c->msgsize);
 63 
 64         //根据配置大小来分配,可能会分配失败
 65         if (c->rbuf == 0 || c->wbuf == 0 || c->ilist == 0 || c->iov == 0 ||
 66                 c->msglist == 0 || c->suffixlist == 0) {
 67             conn_free(c);
 68             fprintf(stderr, "malloc()\n");
 69             return NULL;
 70         }
 71         //end initiate c
 72 }    
 73 */
 74     }
 75     //initiate c
 76 /*
 77 {
 78     c->transport = transport;                 //传输方式
 79     c->protocol = settings.binding_protocol;  //传输协议
 80 
 81     // unix socket mode doesn't need this, so zeroed out.  but why
 82     //  is this done for every command?  presumably for UDP
 83     //  mode.  
 84     if (!settings.socketpath) {
 85         c->request_addr_size = sizeof(c->request_addr);
 86     } else {
 87         c->request_addr_size = 0;
 88     }
 89 
 90     if (settings.verbose > 1) {
 91         if (init_state == conn_listening) {
 92             fprintf(stderr, "<%d server listening (%s)\n", sfd,
 93                 prot_text(c->protocol));
 94         } else if (IS_UDP(transport)) {
 95             fprintf(stderr, "<%d server listening (udp)\n", sfd);
 96         } else if (c->protocol == negotiating_prot) {
 97             fprintf(stderr, "<%d new auto-negotiating client connection\n",
 98                     sfd);
 99         } else if (c->protocol == ascii_prot) {
100             fprintf(stderr, "<%d new ascii client connection.\n", sfd);
101         } else if (c->protocol == binary_prot) {
102             fprintf(stderr, "<%d new binary client connection.\n", sfd);
103         } else {
104             fprintf(stderr, "<%d new unknown (%d) client connection\n",
105                 sfd, c->protocol);
106             assert(false);
107         }
108     }
109 
110 //信息赋值给conn结构,conn的构造把item全用上了
111     c->sfd = sfd;
112     c->state = init_state;
113     c->rlbytes = 0;
114     c->cmd = -1;
115     c->rbytes = c->wbytes = 0;
116     c->wcurr = c->wbuf;
117     c->rcurr = c->rbuf;
118     c->ritem = 0;
119     c->icurr = c->ilist;
120     c->suffixcurr = c->suffixlist;
121     c->ileft = 0;
122     c->suffixleft = 0;
123     c->iovused = 0;
124     c->msgcurr = 0;
125     c->msgused = 0;
126 
127     c->write_and_go = init_state;
128     c->write_and_free = 0;
129     c->item = 0;
130 
131     c->noreply = false;
132 }
133 */
134     //end initiate c
135     
136     c->sfd=sfd;
137     printf("test fd is:%d\n",sfd);
138     event_set(&c->event,sfd,event_flags,event_handler,(void*)c);
139     event_base_set(base,&c->event);
140     c->ev_flags=event_flags;
141 
142     if(event_add(&c->event,0)==-1)
143     {
144         if( conn_add_to_freelist(c))
145             conn_free(c);
146         perror("event_add");
147         return NULL;
148     }
149 
150     //MEMCACHED_CONN_ALLOCATE(c->sfd);
151     
152     return c;
153 }
154 
155 conn *conn_from_freelist()
156 {
157     conn *c;
158     pthread_mutex_lock(&conn_lock);
159 
160     if(freecurr>0)
161         c=freeconns[--freecurr];
162     else
163         c=NULL;
164 
165     pthread_mutex_unlock(&conn_lock);
166 }
167 
168 void event_handler(const int fd,const short which,void *arg)
169 {
170     //real handler
171     char buf[128];
172     int rc=read(fd,buf,sizeof(buf));
173     buf[rc]='\0';
174     printf("%s\n",buf);
175 }
176 
177 bool conn_add_to_freelist(conn *c) 
178 {
179     bool ret = true;
180     pthread_mutex_lock(&conn_lock);
181 
182     if (freecurr < freetotal) 
183     {
184         freeconns[freecurr++] = c;
185         ret = false;
186     }
187     else 
188     {
189         // try to enlarge free connections array 
190         size_t newsize = freetotal * 2;
191         conn **new_freeconns = (conn**)realloc(freeconns, sizeof(conn *) * newsize);
192         if (new_freeconns) 
193         {                
194             freetotal = newsize;
195             freeconns = new_freeconns;
196             freeconns[freecurr++] = c;        
197             ret = false;
198         }
199     }
200 
201     pthread_mutex_unlock(&conn_lock);
202     return ret;
203 }
204 
205 void conn_free(conn *c) {
206     if (c) 
207     {
208         /*
209         MEMCACHED_CONN_DESTROY(c);
210         if (c->hdrbuf)              
211         free(c->hdrbuf);
212         if (c->msglist)
213         free(c->msglist);        
214         if (c->rbuf)        
215         free(c->rbuf);        
216         if (c->wbuf)        
217         free(c->wbuf);            
218         if (c->ilist)        
219         free(c->ilist);        
220         if (c->suffixlist)        
221         free(c->suffixlist);        
222         if (c->iov)
223         free(c->iov);    
224 */
225         free(c);    
226     }
227 }
复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值