1 // Copyright (C) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "icing/legacy/index/icing-storage-file.h"
16
17 #include <unistd.h>
18
19 #include <cinttypes>
20 #include <string>
21
22 #include "icing/legacy/core/icing-compat.h"
23 #include "icing/legacy/core/icing-string-util.h"
24 #include "icing/legacy/core/icing-timer.h"
25 #include "icing/util/logging.h"
26
27 namespace icing {
28 namespace lib {
29
IcingStorageFile(const std::string & filename,const IcingFilesystem * filesystem)30 IcingStorageFile::IcingStorageFile(const std::string &filename,
31 const IcingFilesystem *filesystem)
32 : IIcingStorage(), filesystem_(filesystem), filename_(filename) {}
33
Init()34 bool IcingStorageFile::Init() {
35 if (!is_initialized_) {
36 // Ensure the storage directory exists
37 std::string storage_dir = filesystem_->GetDirname(filename_.c_str());
38 if (!filesystem_->CreateDirectoryRecursively(storage_dir.c_str())) {
39 return false;
40 }
41
42 is_initialized_ = OnInit();
43
44 if (is_initialized_ && fd_.get() < 0) { // if initalized, fd better be set
45 ICING_LOG(FATAL)
46 << "Storage file descriptor not set after initialization";
47 }
48 }
49 return is_initialized_;
50 }
51
Close()52 void IcingStorageFile::Close() {
53 if (is_initialized_) {
54 OnClose();
55 fd_.reset();
56 is_initialized_ = false;
57 }
58 }
59
Remove()60 bool IcingStorageFile::Remove() {
61 Close();
62 return filesystem_->DeleteFile(filename_.c_str());
63 }
64
Sync()65 bool IcingStorageFile::Sync() {
66 if (!is_initialized_) {
67 ICING_LOG(FATAL) << "Storage file not initialized";
68 }
69
70 IcingTimer timer;
71 if (!PreSync()) {
72 ICING_LOG(ERROR) << "Pre-sync " << filename_ << " failed";
73 return false;
74 }
75 if (!filesystem_->DataSync(fd_.get())) {
76 ICING_LOG(ERROR) << "Sync " << filename_ << " failed";
77 return false;
78 }
79 if (!PostSync()) {
80 ICING_LOG(ERROR) << "Post-sync " << filename_ << " failed";
81 return false;
82 }
83 ICING_VLOG(1) << "Syncing " << filename_ << " took " << timer.Elapsed() * 1000 << "ms";
84 return true;
85 }
86
GetDiskUsage() const87 uint64_t IcingStorageFile::GetDiskUsage() const {
88 return filesystem_->GetDiskUsage(fd_.get());
89 }
90
PreSync()91 bool IcingStorageFile::PreSync() {
92 // Default implementation is a no-op.
93 return true;
94 }
95
PostSync()96 bool IcingStorageFile::PostSync() {
97 // Default implementation is a no-op.
98 return true;
99 }
100
GetDebugInfo(int verbosity,std::string * out) const101 void IcingStorageFile::GetDebugInfo(int verbosity, std::string *out) const {
102 if (!is_initialized_) {
103 ICING_LOG(FATAL) << "Storage file not initialized";
104 }
105
106 if (verbosity >= 0) { // Always
107 uint64_t size = filesystem_->GetFileSize(fd_.get());
108 IcingStringUtil::SStringAppendF(
109 out, 1000, "Filename: %s Size: %" PRIu64 "\n", filename_.c_str(), size);
110 }
111 }
112
113 } // namespace lib
114 } // namespace icing
115