/* * __wt_dlclose -- * Close a dynamic library */ int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh) { int ret; ret = 0; /* * FreeBSD dies inside __cxa_finalize when closing handles. * * For now, just skip the dlclose: this may leak some resources until * the process exits, but that is preferable to hard-to-debug crashes * during exit. */ #ifndef __FreeBSD__ if (dlclose(dlh->handle) != 0) { ret = __wt_errno(); __wt_err(session, ret, "dlclose: %s", dlerror()); } #endif __wt_free(session, dlh->name); __wt_free(session, dlh); return (ret); }
int __wt_write(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t offset, size_t len, const void *buf) { size_t chunk; ssize_t nw; const uint8_t *addr; WT_STAT_FAST_CONN_INCR(session, write_io); WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: write %" WT_SIZET_FMT " bytes at offset %" PRIuMAX, fh->name, len, (uintmax_t)offset)); /* Assert direct I/O is aligned and a multiple of the alignment. */ WT_ASSERT(session, !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 = WT_MIN(len, WT_GIGABYTE); if ((nw = pwrite(fh->fd, addr, chunk, offset)) < 0) WT_RET_MSG(session, __wt_errno(), "%s write error: failed to write %" WT_SIZET_FMT " bytes at offset %" PRIuMAX, fh->name, chunk, (uintmax_t)offset); } return (0); }
/* * __wt_mmap -- * Map a file into memory. */ int __wt_mmap(WT_SESSION_IMPL *session, WT_FH *fh, void *mapp, size_t *lenp, void **mappingcookie) { void *map; size_t orig_size; WT_UNUSED(mappingcookie); /* * Record the current size and only map and set that as the length, it * could change between the map call and when we set the return length. * For the same reason we could actually map past the end of the file; * we don't read bytes past the end of the file though, so as long as * the map call succeeds, it's all OK. */ orig_size = (size_t)fh->size; if ((map = mmap(NULL, orig_size, PROT_READ, #ifdef MAP_NOCORE MAP_NOCORE | #endif MAP_PRIVATE, fh->fd, (wt_off_t)0)) == MAP_FAILED) { WT_RET_MSG(session, __wt_errno(), "%s map error: failed to map %" WT_SIZET_FMT " bytes", fh->name, orig_size); } (void)__wt_verbose(session, WT_VERB_FILEOPS, "%s: map %p: %" WT_SIZET_FMT " bytes", fh->name, map, orig_size); *(void **)mapp = map; *lenp = orig_size; return (0); }
/* * __posix_file_write -- * POSIX pwrite. */ static int __posix_file_write(WT_FILE_HANDLE *file_handle, WT_SESSION *wt_session, wt_off_t offset, size_t len, const void *buf) { WT_FILE_HANDLE_POSIX *pfh; WT_SESSION_IMPL *session; size_t chunk; ssize_t nw; const uint8_t *addr; session = (WT_SESSION_IMPL *)wt_session; pfh = (WT_FILE_HANDLE_POSIX *)file_handle; /* Assert direct I/O is aligned and a multiple of the alignment. */ WT_ASSERT(session, !pfh->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 = WT_MIN(len, WT_GIGABYTE); if ((nw = pwrite(pfh->fd, addr, chunk, offset)) < 0) WT_RET_MSG(session, __wt_errno(), "%s: handle-write: pwrite: failed to write %" WT_SIZET_FMT " bytes at offset %" PRIuMAX, file_handle->name, chunk, (uintmax_t)offset); } return (0); }
/* * __wt_close -- * Close a file handle. */ int __wt_close(WT_SESSION_IMPL *session, WT_FH *fh) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; conn = S2C(session); __wt_spin_lock(session, &conn->fh_lock); if (fh == NULL || fh->refcnt == 0 || --fh->refcnt > 0) { __wt_spin_unlock(session, &conn->fh_lock); return (0); } /* Remove from the list. */ TAILQ_REMOVE(&conn->fhqh, fh, q); WT_STAT_FAST_CONN_DECR(session, file_open); __wt_spin_unlock(session, &conn->fh_lock); /* Discard the memory. */ if (close(fh->fd) != 0) { ret = __wt_errno(); __wt_err(session, ret, "%s", fh->name); } __wt_free(session, fh->name); __wt_free(session, fh); return (ret); }
/* * __wt_turtle_update -- * Update the turtle file. */ int __wt_turtle_update( WT_SESSION_IMPL *session, const char *key, const char *value) { FILE *fp; WT_DECL_RET; int vmajor, vminor, vpatch; const char *version; char *path; fp = NULL; path = NULL; /* * Create the turtle setup file: we currently re-write it from scratch * every time. */ WT_RET(__wt_filename(session, WT_METADATA_TURTLE_SET, &path)); if ((fp = fopen(path, "w")) == NULL) ret = __wt_errno(); __wt_free(session, path); if (fp == NULL) return (ret); version = wiredtiger_version(&vmajor, &vminor, &vpatch); WT_ERR_TEST((fprintf(fp, "%s\n%s\n%s\n" "major=%d,minor=%d,patch=%d\n%s\n%s\n", WT_METADATA_VERSION_STR, version, WT_METADATA_VERSION, vmajor, vminor, vpatch, key, value) < 0), __wt_errno()); ret = fclose(fp); fp = NULL; WT_ERR_TEST(ret == EOF, __wt_errno()); WT_ERR( __wt_rename(session, WT_METADATA_TURTLE_SET, WT_METADATA_TURTLE)); if (0) { err: WT_TRET(__wt_remove(session, WT_METADATA_TURTLE_SET)); } if (fp != NULL) WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno()); return (ret); }
/* * __backup_all -- * Backup all objects in the database. */ static int __backup_all(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb) { WT_CONFIG_ITEM cval; WT_CURSOR *cursor; WT_DECL_RET; const char *key, *value; cursor = NULL; /* * Open a cursor on the metadata file and copy all of the entries to * the hot backup file. */ WT_ERR(__wt_metadata_cursor(session, NULL, &cursor)); while ((ret = cursor->next(cursor)) == 0) { WT_ERR(cursor->get_key(cursor, &key)); WT_ERR(cursor->get_value(cursor, &value)); WT_ERR_TEST((fprintf( cb->bfp, "%s\n%s\n", key, value) < 0), __wt_errno()); /* * While reading the metadata file, check there are no "sources" * or "types" which can't support hot backup. This checks for * a data source that's non-standard, which can't be backed up, * but is also sanity checking: if there's an entry backed by * anything other than a file or lsm entry, we're confused. */ if ((ret = __wt_config_getones( session, value, "type", &cval)) == 0 && !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "file") && !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "lsm")) WT_ERR_MSG(session, ENOTSUP, "hot backup is not supported for objects of " "type %.*s", (int)cval.len, cval.str); WT_ERR_NOTFOUND_OK(ret); if ((ret =__wt_config_getones( session, value, "source", &cval)) == 0 && !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "file:") && !WT_PREFIX_MATCH_LEN(cval.str, cval.len, "lsm:")) WT_ERR_MSG(session, ENOTSUP, "hot backup is not supported for objects of " "source %.*s", (int)cval.len, cval.str); WT_ERR_NOTFOUND_OK(ret); } WT_ERR_NOTFOUND_OK(ret); /* Build a list of the file objects that need to be copied. */ WT_WITH_DHANDLE_LOCK(session, ret = __wt_meta_btree_apply( session, __backup_list_all_append, NULL)); err: if (cursor != NULL) WT_TRET(cursor->close(cursor)); return (ret); }
/* * __handle_message_default -- * Default WT_EVENT_HANDLER->handle_message implementation: send to stdout. */ static int __handle_message_default(WT_EVENT_HANDLER *handler, WT_SESSION *session, const char *message) { WT_UNUSED(handler); WT_UNUSED(session); return (printf("%s\n", message) >= 0 && fflush(stdout) == 0 ? 0 : __wt_errno()); }
/* * __wt_close -- * Close a file handle. */ int __wt_close(WT_SESSION_IMPL *session, WT_FH *fh) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; uint64_t bucket; conn = S2C(session); __wt_spin_lock(session, &conn->fh_lock); if (fh == NULL || fh->ref == 0 || --fh->ref > 0) { __wt_spin_unlock(session, &conn->fh_lock); return (0); } /* Remove from the list. */ bucket = fh->name_hash % WT_HASH_ARRAY_SIZE; WT_CONN_FILE_REMOVE(conn, fh, bucket); WT_STAT_FAST_CONN_DECR(session, file_open); __wt_spin_unlock(session, &conn->fh_lock); /* Discard the memory. * Note: For directories, we do not open valid directory handles on * windows since it is not possible to sync a directory */ if (fh->filehandle != INVALID_HANDLE_VALUE && CloseHandle(fh->filehandle) == 0) { ret = __wt_errno(); __wt_err(session, ret, "CloseHandle: %s", fh->name); } if (fh->filehandle_secondary != INVALID_HANDLE_VALUE && CloseHandle(fh->filehandle_secondary) == 0) { ret = __wt_errno(); __wt_err(session, ret, "CloseHandle: secondary: %s", fh->name); } __wt_free(session, fh->name); __wt_free(session, fh); return (ret); }
/* * __handle_error_default -- * Default WT_EVENT_HANDLER->handle_error implementation: send to stderr. */ static int __handle_error_default(WT_EVENT_HANDLER *handler, WT_SESSION *session, int error, const char *errmsg) { WT_UNUSED(handler); WT_UNUSED(session); WT_UNUSED(error); return (fprintf(stderr, "%s\n", errmsg) >= 0 && fflush(stderr) == 0 ? 0 : __wt_errno()); }
/* * __realloc_func -- * ANSI realloc function. */ static int __realloc_func(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, bool clear_memory, void *retp) { void *p; size_t bytes_allocated; /* * !!! * This function MUST handle a NULL WT_SESSION_IMPL handle. * * Sometimes we're allocating memory and we don't care about the * final length -- bytes_allocated_ret may be NULL. */ p = *(void **)retp; bytes_allocated = (bytes_allocated_ret == NULL) ? 0 : *bytes_allocated_ret; WT_ASSERT(session, (p == NULL && bytes_allocated == 0) || (p != NULL && (bytes_allocated_ret == NULL || bytes_allocated != 0))); WT_ASSERT(session, bytes_to_allocate != 0); WT_ASSERT(session, bytes_allocated < bytes_to_allocate); if (session != NULL) { if (p == NULL) WT_STAT_CONN_INCR(session, memory_allocation); else WT_STAT_CONN_INCR(session, memory_grow); } if ((p = realloc(p, bytes_to_allocate)) == NULL) WT_RET_MSG(session, __wt_errno(), "memory allocation of %" WT_SIZET_FMT " bytes failed", bytes_to_allocate); /* * Clear the allocated memory, parts of WiredTiger depend on allocated * memory being cleared. */ if (clear_memory) memset((uint8_t *)p + bytes_allocated, 0, bytes_to_allocate - bytes_allocated); /* Update caller's bytes allocated value. */ if (bytes_allocated_ret != NULL) *bytes_allocated_ret = bytes_to_allocate; *(void **)retp = p; return (0); }
/* * __wt_meta_turtle_read -- * Read the turtle file. */ int __wt_meta_turtle_read( WT_SESSION_IMPL *session, const char *key, const char **valuep) { FILE *fp; WT_DECL_RET; const char *path; char *p, line[1024]; fp = NULL; path = NULL; /* Open the turtle file. */ WT_RET(__wt_filename(session, WT_METADATA_TURTLE, &path)); WT_ERR_TEST((fp = fopen(path, "r")) == NULL, WT_NOTFOUND); /* Search for the key. */ ret = WT_NOTFOUND; while (fgets(line, sizeof(line), fp) != NULL) { if ((p = strchr(line, '\n')) == NULL) goto format; *p = '\0'; if (strcmp(key, line) == 0) ret = 0; /* Key matched: read the subsequent line for the value. */ if (fgets(line, sizeof(line), fp) == NULL) goto format; if ((p = strchr(line, '\n')) == NULL) goto format; *p = '\0'; if (ret == 0) break; } /* Check for an I/O error. */ if (ferror(fp)) WT_ERR(__wt_errno()); WT_ERR(ret); /* Successful: copy the value for the caller. */ WT_ERR(__wt_strdup(session, line, valuep)); if (0) { format: return (__wt_illegal_value(session, WT_METADATA_TURTLE)); } err: if (fp != NULL) WT_TRET(fclose(fp)); __wt_free(session, path); return (ret); }
/* * __wt_realloc -- * ANSI realloc function. */ int __wt_realloc(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp) { void *p; size_t bytes_allocated; /* * !!! * This function MUST handle a NULL WT_SESSION_IMPL handle. * * Sometimes we're allocating memory and we don't care about the * final length -- bytes_allocated_ret may be NULL. */ p = *(void **)retp; bytes_allocated = (bytes_allocated_ret == NULL) ? 0 : *bytes_allocated_ret; WT_ASSERT(session, (p == NULL && bytes_allocated == 0) || (p != NULL && (bytes_allocated_ret == NULL || bytes_allocated != 0))); WT_ASSERT(session, bytes_to_allocate != 0); WT_ASSERT(session, bytes_allocated < bytes_to_allocate); if (session != NULL) { if (p == NULL) WT_STAT_FAST_CONN_INCR(session, memory_allocation); else WT_STAT_FAST_CONN_INCR(session, memory_grow); } if ((p = realloc(p, bytes_to_allocate)) == NULL) WT_RET_MSG(session, __wt_errno(), "memory allocation"); /* * Clear the allocated memory -- an application might: allocate memory, * write secret stuff into it, free the memory, then we re-allocate the * memory and use it for a file page or log record, and then write it to * disk. That would result in the secret stuff being protected by the * WiredTiger permission mechanisms, potentially inappropriate for the * secret stuff. */ memset((uint8_t *) p + bytes_allocated, 0, bytes_to_allocate - bytes_allocated); /* Update caller's bytes allocated value. */ if (bytes_allocated_ret != NULL) *bytes_allocated_ret = bytes_to_allocate; *(void **)retp = p; return (0); }
/* * __wt_ftruncate -- * Truncate a file. */ int __wt_ftruncate(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t len) { WT_DECL_RET; LARGE_INTEGER largeint; largeint.QuadPart = len; if ((ret = SetFilePointerEx( fh->filehandle_secondary, largeint, NULL, FILE_BEGIN)) == FALSE) WT_RET_MSG(session, __wt_errno(), "%s SetFilePointerEx error", fh->name); ret = SetEndOfFile(fh->filehandle_secondary); if (ret != FALSE) return (0); if (GetLastError() == ERROR_USER_MAPPED_FILE) return (EBUSY); WT_RET_MSG(session, __wt_errno(), "%s SetEndOfFile error", fh->name); }
/* * __wt_dlsym -- * Lookup a symbol in a dynamic library. */ int __wt_dlsym( WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, void *sym_ret) { void *sym; if ((sym = dlsym(dlh->handle, name)) == NULL) WT_RET_MSG(session, __wt_errno(), "dlsym(%s in %s): %s", name, dlh->name, dlerror()); *(void **)sym_ret = sym; return (0); }
/* * __backup_file_create -- * Create the meta-data backup file. */ static int __backup_file_create(WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb) { WT_DECL_RET; char *path; /* Open the hot backup file. */ WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path)); WT_ERR_TEST((cb->bfp = fopen(path, "w")) == NULL, __wt_errno()); err: __wt_free(session, path); return (ret); }
/* * __wt_munmap -- * Remove a memory mapping. */ int __wt_munmap(WT_SESSION_IMPL *session, WT_FH *fh, void *map, size_t len) { WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: unmap %" PRIuMAX " bytes", fh->name, (uintmax_t)len)); if (munmap(map, len) == 0) return (0); WT_RET_MSG(session, __wt_errno(), "%s unmap error: failed to unmap %" PRIuMAX " bytes", fh->name, (uintmax_t)len); }
/* * __wt_munmap -- * Remove a memory mapping. */ int __wt_munmap(WT_SESSION_IMPL *session, WT_FH *fh, void *map, size_t len, void **mappingcookie) { WT_UNUSED(mappingcookie); WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: unmap %p: %" WT_SIZET_FMT " bytes", fh->name, map, len)); if (munmap(map, len) == 0) return (0); WT_RET_MSG(session, __wt_errno(), "%s unmap error: failed to unmap %" WT_SIZET_FMT " bytes", fh->name, len); }
/* * __wt_filesize -- * Get the size of a file in bytes. */ int __wt_filesize(WT_SESSION_IMPL *session, WT_FH *fh, wt_off_t *sizep) { WT_DECL_RET; LARGE_INTEGER size; WT_RET(__wt_verbose( session, WT_VERB_FILEOPS, "%s: GetFileSizeEx", fh->name)); if ((ret = GetFileSizeEx(fh->filehandle, &size)) != 0) { *sizep = size.QuadPart; return (0); } WT_RET_MSG(session, __wt_errno(), "%s: GetFileSizeEx", fh->name); }
/* * __wt_dlclose -- * Close a dynamic library */ int __wt_dlclose(WT_SESSION_IMPL *session, WT_DLH *dlh) { WT_DECL_RET; if ((ret = FreeLibrary(dlh->handle)) == FALSE) { __wt_err(session, __wt_errno(), "FreeLibrary"); } /* Windows returns 0 on failure, WT expects 0 on success */ ret = !ret; __wt_free(session, dlh->name); __wt_free(session, dlh); return (ret); }
/* * __wt_dlsym -- * Lookup a symbol in a dynamic library. */ int __wt_dlsym(WT_SESSION_IMPL *session, WT_DLH *dlh, const char *name, int fail, void *sym_ret) { void *sym; *(void **)sym_ret = NULL; sym = GetProcAddress(dlh->handle, name); if (sym == NULL && fail) { WT_RET_MSG(session, __wt_errno(), "GetProcAddress(%s in %s): %s", name, dlh->name, 0); } *(void **)sym_ret = sym; return (0); }
/* * __wt_metadata_load_backup -- * Load the contents of any hot backup file. */ int __wt_metadata_load_backup(WT_SESSION_IMPL *session) { FILE *fp; WT_DECL_ITEM(key); WT_DECL_ITEM(value); WT_DECL_RET; const char *path; fp = NULL; path = NULL; /* Look for a hot backup file: if we find it, load it. */ WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path)); if ((fp = fopen(path, "r")) == NULL) { __wt_free(session, path); return (0); } /* Read line pairs and load them into the metadata file. */ WT_ERR(__wt_scr_alloc(session, 512, &key)); WT_ERR(__wt_scr_alloc(session, 512, &value)); for (;;) { WT_ERR(__wt_getline(session, key, fp)); if (key->size == 0) break; WT_ERR(__wt_getline(session, value, fp)); if (value->size == 0) WT_ERR(__wt_illegal_value(session, WT_METADATA_BACKUP)); WT_ERR(__wt_metadata_update(session, key->data, value->data)); } /* Remove the hot backup file, it's only read (successfully) once. */ WT_ERR(__wt_remove(session, WT_METADATA_BACKUP)); err: if (fp != NULL) WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno()); if (path != NULL) __wt_free(session, path); __wt_scr_free(&key); __wt_scr_free(&value); return (ret); }
/* * __wt_thread_create -- * Create a new thread of control. */ int __wt_thread_create(WT_SESSION_IMPL *session, wt_thread_t *tidret, WT_THREAD_CALLBACK(*func)(void *), void *arg) { /* * Creating a thread isn't a memory barrier, but WiredTiger commonly * sets flags and or state and then expects worker threads to start. * Include a barrier to ensure safety in those cases. */ WT_FULL_BARRIER(); /* Spawn a new thread of control. */ tidret->id = (HANDLE)_beginthreadex(NULL, 0, func, arg, 0, NULL); if (tidret->id != 0) { tidret->created = true; return (0); } WT_RET_MSG(session, __wt_errno(), "thread create: _beginthreadex"); }
/* * __wt_calloc -- * ANSI calloc function. */ int __wt_calloc(WT_SESSION_IMPL *session, size_t number, size_t size, void *retp) { void *p; /* * !!! * This function MUST handle a NULL WT_SESSION_IMPL handle. */ WT_ASSERT(session, number != 0 && size != 0); if (session != NULL) WT_STAT_FAST_CONN_INCR(session, memory_allocation); if ((p = calloc(number, size)) == NULL) WT_RET_MSG(session, __wt_errno(), "memory allocation"); *(void **)retp = p; return (0); }
/* * __wt_dlopen -- * Open a dynamic library. */ int __wt_dlopen(WT_SESSION_IMPL *session, const char *path, WT_DLH **dlhp) { WT_DECL_RET; WT_DLH *dlh; WT_RET(__wt_calloc_one(session, &dlh)); WT_ERR(__wt_strdup(session, path, &dlh->name)); if ((dlh->handle = dlopen(path, RTLD_LAZY)) == NULL) WT_ERR_MSG( session, __wt_errno(), "dlopen(%s): %s", path, dlerror()); *dlhp = dlh; if (0) { err: __wt_free(session, dlh->name); __wt_free(session, dlh); } return (ret); }
/* * __wt_fopen -- * Open a FILE handle. */ int __wt_fopen(WT_SESSION_IMPL *session, const char *name, WT_FHANDLE_MODE mode_flag, u_int flags, FILE **fpp) { WT_DECL_RET; const char *mode, *path; char *pathbuf; WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: fopen", name)); pathbuf = NULL; if (LF_ISSET(WT_FOPEN_FIXED)) path = name; else { WT_RET(__wt_filename(session, name, &pathbuf)); path = pathbuf; } mode = NULL; switch (mode_flag) { case WT_FHANDLE_APPEND: mode = WT_FOPEN_APPEND; break; case WT_FHANDLE_READ: mode = WT_FOPEN_READ; break; case WT_FHANDLE_WRITE: mode = WT_FOPEN_WRITE; break; } *fpp = fopen(path, mode); if (*fpp == NULL) ret = __wt_errno(); if (pathbuf != NULL) __wt_free(session, pathbuf); if (ret == 0) return (0); WT_RET_MSG(session, ret, "%s: fopen", name); }
/* * __metadata_load_hot_backup -- * Load the contents of any hot backup file. */ static int __metadata_load_hot_backup(WT_SESSION_IMPL *session) { FILE *fp; WT_DECL_ITEM(key); WT_DECL_ITEM(value); WT_DECL_RET; char *path; fp = NULL; path = NULL; /* Look for a hot backup file: if we find it, load it. */ WT_RET(__wt_filename(session, WT_METADATA_BACKUP, &path)); fp = fopen(path, "r"); __wt_free(session, path); if (fp == NULL) return (0); /* Read line pairs and load them into the metadata file. */ WT_ERR(__wt_scr_alloc(session, 512, &key)); WT_ERR(__wt_scr_alloc(session, 512, &value)); for (;;) { WT_ERR(__wt_getline(session, key, fp)); if (key->size == 0) break; WT_ERR(__wt_getline(session, value, fp)); if (value->size == 0) WT_ERR(__wt_illegal_value(session, WT_METADATA_BACKUP)); WT_ERR(__wt_metadata_update(session, key->data, value->data)); } F_SET(S2C(session), WT_CONN_WAS_BACKUP); err: if (fp != NULL) WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno()); __wt_scr_free(&key); __wt_scr_free(&value); return (ret); }
/* * __wt_filesize_name -- * Return the size of a file in bytes, given a file name. */ int __wt_filesize_name( WT_SESSION_IMPL *session, const char *filename, wt_off_t *sizep) { WT_DECL_RET; WIN32_FILE_ATTRIBUTE_DATA data; char *path; WT_RET(__wt_filename(session, filename, &path)); ret = GetFileAttributesExA(path, GetFileExInfoStandard, &data); __wt_free(session, path); if (ret != 0) { *sizep = ((int64_t)data.nFileSizeHigh << 32) | data.nFileSizeLow; return (0); } WT_RET_MSG(session, __wt_errno(), "%s: GetFileAttributesEx", filename); }
/* * __wt_backup_list_uri_append -- * Append a new file name to the list, allocate space as necessary. * Called via the schema_worker function. */ int __wt_backup_list_uri_append( WT_SESSION_IMPL *session, const char *name, int *skip) { WT_CURSOR_BACKUP *cb; const char *value; cb = session->bkp_cursor; WT_UNUSED(skip); /* Add the metadata entry to the backup file. */ WT_RET(__wt_metadata_search(session, name, &value)); WT_RET_TEST( (fprintf(cb->bfp, "%s\n%s\n", name, value) < 0), __wt_errno()); __wt_free(session, value); /* Add file type objects to the list of files to be copied. */ if (WT_PREFIX_MATCH(name, "file:")) WT_RET(__backup_list_append(session, cb, name)); 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) { WT_DECL_RET; DWORD size; *envp = NULL; size = GetEnvironmentVariableA(variable, NULL, 0); if (size <= 1) return (WT_NOTFOUND); WT_RET(__wt_calloc(session, 1, size, envp)); ret = GetEnvironmentVariableA(variable, *envp, size); /* We expect the number of bytes not including nul terminator. */ if ((ret + 1) != size) WT_RET_MSG(session, __wt_errno(), "GetEnvironmentVariableA failed: %s", variable); return (0); }