/* * __wt_to_utf8_string -- * Convert UTF-16 encoded string to UTF-8. */ int __wt_to_utf8_string( WT_SESSION_IMPL *session, const wchar_t* wide, WT_ITEM **outbuf) { DWORD windows_error; int bufferSize; WT_DECL_RET; bufferSize = WideCharToMultiByte( CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL); windows_error = __wt_getlasterror(); if (bufferSize == 0 && windows_error != ERROR_INSUFFICIENT_BUFFER) { __wt_errx(session, "WideCharToMultiByte: %s", __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } WT_RET(__wt_scr_alloc(session, bufferSize, outbuf)); bufferSize = WideCharToMultiByte( CP_UTF8, 0, wide, -1, (*outbuf)->mem, bufferSize, NULL, NULL); if (bufferSize == 0) { windows_error = __wt_getlasterror(); __wt_scr_free(session, outbuf); __wt_errx(session, "WideCharToMultiByte: %s", __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } (*outbuf)->size = bufferSize; return (0); }
/* * __win_fs_rename -- * Rename a file. */ static int __win_fs_rename(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags) { DWORD windows_error; WT_SESSION_IMPL *session; WT_UNUSED(file_system); WT_UNUSED(flags); session = (WT_SESSION_IMPL *)wt_session; /* * Check if file exists since Windows does not override the file if * it exists. */ if (GetFileAttributesA(to) != INVALID_FILE_ATTRIBUTES) if (DeleteFileA(to) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: file-rename: DeleteFileA: %s", to, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } if (MoveFileA(from, to) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s to %s: file-rename: MoveFileA: %s", from, to, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } return (0); }
/* * __wt_hazard_close -- * Verify that no hazard pointers are set. */ void __wt_hazard_close(WT_SESSION_IMPL *session) { WT_HAZARD *hp; bool found; /* * Check for a set hazard pointer and complain if we find one. We could * just check the session's hazard pointer count, but this is a useful * diagnostic. */ for (found = false, hp = session->hazard; hp < session->hazard + session->hazard_size; ++hp) if (hp->page != NULL) { found = true; break; } if (session->nhazard == 0 && !found) return; __wt_errx(session, "session %p: close hazard pointer table: table not empty", (void *)session); #ifdef HAVE_DIAGNOSTIC __hazard_dump(session); #endif /* * Clear any hazard pointers because it's not a correctness problem * (any hazard pointer we find can't be real because the session is * being closed when we're called). We do this work because session * close isn't that common that it's an expensive check, and we don't * want to let a hazard pointer lie around, keeping a page from being * evicted. * * We don't panic: this shouldn't be a correctness issue (at least, I * can't think of a reason it would be). */ for (hp = session->hazard; hp < session->hazard + session->hazard_size; ++hp) if (hp->page != NULL) { hp->page = NULL; --session->nhazard; } if (session->nhazard != 0) __wt_errx(session, "session %p: close hazard pointer table: count didn't " "match entries", (void *)session); }
/* * __wt_cache_destroy -- * Discard the underlying cache. */ int __wt_cache_destroy(WT_SESSION_IMPL *session) { WT_CACHE *cache; WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_SESSION *wt_session; int i; conn = S2C(session); cache = conn->cache; if (cache == NULL) return (0); /* The cache should be empty at this point. Complain if not. */ if (cache->pages_inmem != cache->pages_evict) __wt_errx(session, "cache server: exiting with %" PRIu64 " pages in " "memory and %" PRIu64 " pages evicted", cache->pages_inmem, cache->pages_evict); if (cache->bytes_inmem != 0) __wt_errx(session, "cache server: exiting with %" PRIu64 " bytes in memory", cache->bytes_inmem); if (cache->bytes_dirty_intl + cache->bytes_dirty_leaf != 0 || cache->pages_dirty_intl + cache->pages_dirty_leaf != 0) __wt_errx(session, "cache server: exiting with %" PRIu64 " bytes dirty and %" PRIu64 " pages dirty", cache->bytes_dirty_intl + cache->bytes_dirty_leaf, cache->pages_dirty_intl + cache->pages_dirty_leaf); WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond)); __wt_spin_destroy(session, &cache->evict_pass_lock); __wt_spin_destroy(session, &cache->evict_queue_lock); __wt_spin_destroy(session, &cache->evict_walk_lock); wt_session = &cache->walk_session->iface; if (wt_session != NULL) WT_TRET(wt_session->close(wt_session, NULL)); for (i = 0; i < WT_EVICT_QUEUE_MAX; ++i) { __wt_spin_destroy(session, &cache->evict_queues[i].evict_lock); __wt_free(session, cache->evict_queues[i].evict_queue); } __wt_free(session, conn->cache); return (ret); }
/* * __session_commit_transaction -- * WT_SESSION->commit_transaction method. */ static int __session_commit_transaction(WT_SESSION *wt_session, const char *config) { WT_DECL_RET; WT_SESSION_IMPL *session; WT_TXN *txn; session = (WT_SESSION_IMPL *)wt_session; SESSION_API_CALL(session, commit_transaction, config, cfg); WT_CSTAT_INCR(session, txn_commit); txn = &session->txn; if (F_ISSET(txn, TXN_ERROR)) { __wt_errx(session, "failed transaction requires rollback"); ret = EINVAL; } WT_TRET(__session_reset_cursors(session)); if (ret == 0) ret = __wt_txn_commit(session, cfg); else (void)__wt_txn_rollback(session, cfg); err: API_END(session); return (ret); }
/* * __win_fs_remove -- * Remove a file. */ static int __win_fs_remove(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name, uint32_t flags) { DWORD windows_error; WT_DECL_RET; WT_DECL_ITEM(name_wide); WT_SESSION_IMPL *session; WT_UNUSED(file_system); WT_UNUSED(flags); session = (WT_SESSION_IMPL *)wt_session; WT_RET(__wt_to_utf16_string(session, name, &name_wide)); if (DeleteFileW(name_wide->data) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: file-remove: DeleteFileW: %s", name, __wt_formatmessage(session, windows_error)); WT_ERR(__wt_map_windows_error(windows_error)); } err: __wt_scr_free(session, &name_wide); return (ret); }
/* * __win_file_sync -- * MSVC fsync. */ static int __win_file_sync(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session) { DWORD windows_error; WT_FILE_HANDLE_WIN *win_fh; WT_SESSION_IMPL *session; win_fh = (WT_FILE_HANDLE_WIN *)file_handle; session = (WT_SESSION_IMPL *)wt_session; /* * We don't open Windows system handles when opening directories * for flushing, as it is not necessary (or possible) to flush * a directory on Windows. Confirm the file handle is set before * attempting to sync it. */ if (win_fh->filehandle == INVALID_HANDLE_VALUE) return (0); if (FlushFileBuffers(win_fh->filehandle) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s handle-sync: FlushFileBuffers: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } return (0); }
/* * __wt_win_fs_size -- * Get the size of a file in bytes, by file name. */ int __wt_win_fs_size(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name, wt_off_t *sizep) { DWORD windows_error; WT_DECL_RET; WIN32_FILE_ATTRIBUTE_DATA data; WT_DECL_ITEM(name_wide); WT_SESSION_IMPL *session; WT_UNUSED(file_system); session = (WT_SESSION_IMPL *)wt_session; WT_RET(__wt_to_utf16_string(session, name, &name_wide)); if (GetFileAttributesExW( name_wide->data, GetFileExInfoStandard, &data) == 0) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: file-size: GetFileAttributesEx: %s", name, __wt_formatmessage(session, windows_error)); WT_ERR(__wt_map_windows_error(windows_error)); } *sizep = ((int64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow; err: __wt_scr_free(session, &name_wide); return (ret); }
/* * __wt_close_connection_close -- * Close any open file handles at connection close. */ int __wt_close_connection_close(WT_SESSION_IMPL *session) { WT_DECL_RET; WT_FH *fh; WT_CONNECTION_IMPL *conn; conn = S2C(session); while ((fh = TAILQ_FIRST(&conn->fhqh)) != NULL) { /* * In-memory configurations will have open files, but the ref * counts should be zero. */ if (!F_ISSET(conn, WT_CONN_IN_MEMORY) || fh->ref != 0) { ret = EBUSY; __wt_errx(session, "Connection has open file handles: %s", fh->name); } fh->ref = 1; F_CLR(fh, WT_FH_IN_MEMORY); WT_TRET(__wt_close(session, &fh)); } return (ret); }
/* * __wt_dlopen -- * Open a dynamic library. */ int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp) { DWORD windows_error; WT_DECL_RET; WT_DLH *dlh; WT_RET(__wt_calloc_one(session, &dlh)); WT_ERR(__wt_strdup(session, path, &dlh->name)); WT_ERR(__wt_strdup(session, path == NULL ? "local" : path, &dlh->name)); /* NULL means load from the current binary */ if (path == NULL) { if (GetModuleHandleExA( 0, NULL, (HMODULE *)&dlh->handle) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "GetModuleHandleEx: %s: %s", path, __wt_formatmessage(session, windows_error)); WT_ERR(__wt_map_windows_error(windows_error)); } } else { // TODO: load dll here DebugBreak(); } *dlhp = dlh; if (0) { err: __wt_free(session, dlh->name); __wt_free(session, dlh); } return (ret); }
/* * __wt_page_out -- * Discard an in-memory page, freeing all memory associated with it. */ void __wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep) { WT_PAGE *page; /* * When a page is discarded, it's been disconnected from its parent and * its parent's WT_REF structure may now point to a different page. * Make sure we don't accidentally use the page itself or any other * information. */ page = *pagep; *pagep = NULL; page->parent = NULL; page->ref = NULL; WT_ASSERT(session, !F_ISSET_ATOMIC(page, WT_PAGE_EVICT_LRU)); #ifdef HAVE_DIAGNOSTIC { WT_HAZARD *hp; if ((hp = __wt_page_hazard_check(session, page)) != NULL) __wt_errx(session, "discarded page has hazard pointer: (%p: %s, line %d)", hp->page, hp->file, hp->line); } #endif /* Update the cache's information. */ __wt_cache_page_evict(session, page); /* Free the page modification information. */ if (page->modify != NULL) __free_page_modify(session, page); switch (page->type) { case WT_PAGE_COL_FIX: break; case WT_PAGE_COL_INT: __free_page_col_int(session, page); break; case WT_PAGE_COL_VAR: __free_page_col_var(session, page); break; case WT_PAGE_ROW_INT: __free_page_row_int(session, page); break; case WT_PAGE_ROW_LEAF: __free_page_row_leaf(session, page); break; } /* Free any allocated disk image. */ if (!F_ISSET_ATOMIC(page, WT_PAGE_DISK_NOT_ALLOC)) __wt_free(session, page->dsk); __wt_overwrite_and_free(session, page); }
/* * __wt_curindex_joined -- * Produce an error that this cursor is being used in a join call. */ int __wt_curindex_joined(WT_CURSOR *cursor) { WT_SESSION_IMPL *session; session = (WT_SESSION_IMPL *)cursor->session; __wt_errx(session, "index cursor is being used in a join"); return (ENOTSUP); }
/* * __wt_block_read_off -- * Read an addr/size pair referenced block into a buffer. */ int __wt_block_read_off(WT_SESSION_IMPL *session, WT_BLOCK *block, WT_ITEM *buf, wt_off_t offset, uint32_t size, uint32_t cksum) { WT_BLOCK_HEADER *blk; size_t bufsize; uint32_t page_cksum; WT_RET(__wt_verbose(session, WT_VERB_READ, "off %" PRIuMAX ", size %" PRIu32 ", cksum %" PRIu32, (uintmax_t)offset, size, cksum)); WT_STAT_FAST_CONN_INCR(session, block_read); WT_STAT_FAST_CONN_INCRV(session, block_byte_read, size); /* * Grow the buffer as necessary and read the block. Buffers should be * aligned for reading, but there are lots of buffers (for example, file * cursors have two buffers each, key and value), and it's difficult to * be sure we've found all of them. If the buffer isn't aligned, it's * an easy fix: set the flag and guarantee we reallocate it. (Most of * the time on reads, the buffer memory has not yet been allocated, so * we're not adding any additional processing time.) */ if (F_ISSET(buf, WT_ITEM_ALIGNED)) bufsize = size; else { F_SET(buf, WT_ITEM_ALIGNED); bufsize = WT_MAX(size, buf->memsize + 10); } WT_RET(__wt_buf_init(session, buf, bufsize)); WT_RET(__wt_read(session, block->fh, offset, size, buf->mem)); buf->size = size; blk = WT_BLOCK_HEADER_REF(buf->mem); page_cksum = blk->cksum; if (page_cksum == cksum) { blk->cksum = 0; page_cksum = __wt_cksum(buf->mem, F_ISSET(blk, WT_BLOCK_DATA_CKSUM) ? size : WT_BLOCK_COMPRESS_SKIP); if (page_cksum == cksum) return (0); } if (!F_ISSET(session, WT_SESSION_SALVAGE_CORRUPT_OK)) __wt_errx(session, "read checksum error [%" PRIu32 "B @ %" PRIuMAX ", %" PRIu32 " != %" PRIu32 "]", size, (uintmax_t)offset, cksum, page_cksum); /* Panic if a checksum fails during an ordinary read. */ return (block->verify || F_ISSET(session, WT_SESSION_SALVAGE_CORRUPT_OK) ? WT_ERROR : __wt_illegal_value(session, block->name)); }
/* * __win_file_close -- * ANSI C close. */ static int __win_file_close(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session) { DWORD windows_error; 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; /* * Close the primary and secondary handles. * * We don't open Windows system handles when opening directories for * flushing, as it's not necessary (or possible) to flush a directory * on Windows. Confirm the file handle is open before closing it. */ if (win_fh->filehandle != INVALID_HANDLE_VALUE && CloseHandle(win_fh->filehandle) == 0) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-close: CloseHandle: %s", file_handle->name, __wt_formatmessage(session, windows_error)); ret = __wt_map_windows_error(windows_error); } if (win_fh->filehandle_secondary != INVALID_HANDLE_VALUE && CloseHandle(win_fh->filehandle_secondary) == 0) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-close: secondary: CloseHandle: %s", file_handle->name, __wt_formatmessage(session, windows_error)); ret = __wt_map_windows_error(windows_error); } __wt_free(session, file_handle->name); __wt_free(session, win_fh); return (ret); }
/* * __win_fs_rename -- * Rename a file. */ static int __win_fs_rename(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *from, const char *to, uint32_t flags) { DWORD windows_error; WT_DECL_RET; WT_DECL_ITEM(from_wide); WT_DECL_ITEM(to_wide); WT_SESSION_IMPL *session; WT_UNUSED(file_system); WT_UNUSED(flags); session = (WT_SESSION_IMPL *)wt_session; WT_ERR(__wt_to_utf16_string(session, from, &from_wide)); WT_ERR(__wt_to_utf16_string(session, to, &to_wide)); /* * Check if file exists since Windows does not override the file if * it exists. */ if (GetFileAttributesW(to_wide->data) != INVALID_FILE_ATTRIBUTES) if (DeleteFileW(to_wide->data) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: file-rename: DeleteFileW: %s", to, __wt_formatmessage(session, windows_error)); WT_ERR(__wt_map_windows_error(windows_error)); } if (MoveFileW(from_wide->data, to_wide->data) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s to %s: file-rename: MoveFileW: %s", from, to, __wt_formatmessage(session, windows_error)); WT_ERR(__wt_map_windows_error(windows_error)); } err: __wt_scr_free(session, &from_wide); __wt_scr_free(session, &to_wide); return (ret); }
/* * __win_file_lock -- * Lock/unlock a file. */ static int __win_file_lock( WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, bool lock) { DWORD windows_error; WT_FILE_HANDLE_WIN *win_fh; WT_SESSION_IMPL *session; win_fh = (WT_FILE_HANDLE_WIN *)file_handle; session = (WT_SESSION_IMPL *)wt_session; /* * WiredTiger requires this function be able to acquire locks past * the end of file. * * http://msdn.microsoft.com/ * en-us/library/windows/desktop/aa365202%28v=vs.85%29.aspx * * You can lock bytes that are beyond the end of the current file. * This is useful to coordinate adding records to the end of a file. */ if (lock) { if (LockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-lock: LockFile: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } } else if (UnlockFile(win_fh->filehandle, 0, 0, 1, 0) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-lock: UnlockFile: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } return (0); }
/* * __hazard_dump -- * Display the list of hazard pointers. */ static void __hazard_dump(WT_SESSION_IMPL *session) { WT_HAZARD *hp; for (hp = session->hazard; hp < session->hazard + session->hazard_size; ++hp) if (hp->page != NULL) __wt_errx(session, "session %p: hazard pointer %p: %s, line %d", session, hp->page, hp->file, hp->line); }
/* * __wt_cache_destroy -- * Discard the underlying cache. */ int __wt_cache_destroy(WT_SESSION_IMPL *session) { WT_CACHE *cache; WT_CONNECTION_IMPL *conn; WT_DECL_RET; conn = S2C(session); cache = conn->cache; if (cache == NULL) return (0); /* The cache should be empty at this point. Complain if not. */ if (cache->pages_inmem != cache->pages_evict) __wt_errx(session, "cache server: exiting with %" PRIu64 " pages in " "memory and %" PRIu64 " pages evicted", cache->pages_inmem, cache->pages_evict); if (cache->bytes_inmem != 0) __wt_errx(session, "cache server: exiting with %" PRIu64 " bytes in memory", cache->bytes_inmem); if (cache->bytes_dirty != 0 || cache->pages_dirty != 0) __wt_errx(session, "cache server: exiting with %" PRIu64 " bytes dirty and %" PRIu64 " pages dirty", cache->bytes_dirty, cache->pages_dirty); WT_TRET(__wt_cond_auto_destroy(session, &cache->evict_cond)); WT_TRET(__wt_cond_destroy(session, &cache->evict_waiter_cond)); __wt_spin_destroy(session, &cache->evict_lock); __wt_spin_destroy(session, &cache->evict_walk_lock); __wt_free(session, cache->evict_queue); __wt_free(session, conn->cache); return (ret); }
/* * __wt_attach -- * A routine to wait for the debugging to attach. */ void __wt_attach(WT_SESSION_IMPL *session) { #ifdef HAVE_ATTACH __wt_errx(session, "process ID %" PRIdMAX ": waiting for debugger...", (intmax_t)getpid()); /* Sleep forever, the debugger will interrupt us when it attaches. */ for (;;) __wt_sleep(100, 0); #else WT_UNUSED(session); #endif }
/* * __wt_thread_join -- * Wait for a thread of control to exit. */ int __wt_thread_join(WT_SESSION_IMPL *session, wt_thread_t *tid) { DWORD windows_error; /* Only attempt to join if thread was created successfully */ if (!tid->created) return (0); tid->created = false; /* * Joining a thread isn't a memory barrier, but WiredTiger commonly * sets flags and or state and then expects worker threads to halt. * Include a barrier to ensure safety in those cases. */ WT_FULL_BARRIER(); if ((windows_error = WaitForSingleObject(tid->id, INFINITE)) != WAIT_OBJECT_0) { if (windows_error == WAIT_FAILED) windows_error = __wt_getlasterror(); __wt_errx(session, "thread join: WaitForSingleObject: %s", __wt_formatmessage(session, windows_error)); /* If we fail to wait, we will leak handles, do not continue. */ return (WT_PANIC); } if (CloseHandle(tid->id) == 0) { windows_error = __wt_getlasterror(); __wt_errx(session, "thread join: CloseHandle: %s", __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } return (0); }
/* * __wt_meta_track_on -- * Turn on metadata operation tracking. */ int __wt_meta_track_on(WT_SESSION_IMPL *session) { if (session->meta_track_nest++ == 0) { if (!F_ISSET(&session->txn, WT_TXN_RUNNING)) { #ifdef WT_ENABLE_SCHEMA_TXN WT_RET(__wt_txn_begin(session, NULL)); __wt_errx(session, "TRACK: Using internal schema txn"); #endif F_SET(session, WT_SESSION_SCHEMA_TXN); } WT_RET(__meta_track_next(session, NULL)); } return (0); }
/* * __wt_dlclose -- * Close a dynamic library */ int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh) { DWORD windows_error; WT_DECL_RET; if (FreeLibrary(dlh->handle) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "FreeLibrary: %s: %s", dlh->name, __wt_formatmessage(session, windows_error)); ret = __wt_map_windows_error(windows_error); } __wt_free(session, dlh->name); __wt_free(session, dlh); return (ret); }
/* * __win_file_write -- * Write a chunk. */ static int __win_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t offset, size_t len, const void *buf) { DWORD chunk, nw, windows_error; const uint8_t *addr; OVERLAPPED overlapped = { 0 }; WT_FILE_HANDLE_WIN *win_fh; WT_SESSION_IMPL *session; win_fh = (WT_FILE_HANDLE_WIN *)file_handle; session = (WT_SESSION_IMPL *)wt_session; nw = 0; /* Assert direct I/O is aligned and a multiple of the alignment. */ WT_ASSERT(session, !win_fh->direct_io || S2C(session)->buffer_alignment == 0 || (!((uintptr_t)buf & (uintptr_t)(S2C(session)->buffer_alignment - 1)) && len >= S2C(session)->buffer_alignment && len % S2C(session)->buffer_alignment == 0)); /* Break writes larger than 1GB into 1GB chunks. */ for (addr = buf; len > 0; addr += nw, len -= (size_t)nw, offset += nw) { chunk = (DWORD)WT_MIN(len, WT_GIGABYTE); overlapped.Offset = UINT32_MAX & offset; overlapped.OffsetHigh = UINT32_MAX & (offset >> 32); if (!WriteFile( win_fh->filehandle, addr, chunk, &nw, &overlapped)) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-write: WriteFile: failed to write %lu " "bytes at offset %" PRIuMAX ": %s", file_handle->name, chunk, (uintmax_t)offset, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } } return (0); }
/* * __win_fs_remove -- * Remove a file. */ static int __win_fs_remove(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, const char *name, uint32_t flags) { DWORD windows_error; WT_SESSION_IMPL *session; WT_UNUSED(file_system); WT_UNUSED(flags); session = (WT_SESSION_IMPL *)wt_session; if (DeleteFileA(name) == FALSE) { windows_error = __wt_getlasterror(); __wt_errx(session, "%s: file-remove: DeleteFileA: %s", name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } return (0); }
/* * __wt_close_connection_close -- * Close any open file handles at connection close. */ int __wt_close_connection_close(WT_SESSION_IMPL *session) { WT_DECL_RET; WT_FH *fh; WT_CONNECTION_IMPL *conn; conn = S2C(session); while ((fh = TAILQ_FIRST(&conn->fhqh)) != NULL) { if (fh->ref != 0) { ret = EBUSY; __wt_errx(session, "Connection has open file handles: %s", fh->name); } fh->ref = 1; WT_TRET(__wt_close(session, &fh)); } return (ret); }
/* * __wt_dlsym -- * Lookup a symbol in a dynamic library. */ int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, bool fail, void *sym_ret) { DWORD windows_error; void *sym; *(void **)sym_ret = NULL; sym = GetProcAddress(dlh->handle, name); if (sym == NULL && fail) { windows_error = __wt_getlasterror(); __wt_errx(session, "GetProcAddress: %s in %s: %s", name, dlh->name, __wt_formatmessage(session, windows_error)); WT_RET(__wt_map_windows_error(windows_error)); } *(void **)sym_ret = sym; return (0); }
/* * __wt_getenv -- * Get a non-NULL, greater than zero-length environment variable. */ int __wt_getenv(WT_SESSION_IMPL *session, const char *variable, const char **envp) { DWORD size, windows_error; *envp = NULL; if ((size = GetEnvironmentVariableA(variable, NULL, 0)) <= 1) return (0); WT_RET(__wt_malloc(session, (size_t)size, envp)); /* We expect the number of bytes not including nul terminator. */ if (GetEnvironmentVariableA(variable, *envp, size) == size - 1) return (0); windows_error = __wt_getlasterror(); __wt_errx(session, "GetEnvironmentVariableA: %s: %s", variable, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); }
/* * __log_slot_dump -- * Dump the entire slot state. */ static void __log_slot_dump(WT_SESSION_IMPL *session) { WT_CONNECTION_IMPL *conn; WT_LOG *log; WT_LOGSLOT *slot; int earliest, i; conn = S2C(session); log = conn->log; earliest = 0; for (i = 0; i < WT_SLOT_POOL; i++) { slot = &log->slot_pool[i]; if (__wt_log_cmp(&slot->slot_release_lsn, &log->slot_pool[earliest].slot_release_lsn) < 0) earliest = i; __wt_errx(session, "Slot %d:", i); __wt_errx(session, " State: %" PRIx64 " Flags: %" PRIx32, (uint64_t)slot->slot_state, slot->flags); __wt_errx(session, " Start LSN: %" PRIu32 "/%" PRIu32, slot->slot_start_lsn.l.file, slot->slot_start_lsn.l.offset); __wt_errx(session, " End LSN: %" PRIu32 "/%" PRIu32, slot->slot_end_lsn.l.file, slot->slot_end_lsn.l.offset); __wt_errx(session, " Release LSN: %" PRIu32 "/%" PRIu32, slot->slot_release_lsn.l.file, slot->slot_release_lsn.l.offset); __wt_errx(session, " Offset: start: %" PRIuMAX " last:%" PRIuMAX, (uintmax_t)slot->slot_start_offset, (uintmax_t)slot->slot_last_offset); __wt_errx(session, " Unbuffered: %" PRId64 " error: %" PRId32, slot->slot_unbuffered, slot->slot_error); } __wt_errx(session, "Earliest slot: %d", earliest); }
/* * __win_file_size -- * Get the size of a file in bytes, by file handle. */ static int __win_file_size( WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t *sizep) { DWORD windows_error; WT_FILE_HANDLE_WIN *win_fh; WT_SESSION_IMPL *session; LARGE_INTEGER size; win_fh = (WT_FILE_HANDLE_WIN *)file_handle; session = (WT_SESSION_IMPL *)wt_session; if (GetFileSizeEx(win_fh->filehandle, &size) != 0) { *sizep = size.QuadPart; return (0); } windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-size: GetFileSizeEx: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); }
/* * __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; WT_FILE_HANDLE_WIN *win_fh; WT_SESSION_IMPL *session; LARGE_INTEGER largeint; 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(); __wt_errx(session, "%s: handle-set-end: SetFilePointerEx: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } if (SetEndOfFile(win_fh->filehandle_secondary) == FALSE) { if (GetLastError() == ERROR_USER_MAPPED_FILE) return (EBUSY); windows_error = __wt_getlasterror(); __wt_errx(session, "%s: handle-set-end: SetEndOfFile: %s", file_handle->name, __wt_formatmessage(session, windows_error)); return (__wt_map_windows_error(windows_error)); } return (0); }