/* * __block_buffer_to_addr -- * Convert a filesystem address cookie into its components, UPDATING the * caller's buffer reference so it can be called repeatedly to load a buffer. */ static int __block_buffer_to_addr(uint32_t allocsize, const uint8_t **pp, wt_off_t *offsetp, uint32_t *sizep, uint32_t *checksump) { uint64_t o, s, c; WT_RET(__wt_vunpack_uint(pp, 0, &o)); WT_RET(__wt_vunpack_uint(pp, 0, &s)); WT_RET(__wt_vunpack_uint(pp, 0, &c)); /* * To avoid storing large offsets, we minimize the value by subtracting * a block for description information, then storing a count of block * allocation units. That implies there is no such thing as an * "invalid" offset though, they could all be valid (other than very * large numbers), which is what we didn't want to store in the first * place. Use the size: writing a block of size 0 makes no sense, so * that's the out-of-band value. Once we're out of this function and * are working with a real file offset, size and checksum triplet, there * can be invalid offsets, that's simpler than testing sizes of 0 all * over the place. */ if (s == 0) { *offsetp = 0; *sizep = *checksump = 0; } else { *offsetp = (wt_off_t)(o + 1) * allocsize; *sizep = (uint32_t)s * allocsize; *checksump = (uint32_t)c; } return (0); }
/* * __block_buffer_to_ckpt -- * Convert a checkpoint cookie into its components. */ static int __block_buffer_to_ckpt(WT_SESSION_IMPL *session, uint32_t allocsize, const uint8_t *p, WT_BLOCK_CKPT *ci) { uint64_t a; const uint8_t **pp; ci->version = *p++; if (ci->version != WT_BM_CHECKPOINT_VERSION) WT_RET_MSG(session, WT_ERROR, "unsupported checkpoint version"); pp = &p; WT_RET(__block_buffer_to_addr(allocsize, pp, &ci->root_offset, &ci->root_size, &ci->root_checksum)); WT_RET(__block_buffer_to_addr(allocsize, pp, &ci->alloc.offset, &ci->alloc.size, &ci->alloc.checksum)); WT_RET(__block_buffer_to_addr(allocsize, pp, &ci->avail.offset, &ci->avail.size, &ci->avail.checksum)); WT_RET(__block_buffer_to_addr(allocsize, pp, &ci->discard.offset, &ci->discard.size, &ci->discard.checksum)); WT_RET(__wt_vunpack_uint(pp, 0, &a)); ci->file_size = (wt_off_t)a; WT_RET(__wt_vunpack_uint(pp, 0, &a)); ci->ckpt_size = a; return (0); }
/* * __txn_log_recover -- * Roll the log forward to recover committed changes. */ static int __txn_log_recover(WT_SESSION_IMPL *session, WT_ITEM *logrec, WT_LSN *lsnp, WT_LSN *next_lsnp, void *cookie, int firstrecord) { WT_RECOVERY *r; const uint8_t *end, *p; uint64_t txnid; uint32_t rectype; WT_UNUSED(next_lsnp); r = cookie; p = WT_LOG_SKIP_HEADER(logrec->data); end = (const uint8_t *)logrec->data + logrec->size; WT_UNUSED(firstrecord); /* First, peek at the log record type. */ WT_RET(__wt_logrec_read(session, &p, end, &rectype)); switch (rectype) { case WT_LOGREC_CHECKPOINT: if (r->metadata_only) WT_RET(__wt_txn_checkpoint_logread( session, &p, end, &r->ckpt_lsn)); break; case WT_LOGREC_COMMIT: WT_RET(__wt_vunpack_uint(&p, WT_PTRDIFF(end, p), &txnid)); WT_UNUSED(txnid); WT_RET(__txn_commit_apply(r, lsnp, &p, end)); break; } return (0); }
void test_value(int64_t val) { const uint8_t *cp; uint8_t buf[10], *p; int64_t sinput, soutput; uint64_t uinput, uoutput; size_t used_len; sinput = val; p = buf; assert(__wt_vpack_int(&p, sizeof(buf), sinput) == 0); used_len = (size_t)(p - buf); cp = buf; assert(__wt_vunpack_int(&cp, used_len, &soutput) == 0); /* Ensure we got the correct value back */ if (sinput != soutput) { fprintf(stderr, "mismatch %" PRIu64 ", %" PRIu64 "\n", sinput, soutput); abort(); } /* Ensure that decoding used the correct amount of buffer */ if (cp != p) { fprintf(stderr, "Unpack consumed wrong size for %" PRId64 ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n", sinput, used_len, cp > p ? used_len + (size_t)(cp - p) : /* More than buf used */ used_len - (size_t)(p - cp)); /* Less than buf used */ abort(); } /* Test unsigned, convert negative into bigger positive values */ uinput = (uint64_t)val; p = buf; assert(__wt_vpack_uint(&p, sizeof(buf), uinput) == 0); cp = buf; assert(__wt_vunpack_uint( &cp, sizeof(buf), &uoutput) == 0); /* Ensure we got the correct value back */ if (sinput != soutput) { fprintf(stderr, "mismatch %" PRIu64 ", %" PRIu64 "\n", sinput, soutput); abort(); } /* Ensure that decoding used the correct amount of buffer */ if (cp != p) { fprintf(stderr, "Unpack consumed wrong size for %" PRId64 ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n", sinput, used_len, cp > p ? used_len + (size_t)(cp - p) : used_len - (size_t)(p - cp)); abort(); } }
int __wt_logrec_read(WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, uint32_t *rectypep) { uint64_t rectype; WT_UNUSED(session); WT_RET(__wt_vunpack_uint(pp, WT_PTRDIFF(end, *pp), &rectype)); *rectypep = (uint32_t)rectype; return (0); }
/* * __curjoin_split_key -- * Copy the primary key from a cursor (either main table or index) * to another cursor. When copying from an index file, the index * key is also returned. * */ static int __curjoin_split_key(WT_SESSION_IMPL *session, WT_CURSOR_JOIN *cjoin, WT_ITEM *idxkey, WT_CURSOR *tocur, WT_CURSOR *fromcur, const char *repack_fmt, bool isindex) { WT_CURSOR *firstcg_cur; WT_CURSOR_INDEX *cindex; WT_ITEM *keyp; const uint8_t *p; if (isindex) { cindex = ((WT_CURSOR_INDEX *)fromcur); /* * Repack tells us where the index key ends; advance past * that to get where the raw primary key starts. */ WT_RET(__wt_struct_repack(session, cindex->child->key_format, repack_fmt != NULL ? repack_fmt : cindex->iface.key_format, &cindex->child->key, idxkey)); WT_ASSERT(session, cindex->child->key.size > idxkey->size); tocur->key.data = (uint8_t *)idxkey->data + idxkey->size; tocur->key.size = cindex->child->key.size - idxkey->size; if (WT_CURSOR_RECNO(tocur)) { p = (const uint8_t *)tocur->key.data; WT_RET(__wt_vunpack_uint(&p, tocur->key.size, &tocur->recno)); } else tocur->recno = 0; } else { firstcg_cur = ((WT_CURSOR_TABLE *)fromcur)->cg_cursors[0]; keyp = &firstcg_cur->key; if (WT_CURSOR_RECNO(tocur)) { WT_ASSERT(session, keyp->size == sizeof(uint64_t)); tocur->recno = *(uint64_t *)keyp->data; WT_RET(__curjoin_pack_recno(session, tocur->recno, cjoin->recno_buf, sizeof(cjoin->recno_buf), &tocur->key)); } else { WT_ITEM_SET(tocur->key, *keyp); tocur->recno = 0; } idxkey->data = NULL; idxkey->size = 0; } return (0); }
/* * __txn_log_recover -- * Roll the log forward to recover committed changes. */ static int __txn_log_recover(WT_SESSION_IMPL *session, WT_ITEM *logrec, WT_LSN *lsnp, WT_LSN *next_lsnp, void *cookie, int firstrecord) { WT_DECL_RET; WT_RECOVERY *r; uint64_t txnid_unused; uint32_t rectype; const uint8_t *end, *p; r = cookie; p = WT_LOG_SKIP_HEADER(logrec->data); end = (const uint8_t *)logrec->data + logrec->size; WT_UNUSED(firstrecord); /* First, peek at the log record type. */ WT_RET(__wt_logrec_read(session, &p, end, &rectype)); /* * Record the highest LSN we process during the metadata phase. * If not the metadata phase, then stop at that LSN. */ if (r->metadata_only) r->max_rec_lsn = *next_lsnp; else if (__wt_log_cmp(lsnp, &r->max_rec_lsn) >= 0) return (0); switch (rectype) { case WT_LOGREC_CHECKPOINT: if (r->metadata_only) WT_RET(__wt_txn_checkpoint_logread( session, &p, end, &r->ckpt_lsn)); break; case WT_LOGREC_COMMIT: if ((ret = __wt_vunpack_uint( &p, WT_PTRDIFF(end, p), &txnid_unused)) != 0) WT_RET_MSG( session, ret, "txn_log_recover: unpack failure"); WT_RET(__txn_commit_apply(r, lsnp, &p, end)); break; } return (0); }
/* * __curlog_logrec -- * Callback function from log_scan to get a log record. */ static int __curlog_logrec(WT_SESSION_IMPL *session, WT_ITEM *logrec, WT_LSN *lsnp, WT_LSN *next_lsnp, void *cookie, int firstrecord) { WT_CURSOR_LOG *cl; cl = cookie; WT_UNUSED(firstrecord); /* Set up the LSNs and take a copy of the log record for the cursor. */ *cl->cur_lsn = *lsnp; *cl->next_lsn = *next_lsnp; WT_RET(__wt_buf_set(session, cl->logrec, logrec->data, logrec->size)); /* * Read the log header. Set up the step pointers to walk the * operations inside the record. Get the record type. */ cl->stepp = WT_LOG_SKIP_HEADER(cl->logrec->data); cl->stepp_end = (uint8_t *)cl->logrec->data + logrec->size; WT_RET(__wt_logrec_read(session, &cl->stepp, cl->stepp_end, &cl->rectype)); /* A step count of 0 means the entire record. */ cl->step_count = 0; /* * Unpack the txnid so that we can return each * individual operation for this txnid. */ if (cl->rectype == WT_LOGREC_COMMIT) WT_RET(__wt_vunpack_uint(&cl->stepp, WT_PTRDIFF(cl->stepp_end, cl->stepp), &cl->txnid)); else { /* * Step over anything else. * Setting stepp to NULL causes the next() * method to read a new record on the next call. */ cl->stepp = NULL; cl->txnid = 0; } return (0); }
int main(void) { const uint8_t *cp; uint8_t buf[10], *p; uint64_t ncalls, r, r2, s; int i; ncalls = 0; for (i = 0; i < 10000000; i++) { for (s = 0; s < 50; s += 5) { ++ncalls; r = 1ULL << s; #if 1 p = buf; assert(__wt_vpack_uint(&p, sizeof(buf), r) == 0); cp = buf; assert(__wt_vunpack_uint(&cp, sizeof(buf), &r2) == 0); #else /* * Note: use memmove for comparison because GCC does * aggressive optimization of memcpy and it's difficult * to measure anything. */ p = buf; memmove(p, &r, sizeof(r)); cp = buf; memmove(&r2, cp, sizeof(r2)); #endif if (r != r2) { fprintf(stderr, "mismatch!\n"); break; } } } printf("Number of calls: %llu\n", (unsigned long long)ncalls); return (0); }
int main() { uint8_t buf[10], *p; uint64_t r, r2, ncalls; int i, s; ncalls = 0; for (i = 0; i < 10000000; i++) { for (s = 0; s < 50; s += 5) { ++ncalls; r = 1 << s; #if 1 p = buf; __wt_vpack_uint(NULL, &p, sizeof buf, r); p = buf; __wt_vunpack_uint(NULL, &p, sizeof buf, &r2); #else /* * Note: use memmove for comparison because GCC does * aggressive optimization of memcpy and it's difficult * to measure anything. */ p = buf; memmove(p, &r, sizeof r); p = buf; memmove(&r2, p, sizeof r2); #endif if (r != r2) { fprintf(stderr, "mismatch!\n"); break; } } } printf("Number of calls: %llu\n", (unsigned long long)ncalls); return (0); }
/* * __las_page_instantiate -- * Instantiate lookaside update records in a recently read page. */ static int __las_page_instantiate(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t read_id, const uint8_t *addr, size_t addr_size) { WT_CURSOR *cursor; WT_CURSOR_BTREE cbt; WT_DECL_ITEM(current_key); WT_DECL_ITEM(las_addr); WT_DECL_ITEM(las_key); WT_DECL_ITEM(las_value); WT_DECL_RET; WT_PAGE *page; WT_UPDATE *first_upd, *last_upd, *upd; size_t incr, total_incr; uint64_t current_recno, las_counter, las_txnid, recno, upd_txnid; uint32_t las_id, upd_size, session_flags; int exact; const uint8_t *p; cursor = NULL; page = ref->page; first_upd = last_upd = upd = NULL; total_incr = 0; current_recno = recno = WT_RECNO_OOB; session_flags = 0; /* [-Werror=maybe-uninitialized] */ __wt_btcur_init(session, &cbt); __wt_btcur_open(&cbt); WT_ERR(__wt_scr_alloc(session, 0, ¤t_key)); WT_ERR(__wt_scr_alloc(session, 0, &las_addr)); WT_ERR(__wt_scr_alloc(session, 0, &las_key)); WT_ERR(__wt_scr_alloc(session, 0, &las_value)); /* Open a lookaside table cursor. */ WT_ERR(__wt_las_cursor(session, &cursor, &session_flags)); /* * The lookaside records are in key and update order, that is, there * will be a set of in-order updates for a key, then another set of * in-order updates for a subsequent key. We process all of the updates * for a key and then insert those updates into the page, then all the * updates for the next key, and so on. * * Search for the block's unique prefix, stepping through any matching * records. */ las_addr->data = addr; las_addr->size = addr_size; las_key->size = 0; cursor->set_key( cursor, read_id, las_addr, (uint64_t)0, (uint32_t)0, las_key); if ((ret = cursor->search_near(cursor, &exact)) == 0 && exact < 0) ret = cursor->next(cursor); for (; ret == 0; ret = cursor->next(cursor)) { WT_ERR(cursor->get_key(cursor, &las_id, las_addr, &las_counter, &las_txnid, las_key)); /* * Confirm the search using the unique prefix; if not a match, * we're done searching for records for this page. */ if (las_id != read_id || las_addr->size != addr_size || memcmp(las_addr->data, addr, addr_size) != 0) break; /* * If the on-page value has become globally visible, this record * is no longer needed. */ if (__wt_txn_visible_all(session, las_txnid)) continue; /* Allocate the WT_UPDATE structure. */ WT_ERR(cursor->get_value( cursor, &upd_txnid, &upd_size, las_value)); WT_ERR(__wt_update_alloc(session, (upd_size == WT_UPDATE_DELETED_VALUE) ? NULL : las_value, &upd, &incr)); total_incr += incr; upd->txnid = upd_txnid; switch (page->type) { case WT_PAGE_COL_FIX: case WT_PAGE_COL_VAR: p = las_key->data; WT_ERR(__wt_vunpack_uint(&p, 0, &recno)); if (current_recno == recno) break; WT_ASSERT(session, current_recno < recno); if (first_upd != NULL) { WT_ERR(__col_instantiate(session, current_recno, ref, &cbt, first_upd)); first_upd = NULL; } current_recno = recno; break; case WT_PAGE_ROW_LEAF: if (current_key->size == las_key->size && memcmp(current_key->data, las_key->data, las_key->size) == 0) break; if (first_upd != NULL) { WT_ERR(__row_instantiate(session, current_key, ref, &cbt, first_upd)); first_upd = NULL; } WT_ERR(__wt_buf_set(session, current_key, las_key->data, las_key->size)); break; WT_ILLEGAL_VALUE_ERR(session); } /* Append the latest update to the list. */ if (first_upd == NULL) first_upd = last_upd = upd; else { last_upd->next = upd; last_upd = upd; } upd = NULL; } WT_ERR_NOTFOUND_OK(ret); /* Insert the last set of updates, if any. */ if (first_upd != NULL) switch (page->type) { case WT_PAGE_COL_FIX: case WT_PAGE_COL_VAR: WT_ERR(__col_instantiate(session, current_recno, ref, &cbt, first_upd)); first_upd = NULL; break; case WT_PAGE_ROW_LEAF: WT_ERR(__row_instantiate(session, current_key, ref, &cbt, first_upd)); first_upd = NULL; break; WT_ILLEGAL_VALUE_ERR(session); } /* Discard the cursor. */ WT_ERR(__wt_las_cursor_close(session, &cursor, session_flags)); if (total_incr != 0) { __wt_cache_page_inmem_incr(session, page, total_incr); /* * We've modified/dirtied the page, but that's not necessary and * if we keep the page clean, it's easier to evict. We leave the * lookaside table updates in place, so if we evict this page * without dirtying it, any future instantiation of it will find * the records it needs. If the page is dirtied before eviction, * then we'll write any needed lookaside table records for the * new location of the page. */ __wt_page_modify_clear(session, page); } err: WT_TRET(__wt_las_cursor_close(session, &cursor, session_flags)); WT_TRET(__wt_btcur_close(&cbt, 1)); /* * On error, upd points to a single unlinked WT_UPDATE structure, * first_upd points to a list. */ if (upd != NULL) __wt_free(session, upd); if (first_upd != NULL) __wt_free_update_list(session, first_upd); __wt_scr_free(session, ¤t_key); __wt_scr_free(session, &las_addr); __wt_scr_free(session, &las_key); __wt_scr_free(session, &las_value); return (ret); }
/* * __txn_printlog -- * Print a log record in a human-readable format. */ static int __txn_printlog( WT_SESSION_IMPL *session, WT_ITEM *logrec, WT_LSN *lsnp, void *cookie) { FILE *out; WT_LSN ckpt_lsn; const uint8_t *end, *p; const char *msg; uint64_t txnid; uint32_t fileid, rectype; int32_t start; out = cookie; p = (const uint8_t *)logrec->data + offsetof(WT_LOG_RECORD, record); end = (const uint8_t *)logrec->data + logrec->size; /* First, peek at the log record type. */ WT_RET(__wt_logrec_read(session, &p, end, &rectype)); if (fprintf(out, " { \"lsn\" : [%" PRIu32 ",%" PRId64 "],\n", lsnp->file, lsnp->offset) < 0) return (errno); switch (rectype) { case WT_LOGREC_CHECKPOINT: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(IQ), &ckpt_lsn.file, &ckpt_lsn.offset)); if (fprintf(out, " \"type\" : \"checkpoint\"\n") < 0 || fprintf( out, " \"ckpt_lsn\" : [%" PRIu32 ",%" PRId64 "],\n", ckpt_lsn.file, ckpt_lsn.offset) < 0) return (errno); break; case WT_LOGREC_COMMIT: WT_RET(__wt_vunpack_uint(&p, WT_PTRDIFF(end, p), &txnid)); if (fprintf(out, " \"type\" : \"commit\"\n") < 0 || fprintf(out, " \"txnid\" : %" PRIu64 ",\n", txnid) < 0) return (errno); WT_RET(__txn_commit_printlog(session, &p, end, out)); break; case WT_LOGREC_FILE_SYNC: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(Ii), &fileid, &start)); if (fprintf(out, " \"type\" : \"file_sync\"\n") < 0 || fprintf(out, " \"fileid\" : %" PRIu32 "\n", fileid) < 0 || fprintf(out, " \"start\" : %" PRId32 "\n", start) < 0) return (errno); break; case WT_LOGREC_MESSAGE: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(S), &msg)); if (fprintf(out, " \"type\" : \"message\"\n") < 0 || fprintf(out, " \"message\" : \"%s\"\n", msg) < 0) return (errno); break; } if (fprintf(out, " },\n") < 0) return (errno); return (0); }
/* * __txn_printlog -- * Print a log record in a human-readable format. */ static int __txn_printlog(WT_SESSION_IMPL *session, WT_ITEM *rawrec, WT_LSN *lsnp, WT_LSN *next_lsnp, void *cookie, int firstrecord) { WT_LOG_RECORD *logrec; WT_TXN_PRINTLOG_ARGS *args; const uint8_t *end, *p; const char *msg; uint64_t txnid; uint32_t fileid, lsnfile, lsnoffset, rectype; int32_t start; bool compressed; WT_UNUSED(next_lsnp); args = cookie; p = WT_LOG_SKIP_HEADER(rawrec->data); end = (const uint8_t *)rawrec->data + rawrec->size; logrec = (WT_LOG_RECORD *)rawrec->data; compressed = F_ISSET(logrec, WT_LOG_RECORD_COMPRESSED); /* First, peek at the log record type. */ WT_RET(__wt_logrec_read(session, &p, end, &rectype)); if (!firstrecord) WT_RET(__wt_fprintf(session, WT_STDOUT(session), ",\n")); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " { \"lsn\" : [%" PRIu32 ",%" PRIu32 "],\n", lsnp->l.file, lsnp->l.offset)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"hdr_flags\" : \"%s\",\n", compressed ? "compressed" : "")); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"rec_len\" : %" PRIu32 ",\n", logrec->len)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"mem_len\" : %" PRIu32 ",\n", compressed ? logrec->mem_len : logrec->len)); switch (rectype) { case WT_LOGREC_CHECKPOINT: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(II), &lsnfile, &lsnoffset)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"type\" : \"checkpoint\",\n")); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"ckpt_lsn\" : [%" PRIu32 ",%" PRIu32 "]\n", lsnfile, lsnoffset)); break; case WT_LOGREC_COMMIT: WT_RET(__wt_vunpack_uint(&p, WT_PTRDIFF(end, p), &txnid)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"type\" : \"commit\",\n")); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"txnid\" : %" PRIu64 ",\n", txnid)); WT_RET(__txn_oplist_printlog(session, &p, end, args->flags)); break; case WT_LOGREC_FILE_SYNC: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(Ii), &fileid, &start)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"type\" : \"file_sync\",\n")); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"fileid\" : %" PRIu32 ",\n", fileid)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"start\" : %" PRId32 "\n", start)); break; case WT_LOGREC_MESSAGE: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(S), &msg)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"type\" : \"message\",\n")); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"message\" : \"%s\"\n", msg)); break; case WT_LOGREC_SYSTEM: WT_RET(__wt_struct_unpack(session, p, WT_PTRDIFF(end, p), WT_UNCHECKED_STRING(II), &lsnfile, &lsnoffset)); WT_RET(__wt_fprintf(session, WT_STDOUT(session), " \"type\" : \"system\",\n")); WT_RET(__txn_oplist_printlog(session, &p, end, args->flags)); break; } WT_RET(__wt_fprintf(session, WT_STDOUT(session), " }")); return (0); }
void test_value(int64_t val) { const uint8_t *cp; uint8_t buf[WT_INTPACK64_MAXSIZE + 8]; /* -Werror=array-bounds */ uint8_t *p; int64_t sinput, soutput; uint64_t uinput, uoutput; size_t used_len; memset(buf, 0xff, sizeof(buf)); /* -Werror=maybe-uninitialized */ sinput = val; soutput = 0; /* -Werror=maybe-uninitialized */ /* * Required on some systems to pull in parts of the library * for which we have data references. */ testutil_check(__wt_library_init()); p = buf; testutil_check(__wt_vpack_int(&p, sizeof(buf), sinput)); used_len = (size_t)(p - buf); testutil_assert(used_len <= WT_INTPACK64_MAXSIZE); cp = buf; testutil_check(__wt_vunpack_int(&cp, used_len, &soutput)); /* Ensure we got the correct value back */ if (sinput != soutput) { fprintf(stderr, "mismatch %" PRId64 ", %" PRId64 "\n", sinput, soutput); abort(); } /* Ensure that decoding used the correct amount of buffer */ if (cp != p) { fprintf(stderr, "Unpack consumed wrong size for %" PRId64 ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n", sinput, used_len, cp > p ? used_len + (size_t)(cp - p) : /* More than buf used */ used_len - (size_t)(p - cp)); /* Less than buf used */ abort(); } /* Test unsigned, convert negative into bigger positive values */ uinput = (uint64_t)val; p = buf; testutil_check(__wt_vpack_uint(&p, sizeof(buf), uinput)); used_len = (size_t)(p - buf); testutil_assert(used_len <= WT_INTPACK64_MAXSIZE); cp = buf; testutil_check(__wt_vunpack_uint(&cp, sizeof(buf), &uoutput)); /* Ensure we got the correct value back */ if (sinput != soutput) { fprintf(stderr, "mismatch %" PRId64 ", %" PRId64 "\n", sinput, soutput); abort(); } /* Ensure that decoding used the correct amount of buffer */ if (cp != p) { fprintf(stderr, "Unpack consumed wrong size for %" PRId64 ", expected %" WT_SIZET_FMT ", got %" WT_SIZET_FMT "\n", sinput, used_len, cp > p ? used_len + (size_t)(cp - p) : used_len - (size_t)(p - cp)); abort(); } }