X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb2%2Ftdb2.h;h=d9194a5eccce54629595966d277cefa0cb7cf8c5;hp=84228bdcb95eb66292e30cb40e5ba9713cc099a6;hb=dc9da1e34fe6a9d113fd57e116ebbc6d5bd54819;hpb=f1069e4a2d5a8115695fb8ea3e78dbdcf389aead diff --git a/ccan/tdb2/tdb2.h b/ccan/tdb2/tdb2.h index 84228bdc..d9194a5e 100644 --- a/ccan/tdb2/tdb2.h +++ b/ccan/tdb2/tdb2.h @@ -288,6 +288,9 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb); * tdb_transaction_commit): if this succeeds then a transaction will only * fail if the write() or fsync() calls fail. * + * If this fails you must still call tdb_transaction_cancel() to cancel + * the transaction. + * * See Also: * tdb_transaction_commit() */ @@ -311,7 +314,7 @@ enum TDB_ERROR tdb_transaction_prepare_commit(struct tdb_context *tdb); * a negative enum TDB_ERROR value. */ #define tdb_traverse(tdb, fn, p) \ - tdb_traverse_(tdb, typesafe_cb_preargs(int, (fn), (p), \ + tdb_traverse_(tdb, typesafe_cb_preargs(int, void *, (fn), (p), \ struct tdb_context *, \ TDB_DATA, TDB_DATA), (p)) @@ -324,7 +327,7 @@ int64_t tdb_traverse_(struct tdb_context *tdb, * @tdb: the tdb context returned from tdb_open() * @key: the key whose record we should hand to @parse * @parse: the function to call for the data - * @p: the private pointer to hand to @parse (types must match). + * @data: the private pointer to hand to @parse (types must match). * * This avoids a copy for many cases, by handing you a pointer into * the memory-mapped database. It also locks the record to prevent @@ -332,17 +335,18 @@ int64_t tdb_traverse_(struct tdb_context *tdb, * * Do not alter the data handed to parse()! */ -#define tdb_parse_record(tdb, key, parse, p) \ +#define tdb_parse_record(tdb, key, parse, data) \ tdb_parse_record_((tdb), (key), \ - typesafe_cb_preargs(enum TDB_ERROR, (parse), (p), \ - TDB_DATA, TDB_DATA), (p)) + typesafe_cb_preargs(enum TDB_ERROR, void *, \ + (parse), (data), \ + TDB_DATA, TDB_DATA), (data)) enum TDB_ERROR tdb_parse_record_(struct tdb_context *tdb, TDB_DATA key, - enum TDB_ERROR (*parse)(TDB_DATA key, - TDB_DATA data, - void *p), - void *p); + enum TDB_ERROR (*parse)(TDB_DATA k, + TDB_DATA d, + void *data), + void *data); /** * tdb_get_seqnum - get a database sequence number @@ -394,7 +398,7 @@ enum TDB_ERROR tdb_nextkey(struct tdb_context *tdb, struct tdb_data *key); * @tdb: the tdb context returned from tdb_open() * @key: the key to lock. * - * This prevents any changes from occurring to a group of keys including @key, + * This prevents any access occurring to a group of keys including @key, * even if @key does not exist. This allows primitive atomic updates of * records without using transactions. * @@ -416,6 +420,33 @@ enum TDB_ERROR tdb_chainlock(struct tdb_context *tdb, TDB_DATA key); */ void tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); +/** + * tdb_chainlock_read - lock a record in the TDB, for reading + * @tdb: the tdb context returned from tdb_open() + * @key: the key to lock. + * + * This prevents any changes from occurring to a group of keys including @key, + * even if @key does not exist. This allows primitive atomic updates of + * records without using transactions. + * + * You cannot begin a transaction while holding a tdb_chainlock_read(), nor can + * you do any operations on any other keys in the database. This also means + * that you cannot hold more than one tdb_chainlock()/read() at a time. + * + * See Also: + * tdb_chainlock() + */ +enum TDB_ERROR tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); + +/** + * tdb_chainunlock_read - unlock a record in the TDB for reading + * @tdb: the tdb context returned from tdb_open() + * @key: the key to unlock. + * + * The key must have previously been locked by tdb_chainlock_read(). + */ +void tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); + /** * tdb_lockall - lock the entire TDB * @tdb: the tdb context returned from tdb_open() @@ -462,7 +493,7 @@ enum TDB_ERROR tdb_wipe_all(struct tdb_context *tdb); * tdb_check - check a TDB for consistency * @tdb: the tdb context returned from tdb_open() * @check: function to check each key/data pair (or NULL) - * @private_data: argument for @check, must match type. + * @data: argument for @check, must match type. * * This performs a consistency check of the open database, optionally calling * a check() function on each record so you can do your own data consistency @@ -471,18 +502,18 @@ enum TDB_ERROR tdb_wipe_all(struct tdb_context *tdb); * * Returns TDB_SUCCESS or an error. */ -#define tdb_check(tdb, check, private_data) \ - tdb_check_((tdb), typesafe_cb_preargs(enum TDB_ERROR, \ - (check), (private_data), \ +#define tdb_check(tdb, check, data) \ + tdb_check_((tdb), typesafe_cb_preargs(enum TDB_ERROR, void *, \ + (check), (data), \ struct tdb_data, \ struct tdb_data), \ - (private_data)) + (data)) enum TDB_ERROR tdb_check_(struct tdb_context *tdb, - enum TDB_ERROR (*check)(struct tdb_data key, - struct tdb_data data, - void *private_data), - void *private_data); + enum TDB_ERROR (*check)(struct tdb_data k, + struct tdb_data d, + void *data), + void *data); /** * tdb_error - get the last error (not threadsafe) @@ -551,6 +582,61 @@ void tdb_add_flag(struct tdb_context *tdb, unsigned flag); */ void tdb_remove_flag(struct tdb_context *tdb, unsigned flag); +/** + * enum tdb_attribute_type - descriminator for union tdb_attribute. + */ +enum tdb_attribute_type { + TDB_ATTRIBUTE_LOG = 0, + TDB_ATTRIBUTE_HASH = 1, + TDB_ATTRIBUTE_SEED = 2, + TDB_ATTRIBUTE_STATS = 3, + TDB_ATTRIBUTE_OPENHOOK = 4, + TDB_ATTRIBUTE_FLOCK = 5 +}; + +/** + * tdb_get_attribute - get an attribute for an existing tdb + * @tdb: the tdb context returned from tdb_open() + * @attr: the union tdb_attribute to set. + * + * This gets an attribute from a TDB which has previously been set (or + * may return the default values). Set @attr.base.attr to the + * attribute type you want get. + * + * Currently this does not work for TDB_ATTRIBUTE_OPENHOOK. + */ +enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb, + union tdb_attribute *attr); + +/** + * tdb_set_attribute - set an attribute for an existing tdb + * @tdb: the tdb context returned from tdb_open() + * @attr: the union tdb_attribute to set. + * + * This sets an attribute on a TDB, overriding any previous attribute + * of the same type. It returns TDB_ERR_EINVAL if the attribute is + * unknown or invalid. + * + * Note that TDB_ATTRIBUTE_HASH, TDB_ATTRIBUTE_SEED and + * TDB_ATTRIBUTE_OPENHOOK cannot currently be set after tdb_open. + */ +enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb, + const union tdb_attribute *attr); + +/** + * tdb_unset_attribute - reset an attribute for an existing tdb + * @tdb: the tdb context returned from tdb_open() + * @type: the attribute type to unset. + * + * This unsets an attribute on a TDB, returning it to the defaults + * (where applicable). + * + * Note that it only makes sense for TDB_ATTRIBUTE_LOG and TDB_ATTRIBUTE_FLOCK + * to be unset. + */ +void tdb_unset_attribute(struct tdb_context *tdb, + enum tdb_attribute_type type); + /** * tdb_name - get the name of a tdb * @tdb: the tdb context returned from tdb_open() @@ -571,16 +657,6 @@ const char *tdb_name(const struct tdb_context *tdb); */ int tdb_fd(const struct tdb_context *tdb); -/** - * enum tdb_attribute_type - descriminator for union tdb_attribute. - */ -enum tdb_attribute_type { - TDB_ATTRIBUTE_LOG = 0, - TDB_ATTRIBUTE_HASH = 1, - TDB_ATTRIBUTE_SEED = 2, - TDB_ATTRIBUTE_STATS = 3 -}; - /** * struct tdb_attribute_base - common fields for all tdb attributes. */ @@ -612,11 +688,11 @@ enum tdb_log_level { */ struct tdb_attribute_log { struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_LOG */ - void (*log_fn)(struct tdb_context *tdb, - enum tdb_log_level level, - void *log_private, - const char *message); - void *log_private; + void (*fn)(struct tdb_context *tdb, + enum tdb_log_level level, + const char *message, + void *data); + void *data; }; /** @@ -633,9 +709,9 @@ struct tdb_attribute_log { */ struct tdb_attribute_hash { struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_HASH */ - uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, - void *priv); - void *hash_private; + uint64_t (*fn)(const void *key, size_t len, uint64_t seed, + void *data); + void *data; }; /** @@ -653,13 +729,13 @@ struct tdb_attribute_seed { * struct tdb_attribute_stats - tdb operational statistics * * This attribute records statistics of various low-level TDB operations. - * This can be used to assist performance evaluation. + * This can be used to assist performance evaluation. This is only + * useful for tdb_get_attribute(). * * New fields will be added at the end, hence the "size" argument which - * indicates how large your structure is. If your size is larger than - * that known about by this version of tdb, the size will be reduced to - * the known structure size. Thus you can detect older versions, and - * thus know that newer stats will not be updated. + * indicates how large your structure is: it must be filled in before + * calling tdb_get_attribute(), which will overwrite it with the size + * tdb knows about. */ struct tdb_attribute_stats { struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_STATS */ @@ -688,6 +764,41 @@ struct tdb_attribute_stats { uint64_t lock_nonblock; }; +/** + * struct tdb_attribute_openhook - tdb special effects hook for open + * + * This attribute contains a function to call once we have the OPEN_LOCK + * for the tdb, but before we've examined its contents. If this succeeds, + * the tdb will be populated if it's then zero-length. + * + * This is a hack to allow support for TDB1-style TDB_CLEAR_IF_FIRST + * behaviour. + */ +struct tdb_attribute_openhook { + struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_OPENHOOK */ + enum TDB_ERROR (*fn)(int fd, void *data); + void *data; +}; + +/** + * struct tdb_attribute_flock - tdb special effects hook for file locking + * + * This attribute contains function to call to place locks on a file; it can + * be used to support non-blocking operations or lock proxying. + * + * They should return 0 on success, -1 on failure and set errno. + * + * An error will be logged on error if errno is neither EAGAIN nor EINTR + * (normally it would only return EAGAIN if waitflag is false, and + * loop internally on EINTR). + */ +struct tdb_attribute_flock { + struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_FLOCK */ + int (*lock)(int fd,int rw, off_t off, off_t len, bool waitflag, void *); + int (*unlock)(int fd, int rw, off_t off, off_t len, void *); + void *data; +}; + /** * union tdb_attribute - tdb attributes. * @@ -695,7 +806,8 @@ struct tdb_attribute_stats { * * See also: * struct tdb_attribute_log, struct tdb_attribute_hash, - * struct tdb_attribute_seed, struct tdb_attribute_stats. + * struct tdb_attribute_seed, struct tdb_attribute_stats, + * struct tdb_attribute_openhook, struct tdb_attribute_flock. */ union tdb_attribute { struct tdb_attribute_base base; @@ -703,6 +815,8 @@ union tdb_attribute { struct tdb_attribute_hash hash; struct tdb_attribute_seed seed; struct tdb_attribute_stats stats; + struct tdb_attribute_openhook openhook; + struct tdb_attribute_flock flock; }; #ifdef __cplusplus