blob: eaa322df7a40a951423680f422ecad9fec3d2b27 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* aomd_filehandler.c
* Code in this file would have been in aomd.c but is needed in contrib,
* so we separate it out here.
*
* Portions Copyright (c) 2008, Greenplum Inc.
* Portions Copyright (c) 2012-Present VMware, Inc. or its affiliates.
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/access/appendonly/aomd_filehandler.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/aomd.h"
#include "access/appendonlytid.h"
#include "access/appendonlywriter.h"
/*
* Ideally the logic works even for heap tables, but is only used
* currently for AO and AOCS tables to avoid merge conflicts.
*
* There are different rules for the naming of the files, depending on
* the type of table:
*
* Heap Tables: contiguous extensions, no upper bound
* AO Tables: non contiguous extensions [.1 - .127]
* CO Tables: non contiguous extensions based on filenums in pg_attribute_encoding
* [ .1 - .127] for first filenum; .0 reserved for utility and alter
* [.129 - .255] for second filenum; .128 reserved for utility and alter
* [.257 - .283] for third filenum; .256 reserved for utility and alter
* etc upto (128 * MaxFileNumber(3200))
*
* Column rewrites use the filenum from pair (i, i+MaxAttributeNumber)
* where i is in range 1 to MaxAttributeNumber
* Algorithm is coded with the assumption for CO tables that for a given
* concurrency level, the segfiles exist on one of the filenum pairs
* OR stop existing for all columns thereafter.
* For instance, if .2 exists, then .(2 + 128f) MIGHT exist for filenum f=1.
* But if it does not exist for f=1 OR f=1601 then it doesn't exist for f>=2.
*
* We can think of this function as operating on a two-dimensional array:
* column index x concurrency level. The operation is broken up into two
* steps:
*
* 1) Finds for which concurrency levels the table has files using
* [.1 - .127] for filenumber = 1 and same for filenumber = 1601.
* Concurrency level 0 is always checked as its corresponding segno file
* must always exist. However, the caller is expected to handle the that
* file.
* 2) Iterates over present concurrency levels and uses the above assumption to
* stop and proceed to the next concurrency level.
*
* Graphically, showing the step above that can possibly operate on each
* segment file:
* filenumber
* 1 2 3 4 --- MaxFileNumber
* concurrency 0 x 2) 2) 2) 2)
* 1 1) 2) 2) 2) 2)
* 2 1) 2) 2) 2) 2)
* 3 1) 2) 2) 2) 2)
* |
* (MAX_AOREL_CONCURRENCY-1) 1) 2) 2) 2) 2)
*/
void
ao_foreach_extent_file(ao_extent_callback callback, void *ctx)
{
int segno;
int physicalsegno;
int physicalsegnopair;
int filenum;
int concurrency[MAX_AOREL_CONCURRENCY];
int concurrencySize;
bool segnofileexists;
bool segnopairfileexists;
/*
* We always check concurrency level 0 here as the 0 based extensions such
* as .128, .256, ... for CO tables are created by ALTER table or utility
* mode insert. These also need to be copied. Column 0 concurrency level 0
* file is always present and, as noted above, handled by our caller.
*/
concurrency[0] = 0;
concurrencySize = 1;
/*
* As we'll see later, we will exhaustively check file extensions that are based
* on a combination of all possible segno and filenum except for the base file
* (segno=0, filenum=0) as that is not an extension.
* But we still need to check (segno=0, filenum=1600) (i.e. .204800) which is the
* "pair" extension for the base file. That is not going to be covered by the for
* loops below. Check it now.
*/
callback(MaxHeapAttributeNumber * AOTupleId_MultiplierSegmentFileNum, ctx);
/*
* Discover any remaining concurrency levels.
* This checks all combinations of (segno > 0, filenum = 0) for an AO table, and
* additionally (segno > 0, filenum = 1600) for an CO table.
*/
for (segno = 1; segno < MAX_AOREL_CONCURRENCY; segno++)
{
/* For AOCO tables, each column has two possible file segnos from
* filenum pair (i, i+MaxHeapAttributeNumber). Check them both. */
physicalsegno = segno;
physicalsegnopair = MaxHeapAttributeNumber * AOTupleId_MultiplierSegmentFileNum + segno;
segnofileexists = callback(physicalsegno, ctx);
segnopairfileexists = callback(physicalsegnopair, ctx);
if (!(segnofileexists || segnopairfileexists))
continue;
concurrency[concurrencySize] = segno;
concurrencySize++;
}
/*
* Now based on the concurrency levels, discover the rest of file extensions.
* This should only be relevant to CO tables.
*/
for (int index = 0; index < concurrencySize; index++)
{
for (filenum = 1; filenum < MaxHeapAttributeNumber; filenum++)
{
physicalsegno = filenum * AOTupleId_MultiplierSegmentFileNum + concurrency[index];
physicalsegnopair = (filenum + MaxHeapAttributeNumber) * AOTupleId_MultiplierSegmentFileNum + concurrency[index];
/* Call the callback function on both possible files in filenum pair */
segnofileexists = callback(physicalsegno, ctx);
segnopairfileexists = callback(physicalsegnopair, ctx);
/* If they both don't exist, that means none of the further ones exist */
if (!(segnofileexists || segnopairfileexists))
break;
}
}
}