sdbFile.c 6.1 KB
Newer Older
S
Shengliang Guan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * 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 "sdbInt.h"
S
Shengliang Guan 已提交
18
#include "tchecksum.h"
S
Shengliang Guan 已提交
19

S
Shengliang Guan 已提交
20
static int32_t sdbCreateDir(SSdb *pSdb) {
S
Shengliang Guan 已提交
21 22 23 24
  if (taosMkDir(pSdb->currDir) != 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    mError("failed to create dir:%s since %s", pSdb->currDir, terrstr());
    return -1;
S
Shengliang Guan 已提交
25 26
  }

S
Shengliang Guan 已提交
27 28 29 30
  if (taosMkDir(pSdb->syncDir) != 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    mError("failed to create dir:%s since %s", pSdb->syncDir, terrstr());
    return -1;
S
Shengliang Guan 已提交
31 32
  }

S
Shengliang Guan 已提交
33 34 35 36
  if (taosMkDir(pSdb->tmpDir) != 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    mError("failed to create dir:%s since %s", pSdb->tmpDir, terrstr());
    return -1;
S
Shengliang Guan 已提交
37 38 39 40 41
  }

  return 0;
}

S
Shengliang Guan 已提交
42
static int32_t sdbRunDeployFp(SSdb *pSdb) {
S
Shengliang Guan 已提交
43
  mDebug("start to deploy sdb");
S
Shengliang Guan 已提交
44

S
Shengliang Guan 已提交
45
  for (int32_t i = SDB_MAX - 1; i > SDB_START; --i) {
S
Shengliang Guan 已提交
46
    SdbDeployFp fp = pSdb->deployFps[i];
S
Shengliang Guan 已提交
47
    if (fp == NULL) continue;
S
Shengliang Guan 已提交
48

S
Shengliang Guan 已提交
49
    if ((*fp)(pSdb->pMnode) != 0) {
S
Shengliang Guan 已提交
50 51
      mError("failed to deploy sdb:%d since %s", i, terrstr());
      return -1;
S
Shengliang Guan 已提交
52 53 54
    }
  }

S
Shengliang Guan 已提交
55
  mDebug("sdb deploy successfully");
S
Shengliang Guan 已提交
56 57 58
  return 0;
}

S
Shengliang Guan 已提交
59 60 61 62 63 64
int32_t sdbReadFile(SSdb *pSdb) {
  int64_t offset = 0;
  int32_t code = 0;
  int32_t readLen = 0;
  int64_t ret = 0;

S
Shengliang Guan 已提交
65 66
  SSdbRaw *pRaw = malloc(SDB_MAX_SIZE);
  if (pRaw == NULL) {
S
Shengliang Guan 已提交
67 68 69
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    mError("failed read file since %s",  terrstr());
    return -1;
S
Shengliang Guan 已提交
70 71 72
  }

  char file[PATH_MAX] = {0};
S
Shengliang Guan 已提交
73 74
  snprintf(file, sizeof(file), "%s%ssdb.data", pSdb->currDir, TD_DIRSEP);

S
Shengliang Guan 已提交
75
  FileFd fd = taosOpenFileRead(file);
S
Shengliang Guan 已提交
76
  if (fd <= 0) {
S
Shengliang Guan 已提交
77
    free(pRaw);
S
Shengliang Guan 已提交
78 79 80
    terrno = TAOS_SYSTEM_ERROR(errno);
    mError("failed to read file:%s since %s", file, terrstr());
    return -1;
S
Shengliang Guan 已提交
81 82 83
  }

  while (1) {
S
Shengliang Guan 已提交
84 85
    readLen = sizeof(SSdbRaw);
    ret = taosReadFile(fd, pRaw, readLen);
S
Shengliang Guan 已提交
86 87 88 89 90 91 92 93
    if (ret == 0) break;

    if (ret < 0) {
      code = TAOS_SYSTEM_ERROR(errno);
      mError("failed to read file:%s since %s", file, tstrerror(code));
      break;
    }

S
Shengliang Guan 已提交
94
    if (ret != readLen) {
S
Shengliang Guan 已提交
95 96 97 98 99
      code = TSDB_CODE_FILE_CORRUPTED;
      mError("failed to read file:%s since %s", file, tstrerror(code));
      break;
    }

S
Shengliang Guan 已提交
100 101
    readLen = pRaw->dataLen + sizeof(int32_t);
    ret = taosReadFile(fd, pRaw->pData, readLen);
S
Shengliang Guan 已提交
102 103 104 105 106 107
    if (ret < 0) {
      code = TAOS_SYSTEM_ERROR(errno);
      mError("failed to read file:%s since %s", file, tstrerror(code));
      break;
    }

S
Shengliang Guan 已提交
108
    if (ret != readLen) {
S
Shengliang Guan 已提交
109 110 111 112 113
      code = TSDB_CODE_FILE_CORRUPTED;
      mError("failed to read file:%s since %s", file, tstrerror(code));
      break;
    }

S
Shengliang Guan 已提交
114 115
    int32_t totalLen = sizeof(SSdbRaw) + pRaw->dataLen + sizeof(int32_t);
    if (!taosCheckChecksumWhole((const uint8_t *)pRaw, totalLen) != 0) {
S
Shengliang Guan 已提交
116
      code = TSDB_CODE_CHECKSUM_ERROR;
S
Shengliang Guan 已提交
117 118 119 120
      mError("failed to read file:%s since %s", file, tstrerror(code));
      break;
    }

S
Shengliang Guan 已提交
121
    code = sdbWriteRaw(pSdb, pRaw);
S
Shengliang Guan 已提交
122
    if (code != 0) {
S
Shengliang Guan 已提交
123
      mError("failed to read file:%s since %s", file, terrstr());
S
Shengliang Guan 已提交
124 125 126 127 128 129 130 131
      goto PARSE_SDB_DATA_ERROR;
    }
  }

  code = 0;

PARSE_SDB_DATA_ERROR:
  taosCloseFile(fd);
S
Shengliang Guan 已提交
132
  sdbFreeRaw(pRaw);
S
Shengliang Guan 已提交
133

S
Shengliang Guan 已提交
134
  terrno = code;
S
Shengliang Guan 已提交
135 136 137
  return code;
}

S
Shengliang Guan 已提交
138 139 140
int32_t sdbWriteFile(SSdb *pSdb) {
  int32_t code = 0;

S
Shengliang Guan 已提交
141
  char tmpfile[PATH_MAX] = {0};
S
Shengliang Guan 已提交
142
  snprintf(tmpfile, sizeof(tmpfile), "%s%ssdb.data", pSdb->tmpDir, TD_DIRSEP);
S
Shengliang Guan 已提交
143
  char curfile[PATH_MAX] = {0};
S
Shengliang Guan 已提交
144
  snprintf(curfile, sizeof(curfile), "%s%ssdb.data", pSdb->currDir, TD_DIRSEP);
S
Shengliang Guan 已提交
145 146 147

  FileFd fd = taosOpenFileCreateWrite(tmpfile);
  if (fd <= 0) {
S
Shengliang Guan 已提交
148 149 150
    terrno = TAOS_SYSTEM_ERROR(errno);
    mError("failed to open file:%s for write since %s", tmpfile, terrstr());
    return -1;
S
Shengliang Guan 已提交
151 152
  }

S
Shengliang Guan 已提交
153
  for (int32_t i = SDB_MAX - 1; i > SDB_START; --i) {
S
Shengliang Guan 已提交
154
    SdbEncodeFp encodeFp = pSdb->encodeFps[i];
S
Shengliang Guan 已提交
155 156
    if (encodeFp == NULL) continue;

S
Shengliang Guan 已提交
157 158
    SHashObj *hash = pSdb->hashObjs[i];
    SRWLatch *pLock = &pSdb->locks[i];
S
Shengliang Guan 已提交
159
    taosWLockLatch(pLock);
S
Shengliang Guan 已提交
160

S
Shengliang Guan 已提交
161 162 163 164 165 166 167
    SSdbRow **ppRow = taosHashIterate(hash, NULL);
    while (ppRow != NULL) {
      SSdbRow *pRow = *ppRow;
      if (pRow == NULL || pRow->status != SDB_STATUS_READY) {
        ppRow = taosHashIterate(hash, ppRow);
        continue;
      }
S
Shengliang Guan 已提交
168

S
Shengliang Guan 已提交
169 170
      SSdbRaw *pRaw = (*encodeFp)(pRow->pObj);
      if (pRaw != NULL) {
S
Shengliang Guan 已提交
171
        pRaw->status = pRow->status;
S
Shengliang Guan 已提交
172 173 174
        int32_t writeLen = sizeof(SSdbRaw) + pRaw->dataLen;
        if (taosWriteFile(fd, pRaw, writeLen) != writeLen) {
          code = TAOS_SYSTEM_ERROR(terrno);
S
Shengliang Guan 已提交
175
          taosHashCancelIterate(hash, ppRow);
S
Shengliang Guan 已提交
176 177
          break;
        }
S
Shengliang Guan 已提交
178 179

        int32_t cksum = taosCalcChecksum(0, (const uint8_t *)pRaw, sizeof(SSdbRaw) + pRaw->dataLen);
S
Shengliang Guan 已提交
180 181
        if (taosWriteFile(fd, &cksum, sizeof(int32_t)) != sizeof(int32_t)) {
          code = TAOS_SYSTEM_ERROR(terrno);
S
Shengliang Guan 已提交
182
          taosHashCancelIterate(hash, ppRow);
S
Shengliang Guan 已提交
183 184
          break;
        }
S
Shengliang Guan 已提交
185 186
      } else {
        code = TSDB_CODE_SDB_APP_ERROR;
S
Shengliang Guan 已提交
187
        taosHashCancelIterate(hash, ppRow);
S
Shengliang Guan 已提交
188 189 190
        break;
      }

S
Shengliang Guan 已提交
191
      ppRow = taosHashIterate(hash, ppRow);
S
Shengliang Guan 已提交
192
    }
S
Shengliang Guan 已提交
193
    taosWUnLockLatch(pLock);
S
Shengliang Guan 已提交
194 195 196 197
  }

  if (code == 0) {
    code = taosFsyncFile(fd);
S
Shengliang Guan 已提交
198 199 200 201
    if (code != 0) {
      code = TAOS_SYSTEM_ERROR(errno);
      mError("failed to write file:%s since %s", tmpfile, tstrerror(code));
    }
S
Shengliang Guan 已提交
202 203
  }

S
Shengliang Guan 已提交
204 205
  taosCloseFile(fd);

S
Shengliang Guan 已提交
206
  if (code == 0) {
S
Shengliang Guan 已提交
207
    code = taosRenameFile(tmpfile, curfile);
S
Shengliang Guan 已提交
208 209 210 211
    if (code != 0) {
      code = TAOS_SYSTEM_ERROR(errno);
      mError("failed to write file:%s since %s", curfile, tstrerror(code));
    }
S
Shengliang Guan 已提交
212 213 214
  }

  if (code != 0) {
S
Shengliang Guan 已提交
215
    mError("failed to write file:%s since %s", curfile, tstrerror(code));
S
Shengliang Guan 已提交
216
  } else {
S
Shengliang Guan 已提交
217
    mDebug("write file:%s successfully", curfile);
S
Shengliang Guan 已提交
218 219
  }

S
Shengliang Guan 已提交
220
  terrno = code;
S
Shengliang Guan 已提交
221 222 223
  return code;
}

S
Shengliang Guan 已提交
224
int32_t sdbDeploy(SSdb *pSdb) {
S
Shengliang Guan 已提交
225 226
  if (sdbCreateDir(pSdb) != 0) {
    return -1;
S
Shengliang Guan 已提交
227 228
  }

S
Shengliang Guan 已提交
229 230
  if (sdbRunDeployFp(pSdb) != 0) {
    return -1;
S
Shengliang Guan 已提交
231 232
  }

S
Shengliang Guan 已提交
233 234
  if (sdbWriteFile(pSdb) != 0) {
    return -1;
S
Shengliang Guan 已提交
235 236 237 238
  }

  return 0;
}