1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_blob_store: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker============= 4*61c4878aSAndroid Build Coastguard Workerpw_blob_store 5*61c4878aSAndroid Build Coastguard Worker============= 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_blob_store 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker``pw_blob_store`` is a storage container library for storing a single blob of 10*61c4878aSAndroid Build Coastguard Workerdata. ``BlobStore`` is a flash-backed persistent storage system with integrated 11*61c4878aSAndroid Build Coastguard Workerdata integrity checking that serves as a lightweight alternative to a file 12*61c4878aSAndroid Build Coastguard Workersystem. 13*61c4878aSAndroid Build Coastguard Worker 14*61c4878aSAndroid Build Coastguard Worker----- 15*61c4878aSAndroid Build Coastguard WorkerUsage 16*61c4878aSAndroid Build Coastguard Worker----- 17*61c4878aSAndroid Build Coastguard WorkerMost operations on a ``BlobStore`` are done using ``BlobReader`` and 18*61c4878aSAndroid Build Coastguard Worker``BlobWriter`` objects that have been constructed using a ``BlobStore``. Though 19*61c4878aSAndroid Build Coastguard Workera ``BlobStore`` may have multiple open ``BlobReader`` objects, no other 20*61c4878aSAndroid Build Coastguard Workerreaders/writers may be active if a ``BlobWriter`` is opened on a blob store. 21*61c4878aSAndroid Build Coastguard Worker 22*61c4878aSAndroid Build Coastguard WorkerThe data state of a blob can be checked using the ``HasData()`` method. 23*61c4878aSAndroid Build Coastguard WorkerThe method returns true if the blob is currenty valid and has at least one data 24*61c4878aSAndroid Build Coastguard Workerbyte. This allows checking if a blob has stored data without needing to 25*61c4878aSAndroid Build Coastguard Workerinstantiate and open a reader or writer. 26*61c4878aSAndroid Build Coastguard Worker 27*61c4878aSAndroid Build Coastguard WorkerWrite buffer 28*61c4878aSAndroid Build Coastguard Worker============ 29*61c4878aSAndroid Build Coastguard Worker 30*61c4878aSAndroid Build Coastguard WorkerBlobStore uses a write buffer to allow writes smaller than and/or unaligned to 31*61c4878aSAndroid Build Coastguard Workerthe flash write aligment. BlobStore also supports using the write buffer for 32*61c4878aSAndroid Build Coastguard Workerdeferred writes that can be enqueued and written to flash at a later time or by 33*61c4878aSAndroid Build Coastguard Workera different thread/context. 34*61c4878aSAndroid Build Coastguard Worker 35*61c4878aSAndroid Build Coastguard WorkerBlobStore can be used with a zero-size write buffer to reduce memory 36*61c4878aSAndroid Build Coastguard Workerrequirements. When using zero-size write buffer, the user is required to write 37*61c4878aSAndroid Build Coastguard Workermaintain write sizes that are a multiple of the flash write size the blob is 38*61c4878aSAndroid Build Coastguard Workerconfigured for. 39*61c4878aSAndroid Build Coastguard Worker 40*61c4878aSAndroid Build Coastguard WorkerIf a non-zero sized write buffer is used, the write buffer size must be a 41*61c4878aSAndroid Build Coastguard Workermultiple of the flash write size. 42*61c4878aSAndroid Build Coastguard Worker 43*61c4878aSAndroid Build Coastguard WorkerWriting to a BlobStore 44*61c4878aSAndroid Build Coastguard Worker---------------------- 45*61c4878aSAndroid Build Coastguard Worker``BlobWriter`` objects are ``pw::stream::Writer`` compatible, but do not support 46*61c4878aSAndroid Build Coastguard Workerreading any of the blob's contents. Opening a ``BlobWriter`` on a ``BlobStore`` 47*61c4878aSAndroid Build Coastguard Workerthat contains data will discard any existing data if ``Discard()``, ``Write 48*61c4878aSAndroid Build Coastguard Worker()``, or ``Erase()`` are called. Partially written blobs can be resumed using 49*61c4878aSAndroid Build Coastguard Worker``Resume()``. There is currently no mechanism to allow appending to completed 50*61c4878aSAndroid Build Coastguard Workerdata write. 51*61c4878aSAndroid Build Coastguard Worker 52*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 53*61c4878aSAndroid Build Coastguard Worker 54*61c4878aSAndroid Build Coastguard Worker BlobStore::BlobWriterWithBuffer writer(my_blob_store); 55*61c4878aSAndroid Build Coastguard Worker writer.Open(); 56*61c4878aSAndroid Build Coastguard Worker writer.Write(my_data); 57*61c4878aSAndroid Build Coastguard Worker 58*61c4878aSAndroid Build Coastguard Worker // ... 59*61c4878aSAndroid Build Coastguard Worker 60*61c4878aSAndroid Build Coastguard Worker // A close is implied when a BlobWriter is destroyed. Manually closing a 61*61c4878aSAndroid Build Coastguard Worker // BlobWriter enables error handling on Close() failure. 62*61c4878aSAndroid Build Coastguard Worker writer.Close(); 63*61c4878aSAndroid Build Coastguard Worker 64*61c4878aSAndroid Build Coastguard WorkerResuming a BlobStore write 65*61c4878aSAndroid Build Coastguard Worker-------------------------- 66*61c4878aSAndroid Build Coastguard Worker``BlobWriter::Resume()`` supports resuming writes for blobs that have not been 67*61c4878aSAndroid Build Coastguard Workercompleted (``writer.Close()``). Supported resume situations are after ``Abandon()`` 68*61c4878aSAndroid Build Coastguard Workerhas been called on a write or after a crash/reboot with a fresh ``BlobStore`` 69*61c4878aSAndroid Build Coastguard Workerinstance. 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard Worker``Resume()`` opens the ``BlobWriter`` at the most recent safe resume point. 72*61c4878aSAndroid Build Coastguard Worker``Resume()`` finds the furthest written point in the flash partition and then backs 73*61c4878aSAndroid Build Coastguard Workerup by erasing any partially written sector plus a full sector. This backing up is to 74*61c4878aSAndroid Build Coastguard Workertry to avoid any corrupted or otherwise wrong data that might have resulted from the 75*61c4878aSAndroid Build Coastguard Workerprevious write failing. ``Resume()`` returns the current number of valid bytes in the 76*61c4878aSAndroid Build Coastguard Workerresumed write. 77*61c4878aSAndroid Build Coastguard Worker 78*61c4878aSAndroid Build Coastguard WorkerIf the blob is using a ChecksumAlgorithm, the checksum of the resumed blob write instance 79*61c4878aSAndroid Build Coastguard Workercalculated from the content of the already written data. If it is desired to check the 80*61c4878aSAndroid Build Coastguard Workerintegrity of the already written data, ``BlobWriter::CurrentChecksum()`` can be used to 81*61c4878aSAndroid Build Coastguard Workercheck against the incoming data. 82*61c4878aSAndroid Build Coastguard Worker 83*61c4878aSAndroid Build Coastguard WorkerOnce ``Resume()`` has successfully completed, the writer is ready to continue writing 84*61c4878aSAndroid Build Coastguard Workeras normal. 85*61c4878aSAndroid Build Coastguard Worker 86*61c4878aSAndroid Build Coastguard WorkerErasing a BlobStore 87*61c4878aSAndroid Build Coastguard Worker=================== 88*61c4878aSAndroid Build Coastguard WorkerThere are two distinctly different mechanisms to "erase" the contents of a BlobStore: 89*61c4878aSAndroid Build Coastguard Worker 90*61c4878aSAndroid Build Coastguard Worker#. ``Discard()``: Discards any ongoing writes and ensures ``BlobReader`` objects 91*61c4878aSAndroid Build Coastguard Worker see the ``BlobStore`` as empty. This is the fastest way to logically erase a 92*61c4878aSAndroid Build Coastguard Worker ``BlobStore``. 93*61c4878aSAndroid Build Coastguard Worker#. ``Erase()``: Performs an explicit flash erase of the ``BlobStore``'s 94*61c4878aSAndroid Build Coastguard Worker underlying partition. This is useful for manually controlling when a flash 95*61c4878aSAndroid Build Coastguard Worker erase is performed before a ``BlobWriter`` starts to write data (as flash 96*61c4878aSAndroid Build Coastguard Worker erase operations may be time-consuming). 97*61c4878aSAndroid Build Coastguard Worker 98*61c4878aSAndroid Build Coastguard WorkerNaming a BlobStore's contents 99*61c4878aSAndroid Build Coastguard Worker============================= 100*61c4878aSAndroid Build Coastguard WorkerData in a ``BlobStore`` May be named similarly to a file. This enables 101*61c4878aSAndroid Build Coastguard Workeridentification of a BlobStore's contents in cases where different data may be 102*61c4878aSAndroid Build Coastguard Workerstored to a shared blob store. This requires an additional RAM buffer that can 103*61c4878aSAndroid Build Coastguard Workerbe used to encode the BlobStore's KVS metadata entry. Calling 104*61c4878aSAndroid Build Coastguard Worker``MaxFileNameLength()`` on a ``BlobWriter`` will provide the max file name 105*61c4878aSAndroid Build Coastguard Workerlength based on the ``BlobWriter``'s metadata encode buffer size. 106*61c4878aSAndroid Build Coastguard Worker 107*61c4878aSAndroid Build Coastguard Worker``SetFileName()`` performs a copy of the provided file name, meaning it's safe 108*61c4878aSAndroid Build Coastguard Workerfor the ``std::string_view`` to be invalidated after the function returns. 109*61c4878aSAndroid Build Coastguard Worker 110*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 111*61c4878aSAndroid Build Coastguard Worker 112*61c4878aSAndroid Build Coastguard Worker constexpr size_t kMaxFileNameLength = 48; 113*61c4878aSAndroid Build Coastguard Worker BlobStore::BlobWriterWithBuffer<kMaxFileNameLength> writer(my_blob_store); 114*61c4878aSAndroid Build Coastguard Worker writer.Open(); 115*61c4878aSAndroid Build Coastguard Worker writer.SetFileName("stonks.jpg"); 116*61c4878aSAndroid Build Coastguard Worker writer.Write(my_data); 117*61c4878aSAndroid Build Coastguard Worker // ... 118*61c4878aSAndroid Build Coastguard Worker writer.Close(); 119*61c4878aSAndroid Build Coastguard Worker 120*61c4878aSAndroid Build Coastguard WorkerReading from a BlobStore 121*61c4878aSAndroid Build Coastguard Worker------------------------ 122*61c4878aSAndroid Build Coastguard WorkerA ``BlobStore`` may have multiple open ``BlobReader`` objects. No other 123*61c4878aSAndroid Build Coastguard Workerreaders/writers may be open/active if a ``BlobWriter`` is opened on a blob 124*61c4878aSAndroid Build Coastguard Workerstore. 125*61c4878aSAndroid Build Coastguard Worker 126*61c4878aSAndroid Build Coastguard Worker0) Create BlobReader instance 127*61c4878aSAndroid Build Coastguard Worker1) BlobReader::Open() 128*61c4878aSAndroid Build Coastguard Worker2) Read data using BlobReader::Read() or 129*61c4878aSAndroid Build Coastguard Worker BlobReader::GetMemoryMappedBlob(). BlobReader is seekable. Use 130*61c4878aSAndroid Build Coastguard Worker BlobReader::Seek() to read from a desired offset. 131*61c4878aSAndroid Build Coastguard Worker3) BlobReader::Close() 132*61c4878aSAndroid Build Coastguard Worker 133*61c4878aSAndroid Build Coastguard Worker-------------------------- 134*61c4878aSAndroid Build Coastguard WorkerFileSystem RPC integration 135*61c4878aSAndroid Build Coastguard Worker-------------------------- 136*61c4878aSAndroid Build Coastguard Worker``pw_blob_store`` provides an optional ``FileSystemEntry`` implementation for 137*61c4878aSAndroid Build Coastguard Workeruse with ``pw_file``'s ``FlatFileSystemService``. This simplifies the process of 138*61c4878aSAndroid Build Coastguard Workerenumerating ``BlobStore`` objects as files via ``pw_file``'s ``FileSystem`` RPC 139*61c4878aSAndroid Build Coastguard Workerservice. 140*61c4878aSAndroid Build Coastguard Worker 141*61c4878aSAndroid Build Coastguard Worker----------- 142*61c4878aSAndroid Build Coastguard WorkerSize report 143*61c4878aSAndroid Build Coastguard Worker----------- 144*61c4878aSAndroid Build Coastguard WorkerThe following size report showcases the memory usage of the blob store. 145*61c4878aSAndroid Build Coastguard Worker 146*61c4878aSAndroid Build Coastguard Worker.. include:: blob_size 147*61c4878aSAndroid Build Coastguard Worker 148*61c4878aSAndroid Build Coastguard Worker.. note:: 149*61c4878aSAndroid Build Coastguard Worker The documentation for this module is currently incomplete. 150