1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 //
6 #include "file/file_util.h"
7 
8 #include <string>
9 #include <algorithm>
10 
11 #include "file/random_access_file_reader.h"
12 #include "file/sequence_file_reader.h"
13 #include "file/sst_file_manager_impl.h"
14 #include "file/writable_file_writer.h"
15 #include "rocksdb/env.h"
16 
17 namespace ROCKSDB_NAMESPACE {
18 
19 // Utility function to copy a file up to a specified length
CopyFile(FileSystem * fs,const std::string & source,const std::string & destination,uint64_t size,bool use_fsync)20 Status CopyFile(FileSystem* fs, const std::string& source,
21                 const std::string& destination, uint64_t size, bool use_fsync) {
22   const FileOptions soptions;
23   Status s;
24   std::unique_ptr<SequentialFileReader> src_reader;
25   std::unique_ptr<WritableFileWriter> dest_writer;
26 
27   {
28     std::unique_ptr<FSSequentialFile> srcfile;
29     s = fs->NewSequentialFile(source, soptions, &srcfile, nullptr);
30     if (!s.ok()) {
31       return s;
32     }
33     std::unique_ptr<FSWritableFile> destfile;
34     s = fs->NewWritableFile(destination, soptions, &destfile, nullptr);
35     if (!s.ok()) {
36       return s;
37     }
38 
39     if (size == 0) {
40       // default argument means copy everything
41       s = fs->GetFileSize(source, IOOptions(), &size, nullptr);
42       if (!s.ok()) {
43         return s;
44       }
45     }
46     src_reader.reset(new SequentialFileReader(std::move(srcfile), source));
47     dest_writer.reset(
48         new WritableFileWriter(std::move(destfile), destination, soptions));
49   }
50 
51   char buffer[4096];
52   Slice slice;
53   while (size > 0) {
54     size_t bytes_to_read = std::min(sizeof(buffer), static_cast<size_t>(size));
55     s = src_reader->Read(bytes_to_read, &slice, buffer);
56     if (!s.ok()) {
57       return s;
58     }
59     if (slice.size() == 0) {
60       return Status::Corruption("file too small");
61     }
62     s = dest_writer->Append(slice);
63     if (!s.ok()) {
64       return s;
65     }
66     size -= slice.size();
67   }
68   return dest_writer->Sync(use_fsync);
69 }
70 
71 // Utility function to create a file with the provided contents
CreateFile(FileSystem * fs,const std::string & destination,const std::string & contents,bool use_fsync)72 Status CreateFile(FileSystem* fs, const std::string& destination,
73                   const std::string& contents, bool use_fsync) {
74   const EnvOptions soptions;
75   Status s;
76   std::unique_ptr<WritableFileWriter> dest_writer;
77 
78   std::unique_ptr<FSWritableFile> destfile;
79   s = fs->NewWritableFile(destination, soptions, &destfile, nullptr);
80   if (!s.ok()) {
81     return s;
82   }
83   dest_writer.reset(
84       new WritableFileWriter(std::move(destfile), destination, soptions));
85   s = dest_writer->Append(Slice(contents));
86   if (!s.ok()) {
87     return s;
88   }
89   return dest_writer->Sync(use_fsync);
90 }
91 
DeleteDBFile(const ImmutableDBOptions * db_options,const std::string & fname,const std::string & dir_to_sync,const bool force_bg,const bool force_fg)92 Status DeleteDBFile(const ImmutableDBOptions* db_options,
93                     const std::string& fname, const std::string& dir_to_sync,
94                     const bool force_bg, const bool force_fg) {
95 #ifndef ROCKSDB_LITE
96   SstFileManagerImpl* sfm =
97       static_cast<SstFileManagerImpl*>(db_options->sst_file_manager.get());
98   if (sfm && !force_fg) {
99     return sfm->ScheduleFileDeletion(fname, dir_to_sync, force_bg);
100   } else {
101     return db_options->env->DeleteFile(fname);
102   }
103 #else
104   (void)dir_to_sync;
105   (void)force_bg;
106   (void)force_fg;
107   // SstFileManager is not supported in ROCKSDB_LITE
108   // Delete file immediately
109   return db_options->env->DeleteFile(fname);
110 #endif
111 }
112 
IsWalDirSameAsDBPath(const ImmutableDBOptions * db_options)113 bool IsWalDirSameAsDBPath(const ImmutableDBOptions* db_options) {
114   bool same = false;
115   assert(!db_options->db_paths.empty());
116   Status s = db_options->env->AreFilesSame(db_options->wal_dir,
117                                            db_options->db_paths[0].path, &same);
118   if (s.IsNotSupported()) {
119     same = db_options->wal_dir == db_options->db_paths[0].path;
120   }
121   return same;
122 }
123 
124 }  // namespace ROCKSDB_NAMESPACE
125