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

typedef struct TapeShare TapeShare

Function Documentation

◆ LogicalTapeBackspace()

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

Definition at line 1021 of file logtape.c.

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

Referenced by tuplesort_gettuple_common().

1022 {
1023  LogicalTape *lt;
1024  size_t seekpos = 0;
1025 
1026  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1027  lt = &lts->tapes[tapenum];
1028  Assert(lt->frozen);
1029  Assert(lt->buffer_size == BLCKSZ);
1030 
1031  if (lt->buffer == NULL)
1032  ltsInitReadBuffer(lts, lt);
1033 
1034  /*
1035  * Easy case for seek within current block.
1036  */
1037  if (size <= (size_t) lt->pos)
1038  {
1039  lt->pos -= (int) size;
1040  return size;
1041  }
1042 
1043  /*
1044  * Not-so-easy case, have to walk back the chain of blocks. This
1045  * implementation would be pretty inefficient for long seeks, but we
1046  * really aren't doing that (a seek over one tuple is typical).
1047  */
1048  seekpos = (size_t) lt->pos; /* part within this block */
1049  while (size > seekpos)
1050  {
1051  long prev = TapeBlockGetTrailer(lt->buffer)->prev;
1052 
1053  if (prev == -1L)
1054  {
1055  /* Tried to back up beyond the beginning of tape. */
1056  if (lt->curBlockNumber != lt->firstBlockNumber)
1057  elog(ERROR, "unexpected end of tape");
1058  lt->pos = 0;
1059  return seekpos;
1060  }
1061 
1062  ltsReadBlock(lts, prev, (void *) lt->buffer);
1063 
1064  if (TapeBlockGetTrailer(lt->buffer)->next != lt->curBlockNumber)
1065  elog(ERROR, "broken tape, next of block %ld is %ld, expected %ld",
1066  prev,
1067  TapeBlockGetTrailer(lt->buffer)->next,
1068  lt->curBlockNumber);
1069 
1071  lt->curBlockNumber = prev;
1072  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1073 
1074  seekpos += TapeBlockPayloadSize;
1075  }
1076 
1077  /*
1078  * 'seekpos' can now be greater than 'size', because it points to the
1079  * beginning the target block. The difference is the position within the
1080  * page.
1081  */
1082  lt->pos = seekpos - size;
1083  return size;
1084 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
#define TapeBlockPayloadSize
Definition: logtape.c:102
bool frozen
Definition: logtape.c:127
long nextBlockNumber
Definition: logtape.c:143
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:153
long firstBlockNumber
Definition: logtape.c:141
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:545
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
#define elog(elevel,...)
Definition: elog.h:228
int buffer_size
Definition: logtape.c:150
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:261

◆ LogicalTapeFreeze()

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

Definition at line 937 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().

938 {
939  LogicalTape *lt;
940 
941  Assert(tapenum >= 0 && tapenum < lts->nTapes);
942  lt = &lts->tapes[tapenum];
943  Assert(lt->writing);
944  Assert(lt->offsetBlockNumber == 0L);
945 
946  /*
947  * Completion of a write phase. Flush last partial data block, and rewind
948  * for nondestructive read.
949  */
950  if (lt->dirty)
951  {
952  /*
953  * As long as we've filled the buffer at least once, its contents are
954  * entirely defined from valgrind's point of view, even though
955  * contents beyond the current end point may be stale. But it's
956  * possible - at least in the case of a parallel sort - to sort such
957  * small amount of data that we do not fill the buffer even once. Tell
958  * valgrind that its contents are defined, so it doesn't bleat.
959  */
961  lt->buffer_size - lt->nbytes);
962 
963  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
964  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
965  lt->writing = false;
966  }
967  lt->writing = false;
968  lt->frozen = true;
969 
970  /*
971  * The seek and backspace functions assume a single block read buffer.
972  * That's OK with current usage. A larger buffer is helpful to make the
973  * read pattern of the backing file look more sequential to the OS, when
974  * we're reading from multiple tapes. But at the end of a sort, when a
975  * tape is frozen, we only read from a single tape anyway.
976  */
977  if (!lt->buffer || lt->buffer_size != BLCKSZ)
978  {
979  if (lt->buffer)
980  pfree(lt->buffer);
981  lt->buffer = palloc(BLCKSZ);
982  lt->buffer_size = BLCKSZ;
983  }
984 
985  /* Read the first block, or reset if tape is empty */
987  lt->pos = 0;
988  lt->nbytes = 0;
989 
990  if (lt->firstBlockNumber == -1L)
991  lt->nextBlockNumber = -1L;
992  ltsReadBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
993  if (TapeBlockIsLast(lt->buffer))
994  lt->nextBlockNumber = -1L;
995  else
996  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
997  lt->nbytes = TapeBlockGetNBytes(lt->buffer);
998 
999  /* Handle extra steps when caller is to share its tapeset */
1000  if (share)
1001  {
1002  BufFileExportShared(lts->pfile);
1003  share->firstblocknumber = lt->firstBlockNumber;
1004  }
1005 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
#define TapeBlockIsLast(buf)
Definition: logtape.c:106
long offsetBlockNumber
Definition: logtape.c:144
BufFile * pfile
Definition: logtape.c:164
long firstblocknumber
Definition: logtape.h:50
bool frozen
Definition: logtape.c:127
long nextBlockNumber
Definition: logtape.c:143
bool writing
Definition: logtape.c:126
bool dirty
Definition: logtape.c:128
void pfree(void *pointer)
Definition: mcxt.c:1056
int nbytes
Definition: logtape.c:153
long firstBlockNumber
Definition: logtape.c:141
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:110
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
void BufFileExportShared(BufFile *file)
Definition: buffile.c:373
#define TapeBlockGetNBytes(buf)
Definition: logtape.c:107
char * buffer
Definition: logtape.c:149
void * palloc(Size size)
Definition: mcxt.c:949
int buffer_size
Definition: logtape.c:150
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:213
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:261

◆ LogicalTapeRead()

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

Definition at line 880 of file logtape.c.

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

Referenced by getlen().

882 {
883  LogicalTape *lt;
884  size_t nread = 0;
885  size_t nthistime;
886 
887  Assert(tapenum >= 0 && tapenum < lts->nTapes);
888  lt = &lts->tapes[tapenum];
889  Assert(!lt->writing);
890 
891  if (lt->buffer == NULL)
892  ltsInitReadBuffer(lts, lt);
893 
894  while (size > 0)
895  {
896  if (lt->pos >= lt->nbytes)
897  {
898  /* Try to load more data into buffer. */
899  if (!ltsReadFillBuffer(lts, lt))
900  break; /* EOF */
901  }
902 
903  nthistime = lt->nbytes - lt->pos;
904  if (nthistime > size)
905  nthistime = size;
906  Assert(nthistime > 0);
907 
908  memcpy(ptr, lt->buffer + lt->pos, nthistime);
909 
910  lt->pos += nthistime;
911  ptr = (void *) ((char *) ptr + nthistime);
912  size -= nthistime;
913  nread += nthistime;
914  }
915 
916  return nread;
917 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
static bool ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:277
bool writing
Definition: logtape.c:126
int nbytes
Definition: logtape.c:153
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:545
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149

◆ LogicalTapeRewindForRead()

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

Definition at line 776 of file logtape.c.

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

Referenced by mergeruns(), and tuplesort_rescan().

777 {
778  LogicalTape *lt;
779 
780  Assert(tapenum >= 0 && tapenum < lts->nTapes);
781  lt = &lts->tapes[tapenum];
782 
783  /*
784  * Round and cap buffer_size if needed.
785  */
786  if (lt->frozen)
787  buffer_size = BLCKSZ;
788  else
789  {
790  /* need at least one block */
791  if (buffer_size < BLCKSZ)
792  buffer_size = BLCKSZ;
793 
794  /* palloc() larger than max_size is unlikely to be helpful */
795  if (buffer_size > lt->max_size)
796  buffer_size = lt->max_size;
797 
798  /* round down to BLCKSZ boundary */
799  buffer_size -= buffer_size % BLCKSZ;
800  }
801 
802  if (lt->writing)
803  {
804  /*
805  * Completion of a write phase. Flush last partial data block, and
806  * rewind for normal (destructive) read.
807  */
808  if (lt->dirty)
809  {
810  /*
811  * As long as we've filled the buffer at least once, its contents
812  * are entirely defined from valgrind's point of view, even though
813  * contents beyond the current end point may be stale. But it's
814  * possible - at least in the case of a parallel sort - to sort
815  * such small amount of data that we do not fill the buffer even
816  * once. Tell valgrind that its contents are defined, so it
817  * doesn't bleat.
818  */
820  lt->buffer_size - lt->nbytes);
821 
822  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
823  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
824  }
825  lt->writing = false;
826  }
827  else
828  {
829  /*
830  * This is only OK if tape is frozen; we rewind for (another) read
831  * pass.
832  */
833  Assert(lt->frozen);
834  }
835 
836  /* Allocate a read buffer (unless the tape is empty) */
837  if (lt->buffer)
838  pfree(lt->buffer);
839 
840  /* the buffer is lazily allocated, but set the size here */
841  lt->buffer = NULL;
842  lt->buffer_size = buffer_size;
843 }
int max_size
Definition: logtape.c:151
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
bool frozen
Definition: logtape.c:127
bool writing
Definition: logtape.c:126
bool dirty
Definition: logtape.c:128
void pfree(void *pointer)
Definition: mcxt.c:1056
int nbytes
Definition: logtape.c:153
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:110
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
int buffer_size
Definition: logtape.c:150
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:213

◆ LogicalTapeRewindForWrite()

void LogicalTapeRewindForWrite ( LogicalTapeSet lts,
int  tapenum 
)

Definition at line 854 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().

855 {
856  LogicalTape *lt;
857 
858  Assert(tapenum >= 0 && tapenum < lts->nTapes);
859  lt = &lts->tapes[tapenum];
860 
861  Assert(!lt->writing && !lt->frozen);
862  lt->writing = true;
863  lt->dirty = false;
864  lt->firstBlockNumber = -1L;
865  lt->curBlockNumber = -1L;
866  lt->pos = 0;
867  lt->nbytes = 0;
868  if (lt->buffer)
869  pfree(lt->buffer);
870  lt->buffer = NULL;
871  lt->buffer_size = 0;
872 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
bool frozen
Definition: logtape.c:127
bool writing
Definition: logtape.c:126
bool dirty
Definition: logtape.c:128
void pfree(void *pointer)
Definition: mcxt.c:1056
int nbytes
Definition: logtape.c:153
long firstBlockNumber
Definition: logtape.c:141
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
int buffer_size
Definition: logtape.c:150

◆ LogicalTapeSeek()

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

Definition at line 1095 of file logtape.c.

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

Referenced by tuplesort_restorepos().

1097 {
1098  LogicalTape *lt;
1099 
1100  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1101  lt = &lts->tapes[tapenum];
1102  Assert(lt->frozen);
1103  Assert(offset >= 0 && offset <= TapeBlockPayloadSize);
1104  Assert(lt->buffer_size == BLCKSZ);
1105 
1106  if (lt->buffer == NULL)
1107  ltsInitReadBuffer(lts, lt);
1108 
1109  if (blocknum != lt->curBlockNumber)
1110  {
1111  ltsReadBlock(lts, blocknum, (void *) lt->buffer);
1112  lt->curBlockNumber = blocknum;
1114  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1115  }
1116 
1117  if (offset > lt->nbytes)
1118  elog(ERROR, "invalid tape seek position");
1119  lt->pos = offset;
1120 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
#define TapeBlockPayloadSize
Definition: logtape.c:102
bool frozen
Definition: logtape.c:127
long nextBlockNumber
Definition: logtape.c:143
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:153
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:545
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
#define elog(elevel,...)
Definition: elog.h:228
int buffer_size
Definition: logtape.c:150
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:261

◆ LogicalTapeSetBlocks()

long LogicalTapeSetBlocks ( LogicalTapeSet lts)

Definition at line 1153 of file logtape.c.

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

Referenced by tuplesort_end(), and tuplesort_get_stats().

1154 {
1155  return lts->nBlocksAllocated - lts->nHoleBlocks;
1156 }
long nHoleBlocks
Definition: logtape.c:178
long nBlocksAllocated
Definition: logtape.c:176

◆ LogicalTapeSetClose()

void LogicalTapeSetClose ( LogicalTapeSet lts)

Definition at line 651 of file logtape.c.

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

Referenced by tuplesort_end().

652 {
653  LogicalTape *lt;
654  int i;
655 
656  BufFileClose(lts->pfile);
657  for (i = 0; i < lts->nTapes; i++)
658  {
659  lt = &lts->tapes[i];
660  if (lt->buffer)
661  pfree(lt->buffer);
662  }
663  pfree(lts->freeBlocks);
664  pfree(lts);
665 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
BufFile * pfile
Definition: logtape.c:164
void BufFileClose(BufFile *file)
Definition: buffile.c:391
long * freeBlocks
Definition: logtape.c:189
void pfree(void *pointer)
Definition: mcxt.c:1056
char * buffer
Definition: logtape.c:149
int i

◆ LogicalTapeSetCreate()

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

Definition at line 578 of file logtape.c.

References Assert, 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().

580 {
581  LogicalTapeSet *lts;
582  LogicalTape *lt;
583  int i;
584 
585  /*
586  * Create top-level struct including per-tape LogicalTape structs.
587  */
588  Assert(ntapes > 0);
589  lts = (LogicalTapeSet *) palloc(offsetof(LogicalTapeSet, tapes) +
590  ntapes * sizeof(LogicalTape));
591  lts->nBlocksAllocated = 0L;
592  lts->nBlocksWritten = 0L;
593  lts->nHoleBlocks = 0L;
594  lts->forgetFreeSpace = false;
595  lts->freeBlocksLen = 32; /* reasonable initial guess */
596  lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
597  lts->nFreeBlocks = 0;
598  lts->nTapes = ntapes;
599 
600  /*
601  * Initialize per-tape structs. Note we allocate the I/O buffer and the
602  * first block for a tape only when it is first actually written to. This
603  * avoids wasting memory space when tuplesort.c overestimates the number
604  * of tapes needed.
605  */
606  for (i = 0; i < ntapes; i++)
607  {
608  lt = &lts->tapes[i];
609  lt->writing = true;
610  lt->frozen = false;
611  lt->dirty = false;
612  lt->firstBlockNumber = -1L;
613  lt->curBlockNumber = -1L;
614  lt->nextBlockNumber = -1L;
615  lt->offsetBlockNumber = 0L;
616  lt->buffer = NULL;
617  lt->buffer_size = 0;
618  /* palloc() larger than MaxAllocSize would fail */
619  lt->max_size = MaxAllocSize;
620  lt->pos = 0;
621  lt->nbytes = 0;
622  }
623 
624  /*
625  * Create temp BufFile storage as required.
626  *
627  * Leader concatenates worker tapes, which requires special adjustment to
628  * final tapeset data. Things are simpler for the worker case and the
629  * serial case, though. They are generally very similar -- workers use a
630  * shared fileset, whereas serial sorts use a conventional serial BufFile.
631  */
632  if (shared)
633  ltsConcatWorkerTapes(lts, shared, fileset);
634  else if (fileset)
635  {
636  char filename[MAXPGPATH];
637 
638  pg_itoa(worker, filename);
639  lts->pfile = BufFileCreateShared(fileset, filename);
640  }
641  else
642  lts->pfile = BufFileCreateTemp(false);
643 
644  return lts;
645 }
int max_size
Definition: logtape.c:151
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
long offsetBlockNumber
Definition: logtape.c:144
long nBlocksWritten
Definition: logtape.c:177
BufFile * pfile
Definition: logtape.c:164
bool frozen
Definition: logtape.c:127
long nextBlockNumber
Definition: logtape.c:143
bool writing
Definition: logtape.c:126
long * freeBlocks
Definition: logtape.c:189
bool dirty
Definition: logtape.c:128
BufFile * BufFileCreateTemp(bool interXact)
Definition: buffile.c:184
#define MAXPGPATH
BufFile * BufFileCreateShared(SharedFileSet *fileset, const char *name)
Definition: buffile.c:258
long nHoleBlocks
Definition: logtape.c:178
int nbytes
Definition: logtape.c:153
void pg_itoa(int16 i, char *a)
Definition: numutils.c:335
#define MaxAllocSize
Definition: memutils.h:40
long firstBlockNumber
Definition: logtape.c:141
long nFreeBlocks
Definition: logtape.c:190
static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, SharedFileSet *fileset)
Definition: logtape.c:459
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
static char * filename
Definition: pg_dumpall.c:90
void * palloc(Size size)
Definition: mcxt.c:949
bool forgetFreeSpace
Definition: logtape.c:188
int i
Size freeBlocksLen
Definition: logtape.c:191
struct LogicalTape LogicalTape
long nBlocksAllocated
Definition: logtape.c:176
int buffer_size
Definition: logtape.c:150
#define offsetof(type, field)
Definition: c.h:661

◆ LogicalTapeSetForgetFreeSpace()

void LogicalTapeSetForgetFreeSpace ( LogicalTapeSet lts)

Definition at line 677 of file logtape.c.

References LogicalTapeSet::forgetFreeSpace.

Referenced by mergeruns().

678 {
679  lts->forgetFreeSpace = true;
680 }
bool forgetFreeSpace
Definition: logtape.c:188

◆ LogicalTapeTell()

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

Definition at line 1129 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, ltsInitReadBuffer(), LogicalTape::offsetBlockNumber, LogicalTape::pos, and LogicalTapeSet::tapes.

Referenced by tuplesort_markpos().

1131 {
1132  LogicalTape *lt;
1133 
1134  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1135  lt = &lts->tapes[tapenum];
1136 
1137  if (lt->buffer == NULL)
1138  ltsInitReadBuffer(lts, lt);
1139 
1140  Assert(lt->offsetBlockNumber == 0L);
1141 
1142  /* With a larger buffer, 'pos' wouldn't be the same as offset within page */
1143  Assert(lt->buffer_size == BLCKSZ);
1144 
1145  *blocknum = lt->curBlockNumber;
1146  *offset = lt->pos;
1147 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
long offsetBlockNumber
Definition: logtape.c:144
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:545
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
int buffer_size
Definition: logtape.c:150

◆ LogicalTapeWrite()

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

Definition at line 688 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().

690 {
691  LogicalTape *lt;
692  size_t nthistime;
693 
694  Assert(tapenum >= 0 && tapenum < lts->nTapes);
695  lt = &lts->tapes[tapenum];
696  Assert(lt->writing);
697  Assert(lt->offsetBlockNumber == 0L);
698 
699  /* Allocate data buffer and first block on first write */
700  if (lt->buffer == NULL)
701  {
702  lt->buffer = (char *) palloc(BLCKSZ);
703  lt->buffer_size = BLCKSZ;
704  }
705  if (lt->curBlockNumber == -1)
706  {
707  Assert(lt->firstBlockNumber == -1);
708  Assert(lt->pos == 0);
709 
710  lt->curBlockNumber = ltsGetFreeBlock(lts);
712 
713  TapeBlockGetTrailer(lt->buffer)->prev = -1L;
714  }
715 
716  Assert(lt->buffer_size == BLCKSZ);
717  while (size > 0)
718  {
719  if (lt->pos >= TapeBlockPayloadSize)
720  {
721  /* Buffer full, dump it out */
722  long nextBlockNumber;
723 
724  if (!lt->dirty)
725  {
726  /* Hmm, went directly from reading to writing? */
727  elog(ERROR, "invalid logtape state: should be dirty");
728  }
729 
730  /*
731  * First allocate the next block, so that we can store it in the
732  * 'next' pointer of this block.
733  */
734  nextBlockNumber = ltsGetFreeBlock(lts);
735 
736  /* set the next-pointer and dump the current block. */
737  TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber;
738  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
739 
740  /* initialize the prev-pointer of the next block */
741  TapeBlockGetTrailer(lt->buffer)->prev = lt->curBlockNumber;
742  lt->curBlockNumber = nextBlockNumber;
743  lt->pos = 0;
744  lt->nbytes = 0;
745  }
746 
747  nthistime = TapeBlockPayloadSize - lt->pos;
748  if (nthistime > size)
749  nthistime = size;
750  Assert(nthistime > 0);
751 
752  memcpy(lt->buffer + lt->pos, ptr, nthistime);
753 
754  lt->dirty = true;
755  lt->pos += nthistime;
756  if (lt->nbytes < lt->pos)
757  lt->nbytes = lt->pos;
758  ptr = (void *) ((char *) ptr + nthistime);
759  size -= nthistime;
760  }
761 }
LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER]
Definition: logtape.c:195
#define TapeBlockPayloadSize
Definition: logtape.c:102
long offsetBlockNumber
Definition: logtape.c:144
static long ltsGetFreeBlock(LogicalTapeSet *lts)
Definition: logtape.c:348
bool writing
Definition: logtape.c:126
bool dirty
Definition: logtape.c:128
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:153
long firstBlockNumber
Definition: logtape.c:141
long curBlockNumber
Definition: logtape.c:142
#define Assert(condition)
Definition: c.h:738
char * buffer
Definition: logtape.c:149
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
int buffer_size
Definition: logtape.c:150
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:213
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103