TFS数据块同步推送分析

 看了TFS文件系统的代码,描述一下TFS的写文件时数据块复制的处理过程:

   客户端接口函数:

//写文件操作组包的方法:写文件时的协议的方法是会发送多个独立的消息包过去

 int TfsFile::tfs_write(char *data, const int32_t len)

 {

        if (is_open_flag_ == TFS_FILE_OPEN_FLAG_NO)

        {

             snprintf(error_message_, ERR_MSG_SIZE, "tfs file(%s) don't open file", file_name_);

             return -2;

        }

        if (!(mode_ & WRITE_MODE))

        {

             snprintf(error_message_, ERR_MSG_SIZE, "open file mode isn't write.");

             return -1;

        }

        //发起写操作

        WriteDataMessage dsmessage;

        dsmessage.set_file_number(file_number_);

        dsmessage.set_block_id(block_id_);

        dsmessage.set_file_id(file_id_);

        dsmessage.set_offset(offset_);

        dsmessage.set_length(len);        //要写入的字节长度

        dsmessage.set_ds_list(ds_list_);  //数据服务器列表

        dsmessage.set_data(data);         //写的buf

        Message *message = client_->call(&dsmessage);  //客户端发送数据包

 }

从这个接口函数可以看出,写文件时,会分成多个数据包发送.

 接下来看看一下具体的实现过程:

 (1).client_->call(&dsmessage)方法里面,会把数据包放入到发送队列里面:

//发送packet到发送队列

bool Connection::postPacket(Packet *packet, IPacketHandler *packetHandler, void *args, bool noblocking) {

        if (!isConnectState()) {

            if (_iocomponent == NULL ||  _iocomponent->isAutoReconn() == false) {

                return false;

            } else if (_outputQueue.size()>10) {

                return false;

            } else {

                TCPComponent *ioc = dynamic_cast<TCPComponent*>(_iocomponent);

                bool ret = false;

                if (ioc != NULL) {

                    _outputCond.lock();

                    ret = ioc->init(false); //在做一次连接,写事件

                    _outputCond.unlock();

                }

                if (!ret) return false;

            }

        }

        // 如果是client, 并且有queue长度的限制

        _outputCond.lock();

        _queueTotalSize = _outputQueue.size() + _channelPool.getUseListCount() + _myQueue.size();

        //如果操作队列限制数,直接返回

        if (!_isServer && _queueLimit > 0 && noblocking && _queueTotalSize >= _queueLimit) {

            _outputCond.unlock();

            return false;

        }

        _outputCond.unlock();

        Channel *channel = NULL;

        packet->setExpireTime(_queueTimeout);           // 设置超时

        if (_streamer->existPacketHeader()) {            // 存在包头

            uint32_t chid = packet->getChannelId();     // packet中取

            if (_isServer) {

                assert(chid != 0);                      // 不能为空

            } else {

                channel = _channelPool.allocChannel();

                // channel没找到了

                if (channel == NULL) {

                    TBSYS_LOG(WARN, "分配channel出错, id: %u", chid);

                    return false;

                }

                channel->setHandler(packetHandler);

                channel->setArgs(args);

                packet->setChannel(channel);            //设置渠道

            }

        }

        _outputCond.lock();

        // 写入到outputqueue

        _outputQueue.push(packet);

        if (_iocomponent != NULL && _outputQueue.size() == 1U) {

            _iocomponent->enableWrite(true);

        }

        _outputCond.unlock();

        //如果是客户端,并且有队列数限制的话

        if (!_isServer && _queueLimit > 0) {

            _outputCond.lock();

            _queueTotalSize = _outputQueue.size() + _channelPool.getUseListCount() + _myQueue.size();

            if ( _queueTotalSize > _queueLimit && noblocking == false) {

                bool *stop = NULL;

                if (_iocomponent && _iocomponent->getOwner()) {

                    stop = _iocomponent->getOwner()->getStop();

                }

                while (_queueTotalSize > _queueLimit && stop && *stop == false) {

                    if (_outputCond.wait(1000) == false) {

                        if (!isConnectState()) {

                            break;

                        }

                        _queueTotalSize = _outputQueue.size() + _channelPool.getUseListCount() + _myQueue.size();

                    }

                }

            }

            _outputCond.unlock();

        }

 

        if (_isServer && _iocomponent) {

            _iocomponent->subRef();

        }

 

        return true;

    }

 将数据包发送到发送队列后,有一个线程在扫描socket事件:

//socket event 的检测, run函数调用,在线程里面被调用/

void Transport::eventLoop(SocketEvent *socketEvent) {

        IOEvent events[MAX_SOCKET_EVENTS];

        while (!_stop) {

            // 检查是否有事件发生

            int cnt = socketEvent->getEvents(1000, events, MAX_SOCKET_EVENTS);

            if (cnt < 0) {

                TBSYS_LOG(INFO, "得到events出错了: %s(%d)/n"

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值