PebbleOS v4.44.0-150-gc3023ce72
Loading...
Searching...
No Matches
Settings files

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.
 

Detailed Description

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 file;
uint32_t key = 1;
uint8_t value = 42;
if (pbl_settings_open(&file, "myprefs", 1024) == 0) {
pbl_settings_set(&file, &key, sizeof(key), &value, sizeof(value));
pbl_settings_get(&file, &key, sizeof(key), &value, sizeof(value));
}
Open settings file.
Definition settings.h:106
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_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.
void pbl_settings_close(struct pbl_settings_file *file)
Close a settings file.
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.

Data Structure Documentation

◆ pbl_settings_file

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.

◆ pbl_settings_watch

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.

◆ pbl_settings_record

struct pbl_settings_record

Record being visited by pbl_settings_each() or pbl_settings_rewrite().

Data Fields
bool dirty Record has not been marked as synced.
size_t key_len Key length in bytes.
uint32_t last_modified Modification timestamp.
size_t val_len Value length in bytes, 0 for a deleted record.

Macro Definition Documentation

◆ PBL_SETTINGS_KEY_MAX_LEN

#define PBL_SETTINGS_KEY_MAX_LEN   127

Maximum key length in bytes.

◆ PBL_SETTINGS_VAL_MAX_LEN

#define PBL_SETTINGS_VAL_MAX_LEN   2046

Maximum value length in bytes.

Typedef Documentation

◆ pbl_settings_change_cb_t

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.

Parameters
keyKey that was written.
key_lenLength of key in bytes.
last_modifiedTimestamp of the change.
user_dataUser data of the watch.

◆ pbl_settings_each_cb_t

typedef bool(* pbl_settings_each_cb_t) (struct pbl_settings_file *file, struct pbl_settings_record *info, void *context)

Callback for pbl_settings_each().

Parameters
fileSettings file being iterated.
infoCurrent record.
contextContext passed to pbl_settings_each().
Returns
true to continue iterating, false to stop.

◆ pbl_settings_filter_cb_t

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.

Parameters
keyRecord key.
key_lenLength of key in bytes.
valueRecord value.
value_lenLength of value in bytes.
contextContext passed to pbl_settings_rewrite_filtered().
Returns
true to keep the record, false to drop it.

◆ pbl_settings_rewrite_cb_t

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().

Parameters
old_fileOriginal file, to read the record from.
new_fileNew file, to write records that should be kept to.
infoCurrent record of old_file.
contextContext passed to pbl_settings_rewrite().

Function Documentation

◆ pbl_settings_close()

void pbl_settings_close ( struct pbl_settings_file *  file)

Close a settings file.

Parameters
fileSettings file.

◆ pbl_settings_compact()

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.

Parameters
fileSettings file.
Return values
0File compacted.
Returns
Negative errno on failure.

◆ pbl_settings_delete()

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.

Parameters
fileSettings file.
keyKey.
key_lenLength of key in bytes.
Returns
Same as pbl_settings_set().

◆ pbl_settings_each()

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.

Parameters
fileSettings file.
cbCallback.
contextContext passed to cb.

◆ pbl_settings_exists()

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.

Parameters
fileSettings file.
keyKey.
key_lenLength of key in bytes.
Returns
true if the record exists and is not deleted.

◆ pbl_settings_get()

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.

Parameters
fileSettings file.
keyKey.
key_lenLength of key in bytes.
[out]val_outValue buffer.
val_out_lenBytes to read, at most the stored value length.
Return values
0Value read.
-ENOENTNo such record, or it was deleted.
-ERANGEval_out_len exceeds the stored value length.

◆ pbl_settings_get_len()

size_t pbl_settings_get_len ( struct pbl_settings_file *  file,
const void *  key,
size_t  key_len 
)

Get the length of a value.

Parameters
fileSettings file.
keyKey.
key_lenLength of key in bytes.
Returns
Value length in bytes, 0 if the record does not exist or is deleted.

◆ pbl_settings_mark_all_dirty()

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.

Parameters
fileSettings file.
Returns
Same as pbl_settings_rewrite().

◆ pbl_settings_mark_synced()

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.

Parameters
fileSettings file.
keyKey, at most PBL_SETTINGS_KEY_MAX_LEN bytes.
key_lenLength of key in bytes.
Return values
0Record marked.
-ERANGEKey too long.
-ENOENTNo such record.

◆ pbl_settings_open()

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).

Parameters
[out]fileSettings file to initialize.
nameAbsolute path of the file, on PFS.
max_used_spaceSpace valid records may use, in bytes.
Return values
0File opened.
Returns
Negative errno from the file system on failure.

◆ pbl_settings_open_growable()

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.

Parameters
[out]fileSettings file to initialize.
nameAbsolute path of the file, on PFS.
max_used_spaceSpace valid records may use, in bytes.
initial_alloc_sizeInitial allocation in bytes, greater than 0.
Return values
0File opened.
Returns
Negative errno from the file system on failure.

◆ pbl_settings_read_key()

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.

Parameters
fileSettings file being iterated.
[out]bufDestination buffer.
buf_lenBytes to read, at most the key length.

◆ pbl_settings_read_val()

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.

Parameters
fileSettings file being iterated.
[out]bufDestination buffer.
buf_lenBytes to read, at most the value length.

◆ pbl_settings_rewrite()

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.

Parameters
fileSettings file.
cbCallback.
contextContext passed to cb.
Return values
0File rewritten.
-ENOMEMAllocation failed.
Returns
Other negative errno values if opening the new file fails.

◆ pbl_settings_rewrite_filtered()

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.

Parameters
fileSettings file.
filter_cbFilter, or NULL to keep every valid record.
contextContext passed to filter_cb.
Return values
0File rewritten.
-ENOMEMAllocation failed.
Returns
Other negative errno values on failure.

◆ pbl_settings_set()

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.

Parameters
fileSettings file.
keyKey, at most PBL_SETTINGS_KEY_MAX_LEN bytes.
key_lenLength of key in bytes.
valValue.
val_lenLength of val in bytes, at most PBL_SETTINGS_VAL_MAX_LEN. 0 deletes the record.
Return values
0Value written.
-ERANGEKey or value too long.
-ENOSPCNot enough space for valid records.
Returns
Other negative errno values if compaction fails.

◆ pbl_settings_set_byte()

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.

Parameters
fileSettings file.
keyKey, at most PBL_SETTINGS_KEY_MAX_LEN bytes.
key_lenLength of key in bytes.
offsetOffset within the value, less than the value length.
byteByte to write.
Return values
0Byte written.
-ERANGEKey too long.
-ENOENTNo such record, or it was deleted.

◆ pbl_settings_watch_add()

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.

Parameters
watchWatch, with pbl_settings_watch::name and pbl_settings_watch::cb set.