xref: /aosp_15_r20/external/pigweed/pw_blob_store/flat_file_system_entry.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_blob_store/flat_file_system_entry.h"
16 
17 #include <cstddef>
18 #include <mutex>
19 
20 #include "pw_assert/check.h"
21 #include "pw_blob_store/blob_store.h"
22 #include "pw_file/flat_file_system.h"
23 #include "pw_span/span.h"
24 #include "pw_status/status.h"
25 #include "pw_status/status_with_size.h"
26 #include "pw_sync/virtual_basic_lockable.h"
27 
28 namespace pw::blob_store {
29 
Init()30 Status FlatFileSystemBlobStoreEntry::Init() {
31   std::lock_guard lock(blob_store_lock_);
32   if (initialized_) {
33     return OkStatus();
34   }
35   const Status status = blob_store_.Init();
36   initialized_ = status.ok();
37   return status;
38 }
39 
EnsureInitialized()40 void FlatFileSystemBlobStoreEntry::EnsureInitialized() {
41   {  // Only hold lock for initial check so Init() doesn't recursively lock.
42     std::lock_guard lock(blob_store_lock_);
43     if (initialized_) {
44       return;
45     }
46   }
47 
48   // Don't inline the Init() into the DCHECK() as disabling the DCHECK()
49   // statement would disable the Init() call as well.
50   const Status status = Init();
51   PW_DCHECK_OK(status);
52 }
53 
Name(span<char> dest)54 StatusWithSize FlatFileSystemBlobStoreEntry::Name(span<char> dest) {
55   EnsureInitialized();
56   std::lock_guard lock(blob_store_lock_);
57   BlobStore::BlobReader reader(blob_store_);
58   if (const Status status = reader.Open(); !status.ok()) {
59     // When a BlobStore is empty, Open() reports FAILED_PRECONDITION. The
60     // FlatFileSystemService expects NOT_FOUND when a file is not present at the
61     // entry.
62     if (status.IsFailedPrecondition()) {
63       return StatusWithSize(Status::NotFound(), 0);
64     } else if (status.IsUnavailable()) {
65       return StatusWithSize(Status::Unavailable(), 0);
66     } else {
67       return StatusWithSize(Status::Internal(), 0);
68     }
69   }
70   return reader.GetFileName(dest);
71 }
72 
SizeBytes()73 size_t FlatFileSystemBlobStoreEntry::SizeBytes() {
74   EnsureInitialized();
75   std::lock_guard lock(blob_store_lock_);
76   BlobStore::BlobReader reader(blob_store_);
77   if (!reader.Open().ok()) {
78     return 0;
79   }
80   return reader.ConservativeReadLimit();
81 }
82 
83 // TODO: b/234888404 - This file can be deleted even though it is read-only.
84 // This type of behavior should be possible to express via the FileSystem RPC
85 // service.
Delete()86 Status FlatFileSystemBlobStoreEntry::Delete() {
87   EnsureInitialized();
88   std::lock_guard lock(blob_store_lock_);
89 
90   BlobStore::BlobWriterWithBuffer blob_writer(blob_store_);
91   PW_TRY(blob_writer.Open());
92   return blob_writer.Discard();
93 }
94 
95 }  // namespace pw::blob_store
96