PostgreSQL Source Code  git master
logtape.h File Reference
Include dependency graph for logtape.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TapeShare
 

Typedefs

typedef struct LogicalTapeSet LogicalTapeSet
 
typedef struct TapeShare TapeShare
 

Functions

LogicalTapeSetLogicalTapeSetCreate (int ntapes, TapeShare *shared, SharedFileSet *fileset, int worker)
 
void LogicalTapeSetClose (LogicalTapeSet *lts)
 
void LogicalTapeSetForgetFreeSpace (LogicalTapeSet *lts)
 
size_t LogicalTapeRead (LogicalTapeSet *lts, int tapenum, void *ptr, size_t size)
 
void LogicalTapeWrite (LogicalTapeSet *lts, int tapenum, void *ptr, size_t size)
 
void LogicalTapeRewindForRead (LogicalTapeSet *lts, int tapenum, size_t buffer_size)
 
void LogicalTapeRewindForWrite (LogicalTapeSet *lts, int tapenum)
 
void LogicalTapeFreeze (LogicalTapeSet *lts, int tapenum, TapeShare *share)
 
size_t LogicalTapeBackspace (LogicalTapeSet *lts, int tapenum, size_t size)
 
void LogicalTapeSeek (LogicalTapeSet *lts, int tapenum, long blocknum, int offset)
 
void LogicalTapeTell (LogicalTapeSet *lts, int tapenum, long *blocknum, int *offset)
 
long LogicalTapeSetBlocks (LogicalTapeSet *lts)
 

Typedef Documentation

◆ LogicalTapeSet

Definition at line 23 of file logtape.h.

◆ TapeShare

Function Documentation

◆ LogicalTapeBackspace()

size_t LogicalTapeBackspace ( LogicalTapeSet lts,
int  tapenum,
size_t  size 
)

Definition at line 964 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, elog, ERROR, LogicalTape::firstBlockNumber, LogicalTape::frozen, ltsReadBlock(), LogicalTape::nbytes, LogicalTape::nextBlockNumber, LogicalTape::pos, TapeBlockTrailer::prev, TapeBlockGetTrailer, TapeBlockPayloadSize, and LogicalTapeSet::tapes.

Referenced by tuplesort_gettuple_common().

965 {
966  LogicalTape *lt;
967  size_t seekpos = 0;
968 
969  Assert(tapenum >= 0 && tapenum < lts->nTapes);
970  lt = &lts->tapes[tapenum];
971  Assert(lt->frozen);
972  Assert(lt->buffer_size == BLCKSZ);
973 
974  /*
975  * Easy case for seek within current block.
976  */
977  if (size <= (size_t) lt->pos)
978  {
979  lt->pos -= (int) size;
980  return size;
981  }
982 
983  /*
984  * Not-so-easy case, have to walk back the chain of blocks. This
985  * implementation would be pretty inefficient for long seeks, but we
986  * really aren't doing that (a seek over one tuple is typical).
987  */
988  seekpos = (size_t) lt->pos; /* part within this block */
989  while (size > seekpos)
990  {
991  long prev = TapeBlockGetTrailer(lt->buffer)->prev;
992 
993  if (prev == -1L)
994  {
995  /* Tried to back up beyond the beginning of tape. */
996  if (lt->curBlockNumber != lt->firstBlockNumber)
997  elog(ERROR, "unexpected end of tape");
998  lt->pos = 0;
999  return seekpos;
1000  }
1001 
1002  ltsReadBlock(lts, prev, (void *) lt->buffer);
1003 
1004  if (TapeBlockGetTrailer(lt->buffer)->next != lt->curBlockNumber)
1005  elog(ERROR, "broken tape, next of block %ld is %ld, expected %ld",
1006  prev,
1007  TapeBlockGetTrailer(lt->buffer)->next,
1008  lt->curBlockNumber);
1009 
1011  lt->curBlockNumber = prev;
1012  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1013 
1014  seekpos += TapeBlockPayloadSize;
1015  }
1016 
1017  /*
1018  * 'seekpos' can now be greater than 'size', because it points to the
1019  * beginning the target block. The difference is the position within the
1020  * page.
1021  */
1022  lt->pos = seekpos - size;
1023  return size;
1024 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
#define TapeBlockPayloadSize
Definition: logtape.c:106
bool frozen
Definition: logtape.c:131
long nextBlockNumber
Definition: logtape.c:147
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:157
long firstBlockNumber
Definition: logtape.c:145
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153
#define elog
Definition: elog.h:219
int buffer_size
Definition: logtape.c:154
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:107
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:270

◆ LogicalTapeFreeze()

void LogicalTapeFreeze ( LogicalTapeSet lts,
int  tapenum,
TapeShare share 
)

Definition at line 880 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, BufFileExportShared(), LogicalTape::curBlockNumber, LogicalTape::dirty, TapeShare::firstblocknumber, LogicalTape::firstBlockNumber, LogicalTape::frozen, ltsReadBlock(), ltsWriteBlock(), LogicalTape::nbytes, LogicalTape::nextBlockNumber, LogicalTape::offsetBlockNumber, palloc(), LogicalTapeSet::pfile, pfree(), LogicalTape::pos, TapeBlockGetNBytes, TapeBlockGetTrailer, TapeBlockIsLast, TapeBlockSetNBytes, LogicalTapeSet::tapes, VALGRIND_MAKE_MEM_DEFINED, and LogicalTape::writing.

Referenced by mergeruns(), and worker_freeze_result_tape().

881 {
882  LogicalTape *lt;
883 
884  Assert(tapenum >= 0 && tapenum < lts->nTapes);
885  lt = &lts->tapes[tapenum];
886  Assert(lt->writing);
887  Assert(lt->offsetBlockNumber == 0L);
888 
889  /*
890  * Completion of a write phase. Flush last partial data block, and rewind
891  * for nondestructive read.
892  */
893  if (lt->dirty)
894  {
895  /*
896  * As long as we've filled the buffer at least once, its contents are
897  * entirely defined from valgrind's point of view, even though
898  * contents beyond the current end point may be stale. But it's
899  * possible - at least in the case of a parallel sort - to sort such
900  * small amount of data that we do not fill the buffer even once. Tell
901  * valgrind that its contents are defined, so it doesn't bleat.
902  */
904  lt->buffer_size - lt->nbytes);
905 
906  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
907  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
908  lt->writing = false;
909  }
910  lt->writing = false;
911  lt->frozen = true;
912 
913  /*
914  * The seek and backspace functions assume a single block read buffer.
915  * That's OK with current usage. A larger buffer is helpful to make the
916  * read pattern of the backing file look more sequential to the OS, when
917  * we're reading from multiple tapes. But at the end of a sort, when a
918  * tape is frozen, we only read from a single tape anyway.
919  */
920  if (!lt->buffer || lt->buffer_size != BLCKSZ)
921  {
922  if (lt->buffer)
923  pfree(lt->buffer);
924  lt->buffer = palloc(BLCKSZ);
925  lt->buffer_size = BLCKSZ;
926  }
927 
928  /* Read the first block, or reset if tape is empty */
930  lt->pos = 0;
931  lt->nbytes = 0;
932 
933  if (lt->firstBlockNumber == -1L)
934  lt->nextBlockNumber = -1L;
935  ltsReadBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
936  if (TapeBlockIsLast(lt->buffer))
937  lt->nextBlockNumber = -1L;
938  else
939  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
940  lt->nbytes = TapeBlockGetNBytes(lt->buffer);
941 
942  /* Handle extra steps when caller is to share its tapeset */
943  if (share)
944  {
946  share->firstblocknumber = lt->firstBlockNumber;
947  }
948 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
#define TapeBlockIsLast(buf)
Definition: logtape.c:110
long offsetBlockNumber
Definition: logtape.c:148
BufFile * pfile
Definition: logtape.c:168
long firstblocknumber
Definition: logtape.h:50
bool frozen
Definition: logtape.c:131
long nextBlockNumber
Definition: logtape.c:147
bool writing
Definition: logtape.c:130
bool dirty
Definition: logtape.c:132
void pfree(void *pointer)
Definition: mcxt.c:1031
int nbytes
Definition: logtape.c:157
long firstBlockNumber
Definition: logtape.c:145
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:114
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
void BufFileExportShared(BufFile *file)
Definition: buffile.c:379
#define TapeBlockGetNBytes(buf)
Definition: logtape.c:111
char * buffer
Definition: logtape.c:153
void * palloc(Size size)
Definition: mcxt.c:924
int buffer_size
Definition: logtape.c:154
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:222
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:107
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:270

◆ LogicalTapeRead()

size_t LogicalTapeRead ( LogicalTapeSet lts,
int  tapenum,
void *  ptr,
size_t  size 
)

Definition at line 826 of file logtape.c.

References Assert, LogicalTape::buffer, ltsReadFillBuffer(), LogicalTape::nbytes, LogicalTape::pos, LogicalTapeSet::tapes, and LogicalTape::writing.

Referenced by getlen().

828 {
829  LogicalTape *lt;
830  size_t nread = 0;
831  size_t nthistime;
832 
833  Assert(tapenum >= 0 && tapenum < lts->nTapes);
834  lt = &lts->tapes[tapenum];
835  Assert(!lt->writing);
836 
837  while (size > 0)
838  {
839  if (lt->pos >= lt->nbytes)
840  {
841  /* Try to load more data into buffer. */
842  if (!ltsReadFillBuffer(lts, lt))
843  break; /* EOF */
844  }
845 
846  nthistime = lt->nbytes - lt->pos;
847  if (nthistime > size)
848  nthistime = size;
849  Assert(nthistime > 0);
850 
851  memcpy(ptr, lt->buffer + lt->pos, nthistime);
852 
853  lt->pos += nthistime;
854  ptr = (void *) ((char *) ptr + nthistime);
855  size -= nthistime;
856  nread += nthistime;
857  }
858 
859  return nread;
860 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
static bool ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:286
bool writing
Definition: logtape.c:130
int nbytes
Definition: logtape.c:157
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153

◆ LogicalTapeRewindForRead()

void LogicalTapeRewindForRead ( LogicalTapeSet lts,
int  tapenum,
size_t  buffer_size 
)

Definition at line 713 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, LogicalTape::dirty, LogicalTape::firstBlockNumber, LogicalTape::frozen, ltsReadFillBuffer(), ltsWriteBlock(), LogicalTape::max_size, LogicalTape::nbytes, LogicalTape::nextBlockNumber, palloc(), pfree(), LogicalTape::pos, TapeBlockSetNBytes, LogicalTapeSet::tapes, VALGRIND_MAKE_MEM_DEFINED, and LogicalTape::writing.

Referenced by mergeruns(), and tuplesort_rescan().

714 {
715  LogicalTape *lt;
716 
717  Assert(tapenum >= 0 && tapenum < lts->nTapes);
718  lt = &lts->tapes[tapenum];
719 
720  /*
721  * Round and cap buffer_size if needed.
722  */
723  if (lt->frozen)
724  buffer_size = BLCKSZ;
725  else
726  {
727  /* need at least one block */
728  if (buffer_size < BLCKSZ)
729  buffer_size = BLCKSZ;
730 
731  /* palloc() larger than max_size is unlikely to be helpful */
732  if (buffer_size > lt->max_size)
733  buffer_size = lt->max_size;
734 
735  /* round down to BLCKSZ boundary */
736  buffer_size -= buffer_size % BLCKSZ;
737  }
738 
739  if (lt->writing)
740  {
741  /*
742  * Completion of a write phase. Flush last partial data block, and
743  * rewind for normal (destructive) read.
744  */
745  if (lt->dirty)
746  {
747  /*
748  * As long as we've filled the buffer at least once, its contents
749  * are entirely defined from valgrind's point of view, even though
750  * contents beyond the current end point may be stale. But it's
751  * possible - at least in the case of a parallel sort - to sort
752  * such small amount of data that we do not fill the buffer even
753  * once. Tell valgrind that its contents are defined, so it
754  * doesn't bleat.
755  */
757  lt->buffer_size - lt->nbytes);
758 
759  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
760  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
761  }
762  lt->writing = false;
763  }
764  else
765  {
766  /*
767  * This is only OK if tape is frozen; we rewind for (another) read
768  * pass.
769  */
770  Assert(lt->frozen);
771  }
772 
773  /* Allocate a read buffer (unless the tape is empty) */
774  if (lt->buffer)
775  pfree(lt->buffer);
776  lt->buffer = NULL;
777  lt->buffer_size = 0;
778  if (lt->firstBlockNumber != -1L)
779  {
780  lt->buffer = palloc(buffer_size);
781  lt->buffer_size = buffer_size;
782  }
783 
784  /* Read the first block, or reset if tape is empty */
786  lt->pos = 0;
787  lt->nbytes = 0;
788  ltsReadFillBuffer(lts, lt);
789 }
int max_size
Definition: logtape.c:155
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
static bool ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:286
bool frozen
Definition: logtape.c:131
long nextBlockNumber
Definition: logtape.c:147
bool writing
Definition: logtape.c:130
bool dirty
Definition: logtape.c:132
void pfree(void *pointer)
Definition: mcxt.c:1031
int nbytes
Definition: logtape.c:157
long firstBlockNumber
Definition: logtape.c:145
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:114
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153
void * palloc(Size size)
Definition: mcxt.c:924
int buffer_size
Definition: logtape.c:154
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:222

◆ LogicalTapeRewindForWrite()

void LogicalTapeRewindForWrite ( LogicalTapeSet lts,
int  tapenum 
)

Definition at line 800 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, LogicalTape::dirty, LogicalTape::firstBlockNumber, LogicalTape::frozen, LogicalTape::nbytes, pfree(), LogicalTape::pos, LogicalTapeSet::tapes, and LogicalTape::writing.

Referenced by mergeruns(), and tuplesort_gettuple_common().

801 {
802  LogicalTape *lt;
803 
804  Assert(tapenum >= 0 && tapenum < lts->nTapes);
805  lt = &lts->tapes[tapenum];
806 
807  Assert(!lt->writing && !lt->frozen);
808  lt->writing = true;
809  lt->dirty = false;
810  lt->firstBlockNumber = -1L;
811  lt->curBlockNumber = -1L;
812  lt->pos = 0;
813  lt->nbytes = 0;
814  if (lt->buffer)
815  pfree(lt->buffer);
816  lt->buffer = NULL;
817  lt->buffer_size = 0;
818 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
bool frozen
Definition: logtape.c:131
bool writing
Definition: logtape.c:130
bool dirty
Definition: logtape.c:132
void pfree(void *pointer)
Definition: mcxt.c:1031
int nbytes
Definition: logtape.c:157
long firstBlockNumber
Definition: logtape.c:145
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153
int buffer_size
Definition: logtape.c:154

◆ LogicalTapeSeek()

void LogicalTapeSeek ( LogicalTapeSet lts,
int  tapenum,
long  blocknum,
int  offset 
)

Definition at line 1035 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, elog, ERROR, LogicalTape::frozen, ltsReadBlock(), LogicalTape::nbytes, LogicalTape::nextBlockNumber, LogicalTape::pos, TapeBlockGetTrailer, TapeBlockPayloadSize, and LogicalTapeSet::tapes.

Referenced by tuplesort_restorepos().

1037 {
1038  LogicalTape *lt;
1039 
1040  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1041  lt = &lts->tapes[tapenum];
1042  Assert(lt->frozen);
1043  Assert(offset >= 0 && offset <= TapeBlockPayloadSize);
1044  Assert(lt->buffer_size == BLCKSZ);
1045 
1046  if (blocknum != lt->curBlockNumber)
1047  {
1048  ltsReadBlock(lts, blocknum, (void *) lt->buffer);
1049  lt->curBlockNumber = blocknum;
1051  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1052  }
1053 
1054  if (offset > lt->nbytes)
1055  elog(ERROR, "invalid tape seek position");
1056  lt->pos = offset;
1057 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
#define TapeBlockPayloadSize
Definition: logtape.c:106
bool frozen
Definition: logtape.c:131
long nextBlockNumber
Definition: logtape.c:147
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:157
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153
#define elog
Definition: elog.h:219
int buffer_size
Definition: logtape.c:154
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:107
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:270

◆ LogicalTapeSetBlocks()

long LogicalTapeSetBlocks ( LogicalTapeSet lts)

Definition at line 1086 of file logtape.c.

References LogicalTapeSet::nBlocksAllocated, and LogicalTapeSet::nHoleBlocks.

Referenced by tuplesort_end(), and tuplesort_get_stats().

1087 {
1088  return lts->nBlocksAllocated - lts->nHoleBlocks;
1089 }
long nHoleBlocks
Definition: logtape.c:182
long nBlocksAllocated
Definition: logtape.c:180

◆ LogicalTapeSetClose()

void LogicalTapeSetClose ( LogicalTapeSet lts)

Definition at line 588 of file logtape.c.

References LogicalTape::buffer, BufFileClose(), LogicalTapeSet::freeBlocks, i, LogicalTapeSet::nTapes, LogicalTapeSet::pfile, pfree(), and LogicalTapeSet::tapes.

Referenced by tuplesort_end().

589 {
590  LogicalTape *lt;
591  int i;
592 
593  BufFileClose(lts->pfile);
594  for (i = 0; i < lts->nTapes; i++)
595  {
596  lt = &lts->tapes[i];
597  if (lt->buffer)
598  pfree(lt->buffer);
599  }
600  pfree(lts->freeBlocks);
601  pfree(lts);
602 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
BufFile * pfile
Definition: logtape.c:168
void BufFileClose(BufFile *file)
Definition: buffile.c:397
long * freeBlocks
Definition: logtape.c:199
void pfree(void *pointer)
Definition: mcxt.c:1031
char * buffer
Definition: logtape.c:153
int i

◆ LogicalTapeSetCreate()

LogicalTapeSet* LogicalTapeSetCreate ( int  ntapes,
TapeShare shared,
SharedFileSet fileset,
int  worker 
)

Definition at line 514 of file logtape.c.

References Assert, LogicalTapeSet::blocksSorted, LogicalTape::buffer, LogicalTape::buffer_size, BufFileCreateShared(), BufFileCreateTemp(), LogicalTape::curBlockNumber, LogicalTape::dirty, filename, LogicalTape::firstBlockNumber, LogicalTapeSet::forgetFreeSpace, LogicalTapeSet::freeBlocks, LogicalTapeSet::freeBlocksLen, LogicalTape::frozen, i, ltsConcatWorkerTapes(), LogicalTape::max_size, MaxAllocSize, MAXPGPATH, LogicalTapeSet::nBlocksAllocated, LogicalTapeSet::nBlocksWritten, LogicalTape::nbytes, LogicalTape::nextBlockNumber, LogicalTapeSet::nFreeBlocks, LogicalTapeSet::nHoleBlocks, LogicalTapeSet::nTapes, LogicalTape::offsetBlockNumber, offsetof, palloc(), LogicalTapeSet::pfile, pg_itoa(), LogicalTape::pos, LogicalTapeSet::tapes, and LogicalTape::writing.

Referenced by inittapes(), and leader_takeover_tapes().

516 {
517  LogicalTapeSet *lts;
518  LogicalTape *lt;
519  int i;
520 
521  /*
522  * Create top-level struct including per-tape LogicalTape structs.
523  */
524  Assert(ntapes > 0);
525  lts = (LogicalTapeSet *) palloc(offsetof(LogicalTapeSet, tapes) +
526  ntapes * sizeof(LogicalTape));
527  lts->nBlocksAllocated = 0L;
528  lts->nBlocksWritten = 0L;
529  lts->nHoleBlocks = 0L;
530  lts->forgetFreeSpace = false;
531  lts->blocksSorted = true; /* a zero-length array is sorted ... */
532  lts->freeBlocksLen = 32; /* reasonable initial guess */
533  lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
534  lts->nFreeBlocks = 0;
535  lts->nTapes = ntapes;
536 
537  /*
538  * Initialize per-tape structs. Note we allocate the I/O buffer and the
539  * first block for a tape only when it is first actually written to. This
540  * avoids wasting memory space when tuplesort.c overestimates the number
541  * of tapes needed.
542  */
543  for (i = 0; i < ntapes; i++)
544  {
545  lt = &lts->tapes[i];
546  lt->writing = true;
547  lt->frozen = false;
548  lt->dirty = false;
549  lt->firstBlockNumber = -1L;
550  lt->curBlockNumber = -1L;
551  lt->nextBlockNumber = -1L;
552  lt->offsetBlockNumber = 0L;
553  lt->buffer = NULL;
554  lt->buffer_size = 0;
555  /* palloc() larger than MaxAllocSize would fail */
556  lt->max_size = MaxAllocSize;
557  lt->pos = 0;
558  lt->nbytes = 0;
559  }
560 
561  /*
562  * Create temp BufFile storage as required.
563  *
564  * Leader concatenates worker tapes, which requires special adjustment to
565  * final tapeset data. Things are simpler for the worker case and the
566  * serial case, though. They are generally very similar -- workers use a
567  * shared fileset, whereas serial sorts use a conventional serial BufFile.
568  */
569  if (shared)
570  ltsConcatWorkerTapes(lts, shared, fileset);
571  else if (fileset)
572  {
573  char filename[MAXPGPATH];
574 
575  pg_itoa(worker, filename);
576  lts->pfile = BufFileCreateShared(fileset, filename);
577  }
578  else
579  lts->pfile = BufFileCreateTemp(false);
580 
581  return lts;
582 }
int max_size
Definition: logtape.c:155
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
int nFreeBlocks
Definition: logtape.c:200
long offsetBlockNumber
Definition: logtape.c:148
long nBlocksWritten
Definition: logtape.c:181
int freeBlocksLen
Definition: logtape.c:201
BufFile * pfile
Definition: logtape.c:168
bool frozen
Definition: logtape.c:131
long nextBlockNumber
Definition: logtape.c:147
bool writing
Definition: logtape.c:130
long * freeBlocks
Definition: logtape.c:199
bool dirty
Definition: logtape.c:132
BufFile * BufFileCreateTemp(bool interXact)
Definition: buffile.c:182
#define MAXPGPATH
BufFile * BufFileCreateShared(SharedFileSet *fileset, const char *name)
Definition: buffile.c:245
long nHoleBlocks
Definition: logtape.c:182
int nbytes
Definition: logtape.c:157
void pg_itoa(int16 i, char *a)
Definition: numutils.c:120
#define MaxAllocSize
Definition: memutils.h:40
long firstBlockNumber
Definition: logtape.c:145
static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, SharedFileSet *fileset)
Definition: logtape.c:409
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153
static char * filename
Definition: pg_dumpall.c:87
void * palloc(Size size)
Definition: mcxt.c:924
bool forgetFreeSpace
Definition: logtape.c:197
int i
struct LogicalTape LogicalTape
bool blocksSorted
Definition: logtape.c:198
long nBlocksAllocated
Definition: logtape.c:180
int buffer_size
Definition: logtape.c:154
#define offsetof(type, field)
Definition: c.h:622

◆ LogicalTapeSetForgetFreeSpace()

void LogicalTapeSetForgetFreeSpace ( LogicalTapeSet lts)

Definition at line 614 of file logtape.c.

References LogicalTapeSet::forgetFreeSpace.

Referenced by mergeruns().

615 {
616  lts->forgetFreeSpace = true;
617 }
bool forgetFreeSpace
Definition: logtape.c:197

◆ LogicalTapeTell()

void LogicalTapeTell ( LogicalTapeSet lts,
int  tapenum,
long *  blocknum,
int *  offset 
)

Definition at line 1066 of file logtape.c.

References Assert, LogicalTape::buffer_size, LogicalTape::curBlockNumber, LogicalTape::offsetBlockNumber, LogicalTape::pos, and LogicalTapeSet::tapes.

Referenced by tuplesort_markpos().

1068 {
1069  LogicalTape *lt;
1070 
1071  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1072  lt = &lts->tapes[tapenum];
1073  Assert(lt->offsetBlockNumber == 0L);
1074 
1075  /* With a larger buffer, 'pos' wouldn't be the same as offset within page */
1076  Assert(lt->buffer_size == BLCKSZ);
1077 
1078  *blocknum = lt->curBlockNumber;
1079  *offset = lt->pos;
1080 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
long offsetBlockNumber
Definition: logtape.c:148
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
int buffer_size
Definition: logtape.c:154

◆ LogicalTapeWrite()

void LogicalTapeWrite ( LogicalTapeSet lts,
int  tapenum,
void *  ptr,
size_t  size 
)

Definition at line 625 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, LogicalTape::dirty, elog, ERROR, LogicalTape::firstBlockNumber, ltsGetFreeBlock(), ltsWriteBlock(), LogicalTape::nbytes, LogicalTape::offsetBlockNumber, palloc(), LogicalTape::pos, TapeBlockGetTrailer, TapeBlockPayloadSize, LogicalTapeSet::tapes, and LogicalTape::writing.

Referenced by markrunend(), writetup_cluster(), writetup_datum(), writetup_heap(), and writetup_index().

627 {
628  LogicalTape *lt;
629  size_t nthistime;
630 
631  Assert(tapenum >= 0 && tapenum < lts->nTapes);
632  lt = &lts->tapes[tapenum];
633  Assert(lt->writing);
634  Assert(lt->offsetBlockNumber == 0L);
635 
636  /* Allocate data buffer and first block on first write */
637  if (lt->buffer == NULL)
638  {
639  lt->buffer = (char *) palloc(BLCKSZ);
640  lt->buffer_size = BLCKSZ;
641  }
642  if (lt->curBlockNumber == -1)
643  {
644  Assert(lt->firstBlockNumber == -1);
645  Assert(lt->pos == 0);
646 
647  lt->curBlockNumber = ltsGetFreeBlock(lts);
649 
650  TapeBlockGetTrailer(lt->buffer)->prev = -1L;
651  }
652 
653  Assert(lt->buffer_size == BLCKSZ);
654  while (size > 0)
655  {
656  if (lt->pos >= TapeBlockPayloadSize)
657  {
658  /* Buffer full, dump it out */
659  long nextBlockNumber;
660 
661  if (!lt->dirty)
662  {
663  /* Hmm, went directly from reading to writing? */
664  elog(ERROR, "invalid logtape state: should be dirty");
665  }
666 
667  /*
668  * First allocate the next block, so that we can store it in the
669  * 'next' pointer of this block.
670  */
671  nextBlockNumber = ltsGetFreeBlock(lts);
672 
673  /* set the next-pointer and dump the current block. */
674  TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber;
675  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
676 
677  /* initialize the prev-pointer of the next block */
678  TapeBlockGetTrailer(lt->buffer)->prev = lt->curBlockNumber;
679  lt->curBlockNumber = nextBlockNumber;
680  lt->pos = 0;
681  lt->nbytes = 0;
682  }
683 
684  nthistime = TapeBlockPayloadSize - lt->pos;
685  if (nthistime > size)
686  nthistime = size;
687  Assert(nthistime > 0);
688 
689  memcpy(lt->buffer + lt->pos, ptr, nthistime);
690 
691  lt->dirty = true;
692  lt->pos += nthistime;
693  if (lt->nbytes < lt->pos)
694  lt->nbytes = lt->pos;
695  ptr = (void *) ((char *) ptr + nthistime);
696  size -= nthistime;
697  }
698 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:205
#define TapeBlockPayloadSize
Definition: logtape.c:106
long offsetBlockNumber
Definition: logtape.c:148
static long ltsGetFreeBlock(LogicalTapeSet *lts)
Definition: logtape.c:345
bool writing
Definition: logtape.c:130
bool dirty
Definition: logtape.c:132
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:157
long firstBlockNumber
Definition: logtape.c:145
long curBlockNumber
Definition: logtape.c:146
#define Assert(condition)
Definition: c.h:699
char * buffer
Definition: logtape.c:153
void * palloc(Size size)
Definition: mcxt.c:924
#define elog
Definition: elog.h:219
int buffer_size
Definition: logtape.c:154
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:222
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:107