|
PebbleOS v4.44.0-150-gc3023ce72
|
Atomic key-value store on top of PFS. More...
Data Structures | |
| struct | pbl_settings_file |
| Open settings file. More... | |
| struct | pbl_settings_watch |
| Watch on the changes to a settings file. More... | |
| struct | pbl_settings_record |
| Record being visited by pbl_settings_each() or pbl_settings_rewrite(). More... | |
Macros | |
| #define | PBL_SETTINGS_KEY_MAX_LEN 127 |
| Maximum key length in bytes. | |
| #define | PBL_SETTINGS_VAL_MAX_LEN 2046 |
| Maximum value length in bytes. | |
Typedefs | |
| typedef void(* | pbl_settings_change_cb_t) (const void *key, size_t key_len, uint32_t last_modified, void *user_data) |
| Callback invoked after a record of a watched file is written. | |
| typedef bool(* | pbl_settings_each_cb_t) (struct pbl_settings_file *file, struct pbl_settings_record *info, void *context) |
| Callback for pbl_settings_each(). | |
| typedef void(* | pbl_settings_rewrite_cb_t) (struct pbl_settings_file *old_file, struct pbl_settings_file *new_file, struct pbl_settings_record *info, void *context) |
| Callback for pbl_settings_rewrite(). | |
| typedef bool(* | pbl_settings_filter_cb_t) (void *key, size_t key_len, void *value, size_t value_len, void *context) |
| Filter callback for pbl_settings_rewrite_filtered(). | |
Functions | |
| int | pbl_settings_open (struct pbl_settings_file *file, const char *name, int max_used_space) |
| Open or create a settings file. | |
| int | pbl_settings_open_growable (struct pbl_settings_file *file, const char *name, int max_used_space, int initial_alloc_size) |
| Open or create a settings file that grows on demand. | |
| void | pbl_settings_close (struct pbl_settings_file *file) |
| Close a settings file. | |
| bool | pbl_settings_exists (struct pbl_settings_file *file, const void *key, size_t key_len) |
| Check whether a key holds a non-empty value. | |
| int | pbl_settings_delete (struct pbl_settings_file *file, const void *key, size_t key_len) |
| Delete a record. | |
| size_t | pbl_settings_get_len (struct pbl_settings_file *file, const void *key, size_t key_len) |
| Get the length of a value. | |
| int | pbl_settings_get (struct pbl_settings_file *file, const void *key, size_t key_len, void *val_out, size_t val_out_len) |
| Read a value. | |
| int | pbl_settings_set (struct pbl_settings_file *file, const void *key, size_t key_len, const void *val, size_t val_len) |
| Write a value, timestamped with the current time. | |
| int | pbl_settings_mark_synced (struct pbl_settings_file *file, const void *key, size_t key_len) |
| Mark a record as synced. | |
| int | pbl_settings_mark_all_dirty (struct pbl_settings_file *file) |
| Mark all records as not synced, to trigger a full sync. | |
| void | pbl_settings_watch_add (struct pbl_settings_watch *watch) |
| Register a watch on the changes to a settings file. | |
| int | pbl_settings_set_byte (struct pbl_settings_file *file, const void *key, size_t key_len, size_t offset, uint8_t byte) |
| Write a single byte of a value in place. | |
| void | pbl_settings_read_key (struct pbl_settings_file *file, void *buf, size_t buf_len) |
| Read the key of the record being visited. | |
| void | pbl_settings_read_val (struct pbl_settings_file *file, void *buf, size_t buf_len) |
| Read the value of the record being visited. | |
| void | pbl_settings_each (struct pbl_settings_file *file, pbl_settings_each_cb_t cb, void *context) |
| Call a callback for every valid record. | |
| int | pbl_settings_rewrite (struct pbl_settings_file *file, pbl_settings_rewrite_cb_t cb, void *context) |
| Rewrite a settings file record by record. | |
| int | pbl_settings_rewrite_filtered (struct pbl_settings_file *file, pbl_settings_filter_cb_t filter_cb, void *context) |
| Rewrite a settings file, keeping only the records a filter accepts. | |
| int | pbl_settings_compact (struct pbl_settings_file *file) |
| Compact a settings file. | |
Atomic key-value store on top of PFS.
A settings file is a log-structured binary key-value store kept in a single PFS file. Keys (up to PBL_SETTINGS_KEY_MAX_LEN bytes) and values (up to PBL_SETTINGS_VAL_MAX_LEN bytes) are arbitrary bytes. Every update is atomic: after a reboot in the middle of a write, the record holds either the old or the new value. Records carry a modification timestamp and a synced flag used for synchronization with the phone.
Settings files are not thread-safe: callers serialize access to a file themselves, and a file must not be open twice at the same time.
| struct pbl_settings_file |
Open settings file.
The fields are internal to the settings file implementation.
| Data Fields | ||
|---|---|---|
| int | alloc_used_space |
Current allocation budget. Grows from the initial size toward max_used_space for growable files, equals max_used_space otherwise. |
| int | cur_record_pos |
Position of the record being visited by pbl_settings_each() or pbl_settings_rewrite(), so that other records can be read from the callback. 0 when not iterating. |
| int | dead_space | Space taken by overwritten records, reclaimed by compaction. |
| struct pbl_settings_raw_iter | iter | Raw iterator over the underlying file. |
| uint32_t | last_modified | Most recent modification time of any record. |
| int | max_space_total | Space the file may take before a compaction is forced, at least max_used_space. |
| int | max_used_space |
Space valid records may use; writes beyond it fail with -ENOSPC. |
| int | min_alloc_used_space | Lower bound of alloc_used_space when compacting. |
| char * | name | File name, heap allocated. |
| int | used_space | Space taken by valid records. |
| struct pbl_settings_watch |
Watch on the changes to a settings file.
| Data Fields | ||
|---|---|---|
| pbl_settings_change_cb_t | cb | Callback. |
| const char * | name | Name of the watched file, as passed to pbl_settings_open(). |
| struct pbl_settings_watch * | next | Next watch, internal. |
| void * | user_data | User data passed to cb. |
| struct pbl_settings_record |
Record being visited by pbl_settings_each() or pbl_settings_rewrite().
| #define PBL_SETTINGS_KEY_MAX_LEN 127 |
Maximum key length in bytes.
| #define PBL_SETTINGS_VAL_MAX_LEN 2046 |
Maximum value length in bytes.
| typedef void(* pbl_settings_change_cb_t) (const void *key, size_t key_len, uint32_t last_modified, void *user_data) |
Callback invoked after a record of a watched file is written.
Runs with the file still open: it must not open the same file again.
| key | Key that was written. |
| key_len | Length of key in bytes. |
| last_modified | Timestamp of the change. |
| user_data | User data of the watch. |
| typedef bool(* pbl_settings_each_cb_t) (struct pbl_settings_file *file, struct pbl_settings_record *info, void *context) |
Callback for pbl_settings_each().
| file | Settings file being iterated. |
| info | Current record. |
| context | Context passed to pbl_settings_each(). |
| typedef bool(* pbl_settings_filter_cb_t) (void *key, size_t key_len, void *value, size_t value_len, void *context) |
Filter callback for pbl_settings_rewrite_filtered().
Must not call any other settings file function.
| key | Record key. |
| key_len | Length of key in bytes. |
| value | Record value. |
| value_len | Length of value in bytes. |
| context | Context passed to pbl_settings_rewrite_filtered(). |
| typedef void(* pbl_settings_rewrite_cb_t) (struct pbl_settings_file *old_file, struct pbl_settings_file *new_file, struct pbl_settings_record *info, void *context) |
Callback for pbl_settings_rewrite().
| old_file | Original file, to read the record from. |
| new_file | New file, to write records that should be kept to. |
| info | Current record of old_file. |
| context | Context passed to pbl_settings_rewrite(). |
| void pbl_settings_close | ( | struct pbl_settings_file * | file | ) |
Close a settings file.
| file | Settings file. |
| int pbl_settings_compact | ( | struct pbl_settings_file * | file | ) |
Compact a settings file.
Rewrites all valid records, dropping dead space. Growable files shrink their allocation toward pbl_settings_file::min_alloc_used_space.
| file | Settings file. |
| 0 | File compacted. |
| int pbl_settings_delete | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len | ||
| ) |
Delete a record.
Writes an empty value, which marks the record as deleted.
| file | Settings file. |
| key | Key. |
| key_len | Length of key in bytes. |
| void pbl_settings_each | ( | struct pbl_settings_file * | file, |
| pbl_settings_each_cb_t | cb, | ||
| void * | context | ||
| ) |
Call a callback for every valid record.
The callback may read other records but must not modify the file; use pbl_settings_rewrite() for that.
| file | Settings file. |
| cb | Callback. |
| context | Context passed to cb. |
| bool pbl_settings_exists | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len | ||
| ) |
Check whether a key holds a non-empty value.
| file | Settings file. |
| key | Key. |
| key_len | Length of key in bytes. |
| int pbl_settings_get | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len, | ||
| void * | val_out, | ||
| size_t | val_out_len | ||
| ) |
Read a value.
Reads the first val_out_len bytes of the value. On failure val_out is zeroed.
| file | Settings file. | |
| key | Key. | |
| key_len | Length of key in bytes. | |
| [out] | val_out | Value buffer. |
| val_out_len | Bytes to read, at most the stored value length. |
| 0 | Value read. |
| -ENOENT | No such record, or it was deleted. |
| -ERANGE | val_out_len exceeds the stored value length. |
| size_t pbl_settings_get_len | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len | ||
| ) |
Get the length of a value.
| file | Settings file. |
| key | Key. |
| key_len | Length of key in bytes. |
| int pbl_settings_mark_all_dirty | ( | struct pbl_settings_file * | file | ) |
Mark all records as not synced, to trigger a full sync.
Rewrites the whole file, preserving timestamps, which can be slow for large files.
| file | Settings file. |
| int pbl_settings_mark_synced | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len | ||
| ) |
Mark a record as synced.
The flag stays until the record is overwritten.
| file | Settings file. |
| key | Key, at most PBL_SETTINGS_KEY_MAX_LEN bytes. |
| key_len | Length of key in bytes. |
| 0 | Record marked. |
| -ERANGE | Key too long. |
| -ENOENT | No such record. |
| int pbl_settings_open | ( | struct pbl_settings_file * | file, |
| const char * | name, | ||
| int | max_used_space | ||
| ) |
Open or create a settings file.
Corrupt files, files with an unknown version and files whose recovery fails are removed and recreated empty. A file created with a smaller size is rewritten to the requested size.
Persist files need max_used_space of at least 5317 bytes to always fit all records in the worst case (all values booleans).
| [out] | file | Settings file to initialize. |
| name | Absolute path of the file, on PFS. | |
| max_used_space | Space valid records may use, in bytes. |
| 0 | File opened. |
| int pbl_settings_open_growable | ( | struct pbl_settings_file * | file, |
| const char * | name, | ||
| int | max_used_space, | ||
| int | initial_alloc_size | ||
| ) |
Open or create a settings file that grows on demand.
Like pbl_settings_open(), but the file starts with room for initial_alloc_size bytes of records and doubles its allocation as needed, up to max_used_space.
| [out] | file | Settings file to initialize. |
| name | Absolute path of the file, on PFS. | |
| max_used_space | Space valid records may use, in bytes. | |
| initial_alloc_size | Initial allocation in bytes, greater than 0. |
| 0 | File opened. |
| void pbl_settings_read_key | ( | struct pbl_settings_file * | file, |
| void * | buf, | ||
| size_t | buf_len | ||
| ) |
Read the key of the record being visited.
Only valid from a pbl_settings_each() or pbl_settings_rewrite() callback.
| file | Settings file being iterated. | |
| [out] | buf | Destination buffer. |
| buf_len | Bytes to read, at most the key length. |
| void pbl_settings_read_val | ( | struct pbl_settings_file * | file, |
| void * | buf, | ||
| size_t | buf_len | ||
| ) |
Read the value of the record being visited.
Only valid from a pbl_settings_each() or pbl_settings_rewrite() callback.
| file | Settings file being iterated. | |
| [out] | buf | Destination buffer. |
| buf_len | Bytes to read, at most the value length. |
| int pbl_settings_rewrite | ( | struct pbl_settings_file * | file, |
| pbl_settings_rewrite_cb_t | cb, | ||
| void * | context | ||
| ) |
Rewrite a settings file record by record.
Opens a new file with the same name in overwrite mode and calls cb for each record of the original one. Only records the callback writes to the new file are kept. The new file replaces the original atomically, and file is reopened on it.
| file | Settings file. |
| cb | Callback. |
| context | Context passed to cb. |
| 0 | File rewritten. |
| -ENOMEM | Allocation failed. |
| int pbl_settings_rewrite_filtered | ( | struct pbl_settings_file * | file, |
| pbl_settings_filter_cb_t | filter_cb, | ||
| void * | context | ||
| ) |
Rewrite a settings file, keeping only the records a filter accepts.
Much faster than pbl_settings_rewrite() when records are only being dropped.
| file | Settings file. |
| filter_cb | Filter, or NULL to keep every valid record. |
| context | Context passed to filter_cb. |
| 0 | File rewritten. |
| -ENOMEM | Allocation failed. |
| int pbl_settings_set | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len, | ||
| const void * | val, | ||
| size_t | val_len | ||
| ) |
Write a value, timestamped with the current time.
Atomic: after a reboot the record holds either the old or the new value. Compacts or grows the file when needed. Must not be called from a pbl_settings_each() callback. Invokes the change callback, if any, on success.
| file | Settings file. |
| key | Key, at most PBL_SETTINGS_KEY_MAX_LEN bytes. |
| key_len | Length of key in bytes. |
| val | Value. |
| val_len | Length of val in bytes, at most PBL_SETTINGS_VAL_MAX_LEN. 0 deletes the record. |
| 0 | Value written. |
| -ERANGE | Key or value too long. |
| -ENOSPC | Not enough space for valid records. |
| int pbl_settings_set_byte | ( | struct pbl_settings_file * | file, |
| const void * | key, | ||
| size_t | key_len, | ||
| size_t | offset, | ||
| uint8_t | byte | ||
| ) |
Write a single byte of a value in place.
Writes flash directly, so it can only clear bits. Only atomic for a single byte: do not use it to modify several bytes in a row.
| file | Settings file. |
| key | Key, at most PBL_SETTINGS_KEY_MAX_LEN bytes. |
| key_len | Length of key in bytes. |
| offset | Offset within the value, less than the value length. |
| byte | Byte to write. |
| 0 | Byte written. |
| -ERANGE | Key too long. |
| -ENOENT | No such record, or it was deleted. |
| void pbl_settings_watch_add | ( | struct pbl_settings_watch * | watch | ) |
Register a watch on the changes to a settings file.
Meant to be called at initialization, before the file is written. The watch must stay valid forever. Several watches may be registered, also on the same file.
| watch | Watch, with pbl_settings_watch::name and pbl_settings_watch::cb set. |