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, bool preallocate, 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 1137 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().

1138 {
1139  LogicalTape *lt;
1140  size_t seekpos = 0;
1141 
1142  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1143  lt = &lts->tapes[tapenum];
1144  Assert(lt->frozen);
1145  Assert(lt->buffer_size == BLCKSZ);
1146 
1147  if (lt->buffer == NULL)
1148  ltsInitReadBuffer(lts, lt);
1149 
1150  /*
1151  * Easy case for seek within current block.
1152  */
1153  if (size <= (size_t) lt->pos)
1154  {
1155  lt->pos -= (int) size;
1156  return size;
1157  }
1158 
1159  /*
1160  * Not-so-easy case, have to walk back the chain of blocks. This
1161  * implementation would be pretty inefficient for long seeks, but we
1162  * really aren't doing that (a seek over one tuple is typical).
1163  */
1164  seekpos = (size_t) lt->pos; /* part within this block */
1165  while (size > seekpos)
1166  {
1167  long prev = TapeBlockGetTrailer(lt->buffer)->prev;
1168 
1169  if (prev == -1L)
1170  {
1171  /* Tried to back up beyond the beginning of tape. */
1172  if (lt->curBlockNumber != lt->firstBlockNumber)
1173  elog(ERROR, "unexpected end of tape");
1174  lt->pos = 0;
1175  return seekpos;
1176  }
1177 
1178  ltsReadBlock(lts, prev, (void *) lt->buffer);
1179 
1180  if (TapeBlockGetTrailer(lt->buffer)->next != lt->curBlockNumber)
1181  elog(ERROR, "broken tape, next of block %ld is %ld, expected %ld",
1182  prev,
1183  TapeBlockGetTrailer(lt->buffer)->next,
1184  lt->curBlockNumber);
1185 
1187  lt->curBlockNumber = prev;
1188  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1189 
1190  seekpos += TapeBlockPayloadSize;
1191  }
1192 
1193  /*
1194  * 'seekpos' can now be greater than 'size', because it points to the
1195  * beginning the target block. The difference is the position within the
1196  * page.
1197  */
1198  lt->pos = seekpos - size;
1199  return size;
1200 }
#define TapeBlockPayloadSize
Definition: logtape.c:104
bool frozen
Definition: logtape.c:141
long nextBlockNumber
Definition: logtape.c:157
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:167
long firstBlockNumber
Definition: logtape.c:155
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:652
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
#define elog(elevel,...)
Definition: elog.h:214
int buffer_size
Definition: logtape.c:164
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:105
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 1034 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().

1035 {
1036  LogicalTape *lt;
1037 
1038  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1039  lt = &lts->tapes[tapenum];
1040  Assert(lt->writing);
1041  Assert(lt->offsetBlockNumber == 0L);
1042 
1043  /*
1044  * Completion of a write phase. Flush last partial data block, and rewind
1045  * for nondestructive read.
1046  */
1047  if (lt->dirty)
1048  {
1049  /*
1050  * As long as we've filled the buffer at least once, its contents are
1051  * entirely defined from valgrind's point of view, even though
1052  * contents beyond the current end point may be stale. But it's
1053  * possible - at least in the case of a parallel sort - to sort such
1054  * small amount of data that we do not fill the buffer even once. Tell
1055  * valgrind that its contents are defined, so it doesn't bleat.
1056  */
1058  lt->buffer_size - lt->nbytes);
1059 
1060  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
1061  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
1062  lt->writing = false;
1063  }
1064  lt->writing = false;
1065  lt->frozen = true;
1066 
1067  /*
1068  * The seek and backspace functions assume a single block read buffer.
1069  * That's OK with current usage. A larger buffer is helpful to make the
1070  * read pattern of the backing file look more sequential to the OS, when
1071  * we're reading from multiple tapes. But at the end of a sort, when a
1072  * tape is frozen, we only read from a single tape anyway.
1073  */
1074  if (!lt->buffer || lt->buffer_size != BLCKSZ)
1075  {
1076  if (lt->buffer)
1077  pfree(lt->buffer);
1078  lt->buffer = palloc(BLCKSZ);
1079  lt->buffer_size = BLCKSZ;
1080  }
1081 
1082  /* Read the first block, or reset if tape is empty */
1083  lt->curBlockNumber = lt->firstBlockNumber;
1084  lt->pos = 0;
1085  lt->nbytes = 0;
1086 
1087  if (lt->firstBlockNumber == -1L)
1088  lt->nextBlockNumber = -1L;
1089  ltsReadBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
1090  if (TapeBlockIsLast(lt->buffer))
1091  lt->nextBlockNumber = -1L;
1092  else
1093  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1094  lt->nbytes = TapeBlockGetNBytes(lt->buffer);
1095 
1096  /* Handle extra steps when caller is to share its tapeset */
1097  if (share)
1098  {
1099  BufFileExportShared(lts->pfile);
1100  share->firstblocknumber = lt->firstBlockNumber;
1101  }
1102 }
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
#define TapeBlockIsLast(buf)
Definition: logtape.c:108
long offsetBlockNumber
Definition: logtape.c:158
BufFile * pfile
Definition: logtape.c:187
long firstblocknumber
Definition: logtape.h:50
bool frozen
Definition: logtape.c:141
long nextBlockNumber
Definition: logtape.c:157
bool writing
Definition: logtape.c:140
bool dirty
Definition: logtape.c:142
void pfree(void *pointer)
Definition: mcxt.c:1057
int nbytes
Definition: logtape.c:167
long firstBlockNumber
Definition: logtape.c:155
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:112
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
void BufFileExportShared(BufFile *file)
Definition: buffile.c:377
LogicalTape * tapes
Definition: logtape.c:219
#define TapeBlockGetNBytes(buf)
Definition: logtape.c:109
char * buffer
Definition: logtape.c:163
void * palloc(Size size)
Definition: mcxt.c:950
int buffer_size
Definition: logtape.c:164
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:240
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:105
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 977 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().

979 {
980  LogicalTape *lt;
981  size_t nread = 0;
982  size_t nthistime;
983 
984  Assert(tapenum >= 0 && tapenum < lts->nTapes);
985  lt = &lts->tapes[tapenum];
986  Assert(!lt->writing);
987 
988  if (lt->buffer == NULL)
989  ltsInitReadBuffer(lts, lt);
990 
991  while (size > 0)
992  {
993  if (lt->pos >= lt->nbytes)
994  {
995  /* Try to load more data into buffer. */
996  if (!ltsReadFillBuffer(lts, lt))
997  break; /* EOF */
998  }
999 
1000  nthistime = lt->nbytes - lt->pos;
1001  if (nthistime > size)
1002  nthistime = size;
1003  Assert(nthistime > 0);
1004 
1005  memcpy(ptr, lt->buffer + lt->pos, nthistime);
1006 
1007  lt->pos += nthistime;
1008  ptr = (void *) ((char *) ptr + nthistime);
1009  size -= nthistime;
1010  nread += nthistime;
1011  }
1012 
1013  return nread;
1014 }
static bool ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:307
bool writing
Definition: logtape.c:140
int nbytes
Definition: logtape.c:167
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:652
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163

◆ LogicalTapeRewindForRead()

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

Definition at line 863 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 hashagg_spill_finish(), mergeruns(), and tuplesort_rescan().

864 {
865  LogicalTape *lt;
866 
867  Assert(tapenum >= 0 && tapenum < lts->nTapes);
868  lt = &lts->tapes[tapenum];
869 
870  /*
871  * Round and cap buffer_size if needed.
872  */
873  if (lt->frozen)
874  buffer_size = BLCKSZ;
875  else
876  {
877  /* need at least one block */
878  if (buffer_size < BLCKSZ)
879  buffer_size = BLCKSZ;
880 
881  /* palloc() larger than max_size is unlikely to be helpful */
882  if (buffer_size > lt->max_size)
883  buffer_size = lt->max_size;
884 
885  /* round down to BLCKSZ boundary */
886  buffer_size -= buffer_size % BLCKSZ;
887  }
888 
889  if (lt->writing)
890  {
891  /*
892  * Completion of a write phase. Flush last partial data block, and
893  * rewind for normal (destructive) read.
894  */
895  if (lt->dirty)
896  {
897  /*
898  * As long as we've filled the buffer at least once, its contents
899  * are entirely defined from valgrind's point of view, even though
900  * contents beyond the current end point may be stale. But it's
901  * possible - at least in the case of a parallel sort - to sort
902  * such small amount of data that we do not fill the buffer even
903  * once. Tell valgrind that its contents are defined, so it
904  * doesn't bleat.
905  */
907  lt->buffer_size - lt->nbytes);
908 
909  TapeBlockSetNBytes(lt->buffer, lt->nbytes);
910  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
911  }
912  lt->writing = false;
913  }
914  else
915  {
916  /*
917  * This is only OK if tape is frozen; we rewind for (another) read
918  * pass.
919  */
920  Assert(lt->frozen);
921  }
922 
923  if (lt->buffer)
924  pfree(lt->buffer);
925 
926  /* the buffer is lazily allocated, but set the size here */
927  lt->buffer = NULL;
928  lt->buffer_size = buffer_size;
929 
930  /* free the preallocation list, and return unused block numbers */
931  if (lt->prealloc != NULL)
932  {
933  for (int i = lt->nprealloc; i > 0; i--)
934  ltsReleaseBlock(lts, lt->prealloc[i - 1]);
935  pfree(lt->prealloc);
936  lt->prealloc = NULL;
937  lt->nprealloc = 0;
938  lt->prealloc_size = 0;
939  }
940 }
int max_size
Definition: logtape.c:165
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
long * prealloc
Definition: logtape.c:174
int prealloc_size
Definition: logtape.c:176
static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
Definition: logtape.c:485
bool frozen
Definition: logtape.c:141
bool writing
Definition: logtape.c:140
bool dirty
Definition: logtape.c:142
void pfree(void *pointer)
Definition: mcxt.c:1057
int nbytes
Definition: logtape.c:167
int nprealloc
Definition: logtape.c:175
#define TapeBlockSetNBytes(buf, nbytes)
Definition: logtape.c:112
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
int i
int buffer_size
Definition: logtape.c:164
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:240

◆ LogicalTapeRewindForWrite()

void LogicalTapeRewindForWrite ( LogicalTapeSet lts,
int  tapenum 
)

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

952 {
953  LogicalTape *lt;
954 
955  Assert(tapenum >= 0 && tapenum < lts->nTapes);
956  lt = &lts->tapes[tapenum];
957 
958  Assert(!lt->writing && !lt->frozen);
959  lt->writing = true;
960  lt->dirty = false;
961  lt->firstBlockNumber = -1L;
962  lt->curBlockNumber = -1L;
963  lt->pos = 0;
964  lt->nbytes = 0;
965  if (lt->buffer)
966  pfree(lt->buffer);
967  lt->buffer = NULL;
968  lt->buffer_size = 0;
969 }
bool frozen
Definition: logtape.c:141
bool writing
Definition: logtape.c:140
bool dirty
Definition: logtape.c:142
void pfree(void *pointer)
Definition: mcxt.c:1057
int nbytes
Definition: logtape.c:167
long firstBlockNumber
Definition: logtape.c:155
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
int buffer_size
Definition: logtape.c:164

◆ LogicalTapeSeek()

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

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

1213 {
1214  LogicalTape *lt;
1215 
1216  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1217  lt = &lts->tapes[tapenum];
1218  Assert(lt->frozen);
1219  Assert(offset >= 0 && offset <= TapeBlockPayloadSize);
1220  Assert(lt->buffer_size == BLCKSZ);
1221 
1222  if (lt->buffer == NULL)
1223  ltsInitReadBuffer(lts, lt);
1224 
1225  if (blocknum != lt->curBlockNumber)
1226  {
1227  ltsReadBlock(lts, blocknum, (void *) lt->buffer);
1228  lt->curBlockNumber = blocknum;
1230  lt->nextBlockNumber = TapeBlockGetTrailer(lt->buffer)->next;
1231  }
1232 
1233  if (offset > lt->nbytes)
1234  elog(ERROR, "invalid tape seek position");
1235  lt->pos = offset;
1236 }
#define TapeBlockPayloadSize
Definition: logtape.c:104
bool frozen
Definition: logtape.c:141
long nextBlockNumber
Definition: logtape.c:157
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:167
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:652
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
#define elog(elevel,...)
Definition: elog.h:214
int buffer_size
Definition: logtape.c:164
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:105
static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:284

◆ LogicalTapeSetBlocks()

long LogicalTapeSetBlocks ( LogicalTapeSet lts)

Definition at line 1272 of file logtape.c.

References Assert, LogicalTape::buffer, i, LogicalTapeSet::nBlocksWritten, LogicalTapeSet::nHoleBlocks, LogicalTapeSet::nTapes, LogicalTapeSet::tapes, and LogicalTape::writing.

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

1273 {
1274 #ifdef USE_ASSERT_CHECKING
1275  for (int i = 0; i < lts->nTapes; i++)
1276  {
1277  LogicalTape *lt = &lts->tapes[i];
1278  Assert(!lt->writing || lt->buffer == NULL);
1279  }
1280 #endif
1281  return lts->nBlocksWritten - lts->nHoleBlocks;
1282 }
long nBlocksWritten
Definition: logtape.c:200
bool writing
Definition: logtape.c:140
long nHoleBlocks
Definition: logtape.c:201
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
int i

◆ LogicalTapeSetClose()

void LogicalTapeSetClose ( LogicalTapeSet lts)

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

738 {
739  LogicalTape *lt;
740  int i;
741 
742  BufFileClose(lts->pfile);
743  for (i = 0; i < lts->nTapes; i++)
744  {
745  lt = &lts->tapes[i];
746  if (lt->buffer)
747  pfree(lt->buffer);
748  }
749  pfree(lts->tapes);
750  pfree(lts->freeBlocks);
751  pfree(lts);
752 }
BufFile * pfile
Definition: logtape.c:187
void BufFileClose(BufFile *file)
Definition: buffile.c:395
long * freeBlocks
Definition: logtape.c:212
void pfree(void *pointer)
Definition: mcxt.c:1057
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
int i

◆ LogicalTapeSetCreate()

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

Definition at line 685 of file logtape.c.

References Assert, BufFileCreateShared(), BufFileCreateTemp(), LogicalTapeSet::enable_prealloc, 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().

687 {
688  LogicalTapeSet *lts;
689  int i;
690 
691  /*
692  * Create top-level struct including per-tape LogicalTape structs.
693  */
694  Assert(ntapes > 0);
695  lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet));
696  lts->nBlocksAllocated = 0L;
697  lts->nBlocksWritten = 0L;
698  lts->nHoleBlocks = 0L;
699  lts->forgetFreeSpace = false;
700  lts->freeBlocksLen = 32; /* reasonable initial guess */
701  lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
702  lts->nFreeBlocks = 0;
703  lts->enable_prealloc = preallocate;
704  lts->nTapes = ntapes;
705  lts->tapes = (LogicalTape *) palloc(ntapes * sizeof(LogicalTape));
706 
707  for (i = 0; i < ntapes; i++)
708  ltsInitTape(&lts->tapes[i]);
709 
710  /*
711  * Create temp BufFile storage as required.
712  *
713  * Leader concatenates worker tapes, which requires special adjustment to
714  * final tapeset data. Things are simpler for the worker case and the
715  * serial case, though. They are generally very similar -- workers use a
716  * shared fileset, whereas serial sorts use a conventional serial BufFile.
717  */
718  if (shared)
719  ltsConcatWorkerTapes(lts, shared, fileset);
720  else if (fileset)
721  {
722  char filename[MAXPGPATH];
723 
724  pg_itoa(worker, filename);
725  lts->pfile = BufFileCreateShared(fileset, filename);
726  }
727  else
728  lts->pfile = BufFileCreateTemp(false);
729 
730  return lts;
731 }
long nBlocksWritten
Definition: logtape.c:200
BufFile * pfile
Definition: logtape.c:187
long * freeBlocks
Definition: logtape.c:212
BufFile * BufFileCreateTemp(bool interXact)
Definition: buffile.c:188
#define MAXPGPATH
BufFile * BufFileCreateShared(SharedFileSet *fileset, const char *name)
Definition: buffile.c:262
long nHoleBlocks
Definition: logtape.c:201
static void ltsInitTape(LogicalTape *lt)
Definition: logtape.c:626
long nFreeBlocks
Definition: logtape.c:213
static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared, SharedFileSet *fileset)
Definition: logtape.c:542
#define Assert(condition)
Definition: c.h:746
bool enable_prealloc
Definition: logtape.c:215
LogicalTape * tapes
Definition: logtape.c:219
static char * filename
Definition: pg_dumpall.c:91
void * palloc(Size size)
Definition: mcxt.c:950
bool forgetFreeSpace
Definition: logtape.c:211
int i
Size freeBlocksLen
Definition: logtape.c:214
long nBlocksAllocated
Definition: logtape.c:199
int pg_itoa(int16 i, char *a)
Definition: numutils.c:338

◆ LogicalTapeSetExtend()

void LogicalTapeSetExtend ( LogicalTapeSet lts,
int  nAdditional 
)

Definition at line 1109 of file logtape.c.

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

Referenced by hashagg_tapeinfo_assign().

1110 {
1111  int i;
1112  int nTapesOrig = lts->nTapes;
1113 
1114  lts->nTapes += nAdditional;
1115 
1116  lts->tapes = (LogicalTape *) repalloc(lts->tapes,
1117  lts->nTapes * sizeof(LogicalTape));
1118 
1119  for (i = nTapesOrig; i < lts->nTapes; i++)
1120  ltsInitTape(&lts->tapes[i]);
1121 }
static void ltsInitTape(LogicalTape *lt)
Definition: logtape.c:626
LogicalTape * tapes
Definition: logtape.c:219
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
int i

◆ LogicalTapeSetForgetFreeSpace()

void LogicalTapeSetForgetFreeSpace ( LogicalTapeSet lts)

Definition at line 764 of file logtape.c.

References LogicalTapeSet::forgetFreeSpace.

Referenced by mergeruns().

765 {
766  lts->forgetFreeSpace = true;
767 }
bool forgetFreeSpace
Definition: logtape.c:211

◆ LogicalTapeTell()

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

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

1247 {
1248  LogicalTape *lt;
1249 
1250  Assert(tapenum >= 0 && tapenum < lts->nTapes);
1251  lt = &lts->tapes[tapenum];
1252 
1253  if (lt->buffer == NULL)
1254  ltsInitReadBuffer(lts, lt);
1255 
1256  Assert(lt->offsetBlockNumber == 0L);
1257 
1258  /* With a larger buffer, 'pos' wouldn't be the same as offset within page */
1259  Assert(lt->buffer_size == BLCKSZ);
1260 
1261  *blocknum = lt->curBlockNumber;
1262  *offset = lt->pos;
1263 }
long offsetBlockNumber
Definition: logtape.c:158
static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:652
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
int buffer_size
Definition: logtape.c:164

◆ LogicalTapeWrite()

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

Definition at line 775 of file logtape.c.

References Assert, LogicalTape::buffer, LogicalTape::buffer_size, LogicalTape::curBlockNumber, LogicalTape::dirty, elog, ERROR, LogicalTape::firstBlockNumber, ltsGetBlock(), 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().

777 {
778  LogicalTape *lt;
779  size_t nthistime;
780 
781  Assert(tapenum >= 0 && tapenum < lts->nTapes);
782  lt = &lts->tapes[tapenum];
783  Assert(lt->writing);
784  Assert(lt->offsetBlockNumber == 0L);
785 
786  /* Allocate data buffer and first block on first write */
787  if (lt->buffer == NULL)
788  {
789  lt->buffer = (char *) palloc(BLCKSZ);
790  lt->buffer_size = BLCKSZ;
791  }
792  if (lt->curBlockNumber == -1)
793  {
794  Assert(lt->firstBlockNumber == -1);
795  Assert(lt->pos == 0);
796 
797  lt->curBlockNumber = ltsGetBlock(lts, lt);
799 
800  TapeBlockGetTrailer(lt->buffer)->prev = -1L;
801  }
802 
803  Assert(lt->buffer_size == BLCKSZ);
804  while (size > 0)
805  {
806  if (lt->pos >= (int) TapeBlockPayloadSize)
807  {
808  /* Buffer full, dump it out */
809  long nextBlockNumber;
810 
811  if (!lt->dirty)
812  {
813  /* Hmm, went directly from reading to writing? */
814  elog(ERROR, "invalid logtape state: should be dirty");
815  }
816 
817  /*
818  * First allocate the next block, so that we can store it in the
819  * 'next' pointer of this block.
820  */
821  nextBlockNumber = ltsGetBlock(lts, lt);
822 
823  /* set the next-pointer and dump the current block. */
824  TapeBlockGetTrailer(lt->buffer)->next = nextBlockNumber;
825  ltsWriteBlock(lts, lt->curBlockNumber, (void *) lt->buffer);
826 
827  /* initialize the prev-pointer of the next block */
828  TapeBlockGetTrailer(lt->buffer)->prev = lt->curBlockNumber;
829  lt->curBlockNumber = nextBlockNumber;
830  lt->pos = 0;
831  lt->nbytes = 0;
832  }
833 
834  nthistime = TapeBlockPayloadSize - lt->pos;
835  if (nthistime > size)
836  nthistime = size;
837  Assert(nthistime > 0);
838 
839  memcpy(lt->buffer + lt->pos, ptr, nthistime);
840 
841  lt->dirty = true;
842  lt->pos += nthistime;
843  if (lt->nbytes < lt->pos)
844  lt->nbytes = lt->pos;
845  ptr = (void *) ((char *) ptr + nthistime);
846  size -= nthistime;
847  }
848 }
#define TapeBlockPayloadSize
Definition: logtape.c:104
long offsetBlockNumber
Definition: logtape.c:158
bool writing
Definition: logtape.c:140
bool dirty
Definition: logtape.c:142
#define ERROR
Definition: elog.h:43
int nbytes
Definition: logtape.c:167
long firstBlockNumber
Definition: logtape.c:155
long curBlockNumber
Definition: logtape.c:156
#define Assert(condition)
Definition: c.h:746
static long ltsGetBlock(LogicalTapeSet *lts, LogicalTape *lt)
Definition: logtape.c:377
LogicalTape * tapes
Definition: logtape.c:219
char * buffer
Definition: logtape.c:163
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:214
int buffer_size
Definition: logtape.c:164
static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
Definition: logtape.c:240
#define TapeBlockGetTrailer(buf)
Definition: logtape.c:105