Example #1
0
File: aomd.c Project: 50wu/gpdb
/*
 * Open an Append Only relation file segment
 *
 * The fd module's PathNameOpenFile() is used to open the file, so the
 * the File* routines can be used to read, write, close, etc, the file.
 */
bool
OpenAOSegmentFile(
					Relation rel, 
					char *filepathname, 
				  int32	segmentFileNum,
				  int64	logicalEof,
				  MirroredAppendOnlyOpen *mirroredOpen)
{	
	ItemPointerData persistentTid;
	int64 persistentSerialNum;

	int primaryError;

	if (!ReadGpRelationNode(
			rel->rd_rel->reltablespace,
			rel->rd_rel->relfilenode,
			segmentFileNum,
			&persistentTid,
			&persistentSerialNum))
	{
		if (logicalEof == 0)
			return false;

		elog(ERROR, "Did not find gp_relation_node entry for relation name %s, relation id %u, relfilenode %u, segment file #%d, logical eof " INT64_FORMAT,
			 rel->rd_rel->relname.data,
			 rel->rd_id,
			 rel->rd_node.relNode,
			 segmentFileNum,
			 logicalEof);
	}

	MirroredAppendOnly_OpenReadWrite(
							mirroredOpen, 
							&rel->rd_node,
							segmentFileNum,
							/* relationName */ NULL,		// Ok to be NULL -- we don't know the name here.
							logicalEof,
							/* traceOpenFlags */ false,
							&persistentTid,
							persistentSerialNum,
							&primaryError);
	if (primaryError != 0)
		ereport(ERROR,
			   (errcode_for_file_access(),
			    errmsg("Could not open Append-Only segment file '%s': %s",
					   filepathname,
					   strerror(primaryError))));

	return true;
}
Example #2
0
/*
 * Opens the next segment file to write.  The file must already exist.
 * This routine is responsible for seeking to the proper write location
 * given the logical EOF.
 *
 * @filePathName:	The name of the segment file to open.
 * @logicalEof:		The last committed write transaction's EOF
 * 					value to use as the end of the segment file.
 * @parquet_file		The file handler of segment file
 */
static void OpenSegmentFile(
		MirroredAppendOnlyOpen *mirroredOpen,
		char *filePathName,
		int64 logicalEof,
		RelFileNode *relFileNode,
		int32 segmentFileNum,
		char *relname,
		File *parquet_file,
		File *parquet_file_previous,
		CompactProtocol **protocol_read,
		TupleDesc tableAttrs,
		ParquetMetadata *parquetMetadata,
		int64 *fileLen,
		int64 *fileLen_uncompressed,
		int *previous_rowgroupcnt) {
	int primaryError;

	File file;

	int64 seekResult;

	Assert(filePathName != NULL);

	bool metadataExist = false;

	/*
	 * Open the file for metadata reading.
	 */
	MirroredAppendOnly_OpenReadWrite(mirroredOpen, relFileNode, segmentFileNum,
			relname, logicalEof, true, &primaryError);
	if (primaryError != 0)
		ereport(ERROR,
				(errcode_for_file_access(),
						errmsg("file open error when opening file "
								"'%s' for relation '%s': %s", filePathName, relname,
								strerror(primaryError))));

	*parquet_file_previous = mirroredOpen->primaryFile;

	int64 fileSize = FileSeek(*parquet_file_previous, 0, SEEK_END);
	if (fileSize < 0){
		ereport(ERROR,
				(errcode_for_file_access(),
						errmsg("file seek error in file '%s' for relation "
								"'%s'", filePathName, relname)));
	}
	if (logicalEof > fileSize) {
		ereport(ERROR,
				(errcode(ERRCODE_GP_INTERNAL_ERROR),
						errmsg("logical eof exceeds file size in file '%s' for relation '%s'",
								filePathName,
								relname)));
	}

	/*read parquet footer, get metadata information before rowgroup metadata*/
	metadataExist = readParquetFooter(*parquet_file_previous, parquetMetadata, protocol_read,
			logicalEof, filePathName);

	*previous_rowgroupcnt = (*parquetMetadata)->blockCount;

	/*
	 * Open the file for writing.
	 */
	MirroredAppendOnly_OpenReadWrite(mirroredOpen, relFileNode, segmentFileNum,
			relname, logicalEof, false, &primaryError);
	if (primaryError != 0)
		ereport(ERROR,
				(errcode_for_file_access(),
						errmsg("file open error when opening file '%s' "
								"for relation '%s': %s", filePathName, relname,
								strerror(primaryError))));

	file = mirroredOpen->primaryFile;

	seekResult = FileNonVirtualTell(file);
	if (seekResult != logicalEof) {
		/* previous transaction is aborted truncate file*/
		if (FileTruncate(file, logicalEof)) {

			MirroredAppendOnly_Close(mirroredOpen);
			ereport(ERROR,
					(errcode_for_file_access(),
						errmsg("file truncate error in file '%s' for relation "
								"'%s' to position " INT64_FORMAT ": %s",
								filePathName, relname, logicalEof,
								strerror(errno))));
		}
	}

	*parquet_file = file;

	/*if metadata not exist, should initialize the metadata, and write out file header*/
	if (metadataExist == false) {
		/* init parquet metadata information, init schema information using table attributes,
		 * and may get existing information from data file*/
		initparquetMetadata(*parquetMetadata, tableAttrs, *parquet_file);

		/*should judge whether file already exists, if a new file, should write header out*/
		writeParquetHeader(*parquet_file, filePathName, fileLen, fileLen_uncompressed);
	}
	else {
		if (!checkAndSyncMetadata(*parquetMetadata, tableAttrs))
		{
			ereport(ERROR,
					(errcode(ERRCODE_GP_INTERNAL_ERROR),
						errmsg("parquet storage write file's metadata incompatible "
								"with table's schema for relation '%s'.",
						relname)));
		}
	}
}