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()30Status 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()40void 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)54StatusWithSize 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()73size_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()86Status 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