/* * __wt_rename -- * Rename a file. */ int __wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to) { WT_DECL_RET; char *from_path, *to_path; WT_RET(__wt_verbose( session, WT_VERB_FILEOPS, "rename %s to %s", from, to)); WT_ASSERT(session, !F_ISSET(S2C(session), WT_CONN_READONLY)); from_path = to_path = NULL; WT_RET(__wt_filename(session, from, &from_path)); WT_TRET(__wt_filename(session, to, &to_path)); if (ret == 0) WT_SYSCALL_RETRY(rename(from_path, to_path), ret); __wt_free(session, from_path); __wt_free(session, to_path); if (ret == 0) return (0); WT_RET_MSG(session, ret, "rename %s to %s", from, to); }
/* * __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, bool silent, wt_off_t *sizep) { struct stat sb; WT_DECL_RET; char *path; WT_RET(__wt_filename(session, filename, &path)); WT_SYSCALL_RETRY(stat(path, &sb), ret); __wt_free(session, path); if (ret == 0) { *sizep = sb.st_size; return (0); } /* * Some callers of this function expect failure if the file doesn't * exist, and don't want an error message logged. */ if (!silent) WT_RET_MSG(session, ret, "%s: fstat", filename); return (ret); }
/* * __backup_file_create -- * Create the meta-data backup file. */ static int __backup_file_create( WT_SESSION_IMPL *session, WT_CURSOR_BACKUP *cb, int incremental) { WT_DECL_RET; char *path; /* Open the hot backup file. */ if (incremental) WT_RET(__wt_filename(session, WT_INCREMENTAL_BACKUP, &path)); else 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_rename -- * Rename a file. */ int __wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to) { int ret; const char *from_path, *to_path; WT_VERBOSE(session, fileops, "rename %s to %s", from, to); WT_RET(__wt_filename(session, from, &from_path)); WT_RET(__wt_filename(session, to, &to_path)); WT_SYSCALL_RETRY(rename(from_path, to_path), ret); __wt_free(session, from_path); __wt_free(session, to_path); if (ret == 0) return (0); WT_RET_MSG(session, ret, "rename %s to %s", from, to); }
/* * __wt_turtle_read -- * Read the turtle file. */ int __wt_turtle_read(WT_SESSION_IMPL *session, const char *key, char **valuep) { FILE *fp; WT_DECL_ITEM(buf); WT_DECL_RET; int match; char *path; *valuep = NULL; fp = NULL; path = NULL; /* * Open the turtle file; there's one case where we won't find the turtle * file, yet still succeed. We create the metadata file before creating * the turtle file, and that means returning the default configuration * string for the metadata file. */ WT_RET(__wt_filename(session, WT_METADATA_TURTLE, &path)); if ((fp = fopen(path, "r")) == NULL) ret = __wt_errno(); __wt_free(session, path); if (fp == NULL) return (strcmp(key, WT_METAFILE_URI) == 0 ? __metadata_config(session, valuep) : ret); /* Search for the key. */ WT_ERR(__wt_scr_alloc(session, 512, &buf)); for (match = 0;;) { WT_ERR(__wt_getline(session, buf, fp)); if (buf->size == 0) WT_ERR(WT_NOTFOUND); if (strcmp(key, buf->data) == 0) match = 1; /* Key matched: read the subsequent line for the value. */ WT_ERR(__wt_getline(session, buf, fp)); if (buf->size == 0) WT_ERR(__wt_illegal_value(session, WT_METADATA_TURTLE)); if (match) break; } /* Copy the value for the caller. */ WT_ERR(__wt_strdup(session, buf->data, valuep)); err: if (fp != NULL) WT_TRET(fclose(fp) == 0 ? 0 : __wt_errno()); __wt_scr_free(&buf); return (ret); }
/* * __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_rename -- * Rename a file. */ int __wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to) { WT_DECL_RET; uint32_t lasterror; char *from_path, *to_path; WT_RET(__wt_verbose( session, WT_VERB_FILEOPS, "rename %s to %s", from, to)); from_path = to_path = NULL; WT_RET(__wt_filename(session, from, &from_path)); WT_TRET(__wt_filename(session, to, &to_path)); /* * Check if file exists since Windows does not override the file if * it exists. */ if ((ret = GetFileAttributesA(to_path)) != INVALID_FILE_ATTRIBUTES) { if ((ret = DeleteFileA(to_path)) == FALSE) { lasterror = GetLastError(); goto err; } } if ((MoveFileA(from_path, to_path)) == FALSE) lasterror = GetLastError(); err: __wt_free(session, from_path); __wt_free(session, to_path); if (ret != FALSE) return (0); WT_RET_MSG(session, lasterror, "MoveFile %s to %s", from, to); }
/*调用rename系统调用*/ int __wt_rename(WT_SESSION_IMPL *session, const char *from, const char *to) { WT_DECL_RET; char *from_path, *to_path; WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "rename %s to %s", from, to)); from_path = to_path = NULL; /*对路劲进行校验,如果不合法路径,直接返回*/ WT_RET(__wt_filename(session, from, &from_path)); WT_TRET(__wt_filename(session, to, &to_path)); if (ret == 0) WT_SYSCALL_RETRY(rename(from_path, to_path), ret); __wt_free(session, from_path); __wt_free(session, to_path); if(ret == 0) return 0; WT_RET_MSG(session, ret, "rename %s to %s", from, to); }
/* * __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); }
/* * __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_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); }
/* * __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) { struct stat sb; WT_DECL_RET; char *path; WT_RET(__wt_filename(session, filename, &path)); WT_SYSCALL_RETRY(stat(path, &sb), ret); __wt_free(session, path); if (ret == 0) { *sizep = sb.st_size; return (0); } WT_RET_MSG(session, ret, "%s: fstat", filename); }
/* * __wt_remove -- * Remove a file. */ int __wt_remove(WT_SESSION_IMPL *session, const char *name) { WT_DECL_RET; char *path; WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: remove", name)); __remove_file_check(session, name); WT_RET(__wt_filename(session, name, &path)); WT_SYSCALL_RETRY(remove(path), ret); __wt_free(session, path); if (ret == 0 || ret == ENOENT) return (0); WT_RET_MSG(session, ret, "%s: remove", 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_remove -- * Remove a file. */ int __wt_remove(WT_SESSION_IMPL *session, const char *name) { WT_DECL_RET; char *path; uint32_t lasterror; WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: remove", name)); __remove_file_check(session, name); WT_RET(__wt_filename(session, name, &path)); if ((ret = DeleteFileA(path)) == FALSE) lasterror = __wt_errno(); __wt_free(session, path); if (ret != FALSE) return (0); WT_RET_MSG(session, lasterror, "%s: remove", name); }
/* * __wt_exist -- * Return if the file exists. */ int __wt_exist(WT_SESSION_IMPL *session, const char *filename, int *existp) { const char *path; struct stat sb; int ret; WT_RET(__wt_filename(session, filename, &path)); WT_SYSCALL_RETRY(stat(path, &sb), ret); __wt_free(session, path); if (ret == 0) { *existp = 1; return (0); } if (ret == ENOENT) { *existp = 0; return (0); } WT_RET_MSG(session, ret, "%s: fstat", filename); }
/* * __wt_exist -- * Return if the file exists. */ int __wt_exist(WT_SESSION_IMPL *session, const char *filename, bool *existp) { struct stat sb; WT_DECL_RET; char *path; *existp = false; WT_RET(__wt_filename(session, filename, &path)); WT_SYSCALL_RETRY(stat(path, &sb), ret); __wt_free(session, path); if (ret == 0) { *existp = true; return (0); } if (ret == ENOENT) return (0); WT_RET_MSG(session, ret, "%s: fstat", filename); }
/* * __wt_open -- * Open a file handle. */ int __wt_open(WT_SESSION_IMPL *session, const char *name, int ok_create, int exclusive, int dio_type, WT_FH **fhp) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_FH *fh, *tfh; mode_t mode; int direct_io, f, fd, matched; const char *path; conn = S2C(session); fh = NULL; fd = -1; path = NULL; WT_VERBOSE_RET(session, fileops, "%s: open", name); /* Increment the reference count if we already have the file open. */ matched = 0; __wt_spin_lock(session, &conn->fh_lock); TAILQ_FOREACH(tfh, &conn->fhqh, q) if (strcmp(name, tfh->name) == 0) { ++tfh->refcnt; *fhp = tfh; matched = 1; break; } __wt_spin_unlock(session, &conn->fh_lock); if (matched) return (0); WT_RET(__wt_filename(session, name, &path)); f = O_RDWR; #ifdef O_BINARY /* Windows clones: we always want to treat the file as a binary. */ f |= O_BINARY; #endif #ifdef O_CLOEXEC /* * Security: * The application may spawn a new process, and we don't want another * process to have access to our file handles. */ f |= O_CLOEXEC; #endif #ifdef O_NOATIME /* Avoid updating metadata for read-only workloads. */ if (dio_type == WT_FILE_TYPE_DATA) f |= O_NOATIME; #endif if (ok_create) { f |= O_CREAT; if (exclusive) f |= O_EXCL; mode = 0666; } else mode = 0; direct_io = 0; #ifdef O_DIRECT if (dio_type && FLD_ISSET(conn->direct_io, dio_type)) { f |= O_DIRECT; direct_io = 1; } #endif if (dio_type == WT_FILE_TYPE_LOG && FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC)) #ifdef O_DSYNC f |= O_DSYNC; #elif defined(O_SYNC) f |= O_SYNC; #else WT_ERR_MSG(session, ENOTSUP, "Unsupported log sync mode requested"); #endif WT_SYSCALL_RETRY(((fd = open(path, f, mode)) == -1 ? 1 : 0), ret); if (ret != 0) WT_ERR_MSG(session, ret, direct_io ? "%s: open failed with direct I/O configured, some " "filesystem types do not support direct I/O" : "%s", path); #if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) && !defined(O_CLOEXEC) /* * Security: * The application may spawn a new process, and we don't want another * process to have access to our file handles. There's an obvious * race here, so we prefer the flag to open if available. */ if ((f = fcntl(fd, F_GETFD)) == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) WT_ERR_MSG(session, __wt_errno(), "%s: fcntl", name); #endif #if defined(HAVE_POSIX_FADVISE) /* Disable read-ahead on trees: it slows down random read workloads. */ if (dio_type == WT_FILE_TYPE_DATA) WT_ERR(posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM)); #endif if (F_ISSET(conn, WT_CONN_CKPT_SYNC)) WT_ERR(__open_directory_sync(session)); WT_ERR(__wt_calloc(session, 1, sizeof(WT_FH), &fh)); WT_ERR(__wt_strdup(session, name, &fh->name)); fh->fd = fd; fh->refcnt = 1; fh->direct_io = direct_io; /* Set the file's size. */ WT_ERR(__wt_filesize(session, fh, &fh->size)); /* Configure file extension. */ if (dio_type == WT_FILE_TYPE_DATA) fh->extend_len = conn->data_extend_len; /* * Repeat the check for a match, but then link onto the database's list * of files. */ matched = 0; __wt_spin_lock(session, &conn->fh_lock); TAILQ_FOREACH(tfh, &conn->fhqh, q) if (strcmp(name, tfh->name) == 0) { ++tfh->refcnt; *fhp = tfh; matched = 1; break; } if (!matched) { TAILQ_INSERT_TAIL(&conn->fhqh, fh, q); WT_STAT_FAST_CONN_INCR(session, file_open); *fhp = fh; } __wt_spin_unlock(session, &conn->fh_lock); if (matched) { err: if (fh != NULL) { __wt_free(session, fh->name); __wt_free(session, fh); } if (fd != -1) (void)close(fd); } __wt_free(session, path); return (ret); }
/* * __wt_open -- * Open a file handle. */ int __wt_open(WT_SESSION_IMPL *session, const char *name, int ok_create, int exclusive, int dio_type, WT_FH **fhp) { DWORD dwCreationDisposition; HANDLE filehandle, filehandle_secondary; WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_FH *fh, *tfh; uint64_t bucket, hash; int direct_io, f, matched, share_mode; char *path; conn = S2C(session); fh = NULL; path = NULL; filehandle = INVALID_HANDLE_VALUE; filehandle_secondary = INVALID_HANDLE_VALUE; direct_io = 0; hash = __wt_hash_city64(name, strlen(name)); bucket = hash % WT_HASH_ARRAY_SIZE; WT_RET(__wt_verbose(session, WT_VERB_FILEOPS, "%s: open", name)); /* Increment the reference count if we already have the file open. */ matched = 0; __wt_spin_lock(session, &conn->fh_lock); SLIST_FOREACH(tfh, &conn->fhhash[bucket], l) if (strcmp(name, tfh->name) == 0) { ++tfh->ref; *fhp = tfh; matched = 1; break; } __wt_spin_unlock(session, &conn->fh_lock); if (matched) return (0); /* For directories, create empty file handles with invalid handles */ if (dio_type == WT_FILE_TYPE_DIRECTORY) { goto setupfh; } WT_RET(__wt_filename(session, name, &path)); share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; /* * Security: * The application may spawn a new process, and we don't want another * process to have access to our file handles. * * TODO: Set tighter file permissions but set bInheritHandle to false * to prevent inheritance */ f = FILE_ATTRIBUTE_NORMAL; dwCreationDisposition = 0; if (ok_create) { dwCreationDisposition = CREATE_NEW; if (exclusive) dwCreationDisposition = CREATE_ALWAYS; } else dwCreationDisposition = OPEN_EXISTING; if (dio_type && FLD_ISSET(conn->direct_io, dio_type)) { f |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; direct_io = 1; } if (dio_type == WT_FILE_TYPE_LOG && FLD_ISSET(conn->txn_logsync, WT_LOG_DSYNC)) { f |= FILE_FLAG_WRITE_THROUGH; } /* Disable read-ahead on trees: it slows down random read workloads. */ if (dio_type == WT_FILE_TYPE_DATA || dio_type == WT_FILE_TYPE_CHECKPOINT) f |= FILE_FLAG_RANDOM_ACCESS; filehandle = CreateFileA(path, (GENERIC_READ | GENERIC_WRITE), share_mode, NULL, dwCreationDisposition, f, NULL); if (filehandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_EXISTS && ok_create) filehandle = CreateFileA(path, (GENERIC_READ | GENERIC_WRITE), share_mode, NULL, OPEN_EXISTING, f, NULL); if (filehandle == INVALID_HANDLE_VALUE) WT_ERR_MSG(session, __wt_errno(), direct_io ? "%s: open failed with direct I/O configured, some " "filesystem types do not support direct I/O" : "%s", path); } /* * Open a second handle to file to support allocation/truncation * concurrently with reads on the file. Writes would also move the file * pointer. */ filehandle_secondary = CreateFileA(path, (GENERIC_READ | GENERIC_WRITE), share_mode, NULL, OPEN_EXISTING, f, NULL); if (filehandle == INVALID_HANDLE_VALUE) WT_ERR_MSG(session, __wt_errno(), "open failed for secondary handle: %s", path); setupfh: WT_ERR(__wt_calloc_one(session, &fh)); WT_ERR(__wt_strdup(session, name, &fh->name)); fh->name_hash = hash; fh->filehandle = filehandle; fh->filehandle_secondary = filehandle_secondary; fh->ref = 1; fh->direct_io = direct_io; /* Set the file's size. */ if (dio_type != WT_FILE_TYPE_DIRECTORY) WT_ERR(__wt_filesize(session, fh, &fh->size)); /* Configure file extension. */ if (dio_type == WT_FILE_TYPE_DATA || dio_type == WT_FILE_TYPE_CHECKPOINT) fh->extend_len = conn->data_extend_len; /* Configure fallocate/posix_fallocate calls. */ __wt_fallocate_config(session, fh); /* * Repeat the check for a match, but then link onto the database's list * of files. */ matched = 0; __wt_spin_lock(session, &conn->fh_lock); SLIST_FOREACH(tfh, &conn->fhhash[bucket], l) if (strcmp(name, tfh->name) == 0) { ++tfh->ref; *fhp = tfh; matched = 1; break; } if (!matched) { WT_CONN_FILE_INSERT(conn, fh, bucket); WT_STAT_FAST_CONN_INCR(session, file_open); *fhp = fh; } __wt_spin_unlock(session, &conn->fh_lock); if (matched) { err: if (fh != NULL) { __wt_free(session, fh->name); __wt_free(session, fh); } if (filehandle != INVALID_HANDLE_VALUE) (void)CloseHandle(filehandle); if (filehandle_secondary != INVALID_HANDLE_VALUE) (void)CloseHandle(filehandle_secondary); } __wt_free(session, path); return (ret); }
/* * __wt_open -- * Open a file handle. */ int __wt_open(WT_SESSION_IMPL *session, const char *name, uint32_t file_type, uint32_t flags, WT_FH **fhp) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_FH *fh; bool lock_file, open_called; char *path; WT_ASSERT(session, file_type != 0); /* A file type is required. */ conn = S2C(session); fh = NULL; open_called = false; path = NULL; WT_RET(__open_verbose(session, name, file_type, flags)); /* Check if the handle is already open. */ if (__wt_handle_search(session, name, true, NULL, &fh)) { /* * XXX * The in-memory implementation has to reset the file offset * when a file is re-opened (which obviously also depends on * in-memory configurations never opening a file in more than * one thread at a time). This needs to be fixed. */ if (F_ISSET(fh, WT_FH_IN_MEMORY) && fh->ref == 1) fh->off = 0; *fhp = fh; return (0); } /* Allocate a structure and set the name. */ WT_ERR(__wt_calloc_one(session, &fh)); WT_ERR(__wt_strdup(session, name, &fh->name)); /* * If this is a read-only connection, open all files read-only except * the lock file. * * The only file created in read-only mode is the lock file. */ if (F_ISSET(conn, WT_CONN_READONLY)) { lock_file = strcmp(name, WT_SINGLETHREAD) == 0; if (!lock_file) LF_SET(WT_OPEN_READONLY); WT_ASSERT(session, lock_file || !LF_ISSET(WT_OPEN_CREATE)); } /* Create the path to the file. */ if (!LF_ISSET(WT_OPEN_FIXED)) WT_ERR(__wt_filename(session, name, &path)); /* Call the underlying open function. */ WT_ERR(conn->handle_open( session, fh, path == NULL ? name : path, file_type, flags)); open_called = true; /* * Repeat the check for a match: if there's no match, link our newly * created handle onto the database's list of files. */ if (__wt_handle_search(session, name, true, fh, fhp)) { err: if (open_called) WT_TRET(fh->fh_close(session, fh)); if (fh != NULL) { __wt_free(session, fh->name); __wt_free(session, fh); } } __wt_free(session, path); return (ret); }
/* * __wt_open -- * Open a file handle. */ int __wt_open(WT_SESSION_IMPL *session, const char *name, WT_FS_OPEN_FILE_TYPE file_type, u_int flags, WT_FH **fhp) { WT_CONNECTION_IMPL *conn; WT_DECL_RET; WT_FH *fh; WT_FILE_SYSTEM *file_system; bool lock_file, open_called; char *path; WT_ASSERT(session, file_type != 0); /* A file type is required. */ conn = S2C(session); file_system = conn->file_system; fh = NULL; open_called = false; path = NULL; WT_RET(__open_verbose(session, name, file_type, flags)); /* Check if the handle is already open. */ if (__handle_search(session, name, NULL, &fh)) { *fhp = fh; return (0); } /* Allocate and initialize the handle. */ WT_ERR(__wt_calloc_one(session, &fh)); WT_ERR(__wt_strdup(session, name, &fh->name)); /* * If this is a read-only connection, open all files read-only except * the lock file. * * The only file created in read-only mode is the lock file. */ if (F_ISSET(conn, WT_CONN_READONLY)) { lock_file = strcmp(name, WT_SINGLETHREAD) == 0; if (!lock_file) LF_SET(WT_FS_OPEN_READONLY); WT_ASSERT(session, lock_file || !LF_ISSET(WT_FS_OPEN_CREATE)); } /* Create the path to the file. */ if (!LF_ISSET(WT_FS_OPEN_FIXED)) WT_ERR(__wt_filename(session, name, &path)); /* Call the underlying open function. */ WT_ERR(file_system->fs_open_file(file_system, &session->iface, path == NULL ? name : path, file_type, flags, &fh->handle)); open_called = true; WT_ERR(__fhandle_method_finalize( session, fh->handle, LF_ISSET(WT_FS_OPEN_READONLY))); /* * Repeat the check for a match: if there's no match, link our newly * created handle onto the database's list of files. */ if (__handle_search(session, name, fh, fhp)) { err: if (open_called) WT_TRET(fh->handle->close( fh->handle, (WT_SESSION *)session)); if (fh != NULL) { __wt_free(session, fh->name); __wt_free(session, fh); } } __wt_free(session, path); return (ret); }
/* * __wt_dirlist -- * Get a list of files from a directory, optionally filtered by * a given prefix. */ int __wt_dirlist(WT_SESSION_IMPL *session, const char *dir, const char *prefix, uint32_t flags, char ***dirlist, u_int *countp) { struct dirent *dp; DIR *dirp; WT_DECL_RET; size_t dirallocsz; u_int count, dirsz; int match; char **entries, *path; *dirlist = NULL; *countp = 0; WT_RET(__wt_filename(session, dir, &path)); dirp = NULL; dirallocsz = 0; dirsz = 0; entries = NULL; if (flags == 0) LF_SET(WT_DIRLIST_INCLUDE); WT_ERR(__wt_verbose(session, WT_VERB_FILEOPS, "wt_dirlist of %s %s prefix %s", path, LF_ISSET(WT_DIRLIST_INCLUDE) ? "include" : "exclude", prefix == NULL ? "all" : prefix)); WT_SYSCALL_RETRY(((dirp = opendir(path)) == NULL ? 1 : 0), ret); if (ret != 0) WT_ERR_MSG(session, ret, "%s: opendir", path); for (dirsz = 0, count = 0; (dp = readdir(dirp)) != NULL;) { /* * Skip . and .. */ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; match = 0; if (prefix != NULL && ((LF_ISSET(WT_DIRLIST_INCLUDE) && WT_PREFIX_MATCH(dp->d_name, prefix)) || (LF_ISSET(WT_DIRLIST_EXCLUDE) && !WT_PREFIX_MATCH(dp->d_name, prefix)))) match = 1; if (prefix == NULL || match) { /* * We have a file name we want to return. */ count++; if (count > dirsz) { dirsz += WT_DIR_ENTRY; WT_ERR(__wt_realloc_def( session, &dirallocsz, dirsz, &entries)); } WT_ERR(__wt_strdup( session, dp->d_name, &entries[count-1])); } } if (count > 0) *dirlist = entries; *countp = count; err: if (dirp != NULL) (void)closedir(dirp); __wt_free(session, path); if (ret == 0) return (0); if (*dirlist != NULL) { for (count = dirsz; count > 0; count--) __wt_free(session, entries[count]); __wt_free(session, entries); } WT_RET_MSG(session, ret, "dirlist %s prefix %s", dir, prefix); }