/* * __find_column_format -- * Find the format of the named column. */ static int __find_column_format(WT_SESSION_IMPL *session, WT_TABLE *table, WT_CONFIG_ITEM *colname, bool value_only, WT_PACK_VALUE *pv) { WT_CONFIG conf; WT_CONFIG_ITEM k, v; WT_DECL_RET; WT_PACK pack; bool inkey; __wt_config_subinit(session, &conf, &table->colconf); WT_RET(__pack_init(session, &pack, table->key_format)); inkey = true; while ((ret = __wt_config_next(&conf, &k, &v)) == 0) { if ((ret = __pack_next(&pack, pv)) == WT_NOTFOUND && inkey) { ret = __pack_init(session, &pack, table->value_format); if (ret == 0) ret = __pack_next(&pack, pv); inkey = false; } if (ret != 0) return (ret); if (k.len == colname->len && strncmp(colname->str, k.str, k.len) == 0) { if (value_only && inkey) return (__wt_set_return(session, EINVAL)); return (0); } } return (ret); }
/* * __wt_schema_get_table_uri -- * Get the table handle for the named table. */ int __wt_schema_get_table_uri(WT_SESSION_IMPL *session, const char *uri, bool ok_incomplete, uint32_t flags, WT_TABLE **tablep) { WT_DATA_HANDLE *saved_dhandle; WT_DECL_RET; WT_TABLE *table; *tablep = NULL; saved_dhandle = session->dhandle; WT_ERR(__wt_session_get_dhandle(session, uri, NULL, NULL, flags)); table = (WT_TABLE *)session->dhandle; if (!ok_incomplete && !table->cg_complete) { WT_ERR(__wt_session_release_dhandle(session)); ret = __wt_set_return(session, EINVAL); WT_ERR_MSG(session, ret, "'%s' cannot be used " "until all column groups are created", table->iface.name); } *tablep = table; err: session->dhandle = saved_dhandle; return (ret); }
/* * __log_slot_close -- * Close out the slot the caller is using. The slot may already be * closed or freed by another thread. */ static int __log_slot_close( WT_SESSION_IMPL *session, WT_LOGSLOT *slot, bool *releasep, bool forced) { WT_CONNECTION_IMPL *conn; WT_LOG *log; int64_t end_offset, new_state, old_state; #ifdef HAVE_DIAGNOSTIC uint64_t time_start, time_stop; int count; #endif *releasep = false; WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SLOT)); conn = S2C(session); log = conn->log; if (slot == NULL) return (WT_NOTFOUND); retry: old_state = slot->slot_state; /* * If this close is coming from a forced close and a thread is in * the middle of using the slot, return EBUSY. The caller can * decide if retrying is necessary or not. */ if (forced && WT_LOG_SLOT_INPROGRESS(old_state)) return (__wt_set_return(session, EBUSY)); /* * If someone else is switching out this slot we lost. Nothing to * do but return. Return WT_NOTFOUND anytime the given slot was * processed by another closing thread. Only return 0 when we * actually closed the slot. */ if (WT_LOG_SLOT_CLOSED(old_state)) { WT_STAT_CONN_INCR(session, log_slot_close_race); return (WT_NOTFOUND); } /* * If someone completely processed this slot, we're done. */ if (FLD_LOG_SLOT_ISSET( (uint64_t)slot->slot_state, WT_LOG_SLOT_RESERVED)) { WT_STAT_CONN_INCR(session, log_slot_close_race); return (WT_NOTFOUND); } new_state = (old_state | WT_LOG_SLOT_CLOSE); /* * Close this slot. If we lose the race retry. */ if (!__wt_atomic_casiv64(&slot->slot_state, old_state, new_state)) goto retry; /* * We own the slot now. No one else can join. * Set the end LSN. */ WT_STAT_CONN_INCR(session, log_slot_closes); if (WT_LOG_SLOT_DONE(new_state)) *releasep = true; slot->slot_end_lsn = slot->slot_start_lsn; /* * A thread setting the unbuffered flag sets the unbuffered size after * setting the flag. There could be a delay between a thread setting * the flag, a thread closing the slot, and the original thread setting * that value. If the state is unbuffered, wait for the unbuffered * size to be set. */ #ifdef HAVE_DIAGNOSTIC count = 0; time_start = __wt_clock(session); #endif if (WT_LOG_SLOT_UNBUFFERED_ISSET(old_state)) { while (slot->slot_unbuffered == 0) { WT_STAT_CONN_INCR(session, log_slot_close_unbuf); __wt_yield(); #ifdef HAVE_DIAGNOSTIC ++count; if (count > WT_MILLION) { time_stop = __wt_clock(session); if (WT_CLOCKDIFF_SEC( time_stop, time_start) > 10) { __wt_errx(session, "SLOT_CLOSE: Slot %" PRIu32 " Timeout unbuffered, state 0x%" PRIx64 " unbuffered %" PRId64, (uint32_t)(slot - &log->slot_pool[0]), (uint64_t)slot->slot_state, slot->slot_unbuffered); __log_slot_dump(session); __wt_abort(session); } count = 0; } #endif } } end_offset = WT_LOG_SLOT_JOINED_BUFFERED(old_state) + slot->slot_unbuffered; slot->slot_end_lsn.l.offset += (uint32_t)end_offset; WT_STAT_CONN_INCRV(session, log_slot_consolidated, end_offset); /* * XXX Would like to change so one piece of code advances the LSN. */ log->alloc_lsn = slot->slot_end_lsn; WT_ASSERT(session, log->alloc_lsn.l.file >= log->write_lsn.l.file); return (0); }
/* * __win_file_set_end -- * Truncate or extend a file. */ static int __win_file_set_end( WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t len) { DWORD windows_error; LARGE_INTEGER largeint; WT_DECL_RET; WT_FILE_HANDLE_WIN *win_fh; WT_SESSION_IMPL *session; win_fh = (WT_FILE_HANDLE_WIN *)file_handle; session = (WT_SESSION_IMPL *)wt_session; largeint.QuadPart = len; if (win_fh->filehandle_secondary == INVALID_HANDLE_VALUE) WT_RET_MSG(session, EINVAL, "%s: handle-set-end: no secondary handle", file_handle->name); if (SetFilePointerEx(win_fh->filehandle_secondary, largeint, NULL, FILE_BEGIN) == FALSE) { windows_error = __wt_getlasterror(); ret = __wt_map_windows_error(windows_error); __wt_err(session, ret, "%s: handle-set-end: SetFilePointerEx: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (ret); } if (SetEndOfFile(win_fh->filehandle_secondary) == FALSE) { if (GetLastError() == ERROR_USER_MAPPED_FILE) return (__wt_set_return(session, EBUSY)); windows_error = __wt_getlasterror(); ret = __wt_map_windows_error(windows_error); __wt_err(session, ret, "%s: handle-set-end: SetEndOfFile: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (ret); } return (0); }