#include <dirent.h>

Go to the source code of this file.
Defines | |
| #define | PG_TEMP_FILES_DIR "pgsql_tmp" |
| #define | PG_TEMP_FILE_PREFIX "pgsql_tmp" |
Typedefs | |
| typedef char * | FileName |
| typedef int | File |
Functions | |
| File | PathNameOpenFile (FileName fileName, int fileFlags, int fileMode) |
| File | OpenTemporaryFile (bool interXact) |
| void | FileClose (File file) |
| int | FilePrefetch (File file, off_t offset, int amount) |
| int | FileRead (File file, char *buffer, int amount) |
| int | FileWrite (File file, char *buffer, int amount) |
| int | FileSync (File file) |
| off_t | FileSeek (File file, off_t offset, int whence) |
| int | FileTruncate (File file, off_t offset) |
| char * | FilePathName (File file) |
| FILE * | AllocateFile (const char *name, const char *mode) |
| int | FreeFile (FILE *file) |
| FILE * | OpenPipeStream (const char *command, const char *mode) |
| int | ClosePipeStream (FILE *file) |
| DIR * | AllocateDir (const char *dirname) |
| struct dirent * | ReadDir (DIR *dir, const char *dirname) |
| int | FreeDir (DIR *dir) |
| int | OpenTransientFile (FileName fileName, int fileFlags, int fileMode) |
| int | CloseTransientFile (int fd) |
| int | BasicOpenFile (FileName fileName, int fileFlags, int fileMode) |
| void | InitFileAccess (void) |
| void | set_max_safe_fds (void) |
| void | closeAllVfds (void) |
| void | SetTempTablespaces (Oid *tableSpaces, int numSpaces) |
| bool | TempTablespacesAreSet (void) |
| Oid | GetNextTempTableSpace (void) |
| void | AtEOXact_Files (void) |
| void | AtEOSubXact_Files (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid) |
| void | RemovePgTempFiles (void) |
| int | pg_fsync (int fd) |
| int | pg_fsync_no_writethrough (int fd) |
| int | pg_fsync_writethrough (int fd) |
| int | pg_fdatasync (int fd) |
| int | pg_flush_data (int fd, off_t offset, off_t amount) |
Variables | |
| int | max_files_per_process |
| int | max_safe_fds |
| #define PG_TEMP_FILE_PREFIX "pgsql_tmp" |
Definition at line 119 of file fd.h.
Referenced by OpenTemporaryFileInTablespace(), RemovePgTempFilesInDir(), and sendDir().
| #define PG_TEMP_FILES_DIR "pgsql_tmp" |
Definition at line 118 of file fd.h.
Referenced by OpenTemporaryFileInTablespace(), and RemovePgTempFiles().
| DIR* AllocateDir | ( | const char * | dirname | ) |
Definition at line 1747 of file fd.c.
References AllocateDesc::create_subid, AllocateDesc::desc, AllocateDesc::dir, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, MAX_ALLOCATED_DESCS, max_safe_fds, NULL, numAllocatedDescs, opendir(), and ReleaseLruFile().
Referenced by calculate_database_size(), calculate_tablespace_size(), CleanupBackupHistory(), copydir(), db_dir_size(), DeleteAllExportedSnapshotFiles(), destroy_tablespace_directories(), directory_is_empty(), get_available_versions_for_extension(), get_ext_ver_list(), getInstallationPaths(), movedb(), ParseTzFile(), perform_base_backup(), pg_available_extension_versions(), pg_available_extensions(), pg_logdir_ls(), pg_ls_dir(), pg_tablespace_databases(), pg_tzenumerate_next(), pg_tzenumerate_start(), pgarch_readyXlog(), pgstat_reset_remove_files(), PrescanPreparedTransactions(), RecoverPreparedTransactions(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), scan_directory_ci(), SendBaseBackup(), sendDir(), SlruScanDirectory(), and StandbyRecoverPreparedTransactions().
{
DIR *dir;
DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
numAllocatedDescs, dirname));
/*
* The test against MAX_ALLOCATED_DESCS prevents us from overflowing
* allocatedDescs[]; the test against max_safe_fds prevents AllocateDir
* from hogging every one of the available FDs, which'd lead to infinite
* looping.
*/
if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
numAllocatedDescs >= max_safe_fds - 1)
elog(ERROR, "exceeded MAX_ALLOCATED_DESCS while trying to open directory \"%s\"",
dirname);
TryAgain:
if ((dir = opendir(dirname)) != NULL)
{
AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];
desc->kind = AllocateDescDir;
desc->desc.dir = dir;
desc->create_subid = GetCurrentSubTransactionId();
numAllocatedDescs++;
return desc->desc.dir;
}
if (errno == EMFILE || errno == ENFILE)
{
int save_errno = errno;
ereport(LOG,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("out of file descriptors: %m; release and retry")));
errno = 0;
if (ReleaseLruFile())
goto TryAgain;
errno = save_errno;
}
return NULL;
}
| FILE* AllocateFile | ( | const char * | name, | |
| const char * | mode | |||
| ) |
Definition at line 1502 of file fd.c.
References AllocateDesc::create_subid, AllocateDesc::desc, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, AllocateDesc::file, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, MAX_ALLOCATED_DESCS, max_safe_fds, NULL, numAllocatedDescs, and ReleaseLruFile().
Referenced by BeginCopyFrom(), BeginCopyTo(), checkDataDir(), do_pg_start_backup(), do_pg_stop_backup(), existsTimeLineHistory(), ExportSnapshot(), ImportSnapshot(), load_hba(), load_ident(), load_relcache_init_file(), parse_extension_control_file(), ParseTzFile(), perform_base_backup(), pg_backup_start_time(), pgss_shmem_shutdown(), pgss_shmem_startup(), pgstat_read_db_statsfile(), pgstat_read_db_statsfile_timestamp(), pgstat_read_statsfiles(), pgstat_write_db_statsfile(), pgstat_write_statsfiles(), read_backup_label(), read_binary_file(), readRecoveryCommandFile(), readTimeLineHistory(), sendFile(), tokenize_inc_file(), tsearch_readline_begin(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().
{
FILE *file;
DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
numAllocatedDescs, name));
/*
* The test against MAX_ALLOCATED_DESCS prevents us from overflowing
* allocatedFiles[]; the test against max_safe_fds prevents AllocateFile
* from hogging every one of the available FDs, which'd lead to infinite
* looping.
*/
if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
numAllocatedDescs >= max_safe_fds - 1)
elog(ERROR, "exceeded MAX_ALLOCATED_DESCS while trying to open file \"%s\"",
name);
TryAgain:
if ((file = fopen(name, mode)) != NULL)
{
AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];
desc->kind = AllocateDescFile;
desc->desc.file = file;
desc->create_subid = GetCurrentSubTransactionId();
numAllocatedDescs++;
return desc->desc.file;
}
if (errno == EMFILE || errno == ENFILE)
{
int save_errno = errno;
ereport(LOG,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("out of file descriptors: %m; release and retry")));
errno = 0;
if (ReleaseLruFile())
goto TryAgain;
errno = save_errno;
}
return NULL;
}
| void AtEOSubXact_Files | ( | bool | isCommit, | |
| SubTransactionId | mySubid, | |||
| SubTransactionId | parentSubid | |||
| ) |
Definition at line 1996 of file fd.c.
References AllocateDesc::create_subid, FreeDesc(), i, and numAllocatedDescs.
Referenced by AbortSubTransaction(), and CommitSubTransaction().
{
Index i;
for (i = 0; i < numAllocatedDescs; i++)
{
if (allocatedDescs[i].create_subid == mySubid)
{
if (isCommit)
allocatedDescs[i].create_subid = parentSubid;
else
{
/* have to recheck the item after FreeDesc (ugly) */
FreeDesc(&allocatedDescs[i--]);
}
}
}
}
| void AtEOXact_Files | ( | void | ) |
Definition at line 2027 of file fd.c.
References CleanupTempFiles(), numTempTableSpaces, and tempTableSpaces.
Referenced by AbortTransaction(), BackgroundWriterMain(), CheckpointerMain(), CommitTransaction(), PrepareTransaction(), and WalWriterMain().
{
CleanupTempFiles(false);
tempTableSpaces = NULL;
numTempTableSpaces = -1;
}
| int BasicOpenFile | ( | FileName | fileName, | |
| int | fileFlags, | |||
| int | fileMode | |||
| ) |
Definition at line 561 of file fd.c.
References ereport, errcode(), errmsg(), LOG, and ReleaseLruFile().
Referenced by GetNewRelFileNode(), LruInsert(), OpenTransientFile(), PathNameOpenFile(), ReadControlFile(), UpdateControlFile(), WriteControlFile(), XLogFileInit(), XLogFileOpen(), XLogFileRead(), and XLogRead().
{
int fd;
tryAgain:
fd = open(fileName, fileFlags, fileMode);
if (fd >= 0)
return fd; /* success! */
if (errno == EMFILE || errno == ENFILE)
{
int save_errno = errno;
ereport(LOG,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("out of file descriptors: %m; release and retry")));
errno = 0;
if (ReleaseLruFile())
goto tryAgain;
errno = save_errno;
}
return -1; /* failure */
}
| void closeAllVfds | ( | void | ) |
Definition at line 1909 of file fd.c.
References Assert, FileIsNotOpen, i, LruDelete(), and SizeVfdCache.
Referenced by standard_ProcessUtility().
{
Index i;
if (SizeVfdCache > 0)
{
Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
for (i = 1; i < SizeVfdCache; i++)
{
if (!FileIsNotOpen(i))
LruDelete(i);
}
}
}
| int ClosePipeStream | ( | FILE * | file | ) |
Definition at line 1880 of file fd.c.
References AllocateDescPipe, AllocateDesc::desc, DO_DB, elog, AllocateDesc::file, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.
Referenced by ClosePipeToProgram().
{
int i;
DO_DB(elog(LOG, "ClosePipeStream: Allocated %d", numAllocatedDescs));
/* Remove file from list of allocated files, if it's present */
for (i = numAllocatedDescs; --i >= 0;)
{
AllocateDesc *desc = &allocatedDescs[i];
if (desc->kind == AllocateDescPipe && desc->desc.file == file)
return FreeDesc(desc);
}
/* Only get here if someone passes us a file not in allocatedDescs */
elog(WARNING, "file passed to ClosePipeStream was not obtained from OpenPipeStream");
return pclose(file);
}
| int CloseTransientFile | ( | int | fd | ) |
Definition at line 1717 of file fd.c.
References AllocateDescRawFD, close, AllocateDesc::desc, DO_DB, elog, AllocateDesc::fd, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.
Referenced by CheckPointTwoPhase(), copy_file(), EndPrepare(), fsync_fname(), lo_export(), lo_import_internal(), load_relmap_file(), mdunlinkfork(), ReadTwoPhaseFile(), RecreateTwoPhaseFile(), SendTimeLineHistory(), SimpleLruFlush(), SlruInternalWritePage(), SlruPhysicalReadPage(), SlruPhysicalWritePage(), write_relmap_file(), writeTimeLineHistory(), writeTimeLineHistoryFile(), and XLogFileCopy().
{
int i;
DO_DB(elog(LOG, "CloseTransientFile: Allocated %d", numAllocatedDescs));
/* Remove fd from list of allocated files, if it's present */
for (i = numAllocatedDescs; --i >= 0;)
{
AllocateDesc *desc = &allocatedDescs[i];
if (desc->kind == AllocateDescRawFD && desc->desc.fd == fd)
return FreeDesc(desc);
}
/* Only get here if someone passes us a file not in allocatedDescs */
elog(WARNING, "fd passed to CloseTransientFile was not obtained from OpenTransientFile");
return close(fd);
}
| void FileClose | ( | File | file | ) |
Definition at line 1073 of file fd.c.
References Assert, close, Delete(), DO_DB, elog, ereport, errmsg(), ERROR, vfd::fd, FD_TEMPORARY, vfd::fdstate, FileIsNotOpen, FileIsValid, vfd::fileName, vfd::fileSize, FreeVfd(), LOG, log_temp_files, nfile, pgstat_report_tempfile(), ResourceOwnerForgetFile(), vfd::resowner, temporary_files_size, and unlink().
Referenced by BufFileClose(), CleanupTempFiles(), mdclose(), and ResourceOwnerReleaseInternal().
{
Vfd *vfdP;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FileClose: %d (%s)",
file, VfdCache[file].fileName));
vfdP = &VfdCache[file];
if (!FileIsNotOpen(file))
{
/* remove the file from the lru ring */
Delete(file);
/* close the file */
if (close(vfdP->fd))
elog(ERROR, "could not close file \"%s\": %m", vfdP->fileName);
--nfile;
vfdP->fd = VFD_CLOSED;
}
/*
* Delete the file if it was temporary, and make a log entry if wanted
*/
if (vfdP->fdstate & FD_TEMPORARY)
{
struct stat filestats;
int stat_errno;
/*
* If we get an error, as could happen within the ereport/elog calls,
* we'll come right back here during transaction abort. Reset the
* flag to ensure that we can't get into an infinite loop. This code
* is arranged to ensure that the worst-case consequence is failing to
* emit log message(s), not failing to attempt the unlink.
*/
vfdP->fdstate &= ~FD_TEMPORARY;
/* Subtract its size from current usage (do first in case of error) */
temporary_files_size -= vfdP->fileSize;
vfdP->fileSize = 0;
/* first try the stat() */
if (stat(vfdP->fileName, &filestats))
stat_errno = errno;
else
stat_errno = 0;
/* in any case do the unlink */
if (unlink(vfdP->fileName))
elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName);
/* and last report the stat results */
if (stat_errno == 0)
{
pgstat_report_tempfile(filestats.st_size);
if (log_temp_files >= 0)
{
if ((filestats.st_size / 1024) >= log_temp_files)
ereport(LOG,
(errmsg("temporary file: path \"%s\", size %lu",
vfdP->fileName,
(unsigned long) filestats.st_size)));
}
}
else
{
errno = stat_errno;
elog(LOG, "could not stat file \"%s\": %m", vfdP->fileName);
}
}
/* Unregister it from the resource owner */
if (vfdP->resowner)
ResourceOwnerForgetFile(vfdP->resowner, file);
/*
* Return the Vfd slot to the free list
*/
FreeVfd(file);
}
| char* FilePathName | ( | File | file | ) |
Definition at line 1476 of file fd.c.
References Assert, FileIsValid, and vfd::fileName.
Referenced by _mdnblocks(), mdextend(), mdimmedsync(), mdread(), mdsync(), mdtruncate(), mdwrite(), and register_dirty_segment().
{
Assert(FileIsValid(file));
return VfdCache[file].fileName;
}
| int FilePrefetch | ( | File | file, | |
| off_t | offset, | |||
| int | amount | |||
| ) |
Definition at line 1170 of file fd.c.
References Assert, DO_DB, elog, fd(), FileAccess(), FileIsValid, and LOG.
Referenced by mdprefetch().
{
#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
int returnCode;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d",
file, VfdCache[file].fileName,
(int64) offset, amount));
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
POSIX_FADV_WILLNEED);
return returnCode;
#else
Assert(FileIsValid(file));
return 0;
#endif
}
| int FileRead | ( | File | file, | |
| char * | buffer, | |||
| int | amount | |||
| ) |
Definition at line 1196 of file fd.c.
References _dosmaperr(), Assert, DO_DB, EINTR, elog, error(), fd(), FileAccess(), FileIsValid, LOG, pg_usleep(), read, and vfd::seekPos.
Referenced by BufFileLoadBuffer(), and mdread().
{
int returnCode;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
file, VfdCache[file].fileName,
(int64) VfdCache[file].seekPos,
amount, buffer));
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
retry:
returnCode = read(VfdCache[file].fd, buffer, amount);
if (returnCode >= 0)
VfdCache[file].seekPos += returnCode;
else
{
/*
* Windows may run out of kernel buffers and return "Insufficient
* system resources" error. Wait a bit and retry to solve it.
*
* It is rumored that EINTR is also possible on some Unix filesystems,
* in which case immediate retry is indicated.
*/
#ifdef WIN32
DWORD error = GetLastError();
switch (error)
{
case ERROR_NO_SYSTEM_RESOURCES:
pg_usleep(1000L);
errno = EINTR;
break;
default:
_dosmaperr(error);
break;
}
#endif
/* OK to retry if interrupted */
if (errno == EINTR)
goto retry;
/* Trouble, so assume we don't know the file position anymore */
VfdCache[file].seekPos = FileUnknownPos;
}
return returnCode;
}
| off_t FileSeek | ( | File | file, | |
| off_t | offset, | |||
| int | whence | |||
| ) |
Definition at line 1363 of file fd.c.
References Assert, DO_DB, elog, ERROR, fd(), FileAccess(), FileIsNotOpen, FileIsValid, FileUnknownPos, LOG, and vfd::seekPos.
Referenced by _mdnblocks(), BufFileDumpBuffer(), BufFileLoadBuffer(), mdextend(), mdread(), and mdwrite().
{
int returnCode;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FileSeek: %d (%s) " INT64_FORMAT " " INT64_FORMAT " %d",
file, VfdCache[file].fileName,
(int64) VfdCache[file].seekPos,
(int64) offset, whence));
if (FileIsNotOpen(file))
{
switch (whence)
{
case SEEK_SET:
if (offset < 0)
elog(ERROR, "invalid seek offset: " INT64_FORMAT,
(int64) offset);
VfdCache[file].seekPos = offset;
break;
case SEEK_CUR:
VfdCache[file].seekPos += offset;
break;
case SEEK_END:
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
VfdCache[file].seekPos = lseek(VfdCache[file].fd,
offset, whence);
break;
default:
elog(ERROR, "invalid whence: %d", whence);
break;
}
}
else
{
switch (whence)
{
case SEEK_SET:
if (offset < 0)
elog(ERROR, "invalid seek offset: " INT64_FORMAT,
(int64) offset);
if (VfdCache[file].seekPos != offset)
VfdCache[file].seekPos = lseek(VfdCache[file].fd,
offset, whence);
break;
case SEEK_CUR:
if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
VfdCache[file].seekPos = lseek(VfdCache[file].fd,
offset, whence);
break;
case SEEK_END:
VfdCache[file].seekPos = lseek(VfdCache[file].fd,
offset, whence);
break;
default:
elog(ERROR, "invalid whence: %d", whence);
break;
}
}
return VfdCache[file].seekPos;
}
| int FileSync | ( | File | file | ) |
Definition at line 1346 of file fd.c.
References Assert, DO_DB, elog, fd(), FileAccess(), FileIsValid, LOG, and pg_fsync().
Referenced by mdimmedsync(), mdsync(), and register_dirty_segment().
{
int returnCode;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FileSync: %d (%s)",
file, VfdCache[file].fileName));
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
return pg_fsync(VfdCache[file].fd);
}
| int FileTruncate | ( | File | file, | |
| off_t | offset | |||
| ) |
Definition at line 1443 of file fd.c.
References Assert, DO_DB, elog, fd(), FD_TEMPORARY, FileAccess(), FileIsValid, vfd::fileSize, ftruncate, LOG, and temporary_files_size.
Referenced by mdtruncate().
{
int returnCode;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FileTruncate %d (%s)",
file, VfdCache[file].fileName));
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
returnCode = ftruncate(VfdCache[file].fd, offset);
if (returnCode == 0 && VfdCache[file].fileSize > offset)
{
/* adjust our state for truncation of a temp file */
Assert(VfdCache[file].fdstate & FD_TEMPORARY);
temporary_files_size -= VfdCache[file].fileSize - offset;
VfdCache[file].fileSize = offset;
}
return returnCode;
}
| int FileWrite | ( | File | file, | |
| char * | buffer, | |||
| int | amount | |||
| ) |
Definition at line 1251 of file fd.c.
References _dosmaperr(), Assert, DO_DB, EINTR, elog, ereport, errcode(), errmsg(), error(), ERROR, fd(), FD_TEMPORARY, FileAccess(), FileIsValid, vfd::fileSize, LOG, pg_usleep(), vfd::seekPos, temp_file_limit, temporary_files_size, and write.
Referenced by BufFileDumpBuffer(), mdextend(), and mdwrite().
{
int returnCode;
Assert(FileIsValid(file));
DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p",
file, VfdCache[file].fileName,
(int64) VfdCache[file].seekPos,
amount, buffer));
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
/*
* If enforcing temp_file_limit and it's a temp file, check to see if the
* write would overrun temp_file_limit, and throw error if so. Note: it's
* really a modularity violation to throw error here; we should set errno
* and return -1. However, there's no way to report a suitable error
* message if we do that. All current callers would just throw error
* immediately anyway, so this is safe at present.
*/
if (temp_file_limit >= 0 && (VfdCache[file].fdstate & FD_TEMPORARY))
{
off_t newPos = VfdCache[file].seekPos + amount;
if (newPos > VfdCache[file].fileSize)
{
uint64 newTotal = temporary_files_size;
newTotal += newPos - VfdCache[file].fileSize;
if (newTotal > (uint64) temp_file_limit * (uint64) 1024)
ereport(ERROR,
(errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
errmsg("temporary file size exceeds temp_file_limit (%dkB)",
temp_file_limit)));
}
}
retry:
errno = 0;
returnCode = write(VfdCache[file].fd, buffer, amount);
/* if write didn't set errno, assume problem is no disk space */
if (returnCode != amount && errno == 0)
errno = ENOSPC;
if (returnCode >= 0)
{
VfdCache[file].seekPos += returnCode;
/* maintain fileSize and temporary_files_size if it's a temp file */
if (VfdCache[file].fdstate & FD_TEMPORARY)
{
off_t newPos = VfdCache[file].seekPos;
if (newPos > VfdCache[file].fileSize)
{
temporary_files_size += newPos - VfdCache[file].fileSize;
VfdCache[file].fileSize = newPos;
}
}
}
else
{
/*
* See comments in FileRead()
*/
#ifdef WIN32
DWORD error = GetLastError();
switch (error)
{
case ERROR_NO_SYSTEM_RESOURCES:
pg_usleep(1000L);
errno = EINTR;
break;
default:
_dosmaperr(error);
break;
}
#endif
/* OK to retry if interrupted */
if (errno == EINTR)
goto retry;
/* Trouble, so assume we don't know the file position anymore */
VfdCache[file].seekPos = FileUnknownPos;
}
return returnCode;
}
| int FreeDir | ( | DIR * | dir | ) |
Definition at line 1854 of file fd.c.
References AllocateDescDir, closedir(), AllocateDesc::desc, AllocateDesc::dir, DO_DB, elog, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.
Referenced by calculate_database_size(), calculate_tablespace_size(), CleanupBackupHistory(), copydir(), db_dir_size(), DeleteAllExportedSnapshotFiles(), destroy_tablespace_directories(), directory_is_empty(), get_available_versions_for_extension(), get_ext_ver_list(), getInstallationPaths(), movedb(), ParseTzFile(), perform_base_backup(), pg_available_extension_versions(), pg_available_extensions(), pg_logdir_ls(), pg_ls_dir(), pg_tablespace_databases(), pg_tzenumerate_end(), pg_tzenumerate_next(), pgarch_readyXlog(), pgstat_reset_remove_files(), PrescanPreparedTransactions(), RecoverPreparedTransactions(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), scan_directory_ci(), SendBaseBackup(), sendDir(), SlruScanDirectory(), and StandbyRecoverPreparedTransactions().
{
int i;
DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDescs));
/* Remove dir from list of allocated dirs, if it's present */
for (i = numAllocatedDescs; --i >= 0;)
{
AllocateDesc *desc = &allocatedDescs[i];
if (desc->kind == AllocateDescDir && desc->desc.dir == dir)
return FreeDesc(desc);
}
/* Only get here if someone passes us a dir not in allocatedDescs */
elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");
return closedir(dir);
}
| int FreeFile | ( | FILE * | file | ) |
Definition at line 1689 of file fd.c.
References AllocateDescFile, AllocateDesc::desc, DO_DB, elog, AllocateDesc::file, FreeDesc(), i, AllocateDesc::kind, LOG, numAllocatedDescs, and WARNING.
Referenced by checkDataDir(), do_pg_start_backup(), do_pg_stop_backup(), EndCopy(), existsTimeLineHistory(), ExportSnapshot(), ImportSnapshot(), load_hba(), load_ident(), load_relcache_init_file(), parse_extension_control_file(), ParseTzFile(), perform_base_backup(), pg_backup_start_time(), pgss_shmem_shutdown(), pgss_shmem_startup(), pgstat_read_db_statsfile(), pgstat_read_db_statsfile_timestamp(), pgstat_read_statsfiles(), pgstat_write_db_statsfile(), pgstat_write_statsfiles(), read_backup_label(), read_binary_file(), readRecoveryCommandFile(), readTimeLineHistory(), sendFile(), tokenize_inc_file(), tsearch_readline_end(), ValidatePgVersion(), write_relcache_init_file(), XLogArchiveForceDone(), and XLogArchiveNotify().
{
int i;
DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedDescs));
/* Remove file from list of allocated files, if it's present */
for (i = numAllocatedDescs; --i >= 0;)
{
AllocateDesc *desc = &allocatedDescs[i];
if (desc->kind == AllocateDescFile && desc->desc.file == file)
return FreeDesc(desc);
}
/* Only get here if someone passes us a file not in allocatedDescs */
elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");
return fclose(file);
}
| Oid GetNextTempTableSpace | ( | void | ) |
Definition at line 1975 of file fd.c.
References nextTempTableSpace, numTempTableSpaces, and tempTableSpaces.
Referenced by GetDefaultTablespace(), and OpenTemporaryFile().
{
if (numTempTableSpaces > 0)
{
/* Advance nextTempTableSpace counter with wraparound */
if (++nextTempTableSpace >= numTempTableSpaces)
nextTempTableSpace = 0;
return tempTableSpaces[nextTempTableSpace];
}
return InvalidOid;
}
| void InitFileAccess | ( | void | ) |
Definition at line 389 of file fd.c.
References Assert, AtProcExit_Files(), ereport, errcode(), errmsg(), FATAL, vfd::fd, malloc, MemSet, NULL, on_proc_exit(), and SizeVfdCache.
Referenced by BaseInit().
{
Assert(SizeVfdCache == 0); /* call me only once */
/* initialize cache header entry */
VfdCache = (Vfd *) malloc(sizeof(Vfd));
if (VfdCache == NULL)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
VfdCache->fd = VFD_CLOSED;
SizeVfdCache = 1;
/* register proc-exit hook to ensure temp files are dropped at exit */
on_proc_exit(AtProcExit_Files, 0);
}
| FILE* OpenPipeStream | ( | const char * | command, | |
| const char * | mode | |||
| ) |
Definition at line 1595 of file fd.c.
References AllocateDesc::create_subid, AllocateDesc::desc, DO_DB, elog, ereport, errcode(), errmsg(), ERROR, AllocateDesc::file, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, MAX_ALLOCATED_DESCS, max_safe_fds, NULL, numAllocatedDescs, and ReleaseLruFile().
Referenced by BeginCopyFrom(), and BeginCopyTo().
{
FILE *file;
DO_DB(elog(LOG, "OpenPipeStream: Allocated %d (%s)",
numAllocatedDescs, command));
/*
* The test against MAX_ALLOCATED_DESCS prevents us from overflowing
* allocatedFiles[]; the test against max_safe_fds prevents AllocateFile
* from hogging every one of the available FDs, which'd lead to infinite
* looping.
*/
if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
numAllocatedDescs >= max_safe_fds - 1)
elog(ERROR, "exceeded MAX_ALLOCATED_DESCS while trying to execute command \"%s\"",
command);
TryAgain:
fflush(stdout);
fflush(stderr);
errno = 0;
if ((file = popen(command, mode)) != NULL)
{
AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];
desc->kind = AllocateDescPipe;
desc->desc.file = file;
desc->create_subid = GetCurrentSubTransactionId();
numAllocatedDescs++;
return desc->desc.file;
}
if (errno == EMFILE || errno == ENFILE)
{
int save_errno = errno;
ereport(LOG,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("out of file descriptors: %m; release and retry")));
errno = 0;
if (ReleaseLruFile())
goto TryAgain;
errno = save_errno;
}
return NULL;
}
Definition at line 951 of file fd.c.
References CurrentResourceOwner, DEFAULTTABLESPACE_OID, vfd::fdstate, GetNextTempTableSpace(), have_xact_temporary_files, MyDatabaseTableSpace, numTempTableSpaces, OidIsValid, OpenTemporaryFileInTablespace(), ResourceOwnerEnlargeFiles(), ResourceOwnerRememberFile(), and vfd::resowner.
Referenced by BufFileCreateTemp(), and extendBufFile().
{
File file = 0;
/*
* If some temp tablespace(s) have been given to us, try to use the next
* one. If a given tablespace can't be found, we silently fall back to
* the database's default tablespace.
*
* BUT: if the temp file is slated to outlive the current transaction,
* force it into the database's default tablespace, so that it will not
* pose a threat to possible tablespace drop attempts.
*/
if (numTempTableSpaces > 0 && !interXact)
{
Oid tblspcOid = GetNextTempTableSpace();
if (OidIsValid(tblspcOid))
file = OpenTemporaryFileInTablespace(tblspcOid, false);
}
/*
* If not, or if tablespace is bad, create in database's default
* tablespace. MyDatabaseTableSpace should normally be set before we get
* here, but just in case it isn't, fall back to pg_default tablespace.
*/
if (file <= 0)
file = OpenTemporaryFileInTablespace(MyDatabaseTableSpace ?
MyDatabaseTableSpace :
DEFAULTTABLESPACE_OID,
true);
/* Mark it for deletion at close */
VfdCache[file].fdstate |= FD_TEMPORARY;
/* Register it with the current resource owner */
if (!interXact)
{
VfdCache[file].fdstate |= FD_XACT_TEMPORARY;
ResourceOwnerEnlargeFiles(CurrentResourceOwner);
ResourceOwnerRememberFile(CurrentResourceOwner, file);
VfdCache[file].resowner = CurrentResourceOwner;
/* ensure cleanup happens at eoxact */
have_xact_temporary_files = true;
}
return file;
}
| int OpenTransientFile | ( | FileName | fileName, | |
| int | fileFlags, | |||
| int | fileMode | |||
| ) |
Definition at line 1553 of file fd.c.
References BasicOpenFile(), AllocateDesc::create_subid, AllocateDesc::desc, DO_DB, elog, ERROR, AllocateDesc::fd, GetCurrentSubTransactionId(), AllocateDesc::kind, LOG, MAX_ALLOCATED_DESCS, max_safe_fds, and numAllocatedDescs.
Referenced by CheckPointTwoPhase(), copy_file(), EndPrepare(), fsync_fname(), lo_export(), lo_import_internal(), load_relmap_file(), mdunlinkfork(), ReadTwoPhaseFile(), RecreateTwoPhaseFile(), SendTimeLineHistory(), SlruPhysicalReadPage(), SlruPhysicalWritePage(), write_relmap_file(), writeTimeLineHistory(), writeTimeLineHistoryFile(), and XLogFileCopy().
{
int fd;
DO_DB(elog(LOG, "OpenTransientFile: Allocated %d (%s)",
numAllocatedDescs, fileName));
/*
* The test against MAX_ALLOCATED_DESCS prevents us from overflowing
* allocatedFiles[]; the test against max_safe_fds prevents BasicOpenFile
* from hogging every one of the available FDs, which'd lead to infinite
* looping.
*/
if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
numAllocatedDescs >= max_safe_fds - 1)
elog(ERROR, "exceeded MAX_ALLOCATED_DESCS while trying to open file \"%s\"",
fileName);
fd = BasicOpenFile(fileName, fileFlags, fileMode);
if (fd >= 0)
{
AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];
desc->kind = AllocateDescRawFD;
desc->desc.fd = fd;
desc->create_subid = GetCurrentSubTransactionId();
numAllocatedDescs++;
return fd;
}
return -1; /* failure */
}
Definition at line 883 of file fd.c.
References AllocateVfd(), BasicOpenFile(), DO_DB, elog, ereport, errcode(), errmsg(), ERROR, vfd::fd, vfd::fdstate, vfd::fileFlags, vfd::fileMode, vfd::fileName, vfd::fileSize, free, FreeVfd(), Insert(), LOG, max_safe_fds, nfile, NULL, numAllocatedDescs, ReleaseLruFile(), vfd::resowner, and vfd::seekPos.
Referenced by _mdfd_openseg(), mdcreate(), mdopen(), and OpenTemporaryFileInTablespace().
{
char *fnamecopy;
File file;
Vfd *vfdP;
DO_DB(elog(LOG, "PathNameOpenFile: %s %x %o",
fileName, fileFlags, fileMode));
/*
* We need a malloc'd copy of the file name; fail cleanly if no room.
*/
fnamecopy = strdup(fileName);
if (fnamecopy == NULL)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
file = AllocateVfd();
vfdP = &VfdCache[file];
while (nfile + numAllocatedDescs >= max_safe_fds)
{
if (!ReleaseLruFile())
break;
}
vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
if (vfdP->fd < 0)
{
FreeVfd(file);
free(fnamecopy);
return -1;
}
++nfile;
DO_DB(elog(LOG, "PathNameOpenFile: success %d",
vfdP->fd));
Insert(file);
vfdP->fileName = fnamecopy;
/* Saved flags are adjusted to be OK for re-opening file */
vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
vfdP->fileMode = fileMode;
vfdP->seekPos = 0;
vfdP->fileSize = 0;
vfdP->fdstate = 0x0;
vfdP->resowner = NULL;
return file;
}
| int pg_fdatasync | ( | int | fd | ) |
Definition at line 345 of file fd.c.
References enableFsync, and fsync.
Referenced by issue_xlog_fsync().
{
if (enableFsync)
{
#ifdef HAVE_FDATASYNC
return fdatasync(fd);
#else
return fsync(fd);
#endif
}
else
return 0;
}
| int pg_flush_data | ( | int | fd, | |
| off_t | offset, | |||
| off_t | amount | |||
| ) |
Definition at line 368 of file fd.c.
References enableFsync.
Referenced by copy_file().
{
if (enableFsync)
{
#if defined(HAVE_SYNC_FILE_RANGE)
return sync_file_range(fd, offset, amount, SYNC_FILE_RANGE_WRITE);
#elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
return posix_fadvise(fd, offset, amount, POSIX_FADV_DONTNEED);
#endif
}
return 0;
}
| int pg_fsync | ( | int | fd | ) |
Definition at line 293 of file fd.c.
References pg_fsync_no_writethrough(), pg_fsync_writethrough(), sync_method, and SYNC_METHOD_FSYNC_WRITETHROUGH.
Referenced by AddToDataDirLockFile(), assign_xlog_sync_method(), BootStrapXLOG(), CheckPointTwoPhase(), CreateLockFile(), do_pg_start_backup(), FileSync(), fsync_fname(), RecreateTwoPhaseFile(), SimpleLruFlush(), SlruPhysicalWritePage(), UpdateControlFile(), write_relmap_file(), WriteControlFile(), writeTimeLineHistory(), writeTimeLineHistoryFile(), XLogFileCopy(), and XLogFileInit().
{
/* #if is to skip the sync_method test if there's no need for it */
#if defined(HAVE_FSYNC_WRITETHROUGH) && !defined(FSYNC_WRITETHROUGH_IS_FSYNC)
if (sync_method == SYNC_METHOD_FSYNC_WRITETHROUGH)
return pg_fsync_writethrough(fd);
else
#endif
return pg_fsync_no_writethrough(fd);
}
| int pg_fsync_no_writethrough | ( | int | fd | ) |
Definition at line 310 of file fd.c.
References enableFsync, and fsync.
Referenced by issue_xlog_fsync(), and pg_fsync().
{
if (enableFsync)
return fsync(fd);
else
return 0;
}
| int pg_fsync_writethrough | ( | int | fd | ) |
Definition at line 322 of file fd.c.
References enableFsync.
Referenced by issue_xlog_fsync(), pg_fsync(), and test_sync().
{
if (enableFsync)
{
#ifdef WIN32
return _commit(fd);
#elif defined(F_FULLFSYNC)
return (fcntl(fd, F_FULLFSYNC, 0) == -1) ? -1 : 0;
#else
errno = ENOSYS;
return -1;
#endif
}
else
return 0;
}
Definition at line 1814 of file fd.c.
References ereport, errcode_for_file_access(), errmsg(), ERROR, NULL, and readdir().
Referenced by calculate_database_size(), calculate_tablespace_size(), CleanupBackupHistory(), copydir(), db_dir_size(), DeleteAllExportedSnapshotFiles(), destroy_tablespace_directories(), directory_is_empty(), get_available_versions_for_extension(), get_ext_ver_list(), movedb(), perform_base_backup(), pg_available_extension_versions(), pg_available_extensions(), pg_logdir_ls(), pg_ls_dir(), pg_tablespace_databases(), pg_tzenumerate_next(), pgarch_readyXlog(), pgstat_reset_remove_files(), PrescanPreparedTransactions(), RecoverPreparedTransactions(), RelationCacheInitFileRemove(), RelationCacheInitFileRemoveInDir(), RemoveOldXlogFiles(), RemovePgTempFiles(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), RemovePgTempRelationFilesInDbspace(), ResetUnloggedRelations(), ResetUnloggedRelationsInDbspaceDir(), ResetUnloggedRelationsInTablespaceDir(), scan_directory_ci(), sendDir(), SlruScanDirectory(), and StandbyRecoverPreparedTransactions().
{
struct dirent *dent;
/* Give a generic message for AllocateDir failure, if caller didn't */
if (dir == NULL)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m",
dirname)));
errno = 0;
if ((dent = readdir(dir)) != NULL)
return dent;
#ifdef WIN32
/*
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
* released version
*/
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
if (errno)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not read directory \"%s\": %m",
dirname)));
return NULL;
}
| void RemovePgTempFiles | ( | void | ) |
Definition at line 2116 of file fd.c.
References AllocateDir(), dirent::d_name, FreeDir(), NULL, PG_TEMP_FILES_DIR, ReadDir(), RemovePgTempFilesInDir(), RemovePgTempRelationFiles(), snprintf(), and TABLESPACE_VERSION_DIRECTORY.
Referenced by PostmasterMain().
{
char temp_path[MAXPGPATH];
DIR *spc_dir;
struct dirent *spc_de;
/*
* First process temp files in pg_default ($PGDATA/base)
*/
snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
RemovePgTempFilesInDir(temp_path);
RemovePgTempRelationFiles("base");
/*
* Cycle through temp directories for all non-default tablespaces.
*/
spc_dir = AllocateDir("pg_tblspc");
while ((spc_de = ReadDir(spc_dir, "pg_tblspc")) != NULL)
{
if (strcmp(spc_de->d_name, ".") == 0 ||
strcmp(spc_de->d_name, "..") == 0)
continue;
snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s/%s",
spc_de->d_name, TABLESPACE_VERSION_DIRECTORY, PG_TEMP_FILES_DIR);
RemovePgTempFilesInDir(temp_path);
snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
spc_de->d_name, TABLESPACE_VERSION_DIRECTORY);
RemovePgTempRelationFiles(temp_path);
}
FreeDir(spc_dir);
/*
* In EXEC_BACKEND case there is a pgsql_tmp directory at the top level of
* DataDir as well.
*/
#ifdef EXEC_BACKEND
RemovePgTempFilesInDir(PG_TEMP_FILES_DIR);
#endif
}
| void set_max_safe_fds | ( | void | ) |
Definition at line 506 of file fd.c.
References count_usable_fds(), DEBUG2, elog, ereport, errcode(), errdetail(), errmsg(), FATAL, FD_MINFREE, max_files_per_process, max_safe_fds, Min, and NUM_RESERVED_FDS.
Referenced by PostmasterMain().
{
int usable_fds;
int already_open;
/*----------
* We want to set max_safe_fds to
* MIN(usable_fds, max_files_per_process - already_open)
* less the slop factor for files that are opened without consulting
* fd.c. This ensures that we won't exceed either max_files_per_process
* or the experimentally-determined EMFILE limit.
*----------
*/
count_usable_fds(max_files_per_process,
&usable_fds, &already_open);
max_safe_fds = Min(usable_fds, max_files_per_process - already_open);
/*
* Take off the FDs reserved for system() etc.
*/
max_safe_fds -= NUM_RESERVED_FDS;
/*
* Make sure we still have enough to get by.
*/
if (max_safe_fds < FD_MINFREE)
ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("insufficient file descriptors available to start server process"),
errdetail("System allows %d, we need at least %d.",
max_safe_fds + NUM_RESERVED_FDS,
FD_MINFREE + NUM_RESERVED_FDS)));
elog(DEBUG2, "max_safe_fds = %d, usable_fds = %d, already_open = %d",
max_safe_fds, usable_fds, already_open);
}
| void SetTempTablespaces | ( | Oid * | tableSpaces, | |
| int | numSpaces | |||
| ) |
Definition at line 1935 of file fd.c.
References Assert, nextTempTableSpace, numTempTableSpaces, random(), and tempTableSpaces.
Referenced by assign_temp_tablespaces(), and PrepareTempTablespaces().
{
Assert(numSpaces >= 0);
tempTableSpaces = tableSpaces;
numTempTableSpaces = numSpaces;
/*
* Select a random starting point in the list. This is to minimize
* conflicts between backends that are most likely sharing the same list
* of temp tablespaces. Note that if we create multiple temp files in the
* same transaction, we'll advance circularly through the list --- this
* ensures that large temporary sort files are nicely spread across all
* available tablespaces.
*/
if (numSpaces > 1)
nextTempTableSpace = random() % numSpaces;
else
nextTempTableSpace = 0;
}
| bool TempTablespacesAreSet | ( | void | ) |
Definition at line 1963 of file fd.c.
References numTempTableSpaces.
Referenced by PrepareTempTablespaces().
{
return (numTempTableSpaces >= 0);
}
Definition at line 112 of file fd.c.
Referenced by set_max_safe_fds().
| int max_safe_fds |
Definition at line 125 of file fd.c.
Referenced by AllocateDir(), AllocateFile(), LruInsert(), OpenPipeStream(), OpenTransientFile(), PathNameOpenFile(), and set_max_safe_fds().
1.7.1