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

#include "os.h"
H
refact  
Hongze Cheng 已提交
17

H
Hongze Cheng 已提交
18
#include "taosdef.h"
H
Hongze Cheng 已提交
19
#include "taoserror.h"
H
Hongze Cheng 已提交
20
#include "tfs.h"
H
refact  
Hongze Cheng 已提交
21
#include "tfsint.h"
H
Hongze Cheng 已提交
22
#include "thash.h"
H
Hongze Cheng 已提交
23

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

H
Hongze Cheng 已提交
26
typedef struct {
H
Hongze Cheng 已提交
27 28 29 30 31
  pthread_spinlock_t lock;
  SFSMeta            meta;
  int                nlevel;
  STier              tiers[TSDB_MAX_TIERS];
  SHashObj *         map;  // name to did map
H
Hongze Cheng 已提交
32 33
} SFS;

H
Hongze Cheng 已提交
34 35 36 37
typedef struct {
  SDisk *pDisk;
} SDiskIter;

H
Hongze Cheng 已提交
38 39 40 41 42 43
#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 已提交
44 45 46
#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 已提交
47

H
Hongze Cheng 已提交
48 49
#define tfsLock() pthread_spin_lock(&(pfs->lock))
#define tfsUnLock() pthread_spin_unlock(&(pfs->lock))
H
Hongze Cheng 已提交
50

H
Hongze Cheng 已提交
51 52 53 54 55 56 57 58 59 60
static SFS  tfs = {0};
static SFS *pfs = &tfs;

// STATIC DECLARATION
static int    tfsMount(SDiskCfg *pCfg);
static int    tfsCheck();
static int    tfsCheckAndFormatCfg(SDiskCfg *pCfg);
static int    tfsFormatDir(char *idir, char *odir);
static SDisk *tfsGetDiskByID(SDiskID did);
static SDisk *tfsGetDiskByName(const char *dir);
H
Hongze Cheng 已提交
61 62 63
static int    tfsOpendirImpl(TDIR *tdir);
static void   tfsInitDiskIter(SDiskIter *pIter);
static SDisk *tfsNextDisk(SDiskIter *pIter);
H
Hongze Cheng 已提交
64

H
Hongze Cheng 已提交
65
// FS APIs ====================================
H
Hongze Cheng 已提交
66 67 68
int tfsInit(SDiskCfg *pDiskCfg, int ndisk) {
  ASSERT(ndisk > 0);

H
Hongze Cheng 已提交
69
  for (int level = 0; level < TSDB_MAX_TIERS; level++) {
H
Hongze Cheng 已提交
70 71 72 73
    if (tfsInitTier(TFS_TIER_AT(level), level) < 0) {
      while (true) {
        level--;
        if (level < 0) break;
H
Hongze Cheng 已提交
74

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

      return -1;
    }
H
Hongze Cheng 已提交
80 81
  }

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

H
Hongze Cheng 已提交
84
  pfs->map = taosHashInit(TSDB_MAX_TIERS * TSDB_MAX_DISKS_PER_TIER * 2,
H
Hongze Cheng 已提交
85 86 87 88 89 90 91 92
                          taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
  if (pfs->map == NULL) {
    terrno = TSDB_CODE_FS_OUT_OF_MEMORY;
    tfsDestroy();
    return -1;
  }

  for (int idisk = 0; idisk < ndisk; idisk++) {
H
refact  
Hongze Cheng 已提交
93
    if (tfsMount(pDiskCfg + idisk) < 0) {
H
Hongze Cheng 已提交
94 95 96 97 98
      tfsDestroy();
      return -1;
    }
  }

H
Hongze Cheng 已提交
99
  if (tfsCheck() < 0) {
H
Hongze Cheng 已提交
100 101 102 103
    tfsDestroy();
    return -1;
  }

104
  tfsUpdateInfo(NULL, NULL, 0);
H
Hongze Cheng 已提交
105 106 107
  for (int level = 0; level < TFS_NLEVEL(); level++) {
    tfsPosNextId(TFS_TIER_AT(level));
  }
H
Hongze Cheng 已提交
108

H
Hongze Cheng 已提交
109 110 111 112 113 114
  return 0;
}

void tfsDestroy() {
  taosHashCleanup(pfs->map);
  pfs->map = NULL;
H
Hongze Cheng 已提交
115 116

  pthread_spin_destroy(&(pfs->lock));
H
Hongze Cheng 已提交
117 118
  for (int level = 0; level < TFS_NLEVEL(); level++) {
    tfsDestroyTier(TFS_TIER_AT(level));
H
Hongze Cheng 已提交
119 120 121
  }
}

122
void tfsUpdateInfo(SFSMeta *pFSMeta, STierMeta *tierMetas, int8_t numTiers) {
H
Hongze Cheng 已提交
123 124
  SFSMeta   fsMeta;
  STierMeta tierMeta;
H
Hongze Cheng 已提交
125

H
Hongze Cheng 已提交
126 127 128 129 130
  if (pFSMeta == NULL) {
    pFSMeta = &fsMeta;
  }

  memset(pFSMeta, 0, sizeof(*pFSMeta));
H
Hongze Cheng 已提交
131

H
Hongze Cheng 已提交
132
  for (int level = 0; level < TFS_NLEVEL(); level++) {
133 134 135 136 137
    STierMeta *pTierMeta = &tierMeta;
    if (tierMetas && level < numTiers) {
      pTierMeta = tierMetas + level;
    }

H
Hongze Cheng 已提交
138
    STier *pTier = TFS_TIER_AT(level);
139 140 141 142
    tfsUpdateTierInfo(pTier, pTierMeta);
    pFSMeta->tsize += pTierMeta->size;
    pFSMeta->avail += pTierMeta->free;
    pFSMeta->used += pTierMeta->used;
H
Hongze Cheng 已提交
143 144
  }

H
Hongze Cheng 已提交
145
  tfsLock();
H
Hongze Cheng 已提交
146
  pfs->meta = *pFSMeta;
H
Hongze Cheng 已提交
147 148 149
  tfsUnLock();
}

H
Hongze Cheng 已提交
150 151 152
void tfsGetMeta(SFSMeta *pMeta) {
  ASSERT(pMeta);

H
Hongze Cheng 已提交
153
  tfsLock();
H
Hongze Cheng 已提交
154
  *pMeta = pfs->meta;
H
Hongze Cheng 已提交
155 156 157
  tfsUnLock();
}

H
Hongze Cheng 已提交
158 159 160
/* Allocate an existing available tier level
 */
void tfsAllocDisk(int expLevel, int *level, int *id) {
H
Hongze Cheng 已提交
161 162
  ASSERT(expLevel >= 0);

H
Hongze Cheng 已提交
163 164 165
  *level = expLevel;
  *id = TFS_UNDECIDED_ID;

H
Hongze Cheng 已提交
166
  if (*level >= TFS_NLEVEL()) {
H
Hongze Cheng 已提交
167
    *level = TFS_NLEVEL() - 1;
H
Hongze Cheng 已提交
168 169 170
  }

  while (*level >= 0) {
H
Hongze Cheng 已提交
171 172
    *id = tfsAllocDiskOnTier(TFS_TIER_AT(*level));
    if (*id == TFS_UNDECIDED_ID) {
H
Hongze Cheng 已提交
173
      (*level)--;
H
Hongze Cheng 已提交
174 175 176 177 178 179 180 181 182 183
      continue;
    }

    return;
  }

  *level = TFS_UNDECIDED_LEVEL;
  *id = TFS_UNDECIDED_ID;
}

H
Hongze Cheng 已提交
184 185
const char *TFS_PRIMARY_PATH() { return DISK_DIR(TFS_PRIMARY_DISK()); }
const char *TFS_DISK_PATH(int level, int id) { return DISK_DIR(TFS_DISK_AT(level, id)); }
H
Hongze Cheng 已提交
186

H
Hongze Cheng 已提交
187
// TFILE APIs ====================================
H
Hongze Cheng 已提交
188
void tfsInitFile(TFILE *pf, int level, int id, const char *bname) {
H
Hongze Cheng 已提交
189 190 191 192
  ASSERT(TFS_IS_VALID_DISK(level, id));

  SDisk *pDisk = TFS_DISK_AT(level, id);

H
Hongze Cheng 已提交
193 194
  pf->level = level;
  pf->id = id;
195
  tstrncpy(pf->rname, bname, TSDB_FILENAME_LEN);
S
TD-1207  
Shengliang Guan 已提交
196 197 198 199

  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 已提交
200 201
}

202 203 204
bool tfsIsSameFile(const TFILE *pf1, const TFILE *pf2) {
  ASSERT(pf1 != NULL || pf2 != NULL);
  if (pf1 == NULL || pf2 == NULL) return false;
H
Hongze Cheng 已提交
205 206 207 208 209 210
  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;
}

H
Hongze Cheng 已提交
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
int tfsEncodeFile(void **buf, TFILE *pf) {
  int tlen = 0;

  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;
  char *  rname;

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

  tfsInitFile(pf, level, id, rname);

  tfree(rname);
  return buf;
}

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

238 239
  tstrncpy(tname, pf->aname, TSDB_FILENAME_LEN);
  tstrncpy(dest, basename(tname), TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
240 241
}

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

245 246
  tstrncpy(tname, pf->aname, TSDB_FILENAME_LEN);
  tstrncpy(dest, dirname(tname), TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
247 248
}

H
Hongze Cheng 已提交
249
// DIR APIs ====================================
H
Hongze Cheng 已提交
250 251
int tfsMkdirAt(const char *rname, int level, int id) {
  SDisk *pDisk = TFS_DISK_AT(level, id);
S
TD-1207  
Shengliang Guan 已提交
252
  char   aname[TMPNAME_LEN];
H
Hongze Cheng 已提交
253

S
TD-1207  
Shengliang Guan 已提交
254
  snprintf(aname, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), rname);
255
  if (taosMkDir(aname) != 0) {
H
Hongze Cheng 已提交
256 257 258 259 260 261 262
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  return 0;
}

H
Hongze Cheng 已提交
263 264 265 266 267 268
int tfsMkdirRecurAt(const char *rname, int level, int id) {
  if (tfsMkdirAt(rname, level, id) < 0) {
    if (errno == ENOENT) {
      // Try to create upper
      char *s = strdup(rname);

J
Jun Li 已提交
269 270 271 272
      // 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 已提交
273 274
      // See
      // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dirname.3.html
J
Jun Li 已提交
275 276 277 278 279
      char *dir = strdup(dirname(s));

      if (tfsMkdirRecurAt(dir, level, id) < 0) {
        free(s);
        free(dir);
H
Hongze Cheng 已提交
280 281
        return -1;
      }
J
Jun Li 已提交
282 283
      free(s);
      free(dir);
H
Hongze Cheng 已提交
284 285 286 287 288 289 290 291 292 293 294 295

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

  return 0;
}

H
Hongze Cheng 已提交
296
int tfsMkdir(const char *rname) {
H
Hongze Cheng 已提交
297 298 299
  for (int level = 0; level < TFS_NLEVEL(); level++) {
    STier *pTier = TFS_TIER_AT(level);
    for (int id = 0; id < TIER_NDISKS(pTier); id++) {
H
Hongze Cheng 已提交
300
      if (tfsMkdirAt(rname, level, id) < 0) {
H
Hongze Cheng 已提交
301 302 303 304 305 306 307 308
        return -1;
      }
    }
  }

  return 0;
}

H
Hongze Cheng 已提交
309
int tfsRmdir(const char *rname) {
S
TD-1207  
Shengliang Guan 已提交
310
  char aname[TMPNAME_LEN] = "\0";
H
Hongze Cheng 已提交
311

H
Hongze Cheng 已提交
312 313 314
  for (int level = 0; level < TFS_NLEVEL(); level++) {
    STier *pTier = TFS_TIER_AT(level);
    for (int id = 0; id < TIER_NDISKS(pTier); id++) {
H
Hongze Cheng 已提交
315 316
      SDisk *pDisk = DISK_AT_TIER(pTier, id);

S
TD-1207  
Shengliang Guan 已提交
317
      snprintf(aname, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), rname);
H
Hongze Cheng 已提交
318

H
Hongze Cheng 已提交
319
      taosRemoveDir(aname);
H
Hongze Cheng 已提交
320 321 322 323 324 325
    }
  }

  return 0;
}

H
Hongze Cheng 已提交
326
int tfsRename(char *orname, char *nrname) {
S
TD-1207  
Shengliang Guan 已提交
327 328
  char oaname[TMPNAME_LEN] = "\0";
  char naname[TMPNAME_LEN] = "\0";
H
Hongze Cheng 已提交
329 330

  for (int level = 0; level < pfs->nlevel; level++) {
H
Hongze Cheng 已提交
331 332
    STier *pTier = TFS_TIER_AT(level);
    for (int id = 0; id < TIER_NDISKS(pTier); id++) {
H
Hongze Cheng 已提交
333 334
      SDisk *pDisk = DISK_AT_TIER(pTier, id);

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

H
Hongze Cheng 已提交
338
      taosRenameFile(oaname, naname);
H
Hongze Cheng 已提交
339 340 341 342 343 344
    }
  }

  return 0;
}

H
Hongze Cheng 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
struct TDIR {
  SDiskIter iter;
  int       level;
  int       id;
  char      dirname[TSDB_FILENAME_LEN];
  TFILE     tfile;
  DIR *     dir;
};

TDIR *tfsOpendir(const char *rname) {
  TDIR *tdir = (TDIR *)calloc(1, sizeof(*tdir));
  if (tdir == NULL) {
    terrno = TSDB_CODE_FS_OUT_OF_MEMORY;
    return NULL;
  }

  tfsInitDiskIter(&(tdir->iter));
362
  tstrncpy(tdir->dirname, rname, TSDB_FILENAME_LEN);
H
Hongze Cheng 已提交
363 364 365 366 367 368 369 370 371 372 373

  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 已提交
374
  char bname[TMPNAME_LEN * 2] = "\0";
H
Hongze Cheng 已提交
375 376 377 378 379

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

S
TD-1207  
Shengliang Guan 已提交
383
      snprintf(bname, TMPNAME_LEN * 2, "%s/%s", tdir->dirname, dp->d_name);
H
Hongze Cheng 已提交
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
      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 已提交
409
// private
H
refact  
Hongze Cheng 已提交
410 411
static int tfsMount(SDiskCfg *pCfg) {
  SDiskID did;
H
Hongze Cheng 已提交
412
  SDisk * pDisk = NULL;
H
refact  
Hongze Cheng 已提交
413

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

H
refact  
Hongze Cheng 已提交
416
  did.level = pCfg->level;
H
Hongze Cheng 已提交
417 418
  pDisk = tfsMountDiskToTier(TFS_TIER_AT(did.level), pCfg);
  if (pDisk == NULL) {
H
Hongze Cheng 已提交
419
    fError("failed to mount disk %s to level %d since %s", pCfg->dir, pCfg->level, tstrerror(terrno));
H
refact  
Hongze Cheng 已提交
420
    return -1;
H
Hongze Cheng 已提交
421
  }
H
Hongze Cheng 已提交
422
  did.id = DISK_ID(pDisk);
H
Hongze Cheng 已提交
423

H
Hongze Cheng 已提交
424
  taosHashPut(pfs->map, (void *)(pCfg->dir), strnlen(pCfg->dir, TSDB_FILENAME_LEN), (void *)(&did), sizeof(did));
H
Hongze Cheng 已提交
425 426 427 428 429
  if (pfs->nlevel < pCfg->level + 1) pfs->nlevel = pCfg->level + 1;

  return 0;
}

H
Hongze Cheng 已提交
430
static int tfsCheckAndFormatCfg(SDiskCfg *pCfg) {
H
Hongze Cheng 已提交
431 432 433
  char        dirName[TSDB_FILENAME_LEN] = "\0";
  struct stat pstat;

H
Hongze Cheng 已提交
434
  if (pCfg->level < 0 || pCfg->level >= TSDB_MAX_TIERS) {
H
Hongze Cheng 已提交
435
    fError("failed to mount %s to FS since invalid level %d", pCfg->dir, pCfg->level);
H
Hongze Cheng 已提交
436 437 438 439
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

H
refact  
Hongze Cheng 已提交
440 441
  if (pCfg->primary) {
    if (pCfg->level != 0) {
H
Hongze Cheng 已提交
442
      fError("failed to mount %s to FS since disk is primary but level %d not 0", pCfg->dir, pCfg->level);
H
refact  
Hongze Cheng 已提交
443 444 445
      terrno = TSDB_CODE_FS_INVLD_CFG;
      return -1;
    }
H
Hongze Cheng 已提交
446

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

H
Hongze Cheng 已提交
454
  if (tfsFormatDir(pCfg->dir, dirName) < 0) {
H
Hongze Cheng 已提交
455
    fError("failed to mount %s to FS since invalid dir format", pCfg->dir);
H
Hongze Cheng 已提交
456 457 458 459
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

H
refact  
Hongze Cheng 已提交
460
  if (tfsGetDiskByName(dirName) != NULL) {
H
Hongze Cheng 已提交
461
    fError("failed to mount %s to FS since duplicate mount", pCfg->dir);
H
Hongze Cheng 已提交
462 463 464 465 466
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

  if (access(dirName, W_OK | R_OK | F_OK) != 0) {
H
Hongze Cheng 已提交
467
    fError("failed to mount %s to FS since no R/W access rights", pCfg->dir);
H
Hongze Cheng 已提交
468 469 470 471 472
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

  if (stat(dirName, &pstat) < 0) {
H
Hongze Cheng 已提交
473
    fError("failed to mount %s to FS since %s", pCfg->dir, strerror(errno));
H
Hongze Cheng 已提交
474 475 476 477 478
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  if (!S_ISDIR(pstat.st_mode)) {
H
Hongze Cheng 已提交
479
    fError("failed to mount %s to FS since not a directory", pCfg->dir);
H
Hongze Cheng 已提交
480 481 482 483 484 485 486 487 488
    terrno = TSDB_CODE_FS_INVLD_CFG;
    return -1;
  }

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

  return 0;
}

H
Hongze Cheng 已提交
489
static int tfsFormatDir(char *idir, char *odir) {
H
Hongze Cheng 已提交
490 491 492 493 494 495 496 497
  wordexp_t wep = {0};

  int code = wordexp(idir, &wep, 0);
  if (code != 0) {
    terrno = TAOS_SYSTEM_ERROR(code);
    return -1;
  }

498 499
  char tmp[PATH_MAX] = {0};
  if (realpath(wep.we_wordv[0], tmp) == NULL) {
H
Hongze Cheng 已提交
500 501 502 503
    terrno = TAOS_SYSTEM_ERROR(errno);
    wordfree(&wep);
    return -1;
  }
504
  strcpy(odir, tmp);
H
Hongze Cheng 已提交
505 506 507 508 509

  wordfree(&wep);
  return 0;
}

H
Hongze Cheng 已提交
510
static int tfsCheck() {
H
Hongze Cheng 已提交
511
  if (TFS_PRIMARY_DISK() == NULL) {
H
Hongze Cheng 已提交
512 513 514 515 516
    fError("no primary disk is set");
    terrno = TSDB_CODE_FS_NO_PRIMARY_DISK;
    return -1;
  }

H
Hongze Cheng 已提交
517 518
  for (int level = 0; level < TFS_NLEVEL(); level++) {
    if (TIER_NDISKS(TFS_TIER_AT(level)) == 0) {
H
Hongze Cheng 已提交
519
      fError("no disk at level %d", level);
H
refact  
Hongze Cheng 已提交
520
      terrno = TSDB_CODE_FS_NO_MOUNT_AT_TIER;
H
Hongze Cheng 已提交
521 522
      return -1;
    }
H
Hongze Cheng 已提交
523
  }
H
Hongze Cheng 已提交
524

H
Hongze Cheng 已提交
525 526 527
  return 0;
}

H
Hongze Cheng 已提交
528 529 530 531 532 533 534 535 536 537 538 539
static SDisk *tfsGetDiskByID(SDiskID did) { return TFS_DISK_AT(did.level, did.id); }
static SDisk *tfsGetDiskByName(const char *dir) {
  SDiskID did;
  SDisk * pDisk = NULL;
  void *  pr = NULL;

  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 已提交
540

H
Hongze Cheng 已提交
541
  return pDisk;
H
Hongze Cheng 已提交
542 543 544 545
}

static int tfsOpendirImpl(TDIR *tdir) {
  SDisk *pDisk = NULL;
S
TD-1207  
Shengliang Guan 已提交
546
  char   adir[TMPNAME_LEN * 2] = "\0";
H
Hongze Cheng 已提交
547 548 549 550 551 552 553 554 555 556 557 558 559

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

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

    tdir->level = DISK_LEVEL(pDisk);
    tdir->id = DISK_ID(pDisk);

S
TD-1207  
Shengliang Guan 已提交
560
    snprintf(adir, TMPNAME_LEN * 2, "%s/%s", DISK_DIR(pDisk), tdir->dirname);
H
Hongze Cheng 已提交
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
    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;

  int level = DISK_LEVEL(pDisk);
  int id = DISK_ID(pDisk);

  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 已提交
596 597 598 599
// OTHER FUNCTIONS ===================================
void taosGetDisk() {
  const double unit = 1024 * 1024 * 1024;
  SysDiskSize  diskSize;
H
Hongze Cheng 已提交
600
  SFSMeta      fsMeta;
H
compile  
Hongze Cheng 已提交
601

H
Hongze Cheng 已提交
602 603 604 605
  tfsUpdateInfo(&fsMeta, NULL, 0);
  tsTotalDataDirGB = (float)(fsMeta.tsize / unit);
  tsUsedDataDirGB = (float)(fsMeta.used / unit);
  tsAvailDataDirGB = (float)(fsMeta.avail / unit);
H
compile  
Hongze Cheng 已提交
606

S
TD-1207  
Shengliang Guan 已提交
607 608 609
  if (taosGetDiskSize(tsLogDir, &diskSize) == 0) {
    tsTotalLogDirGB = (float)(diskSize.tsize / unit);
    tsAvailLogDirGB = (float)(diskSize.avail / unit);
H
compile  
Hongze Cheng 已提交
610 611
  }

S
TD-1207  
Shengliang Guan 已提交
612
  if (taosGetDiskSize(tsTempDir, &diskSize) == 0) {
S
TD-1207  
Shengliang Guan 已提交
613 614
    tsTotalTmpDirGB = (float)(diskSize.tsize / unit);
    tsAvailTmpDirectorySpace = (float)(diskSize.avail / unit);
H
compile  
Hongze Cheng 已提交
615 616
  }
}