<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Glusterfs之rpc模塊源碼分析(中)之Glusterfs的rpc模塊實現(2)

      第二節、rpc客戶端實現原理及代碼分析

      rpc客戶端主要發起一個rpc請求,執行完rpc請求以后就退出rpc,下面分析客戶端rpc請求建立的整個過程。Rpc客戶端請求建立的第一步是執行cli_rpc_init函數,主要實現代碼如下:

       1         this = THIS;//取得本線程的xlator列表
       2 
       3         cli_rpc_prog = &cli_prog;//設置rpc調用過程集合(許多函數)
       4 
       5         options = dict_new ();//新建一個字典數據結構用于存放選項信息
       6 
       7         ret = dict_set_str (options, "remote-host", state->remote_host);//設置host
       8 
       9         if (state->remote_port)
      10 
      11                 port = state->remote_port;
      12 
      13         ret = dict_set_int32 (options, "remote-port", port);//設置端口號
      14 
      15         ret = dict_set_str (options, "transport.address-family", "inet");//設置協議族為inet
      16 
      17         rpc = rpc_clnt_new (options, this->ctx, this->name);//新建一個rpc客戶端對象
      18 
      19         ret = rpc_clnt_register_notify (rpc, cli_rpc_notify, this);//注冊rpc請求通知函數
      20 
      21         rpc_clnt_start (rpc);//開始rpc

       

      這段代碼其實是glusterfs客戶端程序啟動時建立rpc請求的初始化過程函數,真正獨立開始建立一個rpc請求的過程是從函數rpc_clnt_new開始的,下面就分析這個函數的功能,先看主要代碼:

       1         rpc = GF_CALLOC (1, sizeof (*rpc), gf_common_mt_rpcclnt_t);//為客戶端rpc對象分配內存
       2 
       3         pthread_mutex_init (&rpc->lock, NULL);//初始化鎖
       4 
       5         rpc->ctx = ctx;//屬于哪一個ctx
       6 
       7 //新建請求內存池
       8 
       9         rpc->reqpool = mem_pool_new (struct rpc_req, RPC_CLNT_DEFAULT_REQUEST_COUNT);
      10 
      11         //保存幀數據的內存池
      12 
      13 rpc->saved_frames_pool = mem_pool_new (struct saved_frame,
      14 
      15                                               RPC_CLNT_DEFAULT_REQUEST_COUNT);
      16 
      17         ret = rpc_clnt_connection_init (rpc, ctx, options, name);//初始化rpc請求連接
      18 
      19         rpc = rpc_clnt_ref (rpc);//客戶端對象引用計數加1
      20 
      21         INIT_LIST_HEAD (&rpc->programs);//初始化程序集的鏈表

       

      rpc客戶端發送請求也需要裝載相應的協議庫,它主要使用協議庫里面的初始化函數和鏈接函數,上面代碼中rpc_clnt_connection_init函數主要完成協議庫裝載功能和鏈接選項的一些初始化功能,具體實現的主要代碼如下:

       1         pthread_mutex_init (&clnt->conn.lock, NULL);//初始化鎖
       2 
       3       conn->trans = rpc_transport_load (ctx, options, name);//裝載協議庫并執行初始化init
       4 
       5         rpc_transport_ref (conn->trans);//增加傳輸層的引用計數
       6 
       7         conn->rpc_clnt = clnt;//連接對象屬于哪一個客戶端對象
       8 
       9         ret = rpc_transport_register_notify (conn->trans, rpc_clnt_notify, conn);//注冊通知函數
      10 
      11        conn->saved_frames = saved_frames_new ();//新建一個保存幀數據的對象

       

      通過上面代碼執行以后基本的初始化工作已經完畢,下一步就是建立于rpc服務的鏈接,此功能在函數rpc_clnt_start中實現,也就是在所有初始化工作完成以后調用此函數發起鏈接,主要代碼如下:

      1 rpc_clnt_reconnect (conn->trans);

       

      繼續跟蹤函數rpc_clnt_reconnect

        

       1       pthread_mutex_lock (&conn->lock);//初始化鎖
       2 
       3         {
       4 
       5                 if (conn->reconnect)//如果重新鏈接正在進行
       6 
       7                         gf_timer_call_cancel (clnt->ctx, conn->reconnect);//取消正在的鏈接
       8 
       9                 conn->reconnect = 0;//初始化為0
      10 
      11  
      12 
      13                 if (conn->connected == 0) {//還沒有完成鏈接
      14 
      15                         tv.tv_sec = 3;//時間三秒
      16 
      17 //發起傳輸層的鏈接
      18 
      19                         ret = rpc_transport_connect (trans, conn->config.remote_port);
      20 
      21 //設置重鏈接對象
      22 
      23                         conn->reconnect = gf_timer_call_after (clnt->ctx, tv,
      24 
      25                                                      rpc_clnt_reconnect, trans);
      26 
      27                 } 
      28 
      29         }
      30 
      31         pthread_mutex_unlock (&conn->lock);//解鎖
      32 
      33         if ((ret == -1) && (errno != EINPROGRESS) && (clnt->notifyfn)) {
      34 
      35 //建立鏈接失敗就通知rpc客戶端對象(調用通知函數)
      36 
      37                 clnt->notifyfn (clnt, clnt->mydata, RPC_CLNT_DISCONNECT, NULL);
      38 
      39         }

       

      真正的鏈接是在具體的協議中的鏈接函數中執行,下面以tcp為例,看看它的鏈接函數的實現,主要代碼如下:

       1 //得到客戶端協議族相關信息
       2 
       3         ret = socket_client_get_remote_sockaddr (this, SA (&sockaddr), &sockaddr_len, &sa_family)
       4 
       5         if (port > 0)
       6 
       7                 ((struct sockaddr_in *) (&sockaddr))->sin_port = htons (port);//端口字節序轉換
       8 
       9         pthread_mutex_lock (&priv->lock);
      10 
      11         {
      12 
      13                 memcpy (&this->peerinfo.sockaddr, &sockaddr, sockaddr_len);//賦值sockaddr信息
      14 
      15                 this->peerinfo.sockaddr_len = sockaddr_len;//地址長度保存
      16 
      17                 priv->sock = socket (sa_family, SOCK_STREAM, 0);//創建socket
      18 
      19                 setsockopt (priv->sock, SOL_SOCKET, SO_RCVBUF, &priv->windowsize,
      20 
      21                                 sizeof (priv->windowsize)) < 0) ;//設置接收的系統緩沖區
      22 
      23                 setsockopt (priv->sock, SOL_SOCKET, SO_SNDBUF, &priv->windowsize,
      24 
      25                                 sizeof (priv->windowsize)) < 0);//發送緩沖區設置
      26 
      27                 if (priv->nodelay) {
      28 
      29                         ret = __socket_nodelay (priv->sock);//設置是否延遲發送(等待一個完整的)
      30 
      31                  }
      32 
      33                 if (!priv->bio) {
      34 
      35                         ret = __socket_nonblock (priv->sock);//設置非阻塞
      36 
      37                 }
      38 
      39                 if (priv->keepalive) {
      40 
      41                         ret = __socket_keepalive (priv->sock, priv->keepaliveintvl,
      42 
      43                                                   priv->keepaliveidle);//保存鏈接活動
      44 
      45                 }
      46 
      47                 SA (&this->myinfo.sockaddr)->sa_family =
      48 
      49                         SA (&this->peerinfo.sockaddr)->sa_family;//保存協議族信息
      50 
      51                 ret = client_bind (this, SA (&this->myinfo.sockaddr),//根據協議族做適當的綁定
      52 
      53                                    &this->myinfo.sockaddr_len, priv->sock);
      54 
      55                 ret = connect (priv->sock, SA (&this->peerinfo.sockaddr),//發起鏈接請求
      56 
      57                                this->peerinfo.sockaddr_len);
      58 
      59                priv->connected = 0;
      60 
      61                 rpc_transport_ref (this);//傳輸對象引用加1
      62 
      63                 priv->idx = event_register (ctx->event_pool, priv->sock,//注冊epoll讀寫事件
      64 
      65                                             socket_event_handler, this, 1, 1);
      66 
      67         }
      68 
      69         pthread_mutex_unlock (&priv->lock);//解鎖

       

      整個鏈接過程的建立需要注意一點的就是會根據協議族的類型做適當的綁定,當發起鏈接以后就開始注冊各種讀寫事件。處理這些事件發生的函數是socket_event_handler,主要代碼如下:

       

       1        THIS = this->xl;//取得xlator
       2 
       3         priv = this->private;//取得私有數據
       4 
       5         pthread_mutex_lock (&priv->lock);//加鎖
       6 
       7         {
       8 
       9                 priv->idx = idx;//取得索引下表(對應的socket)
      10 
      11         }
      12 
      13         pthread_mutex_unlock (&priv->lock);
      14 
      15         if (!priv->connected) {//如果鏈接還沒有建立先完成鏈接的建立
      16 
      17                 ret = socket_connect_finish (this);//完成鏈接建立
      18 
      19         }
      20 
      21         if (!ret && poll_out) {//可寫事件處理
      22 
      23                 ret = socket_event_poll_out (this);
      24 
      25         }
      26 
      27         if (!ret && poll_in) {//可讀事件處理
      28 
      29                 ret = socket_event_poll_in (this);
      30 
      31         }

       

      到此客戶端rpc請求過程完全建立,當真正的發送一個rpc請求的時候就會響應相應的epoll的寫事件,把包裝好的數據幀發送到rpc服務器端,rpc客戶端也會通過可讀事件來接收rpc服務器端的響應信息。

      總結:同rpc服務器端一眼,rpc客戶端的建立也是比較復雜的過程,還是通過流程圖加描述來展示一下整個rpc客戶端的初始化過程,圖如下:

       

      posted @ 2012-05-14 22:36  薔薇理想人生  閱讀(3473)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产中文字幕精品喷潮| 国产亚洲情侣一区二区无| 国产成人精品一区二区| 亚洲中文字幕久久精品品| 国产精品av免费观看| 鹿泉市| 久久无码中文字幕免费影院蜜桃 | 久久久久成人精品无码中文字幕| 国产美熟女乱又伦AV果冻传媒| 色综合中文综合网| 国产一区二区日韩在线| 色吊丝免费av一区二区| 国产初高中生粉嫩无套第一次| 精品在免费线中文字幕久久| 香港日本三级亚洲三级| 99久久精品国产免费看| 国产片一区二区三区视频| 国产精品亚洲综合网一区| 最新午夜男女福利片视频| 亚洲精品日韩在线观看| 99热精品国产三级在线观看| 最近2019免费中文字幕8| 一区二区三区鲁丝不卡| 天天干天天干| 久久99国产精品尤物| 国产真人做受视频在线观看| 国产欧美日韩另类精彩视频| 人妻丝袜无码专区视频网站| 国内精品久久久久影院日本| 久久影院九九被窝爽爽| 小嫩模无套内谢第一次| 精品无码国产污污污免费| 无码熟妇人妻AV影音先锋| 国产成人午夜精品福利| 国产精品国产高清国产一区| 欧美性猛交xxxx黑人| 亚洲国产欧美一区二区好看电影| 乱色欧美激惰| 欧美成年性h版影视中文字幕 | 日本久久久久亚洲中字幕| 国产亚洲精品成人aa片新蒲金|