int FileTruncate(File file, int64 offset) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileTruncate %d (%s)", file, VfdCache[file].fileName)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; /* * Call ftruncate with a int64 value. * * WARNING:DO NOT typecast this down to a 32-bit long or * append-only vacuum full adjustment of the eof will erroneously remove * table data. */ returnCode = ftruncate(VfdCache[file].fd, offset); /* Assume we don't know the file position anymore */ VfdCache[file].seekPos = FileUnknownPos; return returnCode; }
void FileInvalidate(File file) { Assert(FileIsValid(file)); if (!FileIsNotOpen(file)) LruDelete(file); }
int64 FileSeek(File file, int64 offset, int whence) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileSeek: %d (%s) " INT64_FORMAT " " INT64_FORMAT " %d", file, VfdCache[file].fileName, VfdCache[file].seekPos, offset, whence)); if (FileIsNotOpen(file)) { switch (whence) { case SEEK_SET: Assert(offset >= INT64CONST(0)); 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 = pg_lseek64(VfdCache[file].fd, offset, whence); break; default: Assert(!"invalid whence"); break; } } else { switch (whence) { case SEEK_SET: Assert(offset >= INT64CONST(0)); if (VfdCache[file].seekPos != offset) VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; case SEEK_CUR: if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos) VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; case SEEK_END: VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd, offset, whence); break; default: Assert(!"invalid whence"); break; } } return VfdCache[file].seekPos; }
/* * close a file when done with it */ void FileClose(File file) { Vfd *vfdP; struct stat filestats; 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 */ if (vfdP->fdstate & FD_TEMPORARY) { /* reset flag so that die() interrupt won't cause problems */ vfdP->fdstate &= ~FD_TEMPORARY; if (log_temp_files >= 0) { if (stat(vfdP->fileName, &filestats) == 0) { if (filestats.st_size >= log_temp_files) ereport(LOG, (errmsg("temporary file: path \"%s\", size %lu", vfdP->fileName, (unsigned long) filestats.st_size))); } else elog(LOG, "could not stat file \"%s\": %m", vfdP->fileName); } if (unlink(vfdP->fileName)) elog(LOG, "could not unlink 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); }
int64 FileTell(File file) { Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileTell %d (%s)", file, VfdCache[file].fileName)); return VfdCache[file].seekPos; }
int FileRead(File file, char *buffer, int amount) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); if (Debug_filerep_print) (elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, 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; }
int FileWrite(File file, char *buffer, int amount) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileWrite: %d (%s) %ld %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; 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; 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; }
/* * close a file and forcibly delete the underlying Unix file */ void FileUnlink(File file) { Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileUnlink: %d (%s)", file, VfdCache[file].fileName)); /* force FileClose to delete it */ VfdCache[file].fdstate |= FD_TEMPORARY; FileClose(file); }
int FileSync(File file) { 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); }
int64 FileNonVirtualCurSeek(File file) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileNonVirtualCurSeek: %d (%s) virtual position" INT64_FORMAT, file, VfdCache[file].fileName, VfdCache[file].seekPos)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; return pg_lseek64(VfdCache[file].fd, 0, SEEK_CUR); }
int FileSync(File file) { int returnCode; FileRepGpmonRecord_s gpmonRecord; FileRepGpmonStatType_e whichStat; if (fileRepRole == FileRepPrimaryRole) { whichStat = FileRepGpmonStatType_PrimaryFsyncSyscall; FileRepGpmonStat_OpenRecord(whichStat, &gpmonRecord); } else { whichStat = FileRepGpmonStatType_MirrorFsyncSyscall; FileRepGpmonStat_OpenRecord(whichStat, &gpmonRecord); } Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileSync: %d (%s)", file, VfdCache[file].fileName)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; #ifdef FAULT_INJECTOR FaultInjector_InjectFaultIfSet( FileRepFlush, DDLNotSpecified, "", //databaseName ""); // tableName #endif returnCode = pg_fsync(VfdCache[file].fd); if (returnCode >= 0) { //only include stats if successful if ((fileRepRole == FileRepPrimaryRole) || (fileRepRole == FileRepMirrorRole)) { FileRepGpmonStat_CloseRecord(whichStat, &gpmonRecord); } } return returnCode; }
int FileTruncate(File file, long offset) { 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, (size_t) offset); return returnCode; }
/* * close a file when done with it */ void FileClose(File file) { 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 (gp_retry_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 */ if (vfdP->fdstate & FD_TEMPORARY) { /* reset flag so that die() interrupt won't cause problems */ vfdP->fdstate &= ~FD_TEMPORARY; if (unlink(vfdP->fileName)) elog(DEBUG1, "failed to unlink \"%s\": %m", vfdP->fileName); } /* * Return the Vfd slot to the free list */ FreeVfd(file); }
int FileWrite(File file, char *buffer, int amount) { int returnCode; FileRepGpmonRecord_s gpmonRecord; FileRepGpmonStatType_e whichStat =0; if (fileRepRole == FileRepPrimaryRole) { whichStat = FileRepGpmonStatType_PrimaryWriteSyscall; FileRepGpmonStat_OpenRecord(whichStat, &gpmonRecord); gpmonRecord.size = amount; } else if (fileRepRole == FileRepMirrorRole) { whichStat = FileRepGpmonStatType_MirrorWriteSyscall; FileRepGpmonStat_OpenRecord(whichStat, &gpmonRecord); gpmonRecord.size = amount; } Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); /* Added temporary for troubleshooting */ if (Debug_filerep_print) elog(LOG, "FileWrite: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer); else FileRep_InsertLogEntry( "FileWrite", FileRep_GetFlatFileIdentifier(VfdCache[file].fileName, ""), FileRepRelationTypeFlatFile, FileRepOperationWrite, FILEREP_UNDEFINED, FILEREP_UNDEFINED, FileRepAckStateNotInitialized, VfdCache[file].seekPos, amount); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; #ifdef FAULT_INJECTOR if (! strcmp(VfdCache[file].fileName, "global/pg_control")) { if (FaultInjector_InjectFaultIfSet( PgControl, DDLNotSpecified, "" /* databaseName */, "" /* tableName */) == FaultInjectorTypeDataCorruption) { MemSet(buffer, 0, amount); } } if (strstr(VfdCache[file].fileName, "pg_xlog/")) { if (FaultInjector_InjectFaultIfSet( PgXlog, DDLNotSpecified, "" /* databaseName */, "" /* tableName */) == FaultInjectorTypeDataCorruption) { MemSet(buffer, 0, amount); } } #endif 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; 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; } if (returnCode >= 0) { //only include stat if successful if ((fileRepRole == FileRepPrimaryRole) || (fileRepRole == FileRepMirrorRole)) { FileRepGpmonStat_CloseRecord(whichStat, &gpmonRecord); } } return returnCode; }
long FileSeek(File file, long offset, int whence) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileSeek: %d (%s) %ld %ld %d", file, VfdCache[file].fileName, VfdCache[file].seekPos, offset, whence)); if (FileIsNotOpen(file)) { switch (whence) { case SEEK_SET: if (offset < 0) elog(ERROR, "invalid seek offset: %ld", 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: %ld", 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; }