YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/filename.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
21
// Use of this source code is governed by a BSD-style license that can be
22
// found in the LICENSE file. See the AUTHORS file for names of contributors.
23
#ifndef __STDC_FORMAT_MACROS
24
#define __STDC_FORMAT_MACROS
25
#endif
26
27
#include "yb/rocksdb/db/filename.h"
28
#include <inttypes.h>
29
30
#include <stdio.h>
31
#include <vector>
32
#include "yb/rocksdb/env.h"
33
#include "yb/rocksdb/util/file_reader_writer.h"
34
#include "yb/rocksdb/util/logging.h"
35
#include "yb/rocksdb/util/sync_point.h"
36
37
namespace rocksdb {
38
39
static const char kRocksDbTFileExt[] = "sst";
40
static const char kLevelDbTFileExt[] = "ldb";
41
static const char kRocksDbTSBlockExtSuffix[] = "sblock";
42
static const char kRocksDbTSBlockFileExt[] = "sst.sblock.0";
43
44
// Given a path, flatten the path name by replacing all chars not in
45
// {[0-9,a-z,A-Z,-,_,.]} with _. And append '_LOG\0' at the end.
46
// Return the number of chars stored in dest not including the trailing '\0'.
47
1.82k
static size_t GetInfoLogPrefix(const std::string& path, char* dest, int len) {
48
1.82k
  const char suffix[] = "_LOG";
49
50
1.82k
  size_t write_idx = 0;
51
1.82k
  size_t i = 0;
52
1.82k
  size_t src_len = path.size();
53
54
94.8k
  while (i < src_len && write_idx < len - sizeof(suffix)) {
55
93.0k
    if ((path[i] >= 'a' && path[i] <= 'z') ||
56
53.9k
        (path[i] >= '0' && path[i] <= '9') ||
57
18.2k
        (path[i] >= 'A' && path[i] <= 'Z') ||
58
18.2k
        path[i] == '-' ||
59
18.2k
        path[i] == '.' ||
60
87.5k
        path[i] == '_') {
61
87.5k
      dest[write_idx++] = path[i];
62
5.45k
    } else {
63
5.45k
      if (i > 0) {
64
3.62k
        dest[write_idx++] = '_';
65
3.62k
      }
66
5.45k
    }
67
93.0k
    i++;
68
93.0k
  }
69
1.82k
  assert(sizeof(suffix) <= len - write_idx);
70
  // "\0" is automatically added by snprintf
71
1.82k
  snprintf(dest + write_idx, len - write_idx, suffix);
72
1.82k
  write_idx += sizeof(suffix) - 1;
73
1.82k
  return write_idx;
74
1.82k
}
75
76
static std::string MakeFileName(const std::string& name, uint64_t number,
77
1.81M
                                const char* suffix) {
78
1.81M
  char buf[100];
79
1.81M
  snprintf(buf, sizeof(buf), "/%06" PRIu64 ".%s", number, suffix);
80
1.81M
  return name + buf;
81
1.81M
}
82
83
396k
std::string LogFileName(const std::string& name, uint64_t number) {
84
396k
  assert(number > 0);
85
396k
  return MakeFileName(name, number, "log");
86
396k
}
87
88
348k
std::string ArchivalDirectory(const std::string& dir) {
89
348k
  return dir + "/" + ARCHIVAL_DIR;
90
348k
}
91
650
std::string ArchivedLogFileName(const std::string& name, uint64_t number) {
92
650
  assert(number > 0);
93
650
  return MakeFileName(name + "/" + ARCHIVAL_DIR, number, "log");
94
650
}
95
96
490k
std::string MakeTableFileName(const std::string& path, uint64_t number) {
97
490k
  return MakeFileName(path, number, kRocksDbTFileExt);
98
490k
}
99
100
12
std::string Rocks2LevelTableFileName(const std::string& fullname) {
101
12
  assert(fullname.size() > sizeof(kRocksDbTFileExt));
102
12
  if (fullname.size() <= sizeof(kRocksDbTFileExt)) {
103
0
    return "";
104
0
  }
105
12
  return fullname.substr(0, fullname.size() - sizeof(kRocksDbTFileExt) + 1) +
106
12
         kLevelDbTFileExt;
107
12
}
108
109
358
uint64_t TableFileNameToNumber(const std::string& name) {
110
358
  uint64_t number = 0;
111
358
  uint64_t base = 1;
112
358
  int pos = static_cast<int>(name.find_last_of('.'));
113
2.50k
  while (--pos >= 0 && name[pos] >= '0' && name[pos] <= '9') {
114
2.14k
    number += (name[pos] - '0') * base;
115
2.14k
    base *= 10;
116
2.14k
  }
117
358
  return number;
118
358
}
119
120
std::string TableFileName(const std::vector<DbPath>& db_paths, uint64_t number,
121
285k
                          uint32_t path_id) {
122
285k
  assert(number > 0);
123
285k
  std::string path;
124
285k
  if (path_id >= db_paths.size()) {
125
0
    path = db_paths.back().path;
126
285k
  } else {
127
285k
    path = db_paths[path_id].path;
128
285k
  }
129
285k
  return MakeTableFileName(path, number);
130
285k
}
131
132
214k
extern std::string TableBaseToDataFileName(const std::string& base_fname) {
133
214k
  return base_fname + "." + kRocksDbTSBlockExtSuffix + ".0";
134
214k
}
135
136
void FormatFileNumber(uint64_t number, uint32_t path_id, char* out_buf,
137
0
                      size_t out_buf_size) {
138
0
  if (path_id == 0) {
139
0
    snprintf(out_buf, out_buf_size, "%" PRIu64, number);
140
0
  } else {
141
0
    snprintf(out_buf, out_buf_size, "%" PRIu64
142
0
                                    "(path "
143
0
                                    "%" PRIu32 ")",
144
0
             number, path_id);
145
0
  }
146
0
}
147
148
1.43M
std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
149
1.43M
  assert(number > 0);
150
1.43M
  char buf[100];
151
1.43M
  snprintf(buf, sizeof(buf), "/MANIFEST-%06" PRIu64, number);
152
1.43M
  return dbname + buf;
153
1.43M
}
154
155
1.27M
std::string CurrentFileName(const std::string& dbname) {
156
1.27M
  return dbname + "/CURRENT";
157
1.27M
}
158
159
687k
std::string LockFileName(const std::string& dbname) {
160
687k
  return dbname + "/LOCK";
161
687k
}
162
163
923k
std::string TempFileName(const std::string& dbname, uint64_t number) {
164
923k
  return MakeFileName(dbname, number, kTempFileNameSuffix);
165
923k
}
166
167
InfoLogPrefix::InfoLogPrefix(bool has_log_dir,
168
2.07M
                             const std::string& db_absolute_path) {
169
2.07M
  if (!has_log_dir) {
170
2.07M
    const char kInfoLogPrefix[] = "LOG";
171
    // "\0" is automatically added to the end
172
2.07M
    snprintf(buf, sizeof(buf), kInfoLogPrefix);
173
2.07M
    prefix = Slice(buf, sizeof(kInfoLogPrefix) - 1);
174
2.52k
  } else {
175
2.52k
    size_t len = GetInfoLogPrefix(db_absolute_path, buf, sizeof(buf));
176
2.52k
    prefix = Slice(buf, len);
177
2.52k
  }
178
2.07M
}
179
180
std::string InfoLogFileName(const std::string& dbname,
181
21.0k
    const std::string& db_path, const std::string& log_dir) {
182
21.0k
  if (log_dir.empty()) {
183
20.7k
    return dbname + "/LOG";
184
20.7k
  }
185
186
268
  InfoLogPrefix info_log_prefix(true, db_path);
187
268
  return log_dir + "/" + info_log_prefix.buf;
188
268
}
189
190
// Return the name of the old info log file for "dbname".
191
std::string OldInfoLogFileName(const std::string& dbname, uint64_t ts,
192
13.0k
    const std::string& db_path, const std::string& log_dir) {
193
13.0k
  char buf[50];
194
13.0k
  snprintf(buf, sizeof(buf), "%" PRIu64, ts);
195
196
13.0k
  if (log_dir.empty()) {
197
12.7k
    return dbname + "/LOG.old." + buf;
198
12.7k
  }
199
200
229
  InfoLogPrefix info_log_prefix(true, db_path);
201
229
  return log_dir + "/" + info_log_prefix.buf + ".old." + buf;
202
229
}
203
204
999k
std::string OptionsFileName(const std::string& dbname, uint64_t file_num) {
205
999k
  char buffer[256];
206
999k
  snprintf(buffer, sizeof(buffer), "%s%06" PRIu64,
207
999k
           kOptionsFileNamePrefix, file_num);
208
999k
  return dbname + "/" + buffer;
209
999k
}
210
211
999k
std::string TempOptionsFileName(const std::string& dbname, uint64_t file_num) {
212
999k
  char buffer[256];
213
999k
  snprintf(buffer, sizeof(buffer), "%s%06" PRIu64 ".%s",
214
999k
           kOptionsFileNamePrefix, file_num,
215
999k
           kTempFileNameSuffix);
216
999k
  return dbname + "/" + buffer;
217
999k
}
218
219
3
std::string MetaDatabaseName(const std::string& dbname, uint64_t number) {
220
3
  char buf[100];
221
3
  snprintf(buf, sizeof(buf), "/METADB-%" PRIu64, number);
222
3
  return dbname + buf;
223
3
}
224
225
676k
std::string IdentityFileName(const std::string& dbname) {
226
676k
  return dbname + "/IDENTITY";
227
676k
}
228
229
// Owned filenames have the form:
230
//    dbname/IDENTITY
231
//    dbname/CURRENT
232
//    dbname/LOCK
233
//    dbname/<info_log_name_prefix>
234
//    dbname/<info_log_name_prefix>.old.[0-9]+
235
//    dbname/MANIFEST-[0-9]+
236
//    dbname/[0-9]+.(log|sst)
237
//    dbname/METADB-[0-9]+
238
//    dbname/OPTIONS-[0-9]+
239
//    dbname/OPTIONS-[0-9]+.dbtmp
240
//    Disregards / at the beginning
241
bool ParseFileName(const std::string& fname,
242
                   uint64_t* number,
243
                   FileType* type,
244
12.3M
                   WalFileType* log_type) {
245
12.3M
  return ParseFileName(fname, number, "", type, log_type);
246
12.3M
}
247
248
bool ParseFileName(const std::string& fname, uint64_t* number,
249
                   const Slice& info_log_name_prefix, FileType* type,
250
26.4M
                   WalFileType* log_type) {
251
26.4M
  Slice rest(fname);
252
26.4M
  if (fname.length() > 1 && fname[0] == '/') {
253
5.00M
    rest.remove_prefix(1);
254
5.00M
  }
255
26.4M
  if (rest == "IDENTITY") {
256
3.02M
    *number = 0;
257
3.02M
    *type = kIdentityFile;
258
23.4M
  } else if (rest == "CURRENT") {
259
3.03M
    *number = 0;
260
3.03M
    *type = kCurrentFile;
261
20.3M
  } else if (rest == "LOCK") {
262
3.02M
    *number = 0;
263
3.02M
    *type = kDBLockFile;
264
17.3M
  } else if (info_log_name_prefix.size() > 0 &&
265
9.01M
             rest.starts_with(info_log_name_prefix)) {
266
794k
    rest.remove_prefix(info_log_name_prefix.size());
267
794k
    if (rest == "" || rest == ".old") {
268
95.4k
      *number = 0;
269
95.4k
      *type = kInfoLogFile;
270
698k
    } else if (rest.starts_with(".old.")) {
271
698k
      uint64_t ts_suffix;
272
      // sizeof also counts the trailing '\0'.
273
698k
      rest.remove_prefix(sizeof(".old.") - 1);
274
698k
      if (!ConsumeDecimalNumber(&rest, &ts_suffix)) {
275
0
        return false;
276
0
      }
277
698k
      *number = ts_suffix;
278
698k
      *type = kInfoLogFile;
279
698k
    }
280
16.5M
  } else if (rest.starts_with("MANIFEST-")) {
281
4.11M
    rest.remove_prefix(strlen("MANIFEST-"));
282
4.11M
    uint64_t num;
283
4.11M
    if (!ConsumeDecimalNumber(&rest, &num)) {
284
1
      return false;
285
1
    }
286
4.11M
    if (!rest.empty()) {
287
1
      return false;
288
1
    }
289
4.11M
    *type = kDescriptorFile;
290
4.11M
    *number = num;
291
12.4M
  } else if (rest.starts_with("METADB-")) {
292
11
    rest.remove_prefix(strlen("METADB-"));
293
11
    uint64_t num;
294
11
    if (!ConsumeDecimalNumber(&rest, &num)) {
295
1
      return false;
296
1
    }
297
10
    if (!rest.empty()) {
298
1
      return false;
299
1
    }
300
9
    *type = kMetaDatabase;
301
9
    *number = num;
302
12.4M
  } else if (rest.starts_with(kOptionsFileNamePrefix)) {
303
3.99M
    uint64_t ts_suffix;
304
3.99M
    bool is_temp_file = false;
305
3.99M
    rest.remove_prefix(sizeof(kOptionsFileNamePrefix) - 1);
306
3.99M
    const std::string kTempFileNameSuffixWithDot =
307
3.99M
        std::string(".") + kTempFileNameSuffix;
308
3.99M
    if (rest.ends_with(kTempFileNameSuffixWithDot)) {
309
169
      rest.remove_suffix(kTempFileNameSuffixWithDot.size());
310
169
      is_temp_file = true;
311
169
    }
312
3.99M
    if (!ConsumeDecimalNumber(&rest, &ts_suffix)) {
313
0
      return false;
314
0
    }
315
3.99M
    *number = ts_suffix;
316
3.99M
    *type = is_temp_file ? kTempFile : kOptionsFile;
317
8.44M
  } else {
318
    // Avoid strtoull() to keep filename format independent of the
319
    // current locale
320
8.44M
    bool archive_dir_found = false;
321
8.44M
    if (rest.starts_with(ARCHIVAL_DIR)) {
322
554
      if (rest.size() < sizeof(ARCHIVAL_DIR)) {
323
553
        return false;
324
553
      }
325
1
      rest.remove_prefix(sizeof(ARCHIVAL_DIR)); // Don't subtract 1 to remove / also
326
1
      if (log_type) {
327
1
        *log_type = kArchivedLogFile;
328
1
      }
329
1
      archive_dir_found = true;
330
1
    }
331
8.44M
    uint64_t num;
332
8.44M
    if (!ConsumeDecimalNumber(&rest, &num)) {
333
5.12M
      return false;
334
5.12M
    }
335
3.33M
    if (rest.size() <= 1 || rest[0] != '.') {
336
2
      return false;
337
2
    }
338
3.32M
    rest.remove_prefix(1);
339
340
3.32M
    Slice suffix = rest;
341
3.32M
    if (suffix == Slice("log")) {
342
2.75M
      *type = kLogFile;
343
2.75M
      if (log_type && !archive_dir_found) {
344
1
        *log_type = kAliveLogFile;
345
1
      }
346
562k
    } else if (archive_dir_found) {
347
0
      return false; // Archive dir can contain only log files
348
562k
    } else if (suffix == Slice(kRocksDbTFileExt) ||
349
322k
               suffix == Slice(kLevelDbTFileExt)) {
350
322k
      *type = kTableFile;
351
255k
    } else if (suffix == Slice(kRocksDbTSBlockFileExt)) {
352
255k
      *type = kTableSBlockFile;
353
18.4E
    } else if (suffix == Slice(kTempFileNameSuffix)) {
354
19
      *type = kTempFile;
355
18.4E
    } else {
356
18.4E
      return false;
357
18.4E
    }
358
3.33M
    *number = num;
359
3.33M
  }
360
21.3M
  return true;
361
26.4M
}
362
363
Status SetCurrentFile(Env* env, const std::string& dbname,
364
                      uint64_t descriptor_number,
365
                      Directory* directory_to_fsync,
366
588k
                      bool disable_data_sync) {
367
  // Remove leading "dbname/" and add newline to manifest file name
368
588k
  std::string manifest = DescriptorFileName(dbname, descriptor_number);
369
588k
  Slice contents = manifest;
370
588k
  assert(contents.starts_with(dbname + "/"));
371
588k
  contents.remove_prefix(dbname.size() + 1);
372
588k
  std::string tmp = TempFileName(dbname, descriptor_number);
373
588k
  Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp, !disable_data_sync);
374
588k
  if (s.ok()) {
375
588k
    TEST_KILL_RANDOM("SetCurrentFile:0", rocksdb_kill_odds * REDUCE_ODDS2);
376
588k
    s = env->RenameFile(tmp, CurrentFileName(dbname));
377
588k
    TEST_KILL_RANDOM("SetCurrentFile:1", rocksdb_kill_odds * REDUCE_ODDS2);
378
588k
  }
379
588k
  if (s.ok()) {
380
588k
    if (directory_to_fsync != nullptr && !disable_data_sync) {
381
9.14k
      RETURN_NOT_OK(directory_to_fsync->Fsync());
382
9.14k
    }
383
18.4E
  } else {
384
18.4E
    env->CleanupFile(tmp);
385
18.4E
  }
386
588k
  return s;
387
588k
}
388
389
335k
Status SetIdentityFile(Env* env, const std::string& dbname) {
390
335k
  std::string id = env->GenerateUniqueId();
391
335k
  assert(!id.empty());
392
  // Reserve the filename dbname/000000.dbtmp for the temporary identity file
393
335k
  std::string tmp = TempFileName(dbname, 0);
394
335k
  Status s = WriteStringToFile(env, id, tmp, true);
395
335k
  if (s.ok()) {
396
334k
    s = env->RenameFile(tmp, IdentityFileName(dbname));
397
334k
  }
398
335k
  if (!s.ok()) {
399
0
    env->CleanupFile(tmp);
400
0
  }
401
335k
  return s;
402
335k
}
403
404
Status SyncManifest(Env* env, const DBOptions* db_options,
405
642k
                    WritableFileWriter* file) {
406
642k
  TEST_KILL_RANDOM("SyncManifest:0", rocksdb_kill_odds * REDUCE_ODDS2);
407
642k
  if (db_options->disableDataSync) {
408
575k
    return Status::OK();
409
67.4k
  } else {
410
67.4k
    return file->Sync(db_options->use_fsync);
411
67.4k
  }
412
642k
}
413
414
}  // namespace rocksdb