mirror of
https://github.com/google/pebble.git
synced 2025-06-27 11:26:15 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
168
src/fw/services/normal/settings/settings_file.h
Normal file
168
src/fw/services/normal/settings/settings_file.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "settings_raw_iter.h"
|
||||
|
||||
// Deleted records have their key stick around for at least DELETED_LIFETIME
|
||||
// before they can be garbage collected from the file in which they are
|
||||
// contained, that way they have time to propegate to all devices we end up
|
||||
// syncronizing with. For more information, refer to the sync protocol proposal:
|
||||
// https://pebbletechnology.atlassian.net/wiki/pages/viewpage.action?pageId=26837564
|
||||
//
|
||||
// FIXME: See PBL-18945
|
||||
#define DELETED_LIFETIME (0 * SECONDS_PER_DAY)
|
||||
|
||||
//! A SettingsFile is just a simple binary key-value store. Keys can be strings,
|
||||
//! uint32_ts, or arbitrary bytes. Values are similarilly flexible. All
|
||||
//! operations are atomic, so a reboot in the middle of changing the value for a
|
||||
//! key will always either complete, returning the new value upon reboot, or
|
||||
//! will just return the old value.
|
||||
//! It also supports bidirection syncronization between the phone & watch,
|
||||
//! using timestamps to resolve conflicts.
|
||||
//! Note that although all operations are atomic, they are not thread-safe. If
|
||||
//! you will be accessing a SettingsFile from multiple threads, make sure you
|
||||
//! use locks!
|
||||
|
||||
// NOTE: These fields are internal, modify them at your own risk!
|
||||
typedef struct SettingsFile {
|
||||
SettingsRawIter iter;
|
||||
char *name;
|
||||
|
||||
//! Maximum total space which can be used by this settings_file before a
|
||||
//! compaction will be forced. (Must be >= max_used_space)
|
||||
int max_space_total;
|
||||
|
||||
//! Maximum space that can be used by valid records within this settings_file.
|
||||
//! Once this has been exceeded, attempting to add more keys or values will
|
||||
//! fail.
|
||||
int max_used_space;
|
||||
|
||||
//! Amount of space in the settings_file that is currently dead, i.e.
|
||||
//! has been written to with some data, but that data is no longer valid.
|
||||
//! (overwritten records get added to this)
|
||||
int dead_space;
|
||||
|
||||
//! Amount of space in the settings_file that is currently used by valid
|
||||
//! records.
|
||||
int used_space;
|
||||
|
||||
//! When this file as a whole was last_modified.
|
||||
//! Defined as records.max(&:last_modified)
|
||||
uint32_t last_modified;
|
||||
|
||||
//! The position of the current record in the iteration (if any). Necessary
|
||||
//! so that clients can read other records in the middle of iteration (i.e.
|
||||
//! settings_file_each()/settings_file_rewrite()), without messing up the
|
||||
//! state of the iteration. Set to 0 if not in use.
|
||||
int cur_record_pos;
|
||||
} SettingsFile;
|
||||
|
||||
|
||||
//! max_used_space should be >= 5317 for persist files to make sure we can
|
||||
//! always fit all of the records in the worst case (if the programmer stored
|
||||
//! nothing but booleans).
|
||||
//! Note: If the settings file already exists, the max_used_space parameter is
|
||||
//! ignored. We could change this if the need arises.
|
||||
status_t settings_file_open(SettingsFile *file, const char *name,
|
||||
int max_used_space);
|
||||
void settings_file_close(SettingsFile *file);
|
||||
|
||||
bool settings_file_exists(SettingsFile *file, const void *key, size_t key_len);
|
||||
status_t settings_file_delete(SettingsFile *file,
|
||||
const void *key, size_t key_len);
|
||||
|
||||
int settings_file_get_len(SettingsFile *file, const void *key, size_t key_len);
|
||||
//! val_out_len must exactly match the length of the record on disk.
|
||||
status_t settings_file_get(SettingsFile *file, const void *key, size_t key_len,
|
||||
void *val_out, size_t val_out_len);
|
||||
status_t settings_file_set(SettingsFile *file, const void *key, size_t key_len,
|
||||
const void *val, size_t val_len);
|
||||
|
||||
//! Mark a record as synced. The flag will remain until the record is overwritten
|
||||
//! @param file the settings_file that contains the record
|
||||
//! @param key the key to the settings file. Note: keys can be up to 127 bytes
|
||||
//! @param key_len the length of the key
|
||||
status_t settings_file_mark_synced(SettingsFile *file, const void *key, size_t key_len);
|
||||
|
||||
//! set a byte in a setting. This can only be used a byte at a time to guarantee
|
||||
//! atomicity. Do not use to modify several bytes in a row!
|
||||
//! Note that only the reset bits will be applied (it writes flash directly)
|
||||
status_t settings_file_set_byte(
|
||||
SettingsFile *file, const void *key, size_t key_len,
|
||||
size_t offset, uint8_t byte);
|
||||
|
||||
|
||||
|
||||
//////////////////
|
||||
// Each/rewrite //
|
||||
//////////////////
|
||||
typedef void (*SettingsFileGetter)(SettingsFile *file,
|
||||
void *buf, size_t buf_len);
|
||||
|
||||
typedef struct {
|
||||
uint32_t last_modified;
|
||||
SettingsFileGetter get_key;
|
||||
int key_len;
|
||||
SettingsFileGetter get_val;
|
||||
int val_len;
|
||||
bool dirty; // has the dirty flag set
|
||||
} SettingsRecordInfo;
|
||||
|
||||
//! Callback used for using settings_file_each.
|
||||
//! The bool returned is used to control the iteration.
|
||||
//! - If a callback returns true, the iteration continues
|
||||
//! - If a callback returns false, the ieration stops.
|
||||
typedef bool (*SettingsFileEachCallback)(SettingsFile *file,
|
||||
SettingsRecordInfo *info,
|
||||
void *context);
|
||||
//! Calls cb for each and every entry within the given file.
|
||||
//! Note that you cannot modify the settings file while iterating. If you want
|
||||
//! to do this, try settings_file_rewrite instead. (you can read other entries
|
||||
//! without fault).
|
||||
status_t settings_file_each(SettingsFile *file, SettingsFileEachCallback cb,
|
||||
void *context);
|
||||
|
||||
|
||||
typedef void (*SettingsFileRewriteCallback)(SettingsFile *old_file,
|
||||
SettingsFile *new_file,
|
||||
SettingsRecordInfo *info,
|
||||
void *context);
|
||||
//! Opens a new SettingsFile with the same name as the original SettingsFile,
|
||||
//! in overwrite mode. This new file is passed into the given
|
||||
//! SettingsFileRewriteCallback, which is called for each entry within the
|
||||
//! original file. If you desire to preserve a key/value pair, you must write
|
||||
//! it to the new file.
|
||||
status_t settings_file_rewrite(SettingsFile *file,
|
||||
SettingsFileRewriteCallback cb,
|
||||
void *context);
|
||||
|
||||
|
||||
//! Callback used for using settings_file_rewrite_filtered.
|
||||
//! The bool returned is used to control whether or not the record is included in the file
|
||||
//! after compaction. This callback is not allowed to use any other settings_file calls.
|
||||
//! - If callback returns true, the record is included
|
||||
//! - If callback returns false, the record is not included
|
||||
typedef bool (*SettingsFileRewriteFilterCallback)(void *key, size_t key_len, void *value,
|
||||
size_t value_len, void *context);
|
||||
|
||||
//! Opens a new SettingsFile with the same name as the original SettingsFile,
|
||||
//! in overwrite mode. Any records from the old file which pass through the filter_cb with
|
||||
//! a true result are included into the new file. This call is much faster than using
|
||||
//! settings_file_rewrite if all you are doing is excluding specific records from the old file.
|
||||
status_t settings_file_rewrite_filtered(SettingsFile *file,
|
||||
SettingsFileRewriteFilterCallback filter_cb, void *context);
|
Loading…
Add table
Add a link
Reference in a new issue