walMeta.c 7.1 KB
Newer Older
L
Liu Jicong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * 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 "taoserror.h"
#include "tref.h"
#include "tfile.h"
#include "cJSON.h"
#include "walInt.h"

#include <libgen.h>
#include <regex.h>

L
Liu Jicong 已提交
27
int64_t walGetFirstVer(SWal *pWal) {
L
Liu Jicong 已提交
28
  return pWal->vers.firstVer;
L
Liu Jicong 已提交
29 30 31
}

int64_t walGetSnaphostVer(SWal *pWal) {
L
Liu Jicong 已提交
32
  return pWal->vers.snapshotVer;
L
Liu Jicong 已提交
33 34 35
}

int64_t walGetLastVer(SWal *pWal) {
L
Liu Jicong 已提交
36
  return pWal->vers.lastVer;
L
Liu Jicong 已提交
37 38
}

L
Liu Jicong 已提交
39 40 41 42 43 44
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

  SArray* pArray = pWal->fileInfoSet;
  if(taosArrayGetSize(pArray) != 0) {
    WalFileInfo *pInfo = taosArrayGetLast(pArray);
L
Liu Jicong 已提交
45
    pInfo->lastVer = pWal->vers.lastVer;
L
Liu Jicong 已提交
46 47 48
    pInfo->closeTs = ts;
  }

L
Liu Jicong 已提交
49
  //TODO: change to emplace back
L
Liu Jicong 已提交
50 51 52 53
  WalFileInfo *pNewInfo = malloc(sizeof(WalFileInfo));
  if(pNewInfo == NULL) {
    return -1;
  }
L
Liu Jicong 已提交
54
  pNewInfo->firstVer = pWal->vers.lastVer + 1;
L
Liu Jicong 已提交
55 56 57 58 59
  pNewInfo->lastVer = -1;
  pNewInfo->createTs = ts;
  pNewInfo->closeTs = -1;
  pNewInfo->fileSize = 0;
  taosArrayPush(pWal->fileInfoSet, pNewInfo);
L
Liu Jicong 已提交
60
  free(pNewInfo);
L
Liu Jicong 已提交
61 62 63
  return 0;
}

64
char* walMetaSerialize(SWal* pWal) {
L
Liu Jicong 已提交
65
  char buf[30];
L
Liu Jicong 已提交
66
  ASSERT(pWal->fileInfoSet);
L
Liu Jicong 已提交
67
  int sz = pWal->fileInfoSet->size;
68 69 70 71 72
  cJSON* pRoot = cJSON_CreateObject();
  cJSON* pMeta = cJSON_CreateObject();
  cJSON* pFiles = cJSON_CreateArray();
  cJSON* pField;
  if(pRoot == NULL || pMeta == NULL || pFiles == NULL) {
L
Liu Jicong 已提交
73 74 75
    //TODO
    return NULL;
  }
76
  cJSON_AddItemToObject(pRoot, "meta", pMeta);
L
Liu Jicong 已提交
77
  sprintf(buf, "%" PRId64, pWal->vers.firstVer);
78
  cJSON_AddStringToObject(pMeta, "firstVer", buf);
L
Liu Jicong 已提交
79
  sprintf(buf, "%" PRId64, pWal->vers.snapshotVer);
80
  cJSON_AddStringToObject(pMeta, "snapshotVer", buf);
L
Liu Jicong 已提交
81
  sprintf(buf, "%" PRId64, pWal->vers.commitVer);
82
  cJSON_AddStringToObject(pMeta, "commitVer", buf);
L
Liu Jicong 已提交
83
  sprintf(buf, "%" PRId64, pWal->vers.lastVer);
84 85 86
  cJSON_AddStringToObject(pMeta, "lastVer", buf);

  cJSON_AddItemToObject(pRoot, "files", pFiles);
L
Liu Jicong 已提交
87 88 89
  WalFileInfo* pData = pWal->fileInfoSet->pData;
  for(int i = 0; i < sz; i++) {
    WalFileInfo* pInfo = &pData[i];
90 91 92
    cJSON_AddItemToArray(pFiles, pField = cJSON_CreateObject());
    if(pField == NULL) {
      cJSON_Delete(pRoot);
L
Liu Jicong 已提交
93 94 95 96
      return NULL;
    }
    //cjson only support int32_t or double
    //string are used to prohibit the loss of precision
97 98 99 100 101 102 103 104 105 106
    sprintf(buf, "%" PRId64, pInfo->firstVer);
    cJSON_AddStringToObject(pField, "firstVer", buf);
    sprintf(buf, "%" PRId64, pInfo->lastVer);
    cJSON_AddStringToObject(pField, "lastVer", buf);
    sprintf(buf, "%" PRId64, pInfo->createTs);
    cJSON_AddStringToObject(pField, "createTs", buf);
    sprintf(buf, "%" PRId64, pInfo->closeTs);
    cJSON_AddStringToObject(pField, "closeTs", buf);
    sprintf(buf, "%" PRId64, pInfo->fileSize);
    cJSON_AddStringToObject(pField, "fileSize", buf);
L
Liu Jicong 已提交
107
  }
L
Liu Jicong 已提交
108 109 110
  char* serialized = cJSON_Print(pRoot);
  cJSON_Delete(pRoot);
  return serialized;
L
Liu Jicong 已提交
111 112
}

113 114 115 116 117 118
int walMetaDeserialize(SWal* pWal, const char* bytes) {
  ASSERT(taosArrayGetSize(pWal->fileInfoSet) == 0);
  cJSON *pRoot, *pMeta, *pFiles, *pInfoJson, *pField;
  pRoot = cJSON_Parse(bytes);
  pMeta = cJSON_GetObjectItem(pRoot, "meta");
  pField = cJSON_GetObjectItem(pMeta, "firstVer");
L
Liu Jicong 已提交
119
  pWal->vers.firstVer = atoll(cJSON_GetStringValue(pField));
120
  pField = cJSON_GetObjectItem(pMeta, "snapshotVer");
L
Liu Jicong 已提交
121
  pWal->vers.snapshotVer = atoll(cJSON_GetStringValue(pField));
122
  pField = cJSON_GetObjectItem(pMeta, "commitVer");
L
Liu Jicong 已提交
123
  pWal->vers.commitVer = atoll(cJSON_GetStringValue(pField));
124
  pField = cJSON_GetObjectItem(pMeta, "lastVer");
L
Liu Jicong 已提交
125
  pWal->vers.lastVer = atoll(cJSON_GetStringValue(pField));
126 127 128

  pFiles = cJSON_GetObjectItem(pRoot, "files");
  int sz = cJSON_GetArraySize(pFiles);
L
Liu Jicong 已提交
129
  //deserialize
L
Liu Jicong 已提交
130 131
  SArray* pArray = pWal->fileInfoSet;
  taosArrayEnsureCap(pArray, sz);
L
Liu Jicong 已提交
132 133
  WalFileInfo *pData = pArray->pData;
  for(int i = 0; i < sz; i++) {
134
    cJSON* pInfoJson = cJSON_GetArrayItem(pFiles, i);
L
Liu Jicong 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147
    WalFileInfo* pInfo = &pData[i];
    pField = cJSON_GetObjectItem(pInfoJson, "firstVer");
    pInfo->firstVer = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "lastVer");
    pInfo->lastVer = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "createTs");
    pInfo->createTs = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "closeTs");
    pInfo->closeTs = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "fileSize");
    pInfo->fileSize = atoll(cJSON_GetStringValue(pField));
  }
  taosArraySetSize(pArray, sz);
148
  pWal->fileInfoSet = pArray;
L
Liu Jicong 已提交
149
  cJSON_Delete(pRoot);
150
  return 0;
L
Liu Jicong 已提交
151 152 153 154 155 156 157 158 159 160 161 162 163
}

static inline int walBuildMetaName(SWal* pWal, int metaVer, char* buf) {
  return sprintf(buf, "%s/meta-ver%d", pWal->path, metaVer);
}

static int walFindCurMetaVer(SWal* pWal) {
  const char * pattern = "^meta-ver[0-9]+$";
  regex_t walMetaRegexPattern;
  regcomp(&walMetaRegexPattern, pattern, REG_EXTENDED);

  DIR *dir = opendir(pWal->path); 
  if(dir == NULL) {
L
Liu Jicong 已提交
164
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
L
Liu Jicong 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    return -1;
  }

  struct dirent* ent;

  //find existing meta-ver[x].json
  int metaVer = -1;
  while((ent = readdir(dir)) != NULL) {
    char *name = basename(ent->d_name);
    int code = regexec(&walMetaRegexPattern, name, 0, NULL, 0);
    if(code == 0) {
      sscanf(name, "meta-ver%d", &metaVer);
      break;
    }
  }
L
Liu Jicong 已提交
180 181
  closedir(dir);
  regfree(&walMetaRegexPattern);
L
Liu Jicong 已提交
182 183 184 185 186 187 188 189 190 191 192
  return metaVer;
}

int walWriteMeta(SWal* pWal) {
  int metaVer = walFindCurMetaVer(pWal);
  char fnameStr[WAL_FILE_LEN];
  walBuildMetaName(pWal, metaVer+1, fnameStr);
  int metaTfd = tfOpenCreateWrite(fnameStr);
  if(metaTfd < 0) {
    return -1;
  }
193
  char* serialized = walMetaSerialize(pWal);
L
Liu Jicong 已提交
194 195 196 197 198 199 200 201 202 203 204 205
  int len = strlen(serialized);
  if(len != tfWrite(metaTfd, serialized, len)) {
    //TODO:clean file
    return -1;
  }
  
  tfClose(metaTfd);
  //delete old file
  if(metaVer > -1) {
    walBuildMetaName(pWal, metaVer, fnameStr);
    remove(fnameStr);
  }
L
Liu Jicong 已提交
206
  free(serialized);
L
Liu Jicong 已提交
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
  return 0;
}

int walReadMeta(SWal* pWal) {
  ASSERT(pWal->fileInfoSet->size == 0);
  //find existing meta file
  int metaVer = walFindCurMetaVer(pWal);
  if(metaVer == -1) {
    return 0;
  }
  char fnameStr[WAL_FILE_LEN];
  walBuildMetaName(pWal, metaVer, fnameStr);
  //read metafile
  struct stat statbuf;
  stat(fnameStr, &statbuf);
  int size = statbuf.st_size;
  char* buf = malloc(size + 5);
  if(buf == NULL) {
    return -1;
  }
L
Liu Jicong 已提交
227
  memset(buf, 0, size+5);
L
Liu Jicong 已提交
228 229 230 231 232 233
  int tfd = tfOpenRead(fnameStr);
  if(tfRead(tfd, buf, size) != size) {
    free(buf);
    return -1;
  }
  //load into fileInfoSet
234 235
  int code = walMetaDeserialize(pWal, buf);
  if(code != 0) {
L
Liu Jicong 已提交
236 237 238 239 240 241
    free(buf);
    return -1;
  }
  free(buf);
  return 0;
}