mail-index.h revision df4018ae2f0a95be602f724ca70df7e0e3bd6a7d
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen/* Number of keywords in mail_index_record. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#define INDEX_KEYWORDS_BYTE_COUNT ((INDEX_KEYWORDS_COUNT+CHAR_BIT-1) / CHAR_BIT)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Create index if it doesn't exist */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Open the index as fast as possible - do only minimal checks and
d0720f3037064af4b92eccfc20a8814adcacf827Timo Sirainen delay opening cache/log files unless they're needed. */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* Don't try to mmap() index files */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen /* Don't try to write() to mmap()ed index files. Required for the few
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen OSes that don't have unified buffer cache
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen (currently OpenBSD <= 3.5) */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* Index file is corrupted, reopen or recreate it. */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* No errors */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* Internal error, see get_error_text() for more information. */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* We ran out of available disk space. */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen (MAIL_ANSWERED | MAIL_FLAGGED | MAIL_DELETED | MAIL_SEEN | MAIL_DRAFT)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainentypedef unsigned char keywords_mask_t[INDEX_KEYWORDS_BYTE_COUNT];
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* major version is increased only when you can't have backwards
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen compatibility. minor version is increased when header size is
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen increased to contain new non-critical fields. */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen uint32_t header_size; /* base + extended header size */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen 1 = sizeof(uoff_t)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen 2 = sizeof(time_t)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen 3 = unused */
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen /* these UIDs may not exist and may not even be unseen */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* We have internal and external sync offsets. External changes are
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen synced into index somewhat more often, so int_offset <= ext_offset */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* daily first UIDs that have been added to index. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint8_t flags; /* mail_flags | mail_index_mail_flags */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* MAIL_INDEX_SYNC_TYPE_FLAGS: */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_free(struct mail_index *index);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainenvoid mail_index_close(struct mail_index *index);
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* View can be used to look into index. Sequence numbers inside view change
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen only when you synchronize it. The view acquires required locks
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen automatically, but you'll have to drop them manually. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct mail_index_view *mail_index_view_open(struct mail_index *index);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Open view to latest index locked. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_view_open_locked(struct mail_index *index,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_view_close(struct mail_index_view *view);
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen/* Returns the index for given view. */
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainenstruct mail_index *mail_index_view_get_index(struct mail_index_view *view);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Call whenever you've done with requesting messages from view for a while. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_view_unlock(struct mail_index_view *view);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen/* Returns number of mails in view. */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenuint32_t mail_index_view_get_messages_count(struct mail_index_view *view);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen/* Returns TRUE if we lost track of changes for some reason. */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenint mail_index_view_is_inconsistent(struct mail_index_view *view);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen/* Transaction has to be opened to be able to modify index. You can have
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen multiple transactions open simultaneously. Note that committed transactions
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen won't show up until you've synchronized mailbox (mail_index_sync_begin). */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenmail_index_transaction_begin(struct mail_index_view *view,
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenint mail_index_transaction_commit(struct mail_index_transaction *t,
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenvoid mail_index_transaction_rollback(struct mail_index_transaction *t);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen/* Returns a view to transaction. Currently this differs from normal view only
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen in that it contains newly appended messages in transaction. The view can
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen still be used after transaction has been committed. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_index_transaction_open_updated_view(struct mail_index_transaction *t);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Begin synchronizing mailbox with index file. This call locks the index
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen exclusively against other modifications. Returns 1 if ok, -1 if error.
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen If log_file_seq is not (uint32_t)-1 and index is already synchronized up
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen to given log_file_offset, the synchronization isn't started and this
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen function returns 0. This should be done when you wish to sync your previous
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen transaction instead of doing a full mailbox synchronization.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_sync_next() returns all changes from previously committed
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen transactions which haven't yet been committed to the actual mailbox.
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen They're returned in ascending order and they never overlap (if we add more
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sync types, then they might). You must go through all of them and update
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen the mailbox accordingly.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen None of the changes actually show up in index until after successful
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_sync_commit().
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen Returned sequence numbers describe the mailbox state at the beginning of
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen synchronization, ie. expunges don't affect them.
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen You may create a new transaction for the returned view. That transaction
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen acts as "external mailbox changes" transaction. Any changes done there are
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen expected to describe mailbox's current state. */
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainenint mail_index_sync_begin(struct mail_index *index,
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen uint32_t log_file_seq, uoff_t log_file_offset,
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen/* Returns -1 if error, 0 if sync is finished, 1 if record was filled. */
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainenint mail_index_sync_next(struct mail_index_sync_ctx *ctx,
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen/* Returns 1 if there's more to sync, 0 if not. */
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainenint mail_index_sync_have_more(struct mail_index_sync_ctx *ctx);
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen/* Commit synchronization by writing all changes to mail index file. */
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainenint mail_index_sync_commit(struct mail_index_sync_ctx *ctx);
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen/* Rollback synchronization - none of the changes listed by sync_next() are
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen actually written to index file. */
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainenvoid mail_index_sync_rollback(struct mail_index_sync_ctx *ctx);
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen/* Mark index file corrupted. Invalidates all views. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Check and fix any found problems. If index is broken beyond repair, it's
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen marked corrupted and 0 is returned. Otherwise returns -1 if there was some
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen I/O error or 1 if everything went ok. */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen/* Synchronize changes in view. You have to go through all records, or view
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen will be marked inconsistent. Only sync_mask type records are
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen synchronized. */
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainenint mail_index_view_sync_begin(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Returns -1 if error, 0 if sync is finished, 1 if record was filled. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_view_sync_next(struct mail_index_view_sync_ctx *ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_index_view_sync_get_expunges(struct mail_index_view_sync_ctx *ctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_view_sync_end(struct mail_index_view_sync_ctx *ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Returns the index header. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_index_get_header(struct mail_index_view *view);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Returns the given message. Returns -1 if error, 1 if ok, 0 if mail was
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen expunged but data was returned from some older index. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Returns the UID for given message. May be slightly faster than
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_lookup()->uid. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Convert UID range to sequence range. If no UIDs are found, sequences are
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen set to 0. Note that any of the returned sequences may have been expunged
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_uid_range(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Find first mail with (mail->flags & flags_mask) == flags. Useful mostly for
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen taking advantage of lowwater-fields in headers. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_first(struct mail_index_view *view, enum mail_flags flags,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Append a new record to index. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_append(struct mail_index_transaction *t, uint32_t uid,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen/* Assigns UIDs for appended mails all at once. UID must have been given as 0
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for mail_index_append(). Returns the next unused UID. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_append_assign_uids(struct mail_index_transaction *t,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Expunge record from index. Note that this doesn't affect sequence numbers
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen until transaction is committed and mailbox is synced. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_expunge(struct mail_index_transaction *t, uint32_t seq);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Update flags in index. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_update_flags(struct mail_index_transaction *t, uint32_t seq,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_flags flags, keywords_mask_t keywords);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Update field in header. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_update_header(struct mail_index_transaction *t,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen size_t offset, const void *data, size_t size);
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen/* Returns the last error code. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenenum mail_index_error mail_index_get_last_error(struct mail_index *index);
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen/* Returns the full error message for last error. This message may
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen contain paths etc. so it shouldn't be shown to users. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenconst char *mail_index_get_error_message(struct mail_index *index);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen/* Reset the error message. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_reset_error(struct mail_index *index);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Apply changes in MAIL_INDEX_SYNC_TYPE_FLAGS typed sync records to given
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen flags variables. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* register index extension. name is a unique identifier for the extension.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen returns unique identifier for the name. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Get current extension sizes. Returns 1 if ok, 0 if extension doesn't exist
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainenint mail_index_ext_get_size(struct mail_index_view *view, uint32_t ext_id,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen uint32_t *hdr_size_r, uint16_t *record_size_r,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen/* Resize existing extension data. If size is grown, the new data will be
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen zero-filled. If size is shrinked, the data is simply dropped. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Reset extension records and header. Any updates for this extension which
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen were issued before the writer had seen this reset are discarded. reset_id is
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen used to figure this out, so it must be different every time. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Returns extension header. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_map_get_header_ext(struct mail_index_view *view,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Returns the wanted extension record for given message. If it doesn't exist,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *data_r is set to NULL. Return values are same as for mail_index_lookup(). */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenint mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen uint32_t ext_id, struct mail_index_map **map_r,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const void **data_r);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen/* Update extension header field. */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid mail_index_update_header_ext(struct mail_index_transaction *t,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen/* Update extension record. If old_data_r is non-NULL and the record extension
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen was already updated in this transaction, it's set to contain the data it's
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen now overwriting. */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid mail_index_update_ext(struct mail_index_transaction *t, uint32_t seq,
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen uint32_t ext_id, const void *data, void *old_data);