YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
91.3k
  while (i < src_len && 
write_idx < len - sizeof(suffix)89.5k
) {
55
89.5k
    if ((path[i] >= 'a' && 
path[i] <= 'z'39.0k
) ||
56
89.5k
        
(50.4k
path[i] >= '0'50.4k
&&
path[i] <= '9'36.0k
) ||
57
89.5k
        
(18.2k
path[i] >= 'A'18.2k
&&
path[i] <= 'Z'3.80k
) ||
58
89.5k
        
path[i] == '-'18.2k
||
59
89.5k
        
path[i] == '.'18.2k
||
60
89.5k
        
path[i] == '_'9.26k
) {
61
84.0k
      dest[write_idx++] = path[i];
62
84.0k
    } else {
63
5.45k
      if (i > 0) {
64
3.62k
        dest[write_idx++] = '_';
65
3.62k
      }
66
5.45k
    }
67
89.5k
    i++;
68
89.5k
  }
69
1.82k
  assert(sizeof(suffix) <= len - write_idx);
70
  // "\0" is automatically added by snprintf
71
0
  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
2.38M
                                const char* suffix) {
78
2.38M
  char buf[100];
79
2.38M
  snprintf(buf, sizeof(buf), "/%06" PRIu64 ".%s", number, suffix);
80
2.38M
  return name + buf;
81
2.38M
}
82
83
491k
std::string LogFileName(const std::string& name, uint64_t number) {
84
491k
  assert(number > 0);
85
0
  return MakeFileName(name, number, "log");
86
491k
}
87
88
423k
std::string ArchivalDirectory(const std::string& dir) {
89
423k
  return dir + "/" + ARCHIVAL_DIR;
90
423k
}
91
650
std::string ArchivedLogFileName(const std::string& name, uint64_t number) {
92
650
  assert(number > 0);
93
0
  return MakeFileName(name + "/" + ARCHIVAL_DIR, number, "log");
94
650
}
95
96
767k
std::string MakeTableFileName(const std::string& path, uint64_t number) {
97
767k
  return MakeFileName(path, number, kRocksDbTFileExt);
98
767k
}
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
1.25k
uint64_t TableFileNameToNumber(const std::string& name) {
110
1.25k
  uint64_t number = 0;
111
1.25k
  uint64_t base = 1;
112
1.25k
  int pos = static_cast<int>(name.find_last_of('.'));
113
8.80k
  while (--pos >= 0 && name[pos] >= '0' && 
name[pos] <= '9'7.54k
) {
114
7.54k
    number += (name[pos] - '0') * base;
115
7.54k
    base *= 10;
116
7.54k
  }
117
1.25k
  return number;
118
1.25k
}
119
120
std::string TableFileName(const std::vector<DbPath>& db_paths, uint64_t number,
121
310k
                          uint32_t path_id) {
122
310k
  assert(number > 0);
123
0
  std::string path;
124
310k
  if (path_id >= db_paths.size()) {
125
0
    path = db_paths.back().path;
126
310k
  } else {
127
310k
    path = db_paths[path_id].path;
128
310k
  }
129
310k
  return MakeTableFileName(path, number);
130
310k
}
131
132
231k
extern std::string TableBaseToDataFileName(const std::string& base_fname) {
133
231k
  return base_fname + "." + kRocksDbTSBlockExtSuffix + ".0";
134
231k
}
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.68M
std::string DescriptorFileName(const std::string& dbname, uint64_t number) {
149
1.68M
  assert(number > 0);
150
0
  char buf[100];
151
1.68M
  snprintf(buf, sizeof(buf), "/MANIFEST-%06" PRIu64, number);
152
1.68M
  return dbname + buf;
153
1.68M
}
154
155
1.57M
std::string CurrentFileName(const std::string& dbname) {
156
1.57M
  return dbname + "/CURRENT";
157
1.57M
}
158
159
855k
std::string LockFileName(const std::string& dbname) {
160
855k
  return dbname + "/LOCK";
161
855k
}
162
163
1.13M
std::string TempFileName(const std::string& dbname, uint64_t number) {
164
1.13M
  return MakeFileName(dbname, number, kTempFileNameSuffix);
165
1.13M
}
166
167
InfoLogPrefix::InfoLogPrefix(bool has_log_dir,
168
2.54M
                             const std::string& db_absolute_path) {
169
2.54M
  if (!has_log_dir) {
170
2.54M
    const char kInfoLogPrefix[] = "LOG";
171
    // "\0" is automatically added to the end
172
2.54M
    snprintf(buf, sizeof(buf), kInfoLogPrefix);
173
2.54M
    prefix = Slice(buf, sizeof(kInfoLogPrefix) - 1);
174
2.54M
  } else {
175
2.84k
    size_t len = GetInfoLogPrefix(db_absolute_path, buf, sizeof(buf));
176
2.84k
    prefix = Slice(buf, len);
177
2.84k
  }
178
2.54M
}
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
21.0k
}
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
13.0k
}
203
204
1.27M
std::string OptionsFileName(const std::string& dbname, uint64_t file_num) {
205
1.27M
  char buffer[256];
206
1.27M
  snprintf(buffer, sizeof(buffer), "%s%06" PRIu64,
207
1.27M
           kOptionsFileNamePrefix, file_num);
208
1.27M
  return dbname + "/" + buffer;
209
1.27M
}
210
211
1.27M
std::string TempOptionsFileName(const std::string& dbname, uint64_t file_num) {
212
1.27M
  char buffer[256];
213
1.27M
  snprintf(buffer, sizeof(buffer), "%s%06" PRIu64 ".%s",
214
1.27M
           kOptionsFileNamePrefix, file_num,
215
1.27M
           kTempFileNameSuffix);
216
1.27M
  return dbname + "/" + buffer;
217
1.27M
}
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
863k
std::string IdentityFileName(const std::string& dbname) {
226
863k
  return dbname + "/IDENTITY";
227
863k
}
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
15.6M
                   WalFileType* log_type) {
245
15.6M
  return ParseFileName(fname, number, "", type, log_type);
246
15.6M
}
247
248
bool ParseFileName(const std::string& fname, uint64_t* number,
249
                   const Slice& info_log_name_prefix, FileType* type,
250
32.6M
                   WalFileType* log_type) {
251
32.6M
  Slice rest(fname);
252
32.6M
  if (fname.length() > 1 && 
fname[0] == '/'29.7M
) {
253
6.02M
    rest.remove_prefix(1);
254
6.02M
  }
255
32.6M
  if (rest == "IDENTITY") {
256
3.80M
    *number = 0;
257
3.80M
    *type = kIdentityFile;
258
28.8M
  } else if (rest == "CURRENT") {
259
3.81M
    *number = 0;
260
3.81M
    *type = kCurrentFile;
261
25.0M
  } else if (rest == "LOCK") {
262
3.80M
    *number = 0;
263
3.80M
    *type = kDBLockFile;
264
21.2M
  } else if (info_log_name_prefix.size() > 0 &&
265
21.2M
             
rest.starts_with(info_log_name_prefix)10.8M
) {
266
795k
    rest.remove_prefix(info_log_name_prefix.size());
267
795k
    if (rest == "" || 
rest == ".old"698k
) {
268
96.8k
      *number = 0;
269
96.8k
      *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
20.4M
  } else if (rest.starts_with("MANIFEST-")) {
281
5.04M
    rest.remove_prefix(strlen("MANIFEST-"));
282
5.04M
    uint64_t num;
283
5.04M
    if (!ConsumeDecimalNumber(&rest, &num)) {
284
1
      return false;
285
1
    }
286
5.04M
    if (!rest.empty()) {
287
1
      return false;
288
1
    }
289
5.04M
    *type = kDescriptorFile;
290
5.04M
    *number = num;
291
15.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
15.4M
  } else if (rest.starts_with(kOptionsFileNamePrefix)) {
303
4.99M
    uint64_t ts_suffix;
304
4.99M
    bool is_temp_file = false;
305
4.99M
    rest.remove_prefix(sizeof(kOptionsFileNamePrefix) - 1);
306
4.99M
    const std::string kTempFileNameSuffixWithDot =
307
4.99M
        std::string(".") + kTempFileNameSuffix;
308
4.99M
    if (rest.ends_with(kTempFileNameSuffixWithDot)) {
309
169
      rest.remove_suffix(kTempFileNameSuffixWithDot.size());
310
169
      is_temp_file = true;
311
169
    }
312
4.99M
    if (!ConsumeDecimalNumber(&rest, &ts_suffix)) {
313
0
      return false;
314
0
    }
315
4.99M
    *number = ts_suffix;
316
4.99M
    *type = is_temp_file ? 
kTempFile169
:
kOptionsFile4.99M
;
317
10.4M
  } else {
318
    // Avoid strtoull() to keep filename format independent of the
319
    // current locale
320
10.4M
    bool archive_dir_found = false;
321
10.4M
    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
10.4M
    uint64_t num;
332
10.4M
    if (!ConsumeDecimalNumber(&rest, &num)) {
333
6.35M
      return false;
334
6.35M
    }
335
4.09M
    
if (4.06M
rest.size() <= 14.06M
|| rest[0] != '.') {
336
2
      return false;
337
2
    }
338
4.06M
    rest.remove_prefix(1);
339
340
4.06M
    Slice suffix = rest;
341
4.06M
    if (suffix == Slice("log")) {
342
3.44M
      *type = kLogFile;
343
3.44M
      if (log_type && 
!archive_dir_found2
) {
344
1
        *log_type = kAliveLogFile;
345
1
      }
346
3.44M
    } else 
if (622k
archive_dir_found622k
) {
347
0
      return false; // Archive dir can contain only log files
348
622k
    } else if (suffix == Slice(kRocksDbTFileExt) ||
349
622k
               
suffix == Slice(kLevelDbTFileExt)288k
) {
350
358k
      *type = kTableFile;
351
358k
    } else 
if (264k
suffix == Slice(kRocksDbTSBlockFileExt)264k
) {
352
288k
      *type = kTableSBlockFile;
353
18.4E
    } else if (suffix == Slice(kTempFileNameSuffix)) {
354
13
      *type = kTempFile;
355
18.4E
    } else {
356
18.4E
      return false;
357
18.4E
    }
358
4.09M
    *number = num;
359
4.09M
  }
360
26.3M
  return true;
361
32.6M
}
362
363
Status SetCurrentFile(Env* env, const std::string& dbname,
364
                      uint64_t descriptor_number,
365
                      Directory* directory_to_fsync,
366
702k
                      bool disable_data_sync) {
367
  // Remove leading "dbname/" and add newline to manifest file name
368
702k
  std::string manifest = DescriptorFileName(dbname, descriptor_number);
369
702k
  Slice contents = manifest;
370
702k
  assert(contents.starts_with(dbname + "/"));
371
0
  contents.remove_prefix(dbname.size() + 1);
372
702k
  std::string tmp = TempFileName(dbname, descriptor_number);
373
702k
  Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp, !disable_data_sync);
374
702k
  if (
s.ok()702k
) {
375
702k
    TEST_KILL_RANDOM("SetCurrentFile:0", rocksdb_kill_odds * REDUCE_ODDS2);
376
702k
    s = env->RenameFile(tmp, CurrentFileName(dbname));
377
702k
    TEST_KILL_RANDOM("SetCurrentFile:1", rocksdb_kill_odds * REDUCE_ODDS2);
378
702k
  }
379
702k
  if (
s.ok()702k
) {
380
702k
    if (directory_to_fsync != nullptr && 
!disable_data_sync429k
) {
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
702k
  return s;
387
702k
}
388
389
428k
Status SetIdentityFile(Env* env, const std::string& dbname) {
390
428k
  std::string id = env->GenerateUniqueId();
391
428k
  assert(!id.empty());
392
  // Reserve the filename dbname/000000.dbtmp for the temporary identity file
393
0
  std::string tmp = TempFileName(dbname, 0);
394
428k
  Status s = WriteStringToFile(env, id, tmp, true);
395
428k
  if (s.ok()) {
396
428k
    s = env->RenameFile(tmp, IdentityFileName(dbname));
397
428k
  }
398
428k
  if (!s.ok()) {
399
1
    env->CleanupFile(tmp);
400
1
  }
401
428k
  return s;
402
428k
}
403
404
Status SyncManifest(Env* env, const DBOptions* db_options,
405
760k
                    WritableFileWriter* file) {
406
760k
  TEST_KILL_RANDOM("SyncManifest:0", rocksdb_kill_odds * REDUCE_ODDS2);
407
760k
  if (db_options->disableDataSync) {
408
692k
    return Status::OK();
409
692k
  } else {
410
67.4k
    return file->Sync(db_options->use_fsync);
411
67.4k
  }
412
760k
}
413
414
}  // namespace rocksdb