tfs.c 15.1 KB
Newer Older
H
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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/>.
 */

S
Shengliang Guan 已提交
16 17
#define _DEFAULT_SOURCE
#include "tfsInt.h"
H
Hongze Cheng 已提交
18

S
TD-1207  
Shengliang Guan 已提交
19
#define TMPNAME_LEN (TSDB_FILENAME_LEN * 2 + 32)
S
TD-1207  
Shengliang Guan 已提交
20

H
Hongze Cheng 已提交
21
typedef struct {
H
Hongze Cheng 已提交
22 23
  pthread_spinlock_t lock;
  SFSMeta            meta;
S
Shengliang Guan 已提交
24
  int32_t            nlevel;
H
Hongze Cheng 已提交
25
  STier              tiers[TSDB_MAX_TIERS];
S
Shengliang Guan 已提交
26
  SHashObj          *map;  // name to did map
H
Hongze Cheng 已提交
27 28
} SFS;

H
Hongze Cheng 已提交
29 30 31 32
typedef struct {
  SDisk *pDisk;
} SDiskIter;

H
Hongze Cheng 已提交
33 34 35 36 37 38
#define TFS_META() (pfs->meta)
#define TFS_NLEVEL() (pfs->nlevel)
#define TFS_TIERS() (pfs->tiers)
#define TFS_TIER_AT(level) (TFS_TIERS() + (level))
#define TFS_DISK_AT(level, id) DISK_AT_TIER(TFS_TIER_AT(level), id)
#define TFS_PRIMARY_DISK() TFS_DISK_AT(TFS_PRIMARY_LEVEL, TFS_PRIMARY_ID)
H
Hongze Cheng 已提交
39 40 41
#define TFS_IS_VALID_LEVEL(level) (((level) >= 0) && ((level) < TFS_NLEVEL()))
#define TFS_IS_VALID_ID(level, id) (((id) >= 0) && ((id) < TIER_NDISKS(TFS_TIER_AT(level))))
#define TFS_IS_VALID_DISK(level, id) (TFS_IS_VALID_LEVEL(level) && TFS_IS_VALID_ID(level, id))
H
Hongze Cheng 已提交
42

H
Hongze Cheng 已提交
43 44
#define tfsLock() pthread_spin_lock(&(pfs->lock))
#define tfsUnLock() pthread_spin_unlock(&(pfs->lock))
H
Hongze Cheng 已提交
45

H
Hongze Cheng 已提交
46 47 48 49
static SFS  tfs = {0};
static SFS *pfs = &tfs;

// STATIC DECLARATION
S
Shengliang Guan 已提交
50 51 52 53 54 55 56 57 58
static int32_t tfsMount(SDiskCfg *pCfg);
static int32_t tfsCheck();
static int32_t tfsCheckAndFormatCfg(SDiskCfg *pCfg);
static int32_t tfsFormatDir(char *idir, char *odir);
static SDisk  *tfsGetDiskByID(SDiskID did);
static SDisk  *tfsGetDiskByName(const char *dir);
static int32_t tfsOpendirImpl(TDIR *tdir);
static void    tfsInitDiskIter(SDiskIter *pIter);
static SDisk  *tfsNextDisk(SDiskIter *pIter);
H
Hongze Cheng 已提交
59

H
Hongze Cheng 已提交
60
// FS APIs ====================================
S
Shengliang Guan 已提交
61
int32_t tfsInit(SDiskCfg *pDiskCfg, int32_t ndisk) {
62 63 64 65
  if (ndisk < 0) {
    terrno = TSDB_CODE_INVALID_PARA;
    return -1;
  }
H
Hongze Cheng 已提交
66

S
Shengliang Guan 已提交
67
  for (int32_t level = 0; level < TSDB_MAX_TIERS; level++) {
H
Hongze Cheng 已提交
68 69 70 71
    if (tfsInitTier(TFS_TIER_AT(level), level) < 0) {
      while (true) {
        level--;
        if (level < 0) break;
H
Hongze Cheng 已提交
72

H
Hongze Cheng 已提交
73 74 75 76 77
        tfsDestroyTier(TFS_TIER_AT(level));
      }

      return -1;
    }
H
Hongze Cheng 已提交
78 79
  }

H
Hongze Cheng 已提交
80 81
  pthread_spin_init(&(pfs->lock), 0);

H
Hongze Cheng 已提交
82
  pfs->map = taosHashInit(TSDB_MAX_TIERS * TSDB_MAX_DISKS_PER_TIER * 2,
H
Hongze Cheng 已提交
83 84
                          taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
  if (pfs->map == NULL) {
S
Shengliang Guan 已提交
85
    terrno = TSDB_CODE_OUT_OF_MEMORY;
S
Shengliang Guan 已提交
86
    tfsCleanup();
H
Hongze Cheng 已提交
87 88 89
    return -1;
  }

S
Shengliang Guan 已提交
90
  for (int32_t idisk = 0; idisk < ndisk; idisk++) {
H
refact  
Hongze Cheng 已提交
91
    if (tfsMount(pDiskCfg + idisk) < 0) {
S
Shengliang Guan 已提交
92
      tfsCleanup();
H
Hongze Cheng 已提交
93 94 95 96
      return -1;
    }
  }

H
Hongze Cheng 已提交
97
  if (tfsCheck() < 0) {
S
Shengliang Guan 已提交
98
    tfsCleanup();
H
Hongze Cheng 已提交
99 100 101
    return -1;
  }

102
  tfsUpdateSize(NULL);
S
Shengliang Guan 已提交
103
  for (int32_t level = 0; level < TFS_NLEVEL(); level++) {
H
Hongze Cheng 已提交
104 105
    tfsPosNextId(TFS_TIER_AT(level));
  }
H
Hongze Cheng 已提交
106

H
Hongze Cheng 已提交
107 108 109
  return 0;
}

S
Shengliang Guan 已提交
110
void tfsCleanup() {
H
Hongze Cheng 已提交
111 112
  taosHashCleanup(pfs->map);
  pfs->map = NULL;
H
Hongze Cheng 已提交
113 114

  pthread_spin_destroy(&(pfs->lock));
S
Shengliang Guan 已提交
115
  for (int32_t level = 0; level < TFS_NLEVEL(); level++) {
H
Hongze Cheng 已提交
116
    tfsDestroyTier(TFS_TIER_AT(level));
H
Hongze Cheng 已提交
117 118 119
  }
}

120 121 122
void tfsUpdateSize(SFSMeta *pFSMeta) {
  SFSMeta   fsMeta = {0};
  SDiskSize size = {0};
H
Hongze Cheng 已提交
123

H
Hongze Cheng 已提交
124 125 126 127
  if (pFSMeta == NULL) {
    pFSMeta = &fsMeta;
  }

128
  memset(pFSMeta, 0, sizeof(SFSMeta));
H
Hongze Cheng 已提交
129

S
Shengliang Guan 已提交
130
  for (int32_t level = 0; level < TFS_NLEVEL(); level++) {
H
Hongze Cheng 已提交
131
    STier *pTier = TFS_TIER_AT(level);
132 133 134 135
    tfsUpdateTierSize(pTier);
    pFSMeta->total += pTier->size.total;
    pFSMeta->avail += pTier->size.avail;
    pFSMeta->used += pTier->size.used;
H
Hongze Cheng 已提交
136 137
  }

H
Hongze Cheng 已提交
138
  tfsLock();
H
Hongze Cheng 已提交
139
  pfs->meta = *pFSMeta;
H
Hongze Cheng 已提交
140 141 142
  tfsUnLock();
}

H
Hongze Cheng 已提交
143 144
/* Allocate an existing available tier level
 */
S
Shengliang Guan 已提交
145
void tfsAllocDisk(int32_t expLevel, int32_t *level, int32_t *id) {
H
Hongze Cheng 已提交
146 147
  ASSERT(expLevel >= 0);

H
Hongze Cheng 已提交
148 149 150
  *level = expLevel;
  *id = TFS_UNDECIDED_ID;

H
Hongze Cheng 已提交
151
  if (*level >= TFS_NLEVEL()) {
H
Hongze Cheng 已提交
152
    *level = TFS_NLEVEL() - 1;
H
Hongze Cheng 已提交
153 154 155
  }

  while (*level >= 0) {
H
Hongze Cheng 已提交
156 157
    *id = tfsAllocDiskOnTier(TFS_TIER_AT(*level));
    if (*id == TFS_UNDECIDED_ID) {
H
Hongze Cheng 已提交
158
      (*level)--;
H
Hongze Cheng 已提交
159 160 161 162 163 164 165 166 167 168
      continue;
    }

    return;
  }

  *level = TFS_UNDECIDED_LEVEL;
  *id = TFS_UNDECIDED_ID;
}

H
Hongze Cheng 已提交
169
const char *TFS_PRIMARY_PATH() { return DISK_DIR(TFS_PRIMARY_DISK()); }
S
Shengliang Guan 已提交
170
const char *TFS_DISK_PATH(int32_t level, int32_t id) { return DISK_DIR(TFS_DISK_AT(level, id)); }
H
Hongze Cheng 已提交
171

H
Hongze Cheng 已提交
172
// TFILE APIs ====================================
S
Shengliang Guan 已提交
173
void tfsInitFile(TFILE *pf, int32_t level, int32_t id, const char *bname) {
H
Hongze Cheng 已提交
174 175 176 177
  ASSERT(TFS_IS_VALID_DISK(level, id));

  SDisk *pDisk = TFS_DISK_AT(level, id);

H
Hongze Cheng 已提交
178 179
  pf->level = level;
  pf->id = id;
180
  tstrncpy(pf->rname, bname, TSDB_FILENAME_LEN);
S
TD-1207  
Shengliang Guan 已提交
181 182 183 184

  char tmpName[TMPNAME_LEN] = {0};
  snprintf(tmpName, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), bname);
  tstrncpy(pf->aname, tmpName, TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
185 186
}

187 188 189
bool tfsIsSameFile(const TFILE *pf1, const TFILE *pf2) {
  ASSERT(pf1 != NULL || pf2 != NULL);
  if (pf1 == NULL || pf2 == NULL) return false;
H
Hongze Cheng 已提交
190 191 192 193 194 195
  if (pf1->level != pf2->level) return false;
  if (pf1->id != pf2->id) return false;
  if (strncmp(pf1->rname, pf2->rname, TSDB_FILENAME_LEN) != 0) return false;
  return true;
}

S
Shengliang Guan 已提交
196 197
int32_t tfsEncodeFile(void **buf, TFILE *pf) {
  int32_t tlen = 0;
H
Hongze Cheng 已提交
198 199 200 201 202 203 204 205 206 207

  tlen += taosEncodeVariantI32(buf, pf->level);
  tlen += taosEncodeVariantI32(buf, pf->id);
  tlen += taosEncodeString(buf, pf->rname);

  return tlen;
}

void *tfsDecodeFile(void *buf, TFILE *pf) {
  int32_t level, id;
S
Shengliang Guan 已提交
208
  char   *rname;
H
Hongze Cheng 已提交
209 210 211 212 213 214 215 216 217 218 219

  buf = taosDecodeVariantI32(buf, &(level));
  buf = taosDecodeVariantI32(buf, &(id));
  buf = taosDecodeString(buf, &rname);

  tfsInitFile(pf, level, id, rname);

  tfree(rname);
  return buf;
}

H
Hongze Cheng 已提交
220
void tfsbasename(const TFILE *pf, char *dest) {
H
Hongze Cheng 已提交
221 222
  char tname[TSDB_FILENAME_LEN] = "\0";

223 224
  tstrncpy(tname, pf->aname, TSDB_FILENAME_LEN);
  tstrncpy(dest, basename(tname), TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
225 226
}

H
Hongze Cheng 已提交
227
void tfsdirname(const TFILE *pf, char *dest) {
H
Hongze Cheng 已提交
228 229
  char tname[TSDB_FILENAME_LEN] = "\0";

230 231
  tstrncpy(tname, pf->aname, TSDB_FILENAME_LEN);
  tstrncpy(dest, dirname(tname), TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
232 233
}

H
Hongze Cheng 已提交
234
// DIR APIs ====================================
S
Shengliang Guan 已提交
235
int32_t tfsMkdirAt(const char *rname, int32_t level, int32_t id) {
H
Hongze Cheng 已提交
236
  SDisk *pDisk = TFS_DISK_AT(level, id);
S
TD-1207  
Shengliang Guan 已提交
237
  char   aname[TMPNAME_LEN];
H
Hongze Cheng 已提交
238

S
TD-1207  
Shengliang Guan 已提交
239
  snprintf(aname, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), rname);
240
  if (taosMkDir(aname) != 0) {
H
Hongze Cheng 已提交
241 242 243 244 245 246 247
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  return 0;
}

S
Shengliang Guan 已提交
248
int32_t tfsMkdirRecurAt(const char *rname, int32_t level, int32_t id) {
H
Hongze Cheng 已提交
249 250 251 252 253
  if (tfsMkdirAt(rname, level, id) < 0) {
    if (errno == ENOENT) {
      // Try to create upper
      char *s = strdup(rname);

J
Jun Li 已提交
254 255 256 257
      // Make a copy of dirname(s) because the implementation of 'dirname' differs on different platforms.
      // Some platform may modify the contents of the string passed into dirname(). Others may return a pointer to
      // internal static storage space that will be overwritten by next call. For case like that, we should not use
      // the pointer directly in this recursion.
H
Hongze Cheng 已提交
258 259
      // See
      // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dirname.3.html
J
Jun Li 已提交
260 261 262 263 264
      char *dir = strdup(dirname(s));

      if (tfsMkdirRecurAt(dir, level, id) < 0) {
        free(s);
        free(dir);
H
Hongze Cheng 已提交
265 266
        return -1;
      }
J
Jun Li 已提交
267 268
      free(s);
      free(dir);
H
Hongze Cheng 已提交
269 270 271 272 273 274 275 276 277 278 279 280

      if (tfsMkdirAt(rname, level, id) < 0) {
        return -1;
      }
    } else {
      return -1;
    }
  }

  return 0;
}

S
Shengliang Guan 已提交
281 282
int32_t tfsMkdir(const char *rname) {
  for (int32_t level = 0; level < TFS_NLEVEL(); level++) {
H
Hongze Cheng 已提交
283
    STier *pTier = TFS_TIER_AT(level);
S
Shengliang Guan 已提交
284
    for (int32_t id = 0; id < TIER_NDISKS(pTier); id++) {
H
Hongze Cheng 已提交
285
      if (tfsMkdirAt(rname, level, id) < 0) {
H
Hongze Cheng 已提交
286 287 288 289 290 291 292 293
        return -1;
      }
    }
  }

  return 0;
}

S
Shengliang Guan 已提交
294
int32_t tfsRmdir(const char *rname) {
S
TD-1207  
Shengliang Guan 已提交
295
  char aname[TMPNAME_LEN] = "\0";
H
Hongze Cheng 已提交
296

S
Shengliang Guan 已提交
297
  for (int32_t level = 0; level < TFS_NLEVEL(); level++) {
H
Hongze Cheng 已提交
298
    STier *pTier = TFS_TIER_AT(level);
S
Shengliang Guan 已提交
299
    for (int32_t id = 0; id < TIER_NDISKS(pTier); id++) {
300
      SDisk *pDisk = pTier->disks[id];
H
Hongze Cheng 已提交
301

302
      snprintf(aname, TMPNAME_LEN, "%s%s%s", DISK_DIR(pDisk), TS_PATH_DELIMITER, rname);
H
Hongze Cheng 已提交
303

H
Hongze Cheng 已提交
304
      taosRemoveDir(aname);
H
Hongze Cheng 已提交
305 306 307 308 309 310
    }
  }

  return 0;
}

S
Shengliang Guan 已提交
311
#if 0
S
Shengliang Guan 已提交
312
int32_t tfsRename(char *orname, char *nrname) {
S
TD-1207  
Shengliang Guan 已提交
313 314
  char oaname[TMPNAME_LEN] = "\0";
  char naname[TMPNAME_LEN] = "\0";
H
Hongze Cheng 已提交
315

S
Shengliang Guan 已提交
316
  for (int32_t level = 0; level < pfs->nlevel; level++) {
H
Hongze Cheng 已提交
317
    STier *pTier = TFS_TIER_AT(level);
S
Shengliang Guan 已提交
318
    for (int32_t id = 0; id < TIER_NDISKS(pTier); id++) {
H
Hongze Cheng 已提交
319 320
      SDisk *pDisk = DISK_AT_TIER(pTier, id);

S
TD-1207  
Shengliang Guan 已提交
321 322
      snprintf(oaname, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), orname);
      snprintf(naname, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), nrname);
H
Hongze Cheng 已提交
323

H
Hongze Cheng 已提交
324
      taosRenameFile(oaname, naname);
H
Hongze Cheng 已提交
325 326 327 328 329
    }
  }

  return 0;
}
S
Shengliang Guan 已提交
330
#endif
H
Hongze Cheng 已提交
331

H
Hongze Cheng 已提交
332 333
struct TDIR {
  SDiskIter iter;
S
Shengliang Guan 已提交
334 335
  int32_t   level;
  int32_t   id;
H
Hongze Cheng 已提交
336 337
  char      dirname[TSDB_FILENAME_LEN];
  TFILE     tfile;
S
Shengliang Guan 已提交
338
  DIR      *dir;
H
Hongze Cheng 已提交
339 340 341 342 343
};

TDIR *tfsOpendir(const char *rname) {
  TDIR *tdir = (TDIR *)calloc(1, sizeof(*tdir));
  if (tdir == NULL) {
344
    terrno = TSDB_CODE_OUT_OF_MEMORY;
H
Hongze Cheng 已提交
345 346 347 348
    return NULL;
  }

  tfsInitDiskIter(&(tdir->iter));
349
  tstrncpy(tdir->dirname, rname, TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
350 351 352 353 354 355 356 357 358 359 360

  if (tfsOpendirImpl(tdir) < 0) {
    free(tdir);
    return NULL;
  }

  return tdir;
}

const TFILE *tfsReaddir(TDIR *tdir) {
  if (tdir == NULL || tdir->dir == NULL) return NULL;
S
TD-1207  
Shengliang Guan 已提交
361
  char bname[TMPNAME_LEN * 2] = "\0";
H
Hongze Cheng 已提交
362 363 364 365 366

  while (true) {
    struct dirent *dp = NULL;
    dp = readdir(tdir->dir);
    if (dp != NULL) {
367 368 369
      // Skip . and ..
      if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue;

S
TD-1207  
Shengliang Guan 已提交
370
      snprintf(bname, TMPNAME_LEN * 2, "%s/%s", tdir->dirname, dp->d_name);
H
Hongze Cheng 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
      tfsInitFile(&(tdir->tfile), tdir->level, tdir->id, bname);
      return &(tdir->tfile);
    }

    if (tfsOpendirImpl(tdir) < 0) {
      return NULL;
    }

    if (tdir->dir == NULL) {
      terrno = TSDB_CODE_SUCCESS;
      return NULL;
    }
  }
}

void tfsClosedir(TDIR *tdir) {
  if (tdir) {
    if (tdir->dir != NULL) {
      closedir(tdir->dir);
      tdir->dir = NULL;
    }
    free(tdir);
  }
}

H
refact  
Hongze Cheng 已提交
396
// private
S
Shengliang Guan 已提交
397
static int32_t tfsMount(SDiskCfg *pCfg) {
H
refact  
Hongze Cheng 已提交
398
  SDiskID did;
S
Shengliang Guan 已提交
399
  SDisk  *pDisk = NULL;
H
refact  
Hongze Cheng 已提交
400

H
Hongze Cheng 已提交
401
  if (tfsCheckAndFormatCfg(pCfg) < 0) return -1;
H
Hongze Cheng 已提交
402

H
refact  
Hongze Cheng 已提交
403
  did.level = pCfg->level;
H
Hongze Cheng 已提交
404 405
  pDisk = tfsMountDiskToTier(TFS_TIER_AT(did.level), pCfg);
  if (pDisk == NULL) {
H
Hongze Cheng 已提交
406
    fError("failed to mount disk %s to level %d since %s", pCfg->dir, pCfg->level, tstrerror(terrno));
H
refact  
Hongze Cheng 已提交
407
    return -1;
H
Hongze Cheng 已提交
408
  }
409
  did.id = pDisk->id;
H
Hongze Cheng 已提交
410

H
Hongze Cheng 已提交
411
  taosHashPut(pfs->map, (void *)(pCfg->dir), strnlen(pCfg->dir, TSDB_FILENAME_LEN), (void *)(&did), sizeof(did));
H
Hongze Cheng 已提交
412 413 414 415 416
  if (pfs->nlevel < pCfg->level + 1) pfs->nlevel = pCfg->level + 1;

  return 0;
}

S
Shengliang Guan 已提交
417
static int32_t tfsCheckAndFormatCfg(SDiskCfg *pCfg) {
H
Hongze Cheng 已提交
418 419 420
  char        dirName[TSDB_FILENAME_LEN] = "\0";
  struct stat pstat;

H
Hongze Cheng 已提交
421
  if (pCfg->level < 0 || pCfg->level >= TSDB_MAX_TIERS) {
H
Hongze Cheng 已提交
422
    fError("failed to mount %s to FS since invalid level %d", pCfg->dir, pCfg->level);
H
Hongze Cheng 已提交
423 424 425 426
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

H
refact  
Hongze Cheng 已提交
427 428
  if (pCfg->primary) {
    if (pCfg->level != 0) {
H
Hongze Cheng 已提交
429
      fError("failed to mount %s to FS since disk is primary but level %d not 0", pCfg->dir, pCfg->level);
H
refact  
Hongze Cheng 已提交
430 431 432
      terrno = TSDB_CODE_FS_INVLD_CFG;
      return -1;
    }
H
Hongze Cheng 已提交
433

H
Hongze Cheng 已提交
434 435
    if (TFS_PRIMARY_DISK() != NULL) {
      fError("failed to mount %s to FS since duplicate primary mount", pCfg->dir);
H
refact  
Hongze Cheng 已提交
436 437 438 439
      terrno = TSDB_CODE_FS_DUP_PRIMARY;
      return -1;
    }
  }
H
Hongze Cheng 已提交
440

H
Hongze Cheng 已提交
441
  if (tfsFormatDir(pCfg->dir, dirName) < 0) {
H
Hongze Cheng 已提交
442
    fError("failed to mount %s to FS since invalid dir format", pCfg->dir);
H
Hongze Cheng 已提交
443 444 445 446
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

H
refact  
Hongze Cheng 已提交
447
  if (tfsGetDiskByName(dirName) != NULL) {
H
Hongze Cheng 已提交
448
    fError("failed to mount %s to FS since duplicate mount", pCfg->dir);
H
Hongze Cheng 已提交
449 450 451 452 453
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

  if (access(dirName, W_OK | R_OK | F_OK) != 0) {
H
Hongze Cheng 已提交
454
    fError("failed to mount %s to FS since no R/W access rights", pCfg->dir);
H
Hongze Cheng 已提交
455 456 457 458 459
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

  if (stat(dirName, &pstat) < 0) {
H
Hongze Cheng 已提交
460
    fError("failed to mount %s to FS since %s", pCfg->dir, strerror(errno));
H
Hongze Cheng 已提交
461 462 463 464 465
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  if (!S_ISDIR(pstat.st_mode)) {
H
Hongze Cheng 已提交
466
    fError("failed to mount %s to FS since not a directory", pCfg->dir);
H
Hongze Cheng 已提交
467 468 469 470 471 472 473 474 475
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

  strncpy(pCfg->dir, dirName, TSDB_FILENAME_LEN);

  return 0;
}

S
Shengliang Guan 已提交
476
static int32_t tfsFormatDir(char *idir, char *odir) {
H
Hongze Cheng 已提交
477 478
  wordexp_t wep = {0};

S
Shengliang Guan 已提交
479
  int32_t code = wordexp(idir, &wep, 0);
H
Hongze Cheng 已提交
480 481 482 483 484
  if (code != 0) {
    terrno = TAOS_SYSTEM_ERROR(code);
    return -1;
  }

485 486
  char tmp[PATH_MAX] = {0};
  if (realpath(wep.we_wordv[0], tmp) == NULL) {
H
Hongze Cheng 已提交
487 488 489 490
    terrno = TAOS_SYSTEM_ERROR(errno);
    wordfree(&wep);
    return -1;
  }
491
  strcpy(odir, tmp);
H
Hongze Cheng 已提交
492 493 494 495 496

  wordfree(&wep);
  return 0;
}

S
Shengliang Guan 已提交
497
static int32_t tfsCheck() {
H
Hongze Cheng 已提交
498
  if (TFS_PRIMARY_DISK() == NULL) {
H
Hongze Cheng 已提交
499 500 501 502 503
    fError("no primary disk is set");
    terrno = TSDB_CODE_FS_NO_PRIMARY_DISK;
    return -1;
  }

S
Shengliang Guan 已提交
504
  for (int32_t level = 0; level < TFS_NLEVEL(); level++) {
H
Hongze Cheng 已提交
505
    if (TIER_NDISKS(TFS_TIER_AT(level)) == 0) {
H
Hongze Cheng 已提交
506
      fError("no disk at level %d", level);
H
refact  
Hongze Cheng 已提交
507
      terrno = TSDB_CODE_FS_NO_MOUNT_AT_TIER;
H
Hongze Cheng 已提交
508 509
      return -1;
    }
H
Hongze Cheng 已提交
510
  }
H
Hongze Cheng 已提交
511

H
Hongze Cheng 已提交
512 513 514
  return 0;
}

H
Hongze Cheng 已提交
515 516 517
static SDisk *tfsGetDiskByID(SDiskID did) { return TFS_DISK_AT(did.level, did.id); }
static SDisk *tfsGetDiskByName(const char *dir) {
  SDiskID did;
S
Shengliang Guan 已提交
518 519
  SDisk  *pDisk = NULL;
  void   *pr = NULL;
H
Hongze Cheng 已提交
520 521 522 523 524 525 526

  pr = taosHashGet(pfs->map, (void *)dir, strnlen(dir, TSDB_FILENAME_LEN));
  if (pr == NULL) return NULL;

  did = *(SDiskID *)pr;
  pDisk = tfsGetDiskByID(did);
  ASSERT(pDisk != NULL);
H
refact  
Hongze Cheng 已提交
527

H
Hongze Cheng 已提交
528
  return pDisk;
H
Hongze Cheng 已提交
529 530
}

S
Shengliang Guan 已提交
531
static int32_t tfsOpendirImpl(TDIR *tdir) {
H
Hongze Cheng 已提交
532
  SDisk *pDisk = NULL;
S
TD-1207  
Shengliang Guan 已提交
533
  char   adir[TMPNAME_LEN * 2] = "\0";
H
Hongze Cheng 已提交
534 535 536 537 538 539 540 541 542 543

  if (tdir->dir != NULL) {
    closedir(tdir->dir);
    tdir->dir = NULL;
  }

  while (true) {
    pDisk = tfsNextDisk(&(tdir->iter));
    if (pDisk == NULL) return 0;

544 545
    tdir->level = pDisk->level;
    tdir->id = pDisk->id;
H
Hongze Cheng 已提交
546

547
    snprintf(adir, TMPNAME_LEN * 2, "%s%s%s", pDisk->path, TS_PATH_DELIMITER,tdir->dirname);
H
Hongze Cheng 已提交
548 549 550 551 552 553 554 555 556 557 558 559 560 561
    tdir->dir = opendir(adir);
    if (tdir->dir != NULL) break;
  }

  return 0;
}

static void tfsInitDiskIter(SDiskIter *pIter) { pIter->pDisk = TFS_DISK_AT(0, 0); }

static SDisk *tfsNextDisk(SDiskIter *pIter) {
  SDisk *pDisk = pIter->pDisk;

  if (pDisk == NULL) return NULL;

562 563
  int32_t level = pDisk->level;
  int32_t id = pDisk->id;
H
Hongze Cheng 已提交
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582

  id++;
  if (id < TIER_NDISKS(TFS_TIER_AT(level))) {
    pIter->pDisk = TFS_DISK_AT(level, id);
    ASSERT(pIter->pDisk != NULL);
  } else {
    level++;
    id = 0;
    if (level < TFS_NLEVEL()) {
      pIter->pDisk = TFS_DISK_AT(level, id);
      ASSERT(pIter->pDisk != NULL);
    } else {
      pIter->pDisk = NULL;
    }
  }

  return pDisk;
}

H
compile  
Hongze Cheng 已提交
583 584 585
// OTHER FUNCTIONS ===================================
void taosGetDisk() {
  const double unit = 1024 * 1024 * 1024;
586
  SDiskSize    diskSize;
H
Hongze Cheng 已提交
587
  SFSMeta      fsMeta;
H
compile  
Hongze Cheng 已提交
588

589 590
  tfsUpdateSize(&fsMeta);
  tsTotalDataDirGB = (float)(fsMeta.total / unit);
H
Hongze Cheng 已提交
591 592
  tsUsedDataDirGB = (float)(fsMeta.used / unit);
  tsAvailDataDirGB = (float)(fsMeta.avail / unit);
H
compile  
Hongze Cheng 已提交
593

S
TD-1207  
Shengliang Guan 已提交
594
  if (taosGetDiskSize(tsLogDir, &diskSize) == 0) {
595
    tsTotalLogDirGB = (float)(diskSize.total / unit);
S
TD-1207  
Shengliang Guan 已提交
596
    tsAvailLogDirGB = (float)(diskSize.avail / unit);
H
compile  
Hongze Cheng 已提交
597 598
  }

S
TD-1207  
Shengliang Guan 已提交
599
  if (taosGetDiskSize(tsTempDir, &diskSize) == 0) {
600
    tsTotalTmpDirGB = (float)(diskSize.total / unit);
S
TD-1207  
Shengliang Guan 已提交
601
    tsAvailTmpDirectorySpace = (float)(diskSize.avail / unit);
H
compile  
Hongze Cheng 已提交
602 603
  }
}