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)
 
void LogicalTapeSetExtend (LogicalTapeSet *lts, int nAdditional)
 
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 1116 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().

1117 {
1118  LogicalTape *lt;
1119  size_t seekpos = 0;
1120 
1121  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1122  lt = &lts->tapes[tapenum];
1123  Assert(lt->frozen);
1124  Assert(lt->buffer_size == BLCKSZ);
1125 
1126  if (lt->buffer == NULL)
1127  ltsInitReadBuffer(lts, lt);
1128 
1129  /*
1130  * Easy case for seek within current block.
1131  */
1132  if (size <= (size_t) lt->pos)
1133  {
1134  lt->pos -= (int) size;
1135  return size;
1136  }
1137 
1138  /*
1139  * Not-so-easy case, have to walk back the chain of blocks. This
1140  * implementation would be pretty inefficient for long seeks, but we
1141  * really aren't doing that (a seek over one tuple is typical).
1142  */
1143  seekpos = (size_t) lt->pos; /* part within this block */
1144  while (size > seekpos)
1145  {
1146  long prev = TapeBlockGetTrailer(lt->buffer)->prev;
1147 
1148  if (prev == -1L)
1149  {
1150  /* Tried to back up beyond the beginning of tape. */
1151  if (lt->curBlockNumber != lt->firstBlockNumber)
1152  elog(ERROR, "unexpected end of tape");
1153  lt->pos = 0;
1154  return seekpos;
1155  }
1156 
1157  ltsReadBlock(lts, prev, (void *) lt->buffer);
1158 
1159  if (TapeBlockGetTrailer(lt->buffer)->next != lt->curBlockNumber)
1160  elog(ERROR, "broken tape, next of block %ld is %ld, expected %ld",
1161  prev,
1162  TapeBlockGetTrailer(lt->buffer)->next,
1163  lt->curBlockNumber);
1164 
1166  lt->curBlockNumber = prev;
1167  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1168 
1169  seekpos += TapeBlockPayloadSize;
1170  }
1171 
1172  /*
1173  * 'seekpos' can now be greater than 'size', because it points to the
1174  * beginning the target block. The difference is the position within the
1175  * page.
1176  */
1177  lt->pos = seekpos - size;
1178  return size;
1179 }
#define TapeBlockPayloadSize
Definition: logtape.c:102
bool frozen
Definition: logtape.c:139
long nextBlockNumber
Definition: logtape.c:155
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:165
long firstBlockNumber
Definition: logtape.c:153
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:632
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
#define elog(elevel,...)
Definition: elog.h:214
int buffer_size
Definition: logtape.c:162
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:284

◆ LogicalTapeFreeze()

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

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

1014 {
1015  LogicalTape *lt;
1016 
1017  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1018  lt = &lts->tapes[tapenum];
1019  Assert(lt->writing);
1020  Assert(lt->offsetBlockNumber == 0L);
1021 
1022  /*
1023  * Completion of a write phase. Flush last partial data block, and rewind
1024  * for nondestructive read.
1025  */
1026  if (lt->dirty)
1027  {
1028  /*
1029  * As long as we've filled the buffer at least once, its contents are
1030  * entirely defined from valgrind's point of view, even though
1031  * contents beyond the current end point may be stale. But it's
1032  * possible - at least in the case of a parallel sort - to sort such
1033  * small amount of data that we do not fill the buffer even once. Tell
1034  * valgrind that its contents are defined, so it doesn't bleat.
1035  */
1037  lt->buffer_size - lt->nbytes);
1038 
1039  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
1040  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
1041  lt->writing = false;
1042  }
1043  lt->writing = false;
1044  lt->frozen = true;
1045 
1046  /*
1047  * The seek and backspace functions assume a single block read buffer.
1048  * That's OK with current usage. A larger buffer is helpful to make the
1049  * read pattern of the backing file look more sequential to the OS, when
1050  * we're reading from multiple tapes. But at the end of a sort, when a
1051  * tape is frozen, we only read from a single tape anyway.
1052  */
1053  if (!lt->buffer || lt->buffer_size != BLCKSZ)
1054  {
1055  if (lt->buffer)
1056  pfree(lt->buffer);
1057  lt->buffer = palloc(BLCKSZ);
1058  lt->buffer_size = BLCKSZ;
1059  }
1060 
1061  /* Read the first block, or reset if tape is empty */
1062  lt->curBlockNumber = lt->firstBlockNumber;
1063  lt->pos = 0;
1064  lt->nbytes = 0;
1065 
1066  if (lt->firstBlockNumber == -1L)
1067  lt->nextBlockNumber = -1L;
1068  ltsReadBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
1069  if (TapeBlockIsLast(lt->buffer))
1070  lt->nextBlockNumber = -1L;
1071  else
1072  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1073  lt->nbytes = TapeBlockGetNBytes(lt->buffer);
1074 
1075  /* Handle extra steps when caller is to share its tapeset */
1076  if (share)
1077  {
1078  BufFileExportShared(lts->pfile);
1079  share->firstblocknumber = lt->firstBlockNumber;
1080  }
1081 }
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
#define TapeBlockIsLast(buf)
Definition: logtape.c:106
long offsetBlockNumber
Definition: logtape.c:156
BufFile * pfile
Definition: logtape.c:185
long firstblocknumber
Definition: logtape.h:50
bool frozen
Definition: logtape.c:139
long nextBlockNumber
Definition: logtape.c:155
bool writing
Definition: logtape.c:138
bool dirty
Definition: logtape.c:140
void pfree(void *pointer)
Definition: mcxt.c:1056
int nbytes
Definition: logtape.c:165
long firstBlockNumber
Definition: logtape.c:153
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:110
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
void BufFileExportShared(BufFile *file)
Definition: buffile.c:373
LogicalTape * tapes
Definition: logtape.c:216
#define TapeBlockGetNBytes(buf)
Definition: logtape.c:107
char * buffer
Definition: logtape.c:161
void * palloc(Size size)
Definition: mcxt.c:949
int buffer_size
Definition: logtape.c:162
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:236
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:284

◆ LogicalTapeRead()

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

Definition at line 956 of file logtape.c.

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

Referenced by getlen(), and hashagg_batch_read().

958 {
959  LogicalTape *lt;
960  size_t nread = 0;
961  size_t nthistime;
962 
963  Assert(tapenum >= 0 && tapenum < lts->nTapes);
964  lt = &lts->tapes[tapenum];
965  Assert(!lt->writing);
966 
967  if (lt->buffer == NULL)
968  ltsInitReadBuffer(lts, lt);
969 
970  while (size > 0)
971  {
972  if (lt->pos >= lt->nbytes)
973  {
974  /* Try to load more data into buffer. */
975  if (!ltsReadFillBuffer(lts, lt))
976  break; /* EOF */
977  }
978 
979  nthistime = lt->nbytes - lt->pos;
980  if (nthistime > size)
981  nthistime = size;
982  Assert(nthistime > 0);
983 
984  memcpy(ptr, lt->buffer + lt->pos, nthistime);
985 
986  lt->pos += nthistime;
987  ptr = (void *) ((char *) ptr + nthistime);
988  size -= nthistime;
989  nread += nthistime;
990  }
991 
992  return nread;
993 }
static bool ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:300
bool writing
Definition: logtape.c:138
int nbytes
Definition: logtape.c:165
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:632
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161

◆ LogicalTapeRewindForRead()

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

Definition at line 842 of file logtape.c.

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

Referenced by agg_refill_hash_table(), mergeruns(), and tuplesort_rescan().

843 {
844  LogicalTape *lt;
845 
846  Assert(tapenum >= 0 && tapenum < lts->nTapes);
847  lt = &lts->tapes[tapenum];
848 
849  /*
850  * Round and cap buffer_size if needed.
851  */
852  if (lt->frozen)
853  buffer_size = BLCKSZ;
854  else
855  {
856  /* need at least one block */
857  if (buffer_size < BLCKSZ)
858  buffer_size = BLCKSZ;
859 
860  /* palloc() larger than max_size is unlikely to be helpful */
861  if (buffer_size > lt->max_size)
862  buffer_size = lt->max_size;
863 
864  /* round down to BLCKSZ boundary */
865  buffer_size -= buffer_size % BLCKSZ;
866  }
867 
868  if (lt->writing)
869  {
870  /*
871  * Completion of a write phase. Flush last partial data block, and
872  * rewind for normal (destructive) read.
873  */
874  if (lt->dirty)
875  {
876  /*
877  * As long as we've filled the buffer at least once, its contents
878  * are entirely defined from valgrind's point of view, even though
879  * contents beyond the current end point may be stale. But it's
880  * possible - at least in the case of a parallel sort - to sort
881  * such small amount of data that we do not fill the buffer even
882  * once. Tell valgrind that its contents are defined, so it
883  * doesn't bleat.
884  */
886  lt->buffer_size - lt->nbytes);
887 
888  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
889  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
890  }
891  lt->writing = false;
892  }
893  else
894  {
895  /*
896  * This is only OK if tape is frozen; we rewind for (another) read
897  * pass.
898  */
899  Assert(lt->frozen);
900  }
901 
902  if (lt->buffer)
903  pfree(lt->buffer);
904 
905  /* the buffer is lazily allocated, but set the size here */
906  lt->buffer = NULL;
907  lt->buffer_size = buffer_size;
908 
909  /* free the preallocation list, and return unused block numbers */
910  if (lt->prealloc != NULL)
911  {
912  for (int i = lt->nprealloc; i > 0; i--)
913  ltsReleaseBlock(lts, lt->prealloc[i - 1]);
914  pfree(lt->prealloc);
915  lt->prealloc = NULL;
916  lt->nprealloc = 0;
917  lt->prealloc_size = 0;
918  }
919 }
int max_size
Definition: logtape.c:163
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
long * prealloc
Definition: logtape.c:172
int prealloc_size
Definition: logtape.c:174
static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
Definition: logtape.c:465
bool frozen
Definition: logtape.c:139
bool writing
Definition: logtape.c:138
bool dirty
Definition: logtape.c:140
void pfree(void *pointer)
Definition: mcxt.c:1056
int nbytes
Definition: logtape.c:165
int nprealloc
Definition: logtape.c:173
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:110
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
int i
int buffer_size
Definition: logtape.c:162
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:236

◆ LogicalTapeRewindForWrite()

void LogicalTapeRewindForWrite ( LogicalTapeSet lts,
int  tapenum 
)

Definition at line 930 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 hashagg_tapeinfo_release(), mergeruns(), and tuplesort_gettuple_common().

931 {
932  LogicalTape *lt;
933 
934  Assert(tapenum >= 0 && tapenum < lts->nTapes);
935  lt = &lts->tapes[tapenum];
936 
937  Assert(!lt->writing && !lt->frozen);
938  lt->writing = true;
939  lt->dirty = false;
940  lt->firstBlockNumber = -1L;
941  lt->curBlockNumber = -1L;
942  lt->pos = 0;
943  lt->nbytes = 0;
944  if (lt->buffer)
945  pfree(lt->buffer);
946  lt->buffer = NULL;
947  lt->buffer_size = 0;
948 }
bool frozen
Definition: logtape.c:139
bool writing
Definition: logtape.c:138
bool dirty
Definition: logtape.c:140
void pfree(void *pointer)
Definition: mcxt.c:1056
int nbytes
Definition: logtape.c:165
long firstBlockNumber
Definition: logtape.c:153
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
int buffer_size
Definition: logtape.c:162

◆ LogicalTapeSeek()

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

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

1192 {
1193  LogicalTape *lt;
1194 
1195  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1196  lt = &lts->tapes[tapenum];
1197  Assert(lt->frozen);
1198  Assert(offset >= 0 && offset <= TapeBlockPayloadSize);
1199  Assert(lt->buffer_size == BLCKSZ);
1200 
1201  if (lt->buffer == NULL)
1202  ltsInitReadBuffer(lts, lt);
1203 
1204  if (blocknum != lt->curBlockNumber)
1205  {
1206  ltsReadBlock(lts, blocknum, (void *) lt->buffer);
1207  lt->curBlockNumber = blocknum;
1209  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1210  }
1211 
1212  if (offset > lt->nbytes)
1213  elog(ERROR, "invalid tape seek position");
1214  lt->pos = offset;
1215 }
#define TapeBlockPayloadSize
Definition: logtape.c:102
bool frozen
Definition: logtape.c:139
long nextBlockNumber
Definition: logtape.c:155
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:165
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:632
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
#define elog(elevel,...)
Definition: elog.h:214
int buffer_size
Definition: logtape.c:162
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:284

◆ LogicalTapeSetBlocks()

long LogicalTapeSetBlocks ( LogicalTapeSet lts)

Definition at line 1248 of file logtape.c.

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

Referenced by hash_agg_update_metrics(), tuplesort_free(), and tuplesort_updatemax().

1249 {
1250  return lts->nBlocksAllocated - lts->nHoleBlocks;
1251 }
long nHoleBlocks
Definition: logtape.c:199
long nBlocksAllocated
Definition: logtape.c:197

◆ LogicalTapeSetClose()

void LogicalTapeSetClose ( LogicalTapeSet lts)

Definition at line 716 of file logtape.c.

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

Referenced by hashagg_reset_spill_state(), and tuplesort_free().

717 {
718  LogicalTape *lt;
719  int i;
720 
721  BufFileClose(lts->pfile);
722  for (i = 0; i < lts->nTapes; i++)
723  {
724  lt = &lts->tapes[i];
725  if (lt->buffer)
726  pfree(lt->buffer);
727  }
728  pfree(lts->tapes);
729  pfree(lts->freeBlocks);
730  pfree(lts);
731 }
BufFile * pfile
Definition: logtape.c:185
void BufFileClose(BufFile *file)
Definition: buffile.c:391
long * freeBlocks
Definition: logtape.c:210
void pfree(void *pointer)
Definition: mcxt.c:1056
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
int i

◆ LogicalTapeSetCreate()

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

Definition at line 665 of file logtape.c.

References Assert, BufFileCreateShared(), BufFileCreateTemp(), filename, LogicalTapeSet::forgetFreeSpace, LogicalTapeSet::freeBlocks, LogicalTapeSet::freeBlocksLen, i, ltsConcatWorkerTapes(), ltsInitTape(), MAXPGPATH, LogicalTapeSet::nBlocksAllocated, LogicalTapeSet::nBlocksWritten, LogicalTapeSet::nFreeBlocks, LogicalTapeSet::nHoleBlocks, LogicalTapeSet::nTapes, palloc(), LogicalTapeSet::pfile, pg_itoa(), and LogicalTapeSet::tapes.

Referenced by hashagg_tapeinfo_init(), inittapes(), and leader_takeover_tapes().

667 {
668  LogicalTapeSet *lts;
669  int i;
670 
671  /*
672  * Create top-level struct including per-tape LogicalTape structs.
673  */
674  Assert(ntapes > 0);
675  lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet));
676  lts->nBlocksAllocated = 0L;
677  lts->nBlocksWritten = 0L;
678  lts->nHoleBlocks = 0L;
679  lts->forgetFreeSpace = false;
680  lts->freeBlocksLen = 32; /* reasonable initial guess */
681  lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
682  lts->nFreeBlocks = 0;
683  lts->nTapes = ntapes;
684  lts->tapes = (LogicalTape *) palloc(ntapes * sizeof(LogicalTape));
685 
686  for (i = 0; i < ntapes; i++)
687  ltsInitTape(&lts->tapes[i]);
688 
689  /*
690  * Create temp BufFile storage as required.
691  *
692  * Leader concatenates worker tapes, which requires special adjustment to
693  * final tapeset data. Things are simpler for the worker case and the
694  * serial case, though. They are generally very similar -- workers use a
695  * shared fileset, whereas serial sorts use a conventional serial BufFile.
696  */
697  if (shared)
698  ltsConcatWorkerTapes(lts, shared, fileset);
699  else if (fileset)
700  {
701  char filename[MAXPGPATH];
702 
703  pg_itoa(worker, filename);
704  lts->pfile = BufFileCreateShared(fileset, filename);
705  }
706  else
707  lts->pfile = BufFileCreateTemp(false);
708 
709  return lts;
710 }
long nBlocksWritten
Definition: logtape.c:198
BufFile * pfile
Definition: logtape.c:185
long * freeBlocks
Definition: logtape.c:210
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:199
void pg_itoa(int16 i, char *a)
Definition: numutils.c:337
static void ltsInitTape(LogicalTape *lt)
Definition: logtape.c:606
long nFreeBlocks
Definition: logtape.c:211
static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, SharedFileSet *fileset)
Definition: logtape.c:522
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
static char * filename
Definition: pg_dumpall.c:90
void * palloc(Size size)
Definition: mcxt.c:949
bool forgetFreeSpace
Definition: logtape.c:209
int i
Size freeBlocksLen
Definition: logtape.c:212
long nBlocksAllocated
Definition: logtape.c:197

◆ LogicalTapeSetExtend()

void LogicalTapeSetExtend ( LogicalTapeSet lts,
int  nAdditional 
)

Definition at line 1088 of file logtape.c.

References i, ltsInitTape(), LogicalTapeSet::nTapes, repalloc(), and LogicalTapeSet::tapes.

Referenced by hashagg_tapeinfo_assign().

1089 {
1090  int i;
1091  int nTapesOrig = lts->nTapes;
1092 
1093  lts->nTapes += nAdditional;
1094 
1095  lts->tapes = (LogicalTape *) repalloc(lts->tapes,
1096  lts->nTapes * sizeof(LogicalTape));
1097 
1098  for (i = nTapesOrig; i < lts->nTapes; i++)
1099  ltsInitTape(&lts->tapes[i]);
1100 }
static void ltsInitTape(LogicalTape *lt)
Definition: logtape.c:606
LogicalTape * tapes
Definition: logtape.c:216
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
int i

◆ LogicalTapeSetForgetFreeSpace()

void LogicalTapeSetForgetFreeSpace ( LogicalTapeSet lts)

Definition at line 743 of file logtape.c.

References LogicalTapeSet::forgetFreeSpace.

Referenced by mergeruns().

744 {
745  lts->forgetFreeSpace = true;
746 }
bool forgetFreeSpace
Definition: logtape.c:209

◆ LogicalTapeTell()

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

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

1226 {
1227  LogicalTape *lt;
1228 
1229  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1230  lt = &lts->tapes[tapenum];
1231 
1232  if (lt->buffer == NULL)
1233  ltsInitReadBuffer(lts, lt);
1234 
1235  Assert(lt->offsetBlockNumber == 0L);
1236 
1237  /* With a larger buffer, 'pos' wouldn't be the same as offset within page */
1238  Assert(lt->buffer_size == BLCKSZ);
1239 
1240  *blocknum = lt->curBlockNumber;
1241  *offset = lt->pos;
1242 }
long offsetBlockNumber
Definition: logtape.c:156
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:632
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
int buffer_size
Definition: logtape.c:162

◆ LogicalTapeWrite()

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

Definition at line 754 of file logtape.c.

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

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

756 {
757  LogicalTape *lt;
758  size_t nthistime;
759 
760  Assert(tapenum >= 0 && tapenum < lts->nTapes);
761  lt = &lts->tapes[tapenum];
762  Assert(lt->writing);
763  Assert(lt->offsetBlockNumber == 0L);
764 
765  /* Allocate data buffer and first block on first write */
766  if (lt->buffer == NULL)
767  {
768  lt->buffer = (char *) palloc(BLCKSZ);
769  lt->buffer_size = BLCKSZ;
770  }
771  if (lt->curBlockNumber == -1)
772  {
773  Assert(lt->firstBlockNumber == -1);
774  Assert(lt->pos == 0);
775 
776  lt->curBlockNumber = ltsGetPreallocBlock(lts, lt);
778 
779  TapeBlockGetTrailer(lt->buffer)->prev = -1L;
780  }
781 
782  Assert(lt->buffer_size == BLCKSZ);
783  while (size > 0)
784  {
785  if (lt->pos >= TapeBlockPayloadSize)
786  {
787  /* Buffer full, dump it out */
788  long nextBlockNumber;
789 
790  if (!lt->dirty)
791  {
792  /* Hmm, went directly from reading to writing? */
793  elog(ERROR, "invalid logtape state: should be dirty");
794  }
795 
796  /*
797  * First allocate the next block, so that we can store it in the
798  * 'next' pointer of this block.
799  */
800  nextBlockNumber = ltsGetPreallocBlock(lts, lt);
801 
802  /* set the next-pointer and dump the current block. */
803  TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber;
804  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
805 
806  /* initialize the prev-pointer of the next block */
807  TapeBlockGetTrailer(lt->buffer)->prev = lt->curBlockNumber;
808  lt->curBlockNumber = nextBlockNumber;
809  lt->pos = 0;
810  lt->nbytes = 0;
811  }
812 
813  nthistime = TapeBlockPayloadSize - lt->pos;
814  if (nthistime > size)
815  nthistime = size;
816  Assert(nthistime > 0);
817 
818  memcpy(lt->buffer + lt->pos, ptr, nthistime);
819 
820  lt->dirty = true;
821  lt->pos += nthistime;
822  if (lt->nbytes < lt->pos)
823  lt->nbytes = lt->pos;
824  ptr = (void *) ((char *) ptr + nthistime);
825  size -= nthistime;
826  }
827 }
#define TapeBlockPayloadSize
Definition: logtape.c:102
long offsetBlockNumber
Definition: logtape.c:156
bool writing
Definition: logtape.c:138
bool dirty
Definition: logtape.c:140
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:165
long firstBlockNumber
Definition: logtape.c:153
static long ltsGetPreallocBlock(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:427
long curBlockNumber
Definition: logtape.c:154
#define Assert(condition)
Definition: c.h:738
LogicalTape * tapes
Definition: logtape.c:216
char * buffer
Definition: logtape.c:161
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
int buffer_size
Definition: logtape.c:162
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:236
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:103