vnodeRead.c 6.9 KB
Newer Older
S
slguan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#define _DEFAULT_SOURCE
#include "os.h"
#include "taosmsg.h"
#include "taoserror.h"
#include "tqueue.h"
#include "trpc.h"
#include "tsdb.h"
#include "twal.h"
S
slguan 已提交
24
#include "tdataformat.h"
S
slguan 已提交
25 26
#include "vnode.h"
#include "vnodeInt.h"
S
slguan 已提交
27
#include "vnodeLog.h"
28
#include "query.h"
S
slguan 已提交
29

30 31 32
static int32_t (*vnodeProcessReadMsgFp[TSDB_MSG_TYPE_MAX])(SVnodeObj *pVnode, SReadMsg *pReadMsg);
static int32_t  vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg);
static int32_t  vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg);
S
slguan 已提交
33 34

void vnodeInitReadFp(void) {
J
jtao1735 已提交
35 36
  vnodeProcessReadMsgFp[TSDB_MSG_TYPE_QUERY] = vnodeProcessQueryMsg;
  vnodeProcessReadMsgFp[TSDB_MSG_TYPE_FETCH] = vnodeProcessFetchMsg;
S
slguan 已提交
37 38
}

39
int32_t vnodeProcessRead(void *param, SReadMsg *pReadMsg) {
S
slguan 已提交
40
  SVnodeObj *pVnode = (SVnodeObj *)param;
41
  int msgType = pReadMsg->rpcMsg.msgType;
S
slguan 已提交
42

43 44
  if (vnodeProcessReadMsgFp[msgType] == NULL) {
    vTrace("vgId:%d, msgType:%s not processed, no handle", pVnode->vgId, taosMsg[msgType]);
45
    return TSDB_CODE_VND_MSG_NOT_PROCESSED;
46
  }
S
slguan 已提交
47

48 49
  if (pVnode->status == TAOS_VN_STATUS_DELETING || pVnode->status == TAOS_VN_STATUS_CLOSING) {
    vTrace("vgId:%d, msgType:%s not processed, vnode status is %d", pVnode->vgId, taosMsg[msgType], pVnode->status);
50
    return TSDB_CODE_VND_INVALID_VGROUP_ID; 
51
  }
S
slguan 已提交
52

H
Hui Li 已提交
53
  // TODO: Later, let slave to support query
54 55
  if (pVnode->syncCfg.replica > 1 && pVnode->role != TAOS_SYNC_ROLE_MASTER) {
    vTrace("vgId:%d, msgType:%s not processed, replica:%d role:%d", pVnode->vgId, taosMsg[msgType], pVnode->syncCfg.replica, pVnode->role);
H
Hui Li 已提交
56
    return TSDB_CODE_RPC_NOT_READY;
57
  }
H
Hui Li 已提交
58

59
  return (*vnodeProcessReadMsgFp[msgType])(pVnode, pReadMsg);
S
slguan 已提交
60 61
}

H
Haojun Liao 已提交
62 63
// notify connection(handle) that current qhandle is created, if current connection from
// client is broken, the query needs to be killed immediately.
64
static int32_t vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId) {
H
Haojun Liao 已提交
65 66 67 68 69 70
  SRetrieveTableMsg* killQueryMsg = rpcMallocCont(sizeof(SRetrieveTableMsg));
  killQueryMsg->qhandle = htobe64((uint64_t) qhandle);
  killQueryMsg->free = htons(1);
  killQueryMsg->header.vgId = htonl(vgId);
  killQueryMsg->header.contLen = htonl(sizeof(SRetrieveTableMsg));

71
  vTrace("QInfo:%p register qhandle to connect:%p", qhandle, handle);
72
  return rpcReportProgress(handle, (char*) killQueryMsg, sizeof(SRetrieveTableMsg));
H
Haojun Liao 已提交
73 74
}

75 76 77 78 79
static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
  void *   pCont = pReadMsg->pCont;
  int32_t  contLen = pReadMsg->contLen;
  SRspRet *pRet = &pReadMsg->rspRet;

S
slguan 已提交
80 81 82
  SQueryTableMsg* pQueryTableMsg = (SQueryTableMsg*) pCont;
  memset(pRet, 0, sizeof(SRspRet));

H
Haojun Liao 已提交
83
  // qHandle needs to be freed correctly
H
Haojun Liao 已提交
84
  if (pReadMsg->rpcMsg.code == TSDB_CODE_RPC_NETWORK_UNAVAIL) {
H
Haojun Liao 已提交
85 86 87 88
    SRetrieveTableMsg* killQueryMsg = (SRetrieveTableMsg*) pReadMsg->pCont;
    killQueryMsg->free = htons(killQueryMsg->free);
    killQueryMsg->qhandle = htobe64(killQueryMsg->qhandle);

89
    vWarn("QInfo:%p connection %p broken, kill query", killQueryMsg->qhandle, pReadMsg->rpcMsg.handle);
H
Haojun Liao 已提交
90
    assert(pReadMsg->rpcMsg.contLen > 0 && killQueryMsg->free == 1);
91

92 93 94 95
    // this message arrived here by means of the query message, so release the vnode is necessary
    qKillQuery((qinfo_t) killQueryMsg->qhandle, vnodeRelease, pVnode);
    vnodeRelease(pVnode);

H
Haojun Liao 已提交
96
    return TSDB_CODE_TSC_QUERY_CANCELLED; // todo change the error code
H
Haojun Liao 已提交
97 98 99
  }

  int32_t code = TSDB_CODE_SUCCESS;
100
  qinfo_t pQInfo = NULL;
H
Haojun Liao 已提交
101

S
slguan 已提交
102
  if (contLen != 0) {
103
    code = qCreateQueryInfo(pVnode->tsdb, pVnode->vgId, pQueryTableMsg, &pQInfo);
104

S
slguan 已提交
105 106
    SQueryTableRsp *pRsp = (SQueryTableRsp *) rpcMallocCont(sizeof(SQueryTableRsp));
    pRsp->qhandle = htobe64((uint64_t) (pQInfo));
107
    pRsp->code = code;
108

S
slguan 已提交
109 110
    pRet->len = sizeof(SQueryTableRsp);
    pRet->rsp = pRsp;
H
Haojun Liao 已提交
111

112 113 114 115 116 117
    // current connect is broken
    if (vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, pQInfo, pVnode->vgId) != TSDB_CODE_SUCCESS) {
      vError("vgId:%d, QInfo:%p, dnode query discarded since link is broken, %p", pVnode->vgId, pQInfo, pReadMsg->rpcMsg.handle);
      pRsp->code = TSDB_CODE_RPC_NETWORK_UNAVAIL;

      //NOTE: there two refcount, needs to kill twice, todo refactor
118 119
      qKillQuery(pQInfo, vnodeRelease, pVnode);
      qKillQuery(pQInfo, vnodeRelease, pVnode);
120 121 122

      return pRsp->code;
    }
H
Haojun Liao 已提交
123

124
    vTrace("vgId:%d, QInfo:%p, dnode query msg disposed", pVnode->vgId, pQInfo);
S
slguan 已提交
125
  } else {
126
    assert(pCont != NULL);
S
slguan 已提交
127
    pQInfo = pCont;
128
    code = TSDB_CODE_VND_ACTION_IN_PROGRESS;
129
    vTrace("vgId:%d, QInfo:%p, dnode query msg in progress", pVnode->vgId, pQInfo);
S
slguan 已提交
130 131
  }

132
  if (pQInfo != NULL) {
133
    vTrace("vgId:%d, QInfo:%p, do qTableQuery", pVnode->vgId, pQInfo);
134
    qTableQuery(pQInfo, vnodeRelease, pVnode); // do execute query
135 136
  }

S
slguan 已提交
137 138 139
  return code;
}

140 141 142 143
static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
  void *   pCont = pReadMsg->pCont;
  SRspRet *pRet = &pReadMsg->rspRet;

S
slguan 已提交
144 145
  SRetrieveTableMsg *pRetrieve = pCont;
  void *pQInfo = (void*) htobe64(pRetrieve->qhandle);
H
Haojun Liao 已提交
146 147
  pRetrieve->free = htons(pRetrieve->free);

S
slguan 已提交
148 149
  memset(pRet, 0, sizeof(SRspRet));

H
Haojun Liao 已提交
150 151
  if (pRetrieve->free == 1) {
    vTrace("vgId:%d, QInfo:%p, retrieve msg received to kill query and free qhandle", pVnode->vgId, pQInfo);
152
    int32_t ret = qKillQuery(pQInfo, vnodeRelease, pVnode);
H
Haojun Liao 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165

    pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp));
    pRet->len = sizeof(SRetrieveTableRsp);

    memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp));
    SRetrieveTableRsp* pRsp = pRet->rsp;
    pRsp->numOfRows = 0;
    pRsp->completed = true;
    pRsp->useconds  = 0;

    return ret;
  }

166
  vTrace("vgId:%d, QInfo:%p, retrieve msg is received", pVnode->vgId, pQInfo);
H
Haojun Liao 已提交
167

168 169
  int32_t code = qRetrieveQueryResultInfo(pQInfo);
  if (code != TSDB_CODE_SUCCESS) {
S
slguan 已提交
170 171 172 173 174
    //TODO
    pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp));
    memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp));
  } else {
    // todo check code and handle error in build result set
175
    code = qDumpRetrieveResult(pQInfo, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len);
S
slguan 已提交
176 177 178

    if (qHasMoreResultsToRetrieve(pQInfo)) {
      pRet->qhandle = pQInfo;
179
      code = TSDB_CODE_VND_ACTION_NEED_REPROCESSED;
H
Haojun Liao 已提交
180
    } else { // no further execution invoked, release the ref to vnode
181
      qDestroyQueryInfo(pQInfo, vnodeRelease, pVnode);
S
slguan 已提交
182 183 184
    }
  }
  
185
  vTrace("vgId:%d, QInfo:%p, retrieve msg is disposed", pVnode->vgId, pQInfo);
S
slguan 已提交
186 187
  return code;
}