pebble/src/fw/services/normal/blob_db/api.h
2025-01-27 11:38:16 -08:00

186 lines
7.4 KiB
C

/*
* 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 "api_types.h"
#include <stdint.h>
#include <stdbool.h>
#include "system/status_codes.h"
#include "util/attributes.h"
#include "util/list.h"
#include "util/time/time.h"
//! The BlobDB API is a single consistent API to a number of key/value stores on the watch.
//! It is used in conjunction with the BlobDB endpoint.
//! Key/Value stores that are meant to be used with the endpoint need to implement this API
//! by implementing each of the Impl functions (see below).
//! A BlobDB is not guaranteed to persist across reboots, but it is guaranteed to
//! have executed a command when it returns a success code.
//! If you want to route commands to your BlobDB implementation API, you need
//! to add it to the \ref BlobDBId enum and to the BlobDBs list (\ref s_blob_dbs) in api.c
typedef enum PACKED {
BlobDBIdTest = 0x00,
BlobDBIdPins = 0x01,
BlobDBIdApps = 0x02,
BlobDBIdReminders = 0x03,
BlobDBIdNotifs = 0x04,
BlobDBIdWeather = 0x05,
BlobDBIdiOSNotifPref = 0x06,
BlobDBIdPrefs = 0x07,
BlobDBIdContacts = 0x08,
BlobDBIdWatchAppPrefs = 0x09,
BlobDBIdHealth = 0x0A,
BlobDBIdAppGlance = 0x0B,
NumBlobDBs,
} BlobDBId;
_Static_assert(sizeof(BlobDBId) == 1, "BlobDBId is larger than 1 byte");
//! A linked list of blob DB items that need to be synced
typedef struct {
ListNode node;
time_t last_updated;
int key_len; //!< length of the key, in bytes
uint8_t key[]; //!< key_len-size byte array of key data
} BlobDBDirtyItem;
//! A Blob DB's initialization routine.
//! This function will be called at boot when all blob dbs are init-ed
typedef void (*BlobDBInitImpl)(void);
//! Implements the insert API. Note that this function should be blocking.
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
//! \param val a pointer to the value data
//! \param val_len the length of the value, in bytes
//! \returns S_SUCCESS if the key/val pair was succesfully inserted
//! and an error code otherwise (See \ref StatusCode)
typedef status_t (*BlobDBInsertImpl)
(const uint8_t *key, int key_len, const uint8_t *val, int val_len);
//! Implements the get length API.
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
//! \returns the length in bytes of the value for key on success
//! and an error code otherwise (See \ref StatusCode)
typedef int (*BlobDBGetLenImpl)
(const uint8_t *key, int key_len);
//! Implements the read API. Note that this function should be blocking.
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
//! \param[out] val_out a pointer to a buffer of size val_len
//! \param val_len the length of the value to be copied, in bytes
//! \returns S_SUCCESS if the value for key was succesfully read,
//! and an error code otherwise (See \ref StatusCode)
typedef status_t (*BlobDBReadImpl)
(const uint8_t *key, int key_len, uint8_t *val_out, int val_len);
//! Implements the delete API. Note that this function should be blocking.
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
//! \returns S_SUCCESS if the key/val pair was succesfully deleted
//! and an error code otherwise (See \ref StatusCode)
typedef status_t (*BlobDBDeleteImpl)
(const uint8_t *key, int key_len);
//! Implements the flush API. Note that this function should be blocking.
//! \returns S_SUCCESS if all key/val pairs were succesfully deleted
//! and an error code otherwise (See \ref StatusCode)
typedef status_t (*BlobDBFlushImpl)(void);
//! Implements the IsDirty API.
//! \param[out] is_dirty_out reference to a boolean that will be set depending on the DB state
//! \note if the function does not return S_SUCCESS, the state of the boolean is undefined.
//! \returns S_SUCCESS if the query succeeded, an error code otherwise
typedef status_t (*BlobDBIsDirtyImpl)(bool *is_dirty_out);
//! Implements the GetDirtyList API.
//! \return a linked list of \ref BlobDBDirtyItem with a node per out-of-sync item.
//! \note There is no limit how large this list can get. Handle OOM scenarios gracefully!
typedef BlobDBDirtyItem *(*BlobDBGetDirtyListImpl)(void);
//! Implements the MarkSynced API.
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
//! \returns S_SUCCESS if the item was marked synced, an error code otherwise
typedef status_t (*BlobDBMarkSyncedImpl)(const uint8_t *key, int key_len);
//! Emits a Blob DB event.
//! \param type The type of event to emit
//! \param db_id the ID of the blob DB
//! \param key a pointer to the key data
//! \param key_len the length of the key, in bytes
void blob_db_event_put(BlobDBEventType type, BlobDBId db_id, const uint8_t *key, int key_len);
//! Call the BlobDBInitImpl for all the databases
void blob_db_init_dbs(void);
//! Call the BlobDBIsDirtyImpl for each database, and fill the 'ids' list
//! with all the dirty DB ids
//! \param[out] ids an array of BlobDbIds of size NumBlobDBs or more.
//! \param[out] num_ids an array of BlobDbIds of size NumBlobDBs or more.
//! \note The unused entries will be set to 0.
void blob_db_get_dirty_dbs(uint8_t *ids, uint8_t *num_ids);
//! Insert a key/val pair in a blob DB.
//! See \ref BlobDBReadImpl
//! \param db_id the ID of the blob DB
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
status_t blob_db_insert(BlobDBId db_id,
const uint8_t *key, int key_len, const uint8_t *val, int val_len);
//! Get the length of the value in a blob DB for a given key.
//! See \ref BlobDBGetLenImpl
//! \param db_id the ID of the blob DB
//! \param key a pointer to the key data
//! \param key_len the lenght of the key, in bytes
int blob_db_get_len(BlobDBId db_id,
const uint8_t *key, int key_len);
//! Get the value of length val_len for a given key
//! \param db_id the ID of the blob DB
//! See \ref BlobDBReadImpl
status_t blob_db_read(BlobDBId db_id,
const uint8_t *key, int key_len, uint8_t *val_out, int val_len);
//! Delete the key/val pair in a blob DB for a given key
//! \param db_id the ID of the blob DB
//! See \ref BlobDBDeleteImpl
status_t blob_db_delete(BlobDBId db_id,
const uint8_t *key, int key_len);
//! Delete all key/val pairs in a blob DB.
//! \param db_id the ID of the blob DB
//! See \ref BlobDBFlushImpl
status_t blob_db_flush(BlobDBId db_id);
//! Get the list of items in a given blob DB that have yet to be synced.
//! Items originating from the phone are always marked as synced.
//! \note Use the APIs in sync.h to initiate a sync.
//! \param db_id the ID of the blob DB
//! \see BlobDBGetDirtyListImpl
BlobDBDirtyItem *blob_db_get_dirty_list(BlobDBId db_id);
//! Mark an item in a blob DB as having been synced
//! \note This API is used upon receiving an ACK from the phone during sync
//! \param db_id the ID of the blob DB
//! \see BlobDBMarkSyncedImpl
status_t blob_db_mark_synced(BlobDBId db_id, uint8_t *key, int key_len);