index_tfile.c 20.0 KB
Newer Older
dengyihao's avatar
dengyihao 已提交
1 2
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
dengyihao's avatar
dengyihao 已提交
3
p *
dengyihao's avatar
dengyihao 已提交
4 5 6 7 8 9 10 11 12 13 14 15
 * 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/>.
 */

dengyihao's avatar
dengyihao 已提交
16 17
//#include <sys/types.h>
//#include <dirent.h>
dengyihao's avatar
dengyihao 已提交
18
#include "index_tfile.h"
19
#include "index.h"
dengyihao's avatar
dengyihao 已提交
20
#include "index_fst.h"
21
#include "index_fst_counting_writer.h"
dengyihao's avatar
dengyihao 已提交
22
#include "index_util.h"
dengyihao's avatar
dengyihao 已提交
23
#include "taosdef.h"
dengyihao's avatar
dengyihao 已提交
24
#include "tcompare.h"
dengyihao's avatar
dengyihao 已提交
25

dengyihao's avatar
dengyihao 已提交
26 27 28 29 30 31 32
typedef struct TFileFstIter {
  FstStreamBuilder* fb;
  StreamWithState*  st;
  AutomationCtx*    ctx;
  TFileReader*      rdr;
} TFileFstIter;

dengyihao's avatar
dengyihao 已提交
33 34
#define TF_TABLE_TATOAL_SIZE(sz) (sizeof(sz) + sz * sizeof(uint64_t))

dengyihao's avatar
dengyihao 已提交
35
static int  tfileUidCompare(const void* a, const void* b);
dengyihao's avatar
dengyihao 已提交
36
static int  tfileStrCompare(const void* a, const void* b);
dengyihao's avatar
dengyihao 已提交
37 38
static int  tfileValueCompare(const void* a, const void* b, const void* param);
static void tfileSerialTableIdsToBuf(char* buf, SArray* tableIds);
dengyihao's avatar
dengyihao 已提交
39

dengyihao's avatar
dengyihao 已提交
40
static int tfileWriteHeader(TFileWriter* writer);
dengyihao's avatar
dengyihao 已提交
41
static int tfileWriteFstOffset(TFileWriter* tw, int32_t offset);
dengyihao's avatar
dengyihao 已提交
42
static int tfileWriteData(TFileWriter* write, TFileValue* tval);
dengyihao's avatar
dengyihao 已提交
43

dengyihao's avatar
dengyihao 已提交
44 45 46
static int tfileReaderLoadHeader(TFileReader* reader);
static int tfileReaderLoadFst(TFileReader* reader);
static int tfileReaderLoadTableIds(TFileReader* reader, int32_t offset, SArray* result);
dengyihao's avatar
dengyihao 已提交
47

dengyihao's avatar
dengyihao 已提交
48 49 50 51 52 53 54
static SArray* tfileGetFileList(const char* path);
static int     tfileRmExpireFile(SArray* result);
static void    tfileDestroyFileName(void* elem);
static int     tfileCompare(const void* a, const void* b);
static int     tfileParseFileName(const char* filename, uint64_t* suid, char* col, int* version);
static void    tfileGenFileName(char* filename, uint64_t suid, const char* col, int version);
static void    tfileGenFileFullName(char* fullname, const char* path, uint64_t suid, const char* col, int32_t version);
dengyihao's avatar
dengyihao 已提交
55

dengyihao's avatar
dengyihao 已提交
56 57
TFileCache* tfileCacheCreate(const char* path) {
  TFileCache* tcache = calloc(1, sizeof(TFileCache));
dengyihao's avatar
dengyihao 已提交
58 59 60
  if (tcache == NULL) {
    return NULL;
  }
61 62 63 64

  tcache->tableCache = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
  tcache->capacity = 64;

dengyihao's avatar
dengyihao 已提交
65
  SArray* files = tfileGetFileList(path);
dengyihao's avatar
dengyihao 已提交
66
  for (size_t i = 0; i < taosArrayGetSize(files); i++) {
dengyihao's avatar
dengyihao 已提交
67
    char* file = taosArrayGetP(files, i);
dengyihao's avatar
dengyihao 已提交
68

dengyihao's avatar
dengyihao 已提交
69
    WriterCtx* wc = writerCtxCreate(TFile, file, true, 1024 * 1024 * 64);
70
    if (wc == NULL) {
dengyihao's avatar
dengyihao 已提交
71
      indexError("failed to open index:%s", file);
72
      goto End;
dengyihao's avatar
dengyihao 已提交
73
    }
dengyihao's avatar
dengyihao 已提交
74

dengyihao's avatar
dengyihao 已提交
75
    TFileReader* reader = tfileReaderCreate(wc);
dengyihao's avatar
dengyihao 已提交
76 77 78
    if (reader == NULL) {
      goto End;
    }
dengyihao's avatar
dengyihao 已提交
79
    TFileHeader* header = &reader->header;
dengyihao's avatar
dengyihao 已提交
80
    ICacheKey    key = {.suid = header->suid, .colName = header->colName, .nColName = strlen(header->colName)};
dengyihao's avatar
dengyihao 已提交
81

dengyihao's avatar
dengyihao 已提交
82
    char    buf[128] = {0};
dengyihao's avatar
dengyihao 已提交
83 84 85
    int32_t sz = indexSerialCacheKey(&key, buf);
    assert(sz < sizeof(buf));
    taosHashPut(tcache->tableCache, buf, sz, &reader, sizeof(void*));
dengyihao's avatar
dengyihao 已提交
86
    tfileReaderRef(reader);
dengyihao's avatar
dengyihao 已提交
87
  }
dengyihao's avatar
dengyihao 已提交
88
  taosArrayDestroyEx(files, tfileDestroyFileName);
dengyihao's avatar
dengyihao 已提交
89
  return tcache;
dengyihao's avatar
dengyihao 已提交
90
End:
91
  tfileCacheDestroy(tcache);
dengyihao's avatar
dengyihao 已提交
92
  taosArrayDestroyEx(files, tfileDestroyFileName);
93
  return NULL;
dengyihao's avatar
dengyihao 已提交
94
}
dengyihao's avatar
dengyihao 已提交
95
void tfileCacheDestroy(TFileCache* tcache) {
dengyihao's avatar
dengyihao 已提交
96 97 98
  if (tcache == NULL) {
    return;
  }
99 100

  // free table cache
dengyihao's avatar
dengyihao 已提交
101
  TFileReader** reader = taosHashIterate(tcache->tableCache, NULL);
102
  while (reader) {
dengyihao's avatar
dengyihao 已提交
103
    TFileReader* p = *reader;
104 105
    indexInfo("drop table cache suid: %" PRIu64 ", colName: %s, colType: %d", p->header.suid, p->header.colName,
              p->header.colType);
dengyihao's avatar
dengyihao 已提交
106

dengyihao's avatar
dengyihao 已提交
107
    tfileReaderUnRef(p);
108 109 110 111
    reader = taosHashIterate(tcache->tableCache, reader);
  }
  taosHashCleanup(tcache->tableCache);
  free(tcache);
dengyihao's avatar
dengyihao 已提交
112 113
}

dengyihao's avatar
dengyihao 已提交
114 115 116 117 118
TFileReader* tfileCacheGet(TFileCache* tcache, ICacheKey* key) {
  char    buf[128] = {0};
  int32_t sz = indexSerialCacheKey(key, buf);
  assert(sz < sizeof(buf));
  TFileReader** reader = taosHashGet(tcache->tableCache, buf, sz);
dengyihao's avatar
dengyihao 已提交
119 120 121
  if (reader == NULL) {
    return NULL;
  }
122
  tfileReaderRef(*reader);
dengyihao's avatar
dengyihao 已提交
123

124
  return *reader;
dengyihao's avatar
dengyihao 已提交
125
}
dengyihao's avatar
dengyihao 已提交
126 127 128
void tfileCachePut(TFileCache* tcache, ICacheKey* key, TFileReader* reader) {
  char    buf[128] = {0};
  int32_t sz = indexSerialCacheKey(key, buf);
dengyihao's avatar
dengyihao 已提交
129
  // remove last version index reader
dengyihao's avatar
dengyihao 已提交
130
  TFileReader** p = taosHashGet(tcache->tableCache, buf, sz);
dengyihao's avatar
dengyihao 已提交
131
  if (p != NULL) {
dengyihao's avatar
dengyihao 已提交
132
    TFileReader* oldReader = *p;
dengyihao's avatar
dengyihao 已提交
133
    taosHashRemove(tcache->tableCache, buf, sz);
dengyihao's avatar
dengyihao 已提交
134
    oldReader->remove = true;
dengyihao's avatar
dengyihao 已提交
135
    tfileReaderUnRef(oldReader);
dengyihao's avatar
dengyihao 已提交
136
  }
dengyihao's avatar
dengyihao 已提交
137

dengyihao's avatar
dengyihao 已提交
138
  taosHashPut(tcache->tableCache, buf, sz, &reader, sizeof(void*));
dengyihao's avatar
dengyihao 已提交
139
  tfileReaderRef(reader);
dengyihao's avatar
dengyihao 已提交
140
  return;
141
}
dengyihao's avatar
dengyihao 已提交
142 143
TFileReader* tfileReaderCreate(WriterCtx* ctx) {
  TFileReader* reader = calloc(1, sizeof(TFileReader));
dengyihao's avatar
dengyihao 已提交
144 145 146
  if (reader == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
147

148
  // T_REF_INC(reader);
dengyihao's avatar
dengyihao 已提交
149
  reader->ctx = ctx;
dengyihao's avatar
dengyihao 已提交
150 151
  if (0 != tfileReaderLoadHeader(reader)) {
    tfileReaderDestroy(reader);
152 153
    indexError("failed to load index header, suid: %" PRIu64 ", colName: %s", reader->header.suid,
               reader->header.colName);
dengyihao's avatar
dengyihao 已提交
154 155 156 157 158 159 160 161 162
    return NULL;
  }

  if (0 != tfileReaderLoadFst(reader)) {
    tfileReaderDestroy(reader);
    indexError("failed to load index fst, suid: %" PRIu64 ", colName: %s", reader->header.suid, reader->header.colName);
    return NULL;
  }

163
  return reader;
dengyihao's avatar
dengyihao 已提交
164
}
dengyihao's avatar
dengyihao 已提交
165
void tfileReaderDestroy(TFileReader* reader) {
dengyihao's avatar
dengyihao 已提交
166 167 168
  if (reader == NULL) {
    return;
  }
169
  // T_REF_INC(reader);
dengyihao's avatar
dengyihao 已提交
170
  fstDestroy(reader->fst);
dengyihao's avatar
dengyihao 已提交
171
  writerCtxDestroy(reader->ctx, reader->remove);
dengyihao's avatar
dengyihao 已提交
172 173 174
  free(reader);
}

dengyihao's avatar
dengyihao 已提交
175
int tfileReaderSearch(TFileReader* reader, SIndexTermQuery* query, SArray* result) {
dengyihao's avatar
dengyihao 已提交
176 177
  SIndexTerm*     term = query->term;
  EIndexQueryType qtype = query->qType;
dengyihao's avatar
dengyihao 已提交
178

dengyihao's avatar
dengyihao 已提交
179
  int ret = -1;
dengyihao's avatar
dengyihao 已提交
180
  // refactor to callback later
dengyihao's avatar
dengyihao 已提交
181
  if (qtype == QUERY_TERM) {
dengyihao's avatar
dengyihao 已提交
182 183 184
    uint64_t offset;
    FstSlice key = fstSliceCreate(term->colVal, term->nColVal);
    if (fstGet(reader->fst, &key, &offset)) {
185 186
      indexInfo("index: %" PRIu64 ", col: %s, colVal: %s, found table info in tindex", term->suid, term->colName,
                term->colVal);
dengyihao's avatar
dengyihao 已提交
187
      ret = tfileReaderLoadTableIds(reader, offset, result);
dengyihao's avatar
dengyihao 已提交
188
    } else {
189 190
      indexInfo("index: %" PRIu64 ", col: %s, colVal: %s, not found table info in tindex", term->suid, term->colName,
                term->colVal);
dengyihao's avatar
dengyihao 已提交
191
    }
dengyihao's avatar
dengyihao 已提交
192 193
    fstSliceDestroy(&key);
  } else if (qtype == QUERY_PREFIX) {
dengyihao's avatar
dengyihao 已提交
194
    // handle later
dengyihao's avatar
dengyihao 已提交
195
    //
dengyihao's avatar
dengyihao 已提交
196 197
  } else {
    // handle later
dengyihao's avatar
dengyihao 已提交
198
  }
dengyihao's avatar
dengyihao 已提交
199
  tfileReaderUnRef(reader);
dengyihao's avatar
dengyihao 已提交
200
  return ret;
dengyihao's avatar
dengyihao 已提交
201 202
}

dengyihao's avatar
dengyihao 已提交
203 204
TFileWriter* tfileWriterOpen(char* path, uint64_t suid, int32_t version, const char* colName, uint8_t colType) {
  char fullname[256] = {0};
dengyihao's avatar
dengyihao 已提交
205
  tfileGenFileFullName(fullname, path, suid, colName, version);
dengyihao's avatar
dengyihao 已提交
206
  // indexInfo("open write file name %s", fullname);
dengyihao's avatar
dengyihao 已提交
207
  WriterCtx* wcx = writerCtxCreate(TFile, fullname, false, 1024 * 1024 * 64);
dengyihao's avatar
dengyihao 已提交
208 209 210
  if (wcx == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
211 212 213 214 215 216 217 218 219

  TFileHeader tfh = {0};
  tfh.suid = suid;
  tfh.version = version;
  memcpy(tfh.colName, colName, strlen(colName));
  tfh.colType = colType;

  return tfileWriterCreate(wcx, &tfh);
}
dengyihao's avatar
dengyihao 已提交
220 221
TFileReader* tfileReaderOpen(char* path, uint64_t suid, int32_t version, const char* colName) {
  char fullname[256] = {0};
dengyihao's avatar
dengyihao 已提交
222 223
  tfileGenFileFullName(fullname, path, suid, colName, version);

dengyihao's avatar
dengyihao 已提交
224
  WriterCtx* wc = writerCtxCreate(TFile, fullname, true, 1024 * 1024 * 1024);
dengyihao's avatar
dengyihao 已提交
225 226 227 228
  indexInfo("open read file name:%s, size: %d", wc->file.buf, wc->file.size);
  if (wc == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
229

dengyihao's avatar
dengyihao 已提交
230
  TFileReader* reader = tfileReaderCreate(wc);
dengyihao's avatar
dengyihao 已提交
231 232
  return reader;
}
dengyihao's avatar
dengyihao 已提交
233 234
TFileWriter* tfileWriterCreate(WriterCtx* ctx, TFileHeader* header) {
  TFileWriter* tw = calloc(1, sizeof(TFileWriter));
dengyihao's avatar
dengyihao 已提交
235
  if (tw == NULL) {
dengyihao's avatar
dengyihao 已提交
236
    indexError("index: %" PRIu64 " failed to alloc TFilerWriter", header->suid);
dengyihao's avatar
dengyihao 已提交
237 238
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
239 240
  tw->ctx = ctx;
  tw->header = *header;
dengyihao's avatar
dengyihao 已提交
241
  tfileWriteHeader(tw);
dengyihao's avatar
dengyihao 已提交
242 243
  return tw;
}
dengyihao's avatar
dengyihao 已提交
244

dengyihao's avatar
dengyihao 已提交
245
int tfileWriterPut(TFileWriter* tw, void* data, bool order) {
dengyihao's avatar
dengyihao 已提交
246
  // sort by coltype and write to tindex
dengyihao's avatar
dengyihao 已提交
247 248
  if (order == false) {
    __compar_fn_t fn;
dengyihao's avatar
dengyihao 已提交
249 250

    int8_t colType = tw->header.colType;
dengyihao's avatar
dengyihao 已提交
251 252 253 254 255 256
    if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_NCHAR) {
      fn = tfileStrCompare;
    } else {
      fn = getComparFunc(colType, 0);
    }
    taosArraySortPWithExt((SArray*)(data), tfileValueCompare, &fn);
dengyihao's avatar
dengyihao 已提交
257
  }
dengyihao's avatar
dengyihao 已提交
258

dengyihao's avatar
dengyihao 已提交
259 260 261
  int32_t bufLimit = 64 * 4096, offset = 0;
  // char*   buf = calloc(1, sizeof(char) * bufLimit);
  // char*   p = buf;
dengyihao's avatar
dengyihao 已提交
262
  int32_t sz = taosArrayGetSize((SArray*)data);
dengyihao's avatar
dengyihao 已提交
263 264 265 266 267
  int32_t fstOffset = tw->offset;

  // ugly code, refactor later
  for (size_t i = 0; i < sz; i++) {
    TFileValue* v = taosArrayGetP((SArray*)data, i);
dengyihao's avatar
dengyihao 已提交
268 269
    taosArraySort(v->tableId, tfileUidCompare);
    taosArrayRemoveDuplicate(v->tableId, tfileUidCompare, NULL);
dengyihao's avatar
dengyihao 已提交
270
    int32_t tbsz = taosArrayGetSize(v->tableId);
dengyihao's avatar
dengyihao 已提交
271
    fstOffset += TF_TABLE_TATOAL_SIZE(tbsz);
dengyihao's avatar
dengyihao 已提交
272 273 274
  }
  tfileWriteFstOffset(tw, fstOffset);

dengyihao's avatar
dengyihao 已提交
275 276 277 278 279 280 281
  for (size_t i = 0; i < sz; i++) {
    TFileValue* v = taosArrayGetP((SArray*)data, i);

    int32_t tbsz = taosArrayGetSize(v->tableId);
    // check buf has enough space or not
    int32_t ttsz = TF_TABLE_TATOAL_SIZE(tbsz);

dengyihao's avatar
dengyihao 已提交
282 283
    char* buf = calloc(1, ttsz * sizeof(char));
    char* p = buf;
dengyihao's avatar
dengyihao 已提交
284
    tfileSerialTableIdsToBuf(p, v->tableId);
dengyihao's avatar
dengyihao 已提交
285
    tw->ctx->write(tw->ctx, buf, ttsz);
dengyihao's avatar
dengyihao 已提交
286 287
    v->offset = tw->offset;
    tw->offset += ttsz;
dengyihao's avatar
dengyihao 已提交
288
    free(buf);
dengyihao's avatar
dengyihao 已提交
289
  }
dengyihao's avatar
dengyihao 已提交
290

dengyihao's avatar
dengyihao 已提交
291 292
  tw->fb = fstBuilderCreate(tw->ctx, 0);
  if (tw->fb == NULL) {
dengyihao's avatar
dengyihao 已提交
293
    tfileWriterClose(tw);
dengyihao's avatar
dengyihao 已提交
294 295
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
296 297

  // write data
dengyihao's avatar
dengyihao 已提交
298 299 300
  for (size_t i = 0; i < sz; i++) {
    // TODO, fst batch write later
    TFileValue* v = taosArrayGetP((SArray*)data, i);
dengyihao's avatar
dengyihao 已提交
301 302 303 304
    if (tfileWriteData(tw, v) != 0) {
      indexError("failed to write data: %s, offset: %d len: %d", v->colVal, v->offset,
                 (int)taosArrayGetSize(v->tableId));
    } else {
dengyihao's avatar
dengyihao 已提交
305 306
      // indexInfo("success to write data: %s, offset: %d len: %d", v->colVal, v->offset,
      //          (int)taosArrayGetSize(v->tableId));
dengyihao's avatar
dengyihao 已提交
307 308
    }
  }
dengyihao's avatar
dengyihao 已提交
309 310 311
  fstBuilderFinish(tw->fb);
  fstBuilderDestroy(tw->fb);
  tw->fb = NULL;
dengyihao's avatar
dengyihao 已提交
312 313
  return 0;
}
dengyihao's avatar
dengyihao 已提交
314
void tfileWriterClose(TFileWriter* tw) {
dengyihao's avatar
dengyihao 已提交
315 316 317
  if (tw == NULL) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
318
  writerCtxDestroy(tw->ctx, false);
dengyihao's avatar
dengyihao 已提交
319 320
  free(tw);
}
dengyihao's avatar
dengyihao 已提交
321
void tfileWriterDestroy(TFileWriter* tw) {
dengyihao's avatar
dengyihao 已提交
322 323 324
  if (tw == NULL) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
325
  writerCtxDestroy(tw->ctx, false);
dengyihao's avatar
dengyihao 已提交
326 327
  free(tw);
}
dengyihao's avatar
dengyihao 已提交
328

dengyihao's avatar
dengyihao 已提交
329
IndexTFile* indexTFileCreate(const char* path) {
dengyihao's avatar
dengyihao 已提交
330
  TFileCache* cache = tfileCacheCreate(path);
dengyihao's avatar
dengyihao 已提交
331 332 333
  if (cache == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
334

dengyihao's avatar
dengyihao 已提交
335
  IndexTFile* tfile = calloc(1, sizeof(IndexTFile));
dengyihao's avatar
dengyihao 已提交
336 337 338 339
  if (tfile == NULL) {
    tfileCacheDestroy(cache);
    return NULL;
  }
340

dengyihao's avatar
dengyihao 已提交
341
  tfile->cache = cache;
dengyihao's avatar
dengyihao 已提交
342 343
  return tfile;
}
344
void indexTFileDestroy(IndexTFile* tfile) {
dengyihao's avatar
dengyihao 已提交
345 346 347
  if (tfile == NULL) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
348 349 350
  tfileCacheDestroy(tfile->cache);
  free(tfile);
}
dengyihao's avatar
dengyihao 已提交
351

dengyihao's avatar
dengyihao 已提交
352
int indexTFileSearch(void* tfile, SIndexTermQuery* query, SArray* result) {
dengyihao's avatar
dengyihao 已提交
353
  int ret = -1;
dengyihao's avatar
dengyihao 已提交
354 355 356
  if (tfile == NULL) {
    return ret;
  }
dengyihao's avatar
dengyihao 已提交
357

dengyihao's avatar
dengyihao 已提交
358
  IndexTFile* pTfile = (IndexTFile*)tfile;
359

dengyihao's avatar
dengyihao 已提交
360 361
  SIndexTerm* term = query->term;
  ICacheKey key = {.suid = term->suid, .colType = term->colType, .colName = term->colName, .nColName = term->nColName};
362
  TFileReader* reader = tfileCacheGet(pTfile->cache, &key);
dengyihao's avatar
dengyihao 已提交
363 364 365
  if (reader == NULL) {
    return 0;
  }
dengyihao's avatar
dengyihao 已提交
366

dengyihao's avatar
dengyihao 已提交
367
  return tfileReaderSearch(reader, query, result);
dengyihao's avatar
dengyihao 已提交
368
}
dengyihao's avatar
dengyihao 已提交
369
int indexTFilePut(void* tfile, SIndexTerm* term, uint64_t uid) {
370 371
  // TFileWriterOpt wOpt = {.suid = term->suid, .colType = term->colType, .colName = term->colName, .nColName =
  // term->nColName, .version = 1};
dengyihao's avatar
dengyihao 已提交
372

373 374
  return 0;
}
dengyihao's avatar
dengyihao 已提交
375 376
static bool tfileIteratorNext(Iterate* iiter) {
  IterateValue* iv = &iiter->val;
dengyihao's avatar
dengyihao 已提交
377 378 379
  if (iv->colVal != NULL && iv->val != NULL) {
    // indexError("value in fst: colVal: %s, size: %d", iv->colVal, (int)taosArrayGetSize(iv->val));
  }
dengyihao's avatar
dengyihao 已提交
380 381 382 383 384 385 386
  iterateValueDestroy(iv, false);

  char*    colVal = NULL;
  uint64_t offset = 0;

  TFileFstIter*          tIter = iiter->iter;
  StreamWithStateResult* rt = streamWithStateNextWith(tIter->st, NULL);
dengyihao's avatar
dengyihao 已提交
387 388 389
  if (rt == NULL) {
    return false;
  }
dengyihao's avatar
dengyihao 已提交
390 391 392 393 394 395 396 397 398

  int32_t sz = 0;
  char*   ch = (char*)fstSliceData(&rt->data, &sz);
  colVal = calloc(1, sz + 1);
  memcpy(colVal, ch, sz);

  offset = (uint64_t)(rt->out.out);
  swsResultDestroy(rt);
  // set up iterate value
dengyihao's avatar
dengyihao 已提交
399 400 401
  if (tfileReaderLoadTableIds(tIter->rdr, offset, iv->val) != 0) {
    return false;
  }
dengyihao's avatar
dengyihao 已提交
402 403

  iv->colVal = colVal;
dengyihao's avatar
dengyihao 已提交
404
  return true;
dengyihao's avatar
dengyihao 已提交
405 406 407
  // std::string key(ch, sz);
}

408
static IterateValue* tifileIterateGetValue(Iterate* iter) { return &iter->val; }
dengyihao's avatar
dengyihao 已提交
409 410

static TFileFstIter* tfileFstIteratorCreate(TFileReader* reader) {
411
  TFileFstIter* tIter = calloc(1, sizeof(TFileFstIter));
dengyihao's avatar
dengyihao 已提交
412 413 414
  if (tIter == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
415

dengyihao's avatar
dengyihao 已提交
416 417 418 419 420 421 422 423
  tIter->ctx = automCtxCreate(NULL, AUTOMATION_ALWAYS);
  tIter->fb = fstSearch(reader->fst, tIter->ctx);
  tIter->st = streamBuilderIntoStream(tIter->fb);
  tIter->rdr = reader;
  return tIter;
}

Iterate* tfileIteratorCreate(TFileReader* reader) {
dengyihao's avatar
dengyihao 已提交
424 425 426
  if (reader == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
427

dengyihao's avatar
dengyihao 已提交
428
  Iterate* iter = calloc(1, sizeof(Iterate));
dengyihao's avatar
dengyihao 已提交
429
  iter->iter = tfileFstIteratorCreate(reader);
430
  if (iter->iter == NULL) {
dengyihao's avatar
dengyihao 已提交
431
    free(iter);
432 433
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
434 435
  iter->next = tfileIteratorNext;
  iter->getValue = tifileIterateGetValue;
dengyihao's avatar
dengyihao 已提交
436
  iter->val.val = taosArrayInit(1, sizeof(uint64_t));
437
  iter->val.colVal = NULL;
dengyihao's avatar
dengyihao 已提交
438 439 440
  return iter;
}
void tfileIteratorDestroy(Iterate* iter) {
dengyihao's avatar
dengyihao 已提交
441 442 443
  if (iter == NULL) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
444

dengyihao's avatar
dengyihao 已提交
445 446 447 448 449 450 451
  IterateValue* iv = &iter->val;
  iterateValueDestroy(iv, true);

  TFileFstIter* tIter = iter->iter;
  streamWithStateDestroy(tIter->st);
  fstStreamBuilderDestroy(tIter->fb);
  automCtxDestroy(tIter->ctx);
452
  free(tIter);
dengyihao's avatar
dengyihao 已提交
453 454 455 456

  free(iter);
}

dengyihao's avatar
dengyihao 已提交
457
TFileReader* tfileGetReaderByCol(IndexTFile* tf, uint64_t suid, char* colName) {
dengyihao's avatar
dengyihao 已提交
458 459 460
  if (tf == NULL) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
461
  ICacheKey key = {.suid = suid, .colType = TSDB_DATA_TYPE_BINARY, .colName = colName, .nColName = strlen(colName)};
dengyihao's avatar
dengyihao 已提交
462 463
  return tfileCacheGet(tf->cache, &key);
}
dengyihao's avatar
dengyihao 已提交
464

dengyihao's avatar
dengyihao 已提交
465 466 467 468 469
static int tfileUidCompare(const void* a, const void* b) {
  uint64_t l = *(uint64_t*)a;
  uint64_t r = *(uint64_t*)b;
  return l - r;
}
dengyihao's avatar
dengyihao 已提交
470 471
static int tfileStrCompare(const void* a, const void* b) {
  int ret = strcmp((char*)a, (char*)b);
dengyihao's avatar
dengyihao 已提交
472 473 474
  if (ret == 0) {
    return ret;
  }
dengyihao's avatar
dengyihao 已提交
475 476 477
  return ret < 0 ? -1 : 1;
}

dengyihao's avatar
dengyihao 已提交
478 479 480 481 482 483 484 485
static int tfileValueCompare(const void* a, const void* b, const void* param) {
  __compar_fn_t fn = *(__compar_fn_t*)param;

  TFileValue* av = (TFileValue*)a;
  TFileValue* bv = (TFileValue*)b;

  return fn(av->colVal, bv->colVal);
}
dengyihao's avatar
dengyihao 已提交
486 487 488

TFileValue* tfileValueCreate(char* val) {
  TFileValue* tf = calloc(1, sizeof(TFileValue));
dengyihao's avatar
dengyihao 已提交
489 490 491
  if (tf == NULL) {
    return NULL;
  }
492
  tf->colVal = tstrdup(val);
dengyihao's avatar
dengyihao 已提交
493 494 495 496
  tf->tableId = taosArrayInit(32, sizeof(uint64_t));
  return tf;
}
int tfileValuePush(TFileValue* tf, uint64_t val) {
dengyihao's avatar
dengyihao 已提交
497 498 499
  if (tf == NULL) {
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
500 501 502 503 504
  taosArrayPush(tf->tableId, &val);
  return 0;
}
void tfileValueDestroy(TFileValue* tf) {
  taosArrayDestroy(tf->tableId);
505
  free(tf->colVal);
dengyihao's avatar
dengyihao 已提交
506 507
  free(tf);
}
dengyihao's avatar
dengyihao 已提交
508 509 510 511 512
static void tfileSerialTableIdsToBuf(char* buf, SArray* ids) {
  int sz = taosArrayGetSize(ids);
  SERIALIZE_VAR_TO_BUF(buf, sz, int32_t);
  for (size_t i = 0; i < sz; i++) {
    uint64_t* v = taosArrayGet(ids, i);
dengyihao's avatar
dengyihao 已提交
513 514 515 516 517 518 519
    SERIALIZE_VAR_TO_BUF(buf, *v, uint64_t);
  }
}

static int tfileWriteFstOffset(TFileWriter* tw, int32_t offset) {
  int32_t fstOffset = offset + sizeof(tw->header.fstOffset);
  tw->header.fstOffset = fstOffset;
dengyihao's avatar
dengyihao 已提交
520 521 522
  if (sizeof(fstOffset) != tw->ctx->write(tw->ctx, (char*)&fstOffset, sizeof(fstOffset))) {
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
523
  tw->offset += sizeof(fstOffset);
dengyihao's avatar
dengyihao 已提交
524 525 526
  return 0;
}
static int tfileWriteHeader(TFileWriter* writer) {
dengyihao's avatar
dengyihao 已提交
527
  char buf[TFILE_HEADER_NO_FST] = {0};
dengyihao's avatar
dengyihao 已提交
528 529 530 531 532

  TFileHeader* header = &writer->header;
  memcpy(buf, (char*)header, sizeof(buf));

  int nwrite = writer->ctx->write(writer->ctx, buf, sizeof(buf));
dengyihao's avatar
dengyihao 已提交
533 534 535
  if (sizeof(buf) != nwrite) {
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
  writer->offset = nwrite;
  return 0;
}
static int tfileWriteData(TFileWriter* write, TFileValue* tval) {
  TFileHeader* header = &write->header;
  uint8_t      colType = header->colType;
  if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_NCHAR) {
    FstSlice key = fstSliceCreate((uint8_t*)(tval->colVal), (size_t)strlen(tval->colVal));
    if (fstBuilderInsert(write->fb, key, tval->offset)) {
      fstSliceDestroy(&key);
      return 0;
    }
    fstSliceDestroy(&key);
    return -1;
  } else {
    // handle other type later
  }
dengyihao's avatar
dengyihao 已提交
553
  return 0;
dengyihao's avatar
dengyihao 已提交
554
}
dengyihao's avatar
dengyihao 已提交
555
static int tfileReaderLoadHeader(TFileReader* reader) {
dengyihao's avatar
dengyihao 已提交
556
  // TODO simple tfile header later
dengyihao's avatar
dengyihao 已提交
557
  char buf[TFILE_HEADER_SIZE] = {0};
dengyihao's avatar
dengyihao 已提交
558

dengyihao's avatar
dengyihao 已提交
559
  int64_t nread = reader->ctx->readFrom(reader->ctx, buf, sizeof(buf), 0);
dengyihao's avatar
dengyihao 已提交
560 561 562
  if (nread == -1) {
    indexError("actual Read: %d, to read: %d, errno: %d, filefd: %d, filename: %s", (int)(nread), (int)sizeof(buf),
               errno, reader->ctx->file.fd, reader->ctx->file.buf);
dengyihao's avatar
dengyihao 已提交
563
  } else {
dengyihao's avatar
dengyihao 已提交
564 565
    indexInfo("actual Read: %d, to read: %d, filefd: %d, filename: %s", (int)(nread), (int)sizeof(buf),
              reader->ctx->file.fd, reader->ctx->file.buf);
dengyihao's avatar
dengyihao 已提交
566 567
  }
  // assert(nread == sizeof(buf));
dengyihao's avatar
dengyihao 已提交
568
  memcpy(&reader->header, buf, sizeof(buf));
dengyihao's avatar
dengyihao 已提交
569

dengyihao's avatar
dengyihao 已提交
570 571
  return 0;
}
dengyihao's avatar
dengyihao 已提交
572
static int tfileReaderLoadFst(TFileReader* reader) {
dengyihao's avatar
dengyihao 已提交
573
  // current load fst into memory, refactor it later
dengyihao's avatar
dengyihao 已提交
574
  static int FST_MAX_SIZE = 64 * 1024 * 1024;
dengyihao's avatar
dengyihao 已提交
575 576

  char* buf = calloc(1, sizeof(char) * FST_MAX_SIZE);
dengyihao's avatar
dengyihao 已提交
577 578 579
  if (buf == NULL) {
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
580 581 582

  WriterCtx* ctx = reader->ctx;
  int32_t    nread = ctx->readFrom(ctx, buf, FST_MAX_SIZE, reader->header.fstOffset);
dengyihao's avatar
dengyihao 已提交
583 584
  indexInfo("nread = %d, and fst offset=%d, filename: %s, size: %d ", nread, reader->header.fstOffset, ctx->file.buf,
            ctx->file.size);
dengyihao's avatar
dengyihao 已提交
585 586 587 588 589 590 591 592
  // we assuse fst size less than FST_MAX_SIZE
  assert(nread > 0 && nread < FST_MAX_SIZE);

  FstSlice st = fstSliceCreate((uint8_t*)buf, nread);
  reader->fst = fstCreate(&st);
  free(buf);
  fstSliceDestroy(&st);

dengyihao's avatar
dengyihao 已提交
593
  return reader->fst != NULL ? 0 : -1;
dengyihao's avatar
dengyihao 已提交
594
}
dengyihao's avatar
dengyihao 已提交
595
static int tfileReaderLoadTableIds(TFileReader* reader, int32_t offset, SArray* result) {
dengyihao's avatar
dengyihao 已提交
596 597
  int32_t    nid;
  WriterCtx* ctx = reader->ctx;
dengyihao's avatar
dengyihao 已提交
598 599

  int32_t nread = ctx->readFrom(ctx, (char*)&nid, sizeof(nid), offset);
dengyihao's avatar
dengyihao 已提交
600 601
  assert(sizeof(nid) == nread);

dengyihao's avatar
dengyihao 已提交
602 603
  int32_t total = sizeof(uint64_t) * nid;
  char*   buf = calloc(1, total);
dengyihao's avatar
dengyihao 已提交
604 605 606
  if (buf == NULL) {
    return -1;
  }
dengyihao's avatar
dengyihao 已提交
607

dengyihao's avatar
dengyihao 已提交
608
  nread = ctx->readFrom(ctx, buf, total, offset + sizeof(nid));
dengyihao's avatar
dengyihao 已提交
609 610
  assert(total == nread);

dengyihao's avatar
dengyihao 已提交
611 612 613
  for (int32_t i = 0; i < nid; i++) {
    taosArrayPush(result, (uint64_t*)buf + i);
  }
dengyihao's avatar
dengyihao 已提交
614 615 616
  free(buf);
  return 0;
}
dengyihao's avatar
dengyihao 已提交
617
void tfileReaderRef(TFileReader* reader) {
dengyihao's avatar
dengyihao 已提交
618 619 620
  if (reader == NULL) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
621 622 623 624
  int ref = T_REF_INC(reader);
  UNUSED(ref);
}

dengyihao's avatar
dengyihao 已提交
625
void tfileReaderUnRef(TFileReader* reader) {
dengyihao's avatar
dengyihao 已提交
626 627 628
  if (reader == NULL) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
629
  int ref = T_REF_DEC(reader);
630
  if (ref == 0) {
dengyihao's avatar
dengyihao 已提交
631
    // do nothing
632 633
    tfileReaderDestroy(reader);
  }
dengyihao's avatar
dengyihao 已提交
634
}
dengyihao's avatar
dengyihao 已提交
635

dengyihao's avatar
dengyihao 已提交
636 637 638
static SArray* tfileGetFileList(const char* path) {
  SArray* files = taosArrayInit(4, sizeof(void*));

dengyihao's avatar
dengyihao 已提交
639 640 641 642
  char     buf[128] = {0};
  uint64_t suid;
  uint32_t version;

dengyihao's avatar
dengyihao 已提交
643
  DIR* dir = opendir(path);
dengyihao's avatar
dengyihao 已提交
644 645 646
  if (NULL == dir) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
647 648
  struct dirent* entry;
  while ((entry = readdir(dir)) != NULL) {
dengyihao's avatar
dengyihao 已提交
649
    char* file = entry->d_name;
dengyihao's avatar
dengyihao 已提交
650 651 652
    if (0 != tfileParseFileName(file, &suid, buf, &version)) {
      continue;
    }
dengyihao's avatar
dengyihao 已提交
653 654 655 656

    size_t len = strlen(path) + 1 + strlen(file) + 1;
    char*  buf = calloc(1, len);
    sprintf(buf, "%s/%s", path, file);
dengyihao's avatar
dengyihao 已提交
657
    taosArrayPush(files, &buf);
dengyihao's avatar
dengyihao 已提交
658 659
  }
  closedir(dir);
dengyihao's avatar
dengyihao 已提交
660 661 662 663 664

  taosArraySort(files, tfileCompare);
  tfileRmExpireFile(files);

  return files;
dengyihao's avatar
dengyihao 已提交
665
}
dengyihao's avatar
dengyihao 已提交
666 667 668 669
static int tfileRmExpireFile(SArray* result) {
  // TODO(yihao): remove expire tindex after restart
  return 0;
}
dengyihao's avatar
dengyihao 已提交
670 671 672 673 674
static void tfileDestroyFileName(void* elem) {
  char* p = *(char**)elem;
  free(p);
}
static int tfileCompare(const void* a, const void* b) {
dengyihao's avatar
dengyihao 已提交
675 676 677
  const char* as = *(char**)a;
  const char* bs = *(char**)b;
  return strcmp(as, bs);
dengyihao's avatar
dengyihao 已提交
678
}
dengyihao's avatar
dengyihao 已提交
679 680 681

static int tfileParseFileName(const char* filename, uint64_t* suid, char* col, int* version) {
  if (3 == sscanf(filename, "%" PRIu64 "-%[^-]-%d.tindex", suid, col, version)) {
dengyihao's avatar
dengyihao 已提交
682 683 684 685 686
    // read suid & colid & version  success
    return 0;
  }
  return -1;
}
dengyihao's avatar
dengyihao 已提交
687 688 689 690 691 692 693 694 695 696
// tfile name suid-colId-version.tindex
static void tfileGenFileName(char* filename, uint64_t suid, const char* col, int version) {
  sprintf(filename, "%" PRIu64 "-%s-%d.tindex", suid, col, version);
  return;
}
static void tfileGenFileFullName(char* fullname, const char* path, uint64_t suid, const char* col, int32_t version) {
  char filename[128] = {0};
  tfileGenFileName(filename, suid, col, version);
  sprintf(fullname, "%s/%s", path, filename);
}