// Copyright 2021 The Pigweed Authors // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. #include "pw_blob_store/flat_file_system_entry.h" #include #include #include "pw_assert/check.h" #include "pw_blob_store/blob_store.h" #include "pw_file/flat_file_system.h" #include "pw_span/span.h" #include "pw_status/status.h" #include "pw_status/status_with_size.h" #include "pw_sync/virtual_basic_lockable.h" namespace pw::blob_store { Status FlatFileSystemBlobStoreEntry::Init() { std::lock_guard lock(blob_store_lock_); if (initialized_) { return OkStatus(); } const Status status = blob_store_.Init(); initialized_ = status.ok(); return status; } void FlatFileSystemBlobStoreEntry::EnsureInitialized() { { // Only hold lock for initial check so Init() doesn't recursively lock. std::lock_guard lock(blob_store_lock_); if (initialized_) { return; } } // Don't inline the Init() into the DCHECK() as disabling the DCHECK() // statement would disable the Init() call as well. const Status status = Init(); PW_DCHECK_OK(status); } StatusWithSize FlatFileSystemBlobStoreEntry::Name(span dest) { EnsureInitialized(); std::lock_guard lock(blob_store_lock_); BlobStore::BlobReader reader(blob_store_); if (const Status status = reader.Open(); !status.ok()) { // When a BlobStore is empty, Open() reports FAILED_PRECONDITION. The // FlatFileSystemService expects NOT_FOUND when a file is not present at the // entry. if (status.IsFailedPrecondition()) { return StatusWithSize(Status::NotFound(), 0); } else if (status.IsUnavailable()) { return StatusWithSize(Status::Unavailable(), 0); } else { return StatusWithSize(Status::Internal(), 0); } } return reader.GetFileName(dest); } size_t FlatFileSystemBlobStoreEntry::SizeBytes() { EnsureInitialized(); std::lock_guard lock(blob_store_lock_); BlobStore::BlobReader reader(blob_store_); if (!reader.Open().ok()) { return 0; } return reader.ConservativeReadLimit(); } // TODO: b/234888404 - This file can be deleted even though it is read-only. // This type of behavior should be possible to express via the FileSystem RPC // service. Status FlatFileSystemBlobStoreEntry::Delete() { EnsureInitialized(); std::lock_guard lock(blob_store_lock_); BlobStore::BlobWriterWithBuffer blob_writer(blob_store_); PW_TRY(blob_writer.Open()); return blob_writer.Discard(); } } // namespace pw::blob_store