/* * __meta_track_next -- * Extend the list of operations we're tracking, as necessary, and * optionally return the next slot. */ static int __meta_track_next(WT_SESSION_IMPL *session, WT_META_TRACK **trkp) { size_t offset, sub_off; if (session->meta_track_next == NULL) session->meta_track_next = session->meta_track; offset = WT_PTRDIFF(session->meta_track_next, session->meta_track); sub_off = WT_PTRDIFF(session->meta_track_sub, session->meta_track); if (offset == session->meta_track_alloc) { WT_RET(__wt_realloc(session, &session->meta_track_alloc, WT_MAX(2 * session->meta_track_alloc, 20 * sizeof(WT_META_TRACK)), &session->meta_track)); /* Maintain positions in the new chunk of memory. */ session->meta_track_next = (uint8_t *)session->meta_track + offset; if (session->meta_track_sub != NULL) session->meta_track_sub = (uint8_t *)session->meta_track + sub_off; } WT_ASSERT(session, session->meta_track_next != NULL); if (trkp != NULL) { *trkp = session->meta_track_next; session->meta_track_next = *trkp + 1; } return (0); }
/* * __wt_raw_to_esc_hex -- * Convert a chunk of data to a nul-terminated printable string using * escaped hex, as necessary. */ int __wt_raw_to_esc_hex( WT_SESSION_IMPL *session, const uint8_t *from, size_t size, WT_ITEM *to) { size_t i; const uint8_t *p; u_char *t; /* * In the worst case, every character takes up 3 spaces, plus a * trailing nul byte. */ WT_RET(__wt_buf_init(session, to, size * 3 + 1)); for (p = from, t = to->mem, i = size; i > 0; --i, ++p) if (__wt_isprint((u_char)*p)) { if (*p == '\\') *t++ = '\\'; *t++ = *p; } else { *t++ = '\\'; *t++ = __wt_hex((*p & 0xf0) >> 4); *t++ = __wt_hex(*p & 0x0f); } *t++ = '\0'; to->size = WT_PTRDIFF(t, to->mem); 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); }
/*将二级制串转化成16进制串,每个字节描述用"\"隔开*/ int __wt_raw_to_esc_hex(WT_SESSION_IMPL *session, const uint8_t *from, size_t size, WT_ITEM *to) { size_t i; const uint8_t* p; u_char* t; WT_RET(__wt_buf_init(session, to, size * 3 + 1)); for(p = from, t = to->mem, i = size; i > 0; --i, ++p){ if (isprint((int)*p)) { if (*p == '\\') *t++ = '\\'; *t++ = *p; } else { *t++ = '\\'; *t++ = hex[(*p & 0xf0) >> 4]; *t++ = hex[*p & 0x0f]; } } *t++ = '\0'; to->size = WT_PTRDIFF(t, to->mem); return 0; }
/* * __wt_debug_offset -- * Read and dump a disk page in debugging mode, using a file * offset/size/checksum triplet. */ int __wt_debug_offset(WT_SESSION_IMPL *session, wt_off_t offset, uint32_t size, uint32_t cksum, const char *ofile) { WT_DECL_ITEM(buf); WT_DECL_RET; uint8_t addr[WT_BTREE_MAX_ADDR_COOKIE], *endp; WT_ASSERT(session, S2BT_SAFE(session) != NULL); /* * This routine depends on the default block manager's view of files, * where an address consists of a file offset, length, and checksum. * This is for debugging only: other block managers might not see a * file or address the same way, that's why there's no block manager * method. * * Convert the triplet into an address structure. */ endp = addr; WT_RET(__wt_block_addr_to_buffer( S2BT(session)->bm->block, &endp, offset, size, cksum)); /* * Read the address through the btree I/O functions (so the block is * decompressed as necessary). */ WT_RET(__wt_scr_alloc(session, 0, &buf)); WT_ERR(__wt_bt_read(session, buf, addr, WT_PTRDIFF(endp, addr))); ret = __wt_debug_disk(session, buf->mem, ofile); err: __wt_scr_free(session, &buf); return (ret); }
/* * __wt_struct_unpack_size -- * Determine the packed size of a buffer matching the format. */ int __wt_struct_unpack_size(WT_SESSION_IMPL *session, const void *buffer, size_t size, const char *fmt, size_t *resultp) { WT_DECL_PACK_VALUE(pv); WT_DECL_RET; WT_PACK pack; const uint8_t *p, *end; p = buffer; end = p + size; WT_RET(__pack_init(session, &pack, fmt)); while ((ret = __pack_next(&pack, &pv)) == 0) WT_RET(__unpack_read(session, &pv, &p, (size_t)(end - p))); /* Be paranoid - __pack_write should never overflow. */ WT_ASSERT(session, p <= end); if (ret != WT_NOTFOUND) return (ret); *resultp = WT_PTRDIFF(p, buffer); return (0); }
int __wt_logop_read(WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, uint32_t *optypep, uint32_t *opsizep) { return (__wt_struct_unpack( session, *pp, WT_PTRDIFF(end, *pp), "II", optypep, opsizep)); }
/* * __wt_ovfl_txnc_add -- * Add a new entry to the page's list of transaction-cached overflow * records. */ int __wt_ovfl_txnc_add(WT_SESSION_IMPL *session, WT_PAGE *page, const uint8_t *addr, size_t addr_size, const void *value, size_t value_size) { WT_OVFL_TXNC **head, **stack[WT_SKIP_MAXDEPTH], *txnc; size_t size; u_int i, skipdepth; uint8_t *p; if (page->modify->ovfl_track == NULL) WT_RET(__ovfl_track_init(session, page)); head = page->modify->ovfl_track->ovfl_txnc; /* Choose a skiplist depth for this insert. */ skipdepth = __wt_skip_choose_depth(session); /* * Allocate the WT_OVFL_TXNC structure, next pointers for the skip * list, room for the address and value, then copy everything into * place. * * To minimize the WT_OVFL_TXNC structure size, the address offset * and size are single bytes: that's safe because the address follows * the structure (which can't be more than about 100B), and address * cookies are limited to 255B. */ size = sizeof(WT_OVFL_TXNC) + skipdepth * sizeof(WT_OVFL_TXNC *) + addr_size + value_size; WT_RET(__wt_calloc(session, 1, size, &txnc)); p = (uint8_t *)txnc + sizeof(WT_OVFL_TXNC) + skipdepth * sizeof(WT_OVFL_TXNC *); txnc->addr_offset = (uint8_t)WT_PTRDIFF(p, txnc); txnc->addr_size = (uint8_t)addr_size; memcpy(p, addr, addr_size); p += addr_size; txnc->value_offset = WT_PTRDIFF32(p, txnc); txnc->value_size = WT_STORE_SIZE(value_size); memcpy(p, value, value_size); txnc->current = __wt_txn_new_id(session); __wt_cache_page_inmem_incr( session, page, WT_OVFL_SIZE(txnc, WT_OVFL_TXNC)); /* Insert the new entry into the skiplist. */ __ovfl_txnc_skip_search_stack(head, stack, addr, addr_size); for (i = 0; i < skipdepth; ++i) { txnc->next[i] = *stack[i]; *stack[i] = txnc; } if (WT_VERBOSE_ISSET(session, WT_VERB_OVERFLOW)) WT_RET(__ovfl_txnc_verbose(session, page, txnc, "add")); return (0); }
/* * __wt_buf_grow -- * Grow a buffer that's currently in-use. */ int __wt_buf_grow(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size) { size_t offset; int set_data; WT_ASSERT(session, size <= UINT32_MAX); /* Clear buffers previously used for mapped returns. */ if (F_ISSET(buf, WT_ITEM_MAPPED)) __wt_buf_clear(buf); if (size > buf->memsize) { /* * Grow the buffer's memory: if the data reference is not set * or references the buffer's memory, maintain it. */ WT_ASSERT(session, buf->mem == NULL || buf->memsize > 0); if (buf->data == NULL) { offset = 0; set_data = 1; } else if (buf->data >= buf->mem && WT_PTRDIFF(buf->data, buf->mem) < buf->memsize) { offset = WT_PTRDIFF(buf->data, buf->mem); set_data = 1; } else { offset = 0; set_data = 0; } if (F_ISSET(buf, WT_ITEM_ALIGNED)) WT_RET(__wt_realloc_aligned( session, &buf->memsize, size, &buf->mem)); else WT_RET(__wt_realloc( session, &buf->memsize, size, &buf->mem)); if (set_data) buf->data = (uint8_t *)buf->mem + offset; } return (0); }
/* * wiredtiger_pack_close -- * Close a packing stream. */ int wiredtiger_pack_close(WT_PACK_STREAM *ps, size_t *usedp) { if (usedp != NULL) *usedp = WT_PTRDIFF(ps->p, ps->start); if (ps != NULL) __wt_free(ps->pack.session, ps); return (0); }
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); }
/* * __wt_mmap_preload -- * Cause a section of a memory map to be faulted in. */ int __wt_mmap_preload(WT_SESSION_IMPL *session, const void *p, size_t size) { #ifdef HAVE_POSIX_MADVISE /* Linux requires the address be aligned to a 4KB boundary. */ WT_BM *bm = S2BT(session)->bm; WT_DECL_RET; void *blk = (void *)((uintptr_t)p & ~(uintptr_t)(WT_VM_PAGESIZE - 1)); size += WT_PTRDIFF(p, blk); /* XXX proxy for "am I doing a scan?" -- manual read-ahead */ if (F_ISSET(session, WT_SESSION_NO_CACHE)) { /* Read in 2MB blocks every 1MB of data. */ if (((uintptr_t)((uint8_t *)blk + size) & (uintptr_t)((1<<20) - 1)) < (uintptr_t)blk) return (0); size = WT_MIN(WT_MAX(20 * size, 2 << 20), WT_PTRDIFF((uint8_t *)bm->map + bm->maplen, blk)); } /* * Manual pages aren't clear on whether alignment is required for the * size, so we will be conservative. */ size &= ~(size_t)(WT_VM_PAGESIZE - 1); if (size > WT_VM_PAGESIZE && (ret = posix_madvise(blk, size, POSIX_MADV_WILLNEED)) != 0) WT_RET_MSG(session, ret, "posix_madvise will need"); #else WT_UNUSED(session); WT_UNUSED(p); WT_UNUSED(size); #endif return (0); }
/* * __wt_schema_get_index -- * Find an index by URI. */ int __wt_schema_get_index(WT_SESSION_IMPL *session, const char *uri, bool quiet, WT_TABLE **tablep, WT_INDEX **indexp) { WT_DECL_RET; WT_INDEX *idx; WT_TABLE *table; const char *tablename, *tend; u_int i; *indexp = NULL; tablename = uri; if (!WT_PREFIX_SKIP(tablename, "index:") || (tend = strchr(tablename, ':')) == NULL) return (__wt_bad_object_type(session, uri)); WT_RET(__wt_schema_get_table(session, tablename, WT_PTRDIFF(tend, tablename), false, &table)); /* Try to find the index in the table. */ for (i = 0; i < table->nindices; i++) { idx = table->indices[i]; if (idx != NULL && strcmp(idx->name, uri) == 0) { if (tablep != NULL) *tablep = table; else __wt_schema_release_table(session, table); *indexp = idx; return (0); } } /* Otherwise, open it. */ WT_ERR(__wt_schema_open_index( session, table, tend + 1, strlen(tend + 1), indexp)); if (tablep != NULL) *tablep = table; err: __wt_schema_release_table(session, table); WT_RET(ret); if (*indexp != NULL) return (0); if (quiet) WT_RET(ENOENT); WT_RET_MSG(session, ENOENT, "%s not found in table", uri); }
int __wt_logop_row_truncate_unpack( WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, uint32_t *fileidp, WT_ITEM *startp, WT_ITEM *stopp, uint32_t *modep) { const char *fmt = WT_UNCHECKED_STRING(IIIuuI); uint32_t optype, size; WT_RET(__wt_struct_unpack(session, *pp, WT_PTRDIFF(end, *pp), fmt, &optype, &size, fileidp, startp, stopp, modep)); WT_ASSERT(session, optype == WT_LOGOP_ROW_TRUNCATE); *pp += size; return (0); }
int __wt_logop_row_remove_unpack( WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, uint32_t *fileidp, WT_ITEM *keyp) { const char *fmt = WT_UNCHECKED_STRING(IIIu); uint32_t optype, size; WT_RET(__wt_struct_unpack(session, *pp, WT_PTRDIFF(end, *pp), fmt, &optype, &size, fileidp, keyp)); WT_ASSERT(session, optype == WT_LOGOP_ROW_REMOVE); *pp += size; return (0); }
/*将buffer的数据写入到block对应的文件中*/ int __wt_block_write(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_ITEM *buf, uint8_t *addr, size_t *addr_sizep, int data_cksum) { wt_off_t offset; uint32_t size, cksum; uint8_t *endp; WT_RET(__wt_block_write_off(session, block, buf, &offset, &size, &cksum, data_cksum, 0)); endp = addr; /*将block的checksum/长度对齐个数/偏移位置写入addr中*/ WT_RET(__wt_block_addr_to_buffer(block, &endp, offset, size, cksum)); *addr_sizep = WT_PTRDIFF(endp, addr); return 0; }
int __wt_logop_col_put_unpack( WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, uint32_t *fileidp, uint64_t *recnop, WT_ITEM *valuep) { const char *fmt = WT_UNCHECKED_STRING(IIIru); uint32_t optype, size; WT_RET(__wt_struct_unpack(session, *pp, WT_PTRDIFF(end, *pp), fmt, &optype, &size, fileidp, recnop, valuep)); WT_ASSERT(session, optype == WT_LOGOP_COL_PUT); *pp += size; return (0); }
/*将src转换成可见的16进制串*/ static inline void __fill_hex(const uint8_t* src, size_t src_max, uint8_t* dest, size_t dest_max, size_t* lenp) { uint8_t* dest_orig; dest_orig = dest; if(dest_max > 0) -- dest_max; for(; src_max > 0 && dest_max > 1; src_max -= 1, dest_max -= 2, ++src){ *dest++ = hex[(*src & 0xf0) >> 4]; *dest++ = hex[*src & 0x0f]; } *dest++ = '\0'; if(lenp != NULL) *lenp = WT_PTRDIFF(dest, dest_orig); }
/* * __wt_block_write -- * Write a buffer into a block, returning the block's address cookie. */ int __wt_block_write(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_ITEM *buf, uint8_t *addr, size_t *addr_sizep, bool data_cksum) { wt_off_t offset; uint32_t size, cksum; uint8_t *endp; WT_RET(__wt_block_write_off( session, block, buf, &offset, &size, &cksum, data_cksum, false)); endp = addr; WT_RET(__wt_block_addr_to_buffer(block, &endp, offset, size, cksum)); *addr_sizep = WT_PTRDIFF(endp, addr); 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); }
/* * __wt_txn_checkpoint_logread -- * Read a log record for a checkpoint operation. */ int __wt_txn_checkpoint_logread( WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, WT_LSN *ckpt_lsn) { const char *fmt = WT_UNCHECKED_STRING(IQIU); WT_ITEM ckpt_snapshot; u_int ckpt_nsnapshot; WT_RET(__wt_struct_unpack(session, *pp, WT_PTRDIFF(end, *pp), fmt, &ckpt_lsn->file, &ckpt_lsn->offset, &ckpt_nsnapshot, &ckpt_snapshot)); WT_UNUSED(ckpt_nsnapshot); WT_UNUSED(ckpt_snapshot); *pp = end; 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); }
/* * __wt_mmap_discard -- * Discard a chunk of the memory map. */ int __wt_mmap_discard(WT_SESSION_IMPL *session, void *p, size_t size) { #ifdef HAVE_POSIX_MADVISE /* Linux requires the address be aligned to a 4KB boundary. */ WT_DECL_RET; void *blk = (void *)((uintptr_t)p & ~(uintptr_t)(WT_VM_PAGESIZE - 1)); size += WT_PTRDIFF(p, blk); if ((ret = posix_madvise(blk, size, POSIX_MADV_DONTNEED)) != 0) WT_RET_MSG(session, ret, "posix_madvise don't need"); #else WT_UNUSED(session); WT_UNUSED(p); WT_UNUSED(size); #endif return (0); }
/* * __fill_hex -- * In-memory conversion of raw bytes to a hexadecimal representation. */ static inline void __fill_hex(const uint8_t *src, size_t src_max, uint8_t *dest, size_t dest_max, size_t *lenp) { uint8_t *dest_orig; dest_orig = dest; if (dest_max > 0) /* save a byte for nul-termination */ --dest_max; for (; src_max > 0 && dest_max > 1; src_max -= 1, dest_max -= 2, ++src) { *dest++ = __wt_hex((*src & 0xf0) >> 4); *dest++ = __wt_hex(*src & 0x0f); } *dest++ = '\0'; if (lenp != NULL) *lenp = WT_PTRDIFF(dest, dest_orig); }
/*将16进制描述串转换成二进制串,并且存入item中*/ int __wt_nhex_to_raw(WT_SESSION_IMPL *session, const char *from, size_t size, WT_ITEM *to) { const u_char *p; u_char *t; if (size % 2 != 0) return (__hex_fmterr(session)); WT_RET(__wt_buf_init(session, to, size / 2)); for (p = (u_char *)from, t = to->mem; size > 0; p += 2, size -= 2, ++t){ if (__wt_hex2byte(p, t)) return (__hex_fmterr(session)); } to->size = WT_PTRDIFF(t, to->mem); return 0; }
/* * __fstream_getline -- * Get a line from a stream. * * Implementation of the POSIX getline or BSD fgetln functions (finding the * function in a portable way is hard, it's simple enough to write it instead). * * Note: Unlike the standard getline calls, this function doesn't include the * trailing newline character in the returned buffer and discards empty lines * (so the caller's EOF marker is a returned line length of 0). */ static int __fstream_getline(WT_SESSION_IMPL *session, WT_FSTREAM *fstr, WT_ITEM *buf) { const char *p; size_t len; char c; /* * We always NUL-terminate the returned string (even if it's empty), * make sure there's buffer space for a trailing NUL in all cases. */ WT_RET(__wt_buf_init(session, buf, 100)); for (;;) { /* Check if we need to refill the buffer. */ if (WT_PTRDIFF(fstr->buf.data, fstr->buf.mem) >= fstr->buf.size) { len = WT_MIN(WT_STREAM_BUFSIZE, (size_t)(fstr->size - fstr->off)); if (len == 0) break; /* EOF */ WT_RET(__wt_buf_initsize(session, &fstr->buf, len)); WT_RET(__wt_read( session, fstr->fh, fstr->off, len, fstr->buf.mem)); fstr->off += (wt_off_t)len; } c = *(p = fstr->buf.data); fstr->buf.data = ++p; /* Leave space for a trailing NUL. */ WT_RET(__wt_buf_extend(session, buf, buf->size + 2)); if (c == '\n') { if (buf->size == 0) continue; break; } ((char *)buf->mem)[buf->size++] = c; } ((char *)buf->mem)[buf->size] = '\0'; return (0); }
/* * __wt_txn_checkpoint_logread -- * Read a log record for a checkpoint operation. */ int __wt_txn_checkpoint_logread(WT_SESSION_IMPL *session, const uint8_t **pp, const uint8_t *end, WT_LSN *ckpt_lsn) { WT_DECL_RET; WT_ITEM ckpt_snapshot_unused; uint32_t ckpt_file, ckpt_offset; u_int ckpt_nsnapshot_unused; const char *fmt = WT_UNCHECKED_STRING(IIIu); if ((ret = __wt_struct_unpack(session, *pp, WT_PTRDIFF(end, *pp), fmt, &ckpt_file, &ckpt_offset, &ckpt_nsnapshot_unused, &ckpt_snapshot_unused)) != 0) WT_RET_MSG(session, ret, "txn_checkpoint_logread: unpack failure"); WT_SET_LSN(ckpt_lsn, ckpt_file, ckpt_offset); *pp = end; return (0); }
/* * __wt_struct_repack -- * Return the subset of the packed buffer that represents part of * the format. If the result is not contiguous in the existing * buffer, a buffer is reallocated and filled. */ int __wt_struct_repack(WT_SESSION_IMPL *session, const char *infmt, const char *outfmt, const WT_ITEM *inbuf, WT_ITEM *outbuf) { WT_DECL_PACK_VALUE(pvin); WT_DECL_PACK_VALUE(pvout); WT_DECL_RET; WT_PACK packin, packout; const uint8_t *before, *end, *p; const void *start; start = NULL; p = inbuf->data; end = p + inbuf->size; WT_RET(__pack_init(session, &packout, outfmt)); WT_RET(__pack_init(session, &packin, infmt)); /* Outfmt should complete before infmt */ while ((ret = __pack_next(&packout, &pvout)) == 0) { if (p >= end) WT_RET(EINVAL); if (pvout.type == 'x' && pvout.size == 0 && pvout.havesize) continue; WT_RET(__pack_next(&packin, &pvin)); before = p; WT_RET(__unpack_read(session, &pvin, &p, (size_t)(end - p))); if (pvout.type != pvin.type) WT_RET(ENOTSUP); if (start == NULL) start = before; } WT_RET_NOTFOUND_OK(ret); /* Be paranoid - __pack_write should never overflow. */ WT_ASSERT(session, p <= end); outbuf->data = start; outbuf->size = WT_PTRDIFF(p, start); return (0); }
/*带有'\'格式化的16进制串转化成二进制串,并且存入item中*/ int __wt_esc_hex_to_raw(WT_SESSION_IMPL *session, const char *from, WT_ITEM *to) { const u_char *p; u_char *t; WT_RET(__wt_buf_init(session, to, strlen(from))); for (p = (u_char *)from, t = to->mem; *p != '\0'; ++p, ++t) { if ((*t = *p) != '\\') continue; ++p; if (p[0] != '\\') { if (p[0] == '\0' || p[1] == '\0' || __wt_hex2byte(p, t)) return (__hex_fmterr(session)); ++p; } } to->size = WT_PTRDIFF(t, to->mem); return (0); }
/* * __wt_schema_get_colgroup -- * Find a column group by URI. */ int __wt_schema_get_colgroup(WT_SESSION_IMPL *session, const char *uri, bool quiet, WT_TABLE **tablep, WT_COLGROUP **colgroupp) { WT_COLGROUP *colgroup; WT_TABLE *table; const char *tablename, *tend; u_int i; *colgroupp = NULL; tablename = uri; if (!WT_PREFIX_SKIP(tablename, "colgroup:")) return (__wt_bad_object_type(session, uri)); if ((tend = strchr(tablename, ':')) == NULL) tend = tablename + strlen(tablename); WT_RET(__wt_schema_get_table(session, tablename, WT_PTRDIFF(tend, tablename), false, &table)); for (i = 0; i < WT_COLGROUPS(table); i++) { colgroup = table->cgroups[i]; if (strcmp(colgroup->name, uri) == 0) { *colgroupp = colgroup; if (tablep != NULL) *tablep = table; else __wt_schema_release_table(session, table); return (0); } } __wt_schema_release_table(session, table); if (quiet) WT_RET(ENOENT); WT_RET_MSG(session, ENOENT, "%s not found in table", uri); }