com.taobao.common.tfs.impl.TfsSession.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.common.tfs.impl.TfsSession.java

Source

/*
 * (C) 2007-2010 Alibaba Group Holding Limited.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */
package com.taobao.common.tfs.impl;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.taobao.common.tfs.etc.TfsConstant;
import com.taobao.common.tfs.etc.TfsUtil;
import com.taobao.common.tfs.impl.SegmentData;
import com.taobao.common.tfs.impl.SegmentData.SegmentStatus;
import com.taobao.common.tfs.TfsException;
import com.taobao.common.tfs.exception.ConnectionException;
import com.taobao.common.tfs.exception.ErrorStatusException;
import com.taobao.common.tfs.exception.UnexpectMessageException;
import com.taobao.common.tfs.packet.BasePacket;
import com.taobao.common.tfs.packet.ClientCmdMessage;
import com.taobao.common.tfs.packet.CloseFileInfo;
import com.taobao.common.tfs.packet.CloseFileMessage;
import com.taobao.common.tfs.packet.CreateFilenameMessage;
import com.taobao.common.tfs.packet.DsListWrapper;
import com.taobao.common.tfs.packet.FileInfo;
import com.taobao.common.tfs.packet.FileInfoMessage;
import com.taobao.common.tfs.packet.GetBlockInfoMessage;
import com.taobao.common.tfs.packet.BatchGetBlockInfoMessage;
import com.taobao.common.tfs.packet.ReadDataMessage;
import com.taobao.common.tfs.packet.ReadDataMessageV2;
import com.taobao.common.tfs.packet.RenameFileMessage;
import com.taobao.common.tfs.packet.RespCreateFilenameMessage;
import com.taobao.common.tfs.packet.RespFileInfoMessage;
import com.taobao.common.tfs.packet.RespReadDataMessage;
import com.taobao.common.tfs.packet.RespReadDataMessageV2;
import com.taobao.common.tfs.packet.SetBlockInfoMessage;
import com.taobao.common.tfs.packet.BatchSetBlockInfoMessage;
import com.taobao.common.tfs.packet.StatusMessage;
import com.taobao.common.tfs.packet.UnlinkFileMessage;
import com.taobao.common.tfs.packet.WriteDataInfo;
import com.taobao.common.tfs.packet.WriteDataMessage;

public class TfsSession {
    private static final Log log = LogFactory.getLog(TfsSession.class);
    private static final boolean isDebugEnabled = log.isDebugEnabled();

    public static final int CLIENT_CMD_SET_PARAM = 0x6;

    private long nameServerId;
    private char tfsClusterIndex;

    private ClientCache clientCache = new ClientCache();
    private ClientManager clientManager = new ClientManager();

    public TfsSession() {
        tfsClusterIndex = '0';
    }

    /**
     * initialize client cache and client manager,
     * get tfs cluster index from nameserver, use configured value if fail to get
     *
     */
    public int init() {
        clientCache.clear();
        clientManager.init();
        int ret;
        int retry = 3;
        do {
            ret = getTfsClusterIndexFromNs();
        } while (ret != TfsConstant.TFS_SUCCESS && --retry > 0);

        return ret;
    }

    public void destroy() {
        clientManager.destroy();
    }

    public void setClientManager(ClientManager clientManager) {
        this.clientManager = clientManager;
    }

    public ClientManager getClientManager() {
        return clientManager;
    }

    public void setNameServerIp(String ip) {
        // String [] a = ip.split(":");
        // not use client config cluster id any more
        // if (a.length > 2) {
        //     setTfsClusterIndex(a[2].charAt(0));
        // }
        setNameServerId(TfsUtil.hostToLong(ip));
    }

    public String getNameServerIp() {
        return TfsUtil.longToHost(getNameServerId());
    }

    public void setNameServerId(long nameServerId) {
        this.nameServerId = nameServerId;
    }

    public long getNameServerId() {
        return nameServerId;
    }

    public void setTfsClusterIndex(char tfsClusterIndex) {
        if (Character.isLetterOrDigit(tfsClusterIndex)) {
            this.tfsClusterIndex = tfsClusterIndex;
        }
    }

    public char getTfsClusterIndex() {
        return tfsClusterIndex;
    }

    public int getMaxCacheItemCount() {
        return clientCache.getMaxCacheItemCount();
    }

    public void setMaxCacheItemCount(int maxCacheItemCount) {
        clientCache.setMaxCacheItemCount(maxCacheItemCount);
    }

    public void setMaxCacheTime(int maxCacheTime) {
        clientCache.setMaxCacheTime(maxCacheTime);
    }

    public int getMaxCacheTime() {
        return clientCache.getMaxCacheTime();
    }

    public void setCacheMetric(CacheMetric cacheMetric) {
        clientCache.setCacheMetric(cacheMetric);
    }

    public CacheMetric getCacheMetric() {
        return clientCache.getCacheMetric();
    }

    public void setMaxWaitThread(int maxWaitThread) {
        clientManager.setMaxWaitThread(maxWaitThread);
    }

    public int getMaxWaitThread() {
        return clientManager.getMaxWaitThread();
    }

    public void setTimeout(int timeout) {
        clientManager.setTimeout(timeout);
    }

    public int getTimeout() {
        return clientManager.getTimeout();
    }

    /**
     * get tfs cluster index from nameserver
     *
     * @return
     */
    private int getTfsClusterIndexFromNs() {
        ClientCmdMessage cmd = new ClientCmdMessage(clientManager.getTranscoder());
        cmd.setType(CLIENT_CMD_SET_PARAM); // CLIENT_CMD_SET_PARAM
        cmd.setBlockId(20); // TfsClusterIndex param
        cmd.setServerId(0); // no meaning
        cmd.setVersion(0);
        cmd.setFromServerId(0);

        int ret = TfsConstant.TFS_ERROR;
        try {
            BasePacket retPacket = clientManager.sendPacket(this.nameServerId, cmd);
            if (retPacket != null && retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
                StatusMessage status = (StatusMessage) retPacket;
                if (status.getStatus() == StatusMessage.STATUS_MESSAGE_OK) {
                    String value = status.getError();
                    if (value.length() > 0) {
                        int index = Integer.parseInt(value);
                        if (Character.isLetterOrDigit(index)) {
                            this.tfsClusterIndex = (char) index;
                            ret = TfsConstant.TFS_SUCCESS;
                        }
                    }
                }
            }
        } catch (ConnectionException e) {
            log.error("get tfs cluster index error:", e);
        } catch (NumberFormatException e) {
            log.error("get tfs cluster index error:", e);
        }
        return ret;
    }

    public void removeBlockCache(int blockId) {
        clientCache.remove(blockId);
    }

    public DsListWrapper getReadBlockInfo(int blockId) throws ConnectionException {
        // fetch from client cache.
        List<Long> dsList = clientCache.get(blockId);
        // not found from cache, then retrieve from nameserver
        DsListWrapper dsListWrapper;
        if (dsList == null) {
            dsListWrapper = getBlockInfoEx(blockId, TfsConstant.READ_MODE).getDsListWrapper();
            // put into cache
            clientCache.put(blockId, dsListWrapper.getDsList());
        } else {
            dsListWrapper = new DsListWrapper();
            dsListWrapper.setDsList(dsList);
        }
        return dsListWrapper;
    }

    public void getReadBlockInfo(List<SegmentData> segmentList) throws TfsException {
        List<Integer> needBlockList = new ArrayList<Integer>();
        for (SegmentData segmentData : segmentList) {
            int blockId = segmentData.getBlockId();
            List<Long> dsList = clientCache.get(blockId);
            if (dsList == null) {
                needBlockList.add(blockId);
            } else {
                segmentData.setDsListWrapper(new DsListWrapper(dsList));
                segmentData.setSegmentStatus(SegmentStatus.SEG_STATUS_OPEN_OVER);
                segmentData.setReadPrimaryDsIndex();
            }
        }
        if (needBlockList.size() == 0) {
            log.debug("all block id ds list cached, count: " + segmentList.size());
        } else {
            Map<Integer, DsListWrapper> dsListMap = getBlockInfoEx(needBlockList, TfsConstant.READ_MODE, 0)
                    .getBlockDsMap();
            int blockId;
            DsListWrapper dsListWrapper;
            for (SegmentData segmentData : segmentList) {
                if (segmentData.getDsListWrapper() == null) {
                    blockId = segmentData.getBlockId();
                    dsListWrapper = dsListMap.get(blockId);
                    if (dsListWrapper == null || dsListWrapper.getDsList().size() == 0) {
                        throw new TfsException("get block info fail " + blockId);
                    } else {
                        segmentData.setDsListWrapper(dsListWrapper);
                        segmentData.setReadPrimaryDsIndex();
                        clientCache.put(blockId, dsListWrapper.getDsList());
                    }
                    segmentData.setSegmentStatus(SegmentStatus.SEG_STATUS_OPEN_OVER);
                }
            }
        }
    }

    public SetBlockInfoMessage getWriteBlockInfo(int blockId, int mode) throws ConnectionException {
        return getBlockInfoEx(blockId, mode | TfsConstant.CREATEBLK_MODE);
    }

    public void getWriteBlockInfo(List<SegmentData> segmentList) throws TfsException {
        Map<Integer, DsListWrapper> dsListMap = getBlockInfoEx(null,
                TfsConstant.WRITE_MODE | TfsConstant.CREATEBLK_MODE, segmentList.size()).getBlockDsMap();

        if (segmentList.size() != dsListMap.size()) {
            throw new TfsException("get write block fail, request count conflict response: " + segmentList.size()
                    + " <> " + dsListMap.size());
        }
        int i = 0;
        for (Entry<Integer, DsListWrapper> entry : dsListMap.entrySet()) {
            SegmentData segmentData = segmentList.get(i++);
            segmentData.setBlockId(entry.getKey());
            segmentData.setDsListWrapper(entry.getValue());
            segmentData.setSegmentStatus(SegmentStatus.SEG_STATUS_OPEN_OVER);
        }
    }

    public DsListWrapper getUnlinkBlockInfo(int blockId) throws ConnectionException {
        return getBlockInfoEx(blockId, TfsConstant.WRITE_MODE).getDsListWrapper();
    }

    /**
     * get block information message
     *
     * @param blockId
     * @param mode
     * @return
     * @exception
     */
    private SetBlockInfoMessage getBlockInfoEx(int blockId, int mode) throws ConnectionException {
        GetBlockInfoMessage sm = new GetBlockInfoMessage(clientManager.getTranscoder());
        sm.setBlockId(blockId);
        sm.setMode(mode);

        BasePacket retPacket = clientManager.sendPacket(nameServerId, sm);
        if (retPacket.getPcode() == TfsConstant.SET_BLOCK_INFO_MESSAGE) {
            return (SetBlockInfoMessage) retPacket;
        }
        if (retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("call GetBlockInfoMessage failed:" + ((StatusMessage) retPacket).getStatus() + ", error:"
                    + ((StatusMessage) retPacket).getError());
            throw new ErrorStatusException(this.nameServerId, (StatusMessage) retPacket);
        }
        throw new UnexpectMessageException(nameServerId, retPacket);
    }

    /**
     * batch get block information message
     *
     * @param blockId list
     * @param mode
     * @return
     * @exception
     */
    private BatchSetBlockInfoMessage getBlockInfoEx(List<Integer> blockIdList, int mode, int blockCount)
            throws TfsException {
        BatchGetBlockInfoMessage bsm = new BatchGetBlockInfoMessage(clientManager.getTranscoder());
        if ((mode & TfsConstant.READ_MODE) != 0 && blockIdList != null) {
            bsm.setBlockId(blockIdList);
        } else if ((mode & TfsConstant.WRITE_MODE) != 0 && blockCount > 0) {
            bsm.setBlockCount(blockCount);
        } else {
            throw new TfsException("invalid paramter. mode: " + mode + " blockIdList: " + blockIdList
                    + "blockcount: " + blockCount);
        }

        bsm.setMode(mode);
        BasePacket retPacket = clientManager.sendPacket(nameServerId, bsm);
        if (retPacket.getPcode() == TfsConstant.BATCH_SET_BLOCK_INFO_MESSAGE) {
            return (BatchSetBlockInfoMessage) retPacket;
        }
        if (retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("call BatchGetBlockInfoMessage failed:" + ((StatusMessage) retPacket).getStatus() + ", error:"
                    + ((StatusMessage) retPacket).getError());
            throw new ErrorStatusException(this.nameServerId, (StatusMessage) retPacket);
        }
        throw new UnexpectMessageException(nameServerId, retPacket);
    }

    public RespCreateFilenameMessage createFileName(int blockId, long fileId, long primaryDs)
            throws ConnectionException {
        CreateFilenameMessage sm = new CreateFilenameMessage(clientManager.getTranscoder(), blockId, fileId);
        BasePacket retPacket = clientManager.sendPacket(primaryDs, sm);
        if (retPacket.getPcode() == TfsConstant.RESP_CREATE_FILENAME_MESSAGE) {
            return (RespCreateFilenameMessage) retPacket;
        }

        if (retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("call CreateFilenameMessage failed:" + ((StatusMessage) retPacket).getStatus() + ", error:"
                    + ((StatusMessage) retPacket).getError());

            if (((StatusMessage) retPacket).getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(blockId);
            }

            throw new ErrorStatusException(primaryDs, (StatusMessage) retPacket);
        }

        throw new UnexpectMessageException(primaryDs, retPacket);
    }

    public int writeData(WriteDataInfo writeDataInfo, DsListWrapper dsListWrapper, byte[] writeData, int offset)
            throws ConnectionException {
        WriteDataMessage wdm = new WriteDataMessage(clientManager.getTranscoder());
        wdm.setWriteDataInfo(writeDataInfo);
        wdm.setWriteData(writeData);
        wdm.setSourceOffset(offset);
        wdm.setDsListWrapper(dsListWrapper);
        int ret = TfsConstant.TFS_SUCCESS;

        try {
            ret = clientManager.sendPacketNoReturn(getPrimaryDs(dsListWrapper), wdm);
        } catch (ErrorStatusException e) {
            if (e.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(writeDataInfo.getBlockId());
            }
            throw e;
        } catch (ConnectionException e) {
            removeBlockCache(writeDataInfo.getBlockId());
            throw e;
        }

        return ret;
    }

    public int closeFile(CloseFileInfo closeFileInfo, DsListWrapper dsListWrapper, int optionFlag)
            throws ConnectionException {
        CloseFileMessage cfm = new CloseFileMessage(clientManager.getTranscoder());
        cfm.setCloseFileInfo(closeFileInfo);
        cfm.setDsListWrapper(dsListWrapper);
        cfm.setOptionFlag(optionFlag);
        int ret = TfsConstant.TFS_SUCCESS;

        try {
            ret = clientManager.sendPacketNoReturn(getPrimaryDs(dsListWrapper), cfm);
        } catch (ErrorStatusException e) {
            if (e.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(closeFileInfo.getBlockId());
            }
            throw e;
        } catch (ConnectionException e) {
            removeBlockCache(closeFileInfo.getBlockId());
            throw e;
        }

        return ret;
    }

    public FileInfo getFileInfo(int blockId, long fileId, int mode, long primaryDs) throws ConnectionException {
        FileInfoMessage fm = new FileInfoMessage(clientManager.getTranscoder());
        fm.setBlockId(blockId);
        fm.setFileId(fileId);
        fm.setMode(mode);

        BasePacket retPacket;
        try {
            retPacket = clientManager.sendPacket(primaryDs, fm);
        } catch (ConnectionException e) {
            removeBlockCache(blockId);
            throw e;
        }
        if (retPacket.getPcode() == TfsConstant.RESP_FILE_INFO_MESSAGE) {
            return ((RespFileInfoMessage) retPacket).getFileInfo();
        }
        if (retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("call FileInfoMessage failed:" + ((StatusMessage) retPacket).getStatus() + ", error:"
                    + ((StatusMessage) retPacket).getError());

            if (((StatusMessage) retPacket).getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(blockId);
            }

            throw new ErrorStatusException(primaryDs, (StatusMessage) retPacket);
        }
        throw new UnexpectMessageException(primaryDs, retPacket);
    }

    public byte[] readData(int blockId, long fileId, int offset, int length, long primaryDs) throws TfsException {
        ReadDataMessage rm = new ReadDataMessage(clientManager.getTranscoder());
        rm.setBlockId(blockId);
        rm.setFileId(fileId);
        rm.setOffset(offset);
        rm.setLength(length);
        BasePacket retPacket;
        try {
            retPacket = clientManager.sendPacket(primaryDs, rm);
        } catch (ConnectionException e) {
            removeBlockCache(blockId);
            throw e;
        }
        if (retPacket.getPcode() == TfsConstant.RESP_READ_DATA_MESSAGE) {
            int retLength = ((RespReadDataMessage) retPacket).getLength();
            if (retLength < 0) {
                if (retLength == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                    removeBlockCache(blockId);
                }
                throw new TfsException(
                        "readDataMessage fail. server: " + TfsUtil.longToHost(primaryDs) + " ret: " + retLength);
            }
            return ((RespReadDataMessage) retPacket).getData();
        }

        // actually no return StatusMessage
        if (retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("call ReadDataMessage failed. ret: " + ((StatusMessage) retPacket).getStatus() + " error:"
                    + ((StatusMessage) retPacket).getError());

            if (((StatusMessage) retPacket).getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(blockId);
            }

            throw new ErrorStatusException(primaryDs, (StatusMessage) retPacket);
        }
        throw new UnexpectMessageException(primaryDs, retPacket);
    }

    public RespReadDataMessageV2 readDataV2(int blockId, long fileId, int offset, int length, long primaryDs)
            throws TfsException {
        ReadDataMessageV2 rm = new ReadDataMessageV2(clientManager.getTranscoder());
        rm.setBlockId(blockId);
        rm.setFileId(fileId);
        rm.setOffset(offset);
        rm.setLength(length);

        BasePacket retPacket;
        try {
            retPacket = clientManager.sendPacket(primaryDs, rm);
        } catch (ConnectionException e) {
            removeBlockCache(blockId);
            throw e;
        }
        if (retPacket.getPcode() == TfsConstant.RESP_READ_DATA_MESSAGE_V2) {
            int retLength = ((RespReadDataMessage) retPacket).getLength();
            if (retLength < 0) {
                if (retLength == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                    removeBlockCache(blockId);
                }
                throw new TfsException(
                        "readDataMessageV2 fail. server: " + TfsUtil.longToHost(primaryDs) + " ret: " + retLength);
            }
            if (offset == 0 && ((RespReadDataMessageV2) retPacket).getFileInfo() == null) {
                throw new TfsException("readDataMessageV2 fail. server: " + TfsUtil.longToHost(primaryDs)
                        + " first read cannot get fileinfo, ret:" + retLength);
            }
            return ((RespReadDataMessageV2) retPacket);
        }

        // actually no return StatusMessage
        if (retPacket.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("call ReadDataMessageV2 failed:" + ((StatusMessage) retPacket).getStatus() + ", error:"
                    + ((StatusMessage) retPacket).getError());

            if (((StatusMessage) retPacket).getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(blockId);
            }

            throw new ErrorStatusException(primaryDs, (StatusMessage) retPacket);
        }
        throw new UnexpectMessageException(primaryDs, retPacket);
    }

    public int unlinkFile(int blockId, long fileId, int action, int optionFlag, DsListWrapper dsListWrapper)
            throws ConnectionException {
        UnlinkFileMessage ufm = new UnlinkFileMessage(clientManager.getTranscoder());
        ufm.setBlockId(blockId);
        ufm.setFileId(fileId);
        ufm.setDsListWrapper(dsListWrapper);
        ufm.setOptionFlag(optionFlag);
        ufm.setUnlinkType(action);

        int ret = TfsConstant.TFS_SUCCESS;
        try {
            ret = clientManager.sendPacketNoReturn(dsListWrapper.getDsList().get(0), ufm);
        } catch (ErrorStatusException e) {
            if (e.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(blockId);
            }
            throw e;
        } catch (ConnectionException e) {
            removeBlockCache(blockId);
            throw e;
        }
        return ret;
    }

    public int renameFile(int blockId, long fileId, long newFileId, int optionFlag, DsListWrapper dsListWrapper)
            throws ConnectionException {
        RenameFileMessage rfm = new RenameFileMessage(clientManager.getTranscoder());
        rfm.setBlockId(blockId);
        rfm.setFileId(fileId);
        rfm.setNewFileId(newFileId);
        rfm.setOptionFlag(optionFlag);
        rfm.setDsListWrapper(dsListWrapper);

        int ret = TfsConstant.TFS_SUCCESS;
        try {
            ret = clientManager.sendPacketNoReturn(dsListWrapper.getDsList().get(0), rfm);
        } catch (ErrorStatusException e) {
            if (e.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(blockId);
            }
            throw e;
        } catch (ConnectionException e) {
            removeBlockCache(blockId);
            throw e;
        }

        return ret;
    }

    // process
    public int process(List<SegmentData> segmentList, FilePhase phase) {
        int ret = TfsConstant.TFS_SUCCESS;
        int requestId = clientManager.getAsyncId();
        int requestCount = 0;

        if (isDebugEnabled) {
            log.debug("process phase " + phase + " count " + segmentList.size());
        }
        // just use list index as seqId
        int seqId = 0;
        for (SegmentData segmentData : segmentList) {
            if (segmentData.getSegmentStatus() == phase.getPreviousStatus()) {
                if (!doRequest(phase, segmentData, requestId, seqId)) {
                    removeBlockCache(segmentData.getBlockId());
                } else {
                    requestCount++;
                }
            }
            seqId++;
        }

        if (requestCount == 0) {
            log.error("process all request fail");
            ret = TfsConstant.EXIT_ALL_SEGMENT_FAIL_ERROR;
        } else {
            // wait not ture, then not all success
            if (!clientManager.await(requestId)) {
                List<Integer> failIdList = clientManager.getFailIdList(requestId);
                if (failIdList != null) {
                    for (Integer failId : failIdList) {
                        removeBlockCache(segmentList.get(failId).getBlockId());
                    }
                }
            }

            List<BasePacket> responseList = clientManager.getResponseList(requestId);
            if (responseList == null || responseList.isEmpty()) {
                log.error("get all response fail.");
                ret = TfsConstant.EXIT_ALL_SEGMENT_FAIL_ERROR;
            } else {
                int responseCount = 0;
                for (BasePacket response : responseList) {
                    if (doResponse(phase, segmentList, response) == TfsConstant.TFS_SUCCESS) {
                        responseCount++;
                    }
                }

                ret = responseCount == 0 ? TfsConstant.EXIT_ALL_SEGMENT_FAIL_ERROR
                        : responseCount != requestCount ? TfsConstant.TFS_ERROR : TfsConstant.TFS_SUCCESS;
            }
        }
        clientManager.destroyAsync(requestId);
        return ret;
    }

    private long getPrimaryDs(DsListWrapper dsListWrapper) {
        return dsListWrapper.getDsList().get(0);
    }

    private boolean doRequest(FilePhase phase, SegmentData segmentData, int requstId, int seqId) {
        boolean ret = false;

        switch (phase) {
        case FILE_PHASE_CREATE_FILE:
            ret = reqCreateFileName(segmentData, requstId, seqId);
            break;
        case FILE_PHASE_WRITE_FILE:
            ret = reqWriteData(segmentData, requstId, seqId);
            break;
        case FILE_PHASE_READ_FILE:
            ret = reqReadData(segmentData, requstId, seqId);
            break;
        case FILE_PHASE_CLOSE_FILE:
            ret = reqCloseFile(segmentData, requstId, seqId);
            break;
        }

        if (ret) {
            log.debug(phase + " seqId: " + seqId + " request success: ");
        } else {
            log.error(phase + " seqId: " + seqId + " request fail: " + segmentData);
        }
        return ret;
    }

    private int doResponse(FilePhase phase, List<SegmentData> segList, BasePacket response) {
        // seqId valid
        int seqId = response.getSeqId();
        SegmentData segmentData = segList.get(seqId);
        int ret = TfsConstant.TFS_SUCCESS;

        switch (phase) {
        case FILE_PHASE_CREATE_FILE:
            ret = respCreateFileName(segmentData, response);
            break;
        case FILE_PHASE_WRITE_FILE:
            ret = respWriteData(segmentData, response);
            break;
        case FILE_PHASE_READ_FILE:
            ret = respReadData(segmentData, response);
            break;
        case FILE_PHASE_CLOSE_FILE:
            ret = respCloseFile(segmentData, response);
            break;
        }

        if (ret == TfsConstant.TFS_SUCCESS) {
            segmentData.setSegmentStatus(phase.getCurrentStatus());
            log.debug(phase + " seqId: " + seqId + " response success.");
        } else {
            log.error(phase + " seqId: " + seqId + " response fail: " + segmentData);
        }

        return ret;
    }

    private boolean reqCreateFileName(SegmentData segmentData, int requestId, int seqId) {
        CreateFilenameMessage cfm = new CreateFilenameMessage(clientManager.getTranscoder(),
                segmentData.getBlockId(), segmentData.getFileId());
        return clientManager.postPacket(segmentData.getPrimaryDs(), cfm, requestId, seqId);
    }

    private boolean reqWriteData(SegmentData segmentData, int requestId, int seqId) {
        WriteDataInfo writeDataInfo = new WriteDataInfo();
        writeDataInfo.setBlockId(segmentData.getBlockId());
        writeDataInfo.setFileId(segmentData.getFileId());
        writeDataInfo.setFileNumber(segmentData.getFileNumber());
        writeDataInfo.setOffset(segmentData.getInnerOffset());
        writeDataInfo.setLength(segmentData.getDataLength());
        writeDataInfo.setIsServer(0);

        WriteDataMessage wdm = new WriteDataMessage(clientManager.getTranscoder());
        wdm.setWriteDataInfo(writeDataInfo);
        wdm.setWriteData(segmentData.getData());
        wdm.setSourceOffset(segmentData.getDataOffset());
        wdm.setDsListWrapper(segmentData.getDsListWrapper());

        return clientManager.postPacket(segmentData.getPrimaryDs(), wdm, requestId, seqId);
    }

    private boolean reqReadData(SegmentData segmentData, int requestId, int seqId, BasePacket rdm) {
        boolean removeCache = false;
        boolean ret = false;
        int retry = segmentData.getReadPrimaryDsIndex() - segmentData.getPrimaryDsIndex();
        retry = retry <= 0 ? segmentData.getDsListWrapper().getDsList().size() + retry : retry;

        // try until post success
        while (retry-- > 0
                && !(ret = clientManager.postPacket(segmentData.getPrimaryDs(), rdm, requestId, seqId))) {
            log.warn("req read post fail to: " + segmentData.getPrimaryDs() + " retry: " + retry);
            removeCache = true;
            segmentData.readReset();
        }

        // outer loop may removeBlockCache again. no harm
        if (removeCache) {
            removeBlockCache(segmentData.getBlockId());
        }

        if (retry == 0) { // try the last ds
            segmentData.setPrimaryDsIndex(-1);
        } else {
            segmentData.readReset();
        }
        return ret;
    }

    private boolean reqReadData(SegmentData segmentData, int requestId, int seqId) {
        if (segmentData.getPrimaryDsIndex() < 0) {
            return false;
        }

        ReadDataMessage rdm = new ReadDataMessage(clientManager.getTranscoder());
        rdm.setBlockId(segmentData.getBlockId());
        rdm.setFileId(segmentData.getFileId());
        rdm.setOffset(segmentData.getInnerOffset());
        rdm.setLength(segmentData.getDataLength());
        return reqReadData(segmentData, requestId, seqId, rdm);
    }

    private boolean reqReadDataV2(SegmentData segmentData, int requestId, int seqId) {
        ReadDataMessageV2 rdmV2 = new ReadDataMessageV2(clientManager.getTranscoder());
        rdmV2.setBlockId(segmentData.getBlockId());
        rdmV2.setFileId(segmentData.getFileId());
        rdmV2.setOffset(segmentData.getInnerOffset());
        rdmV2.setLength(segmentData.getDataLength());

        return reqReadData(segmentData, requestId, seqId, rdmV2);
    }

    private boolean reqCloseFile(SegmentData segmentData, int requestId, int seqId) {
        CloseFileInfo closeFileInfo = new CloseFileInfo();
        closeFileInfo.setBlockId(segmentData.getBlockId());
        closeFileInfo.setFileId(segmentData.getFileId());
        closeFileInfo.setFileNumber(segmentData.getFileNumber());
        closeFileInfo.setCrc(segmentData.getCrc());
        closeFileInfo.setMode(0);

        CloseFileMessage cfm = new CloseFileMessage(clientManager.getTranscoder());
        cfm.setCloseFileInfo(closeFileInfo);
        cfm.setDsListWrapper(segmentData.getDsListWrapper());
        cfm.setOptionFlag(0); // TODO option flag

        // write and close should be the same primaryDs,
        // Absolutely now
        return clientManager.postPacket(segmentData.getPrimaryDs(), cfm, requestId, seqId);
    }

    private int respCreateFileName(SegmentData segmentData, BasePacket response) {
        if (response.getPcode() == TfsConstant.RESP_CREATE_FILENAME_MESSAGE) {
            RespCreateFilenameMessage rcfn = (RespCreateFilenameMessage) response;
            if (rcfn.getFileId() == 0 || rcfn.getFileNumber() == 0) {
                log.error("resp create file name fail. fileid filenumber zero return."
                        + segmentData.getSegmentInfo());
                return TfsConstant.TFS_ERROR;
            }
            // no suffix to segment
            segmentData.setFileId(rcfn.getFileId());
            segmentData.setFileNumber(rcfn.getFileNumber());

            return TfsConstant.TFS_SUCCESS;
        } else if (response.getPcode() == TfsConstant.STATUS_MESSAGE) {
            StatusMessage sm = (StatusMessage) response;
            if (sm.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                removeBlockCache(segmentData.getBlockId());
            }
            log.error("resp create name fail. ret: " + sm.getStatus() + " error: " + sm.getError());
            return sm.getStatus();
        } else {
            log.error("resp create file name fail. invalid packet return: " + response.getPcode());
        }
        return TfsConstant.TFS_ERROR;
    }

    private int respWriteData(SegmentData segmentData, BasePacket response) {
        if (response.getPcode() == TfsConstant.STATUS_MESSAGE) {
            StatusMessage sm = (StatusMessage) response;
            if (sm.getStatus() == TfsConstant.TFS_SUCCESS) {
                segmentData.setCrc(TfsUtil.crc32(segmentData.getCrc(), segmentData.getData(),
                        segmentData.getDataOffset(), segmentData.getLength()));
            } else {
                if (sm.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                    removeBlockCache(segmentData.getBlockId());
                }
                log.error("resp write data fail. ret: " + sm.getStatus() + " error: " + sm.getError());
            }
            return sm.getStatus();
        } else {
            log.error("resp write data fail. invalid packet return: " + response.getPcode());
        }

        return TfsConstant.TFS_ERROR;
    }

    private int respReadData(SegmentData segmentData, BasePacket response) {
        if (response.getPcode() == TfsConstant.RESP_READ_DATA_MESSAGE) {
            int retLength = ((RespReadDataMessage) response).getLength();
            if (retLength < 0) {
                if (retLength == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                    removeBlockCache(segmentData.getBlockId());
                }
                log.error("resp readData fail. ret: " + retLength);
                return retLength;
            }

            // no check eof
            segmentData.putData(((RespReadDataMessage) response).getData());
            return TfsConstant.TFS_SUCCESS;
        }

        // read return status message
        if (response.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("resp readData fail. get statusmessage. ret: " + ((StatusMessage) response).getStatus()
                    + " error: " + ((StatusMessage) response).getError());
        } else {
            log.error("resp readData fail. invalid packet return: " + response.getPcode());
        }

        return TfsConstant.TFS_ERROR;
    }

    private int respReadDataV2(SegmentData segmentData, BasePacket response) {
        if (response.getPcode() == TfsConstant.RESP_READ_DATA_MESSAGE_V2) {
            int retLength = ((RespReadDataMessageV2) response).getLength();
            if (retLength < 0) {
                if (retLength == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                    removeBlockCache(segmentData.getBlockId());
                }
                log.error("resp readDataV2 fail. ret: " + retLength);
                return retLength;
            }

            if (segmentData.getInnerOffset() == 0 && ((RespReadDataMessageV2) response).getFileInfo() == null) {
                log.error("resp readDataV2 can't get fileinfo");
                return TfsConstant.TFS_ERROR;
            }
            // no check eof
            segmentData.putData(((RespReadDataMessageV2) response).getData());
            return TfsConstant.TFS_SUCCESS;
        }

        // read should not return statusmessage
        if (response.getPcode() == TfsConstant.STATUS_MESSAGE) {
            log.error("resp readDataV2 fail. get statusmessage. ret: " + ((StatusMessage) response).getStatus()
                    + " error: " + ((StatusMessage) response).getError());
        } else {
            log.error("resp readDataV2 fail. invalid packet return: " + response.getPcode());
        }

        return TfsConstant.TFS_ERROR;
    }

    private int respCloseFile(SegmentData segmentData, BasePacket response) {
        if (response.getPcode() == TfsConstant.STATUS_MESSAGE) {
            StatusMessage sm = (StatusMessage) response;
            if (sm.getStatus() != TfsConstant.TFS_SUCCESS) {
                if (sm.getStatus() == TfsConstant.EXIT_NO_LOGICBLOCK_ERROR) {
                    removeBlockCache(segmentData.getBlockId());
                }
                log.error("resp close fail, ret: " + sm.getStatus() + " error:" + sm.getError());
            }
            return sm.getStatus();
        } else {
            log.error("resp close fail. invalid packet return: " + response.getPcode());
        }
        return TfsConstant.TFS_ERROR;
    }

}