bool PersistentFilespace_TryGetPrimaryAndMirror( Oid filespaceOid, /* The filespace OID to lookup. */ char **primaryFilespaceLocation, /* The primary filespace directory path. Return NULL for global and base. */ char **mirrorFilespaceLocation) /* * The primary filespace directory path. Return NULL for global and base. * Or, returns NULL when mirror not configured. */ { FilespaceDirEntry filespaceDirEntry; bool result = false; *primaryFilespaceLocation = NULL; *mirrorFilespaceLocation = NULL; #ifdef MASTER_MIRROR_SYNC /* * Can't rely on persistent tables or memory structures on the standby so * get it from the cache maintained by the master mirror sync code */ if (IsStandbyMode()) { return mmxlog_filespace_get_path( filespaceOid, primaryFilespaceLocation); } #endif /* * Important to make this call AFTER we check if we are the Standby * Master. */ PersistentFilespace_VerifyInitScan(); LWLockAcquire(FilespaceHashLock, LW_SHARED); filespaceDirEntry = PersistentFilespace_FindDirUnderLock(filespaceOid); if (filespaceDirEntry) { PersistentFilespace_GetPaths(filespaceDirEntry, primaryFilespaceLocation, mirrorFilespaceLocation); result = true; } LWLockRelease(FilespaceHashLock); return result; }
PersistentTablespaceGetFilespaces PersistentTablespace_TryGetPrimaryAndMirrorFilespaces( Oid tablespaceOid, /* The tablespace OID for the create. */ char **primaryFilespaceLocation, /* The primary filespace directory path. Return NULL for global and base. */ char **mirrorFilespaceLocation, /* * The primary filespace directory path. Return NULL for global and base. * Or, returns NULL when mirror not configured. */ Oid *filespaceOid) { *primaryFilespaceLocation = NULL; *mirrorFilespaceLocation = NULL; *filespaceOid = InvalidOid; if (IsBuiltinTablespace(tablespaceOid)) { /* * Optimize out the common cases. */ return PersistentTablespaceGetFilespaces_Ok; } #ifdef MASTER_MIRROR_SYNC /* * Can't rely on persistent tables or memory structures on the standby so * get it from the cache maintained by the master mirror sync code */ if (IsStandbyMode()) { if (!mmxlog_tablespace_get_filespace( tablespaceOid, filespaceOid)) { if (!Debug_persistent_recovery_print) { /* Print this information when we are not doing other tracing. */ mmxlog_print_tablespaces( LOG, "Standby Get Filespace for Tablespace"); } return PersistentTablespaceGetFilespaces_TablespaceNotFound; } if (!mmxlog_filespace_get_path( *filespaceOid, primaryFilespaceLocation)) { if (!Debug_persistent_recovery_print) { /* Print this information when we are not doing other tracing. */ mmxlog_print_filespaces( LOG, "Standby Get Filespace Location"); } return PersistentTablespaceGetFilespaces_FilespaceNotFound; } return PersistentTablespaceGetFilespaces_Ok; } #endif /* * MPP-10111 - There is a point during gpexpand where we need to bring the * database up to fix the filespace locations for a segment. At this * point in time the old filespace locations are wrong and we should not * trust anything currently stored there. If the guc is set we prevent * the lookup of a any non builtin filespaces. */ if (gp_before_filespace_setup) elog(ERROR, "can not lookup tablespace location: gp_before_filespace_setup=true"); /* * Important to make this call AFTER we check if we are the Standby * Master. */ PersistentTablespace_VerifyInitScan(); return PersistentFilespace_GetFilespaceFromTablespace( tablespaceOid, primaryFilespaceLocation, mirrorFilespaceLocation, filespaceOid); }
/* * Open a relation during XLOG replay * * Note: this once had an API that allowed NULL return on failure, but it * no longer does; any failure results in elog(). */ Relation XLogOpenRelation(RelFileNode rnode) { XLogRelDesc *res; XLogRelCacheEntry *hentry; bool found; hentry = (XLogRelCacheEntry *) hash_search(_xlrelcache, (void *) &rnode, HASH_FIND, NULL); if (hentry) { res = hentry->rdesc; res->lessRecently->moreRecently = res->moreRecently; res->moreRecently->lessRecently = res->lessRecently; } else { /* * We need to fault in the database directory on the standby. */ if (rnode.spcNode != GLOBALTABLESPACE_OID && IsStandbyMode()) { char *primaryFilespaceLocation = NULL; char *dbPath; if (IsBuiltinTablespace(rnode.spcNode)) { /* * No filespace to fetch. */ } else { char *mirrorFilespaceLocation = NULL; /* * Investigate whether the containing directories exist to give more detail. */ PersistentTablespace_GetPrimaryAndMirrorFilespaces( rnode.spcNode, &primaryFilespaceLocation, &mirrorFilespaceLocation); if (primaryFilespaceLocation == NULL || strlen(primaryFilespaceLocation) == 0) { elog(ERROR, "Empty primary filespace directory location"); } if (mirrorFilespaceLocation != NULL) { pfree(mirrorFilespaceLocation); mirrorFilespaceLocation = NULL; } } dbPath = (char*)palloc(MAXPGPATH + 1); FormDatabasePath( dbPath, primaryFilespaceLocation, rnode.spcNode, rnode.dbNode); if (primaryFilespaceLocation != NULL) { pfree(primaryFilespaceLocation); primaryFilespaceLocation = NULL; } if (mkdir(dbPath, 0700) == 0) { if (Debug_persistent_recovery_print) { elog(PersistentRecovery_DebugPrintLevel(), "XLogOpenRelation: Re-created database directory \"%s\"", dbPath); } } else { /* * Allowed to already exist. */ if (errno != EEXIST) { elog(ERROR, "could not create database directory \"%s\": %m", dbPath); } else { if (Debug_persistent_recovery_print) { elog(PersistentRecovery_DebugPrintLevel(), "XLogOpenRelation: Database directory \"%s\" already exists", dbPath); } } } pfree(dbPath); } res = _xl_new_reldesc(); sprintf(RelationGetRelationName(&(res->reldata)), "%u", rnode.relNode); res->reldata.rd_node = rnode; /* * We set up the lockRelId in case anything tries to lock the dummy * relation. Note that this is fairly bogus since relNode may be * different from the relation's OID. It shouldn't really matter * though, since we are presumably running by ourselves and can't have * any lock conflicts ... */ res->reldata.rd_lockInfo.lockRelId.dbId = rnode.dbNode; res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode; hentry = (XLogRelCacheEntry *) hash_search(_xlrelcache, (void *) &rnode, HASH_ENTER, &found); if (found) elog(PANIC, "xlog relation already present on insert into cache"); hentry->rdesc = res; res->reldata.rd_targblock = InvalidBlockNumber; res->reldata.rd_smgr = NULL; RelationOpenSmgr(&(res->reldata)); /* * Create the target file if it doesn't already exist. This lets us * cope if the replay sequence contains writes to a relation that is * later deleted. (The original coding of this routine would instead * return NULL, causing the writes to be suppressed. But that seems * like it risks losing valuable data if the filesystem loses an inode * during a crash. Better to write the data until we are actually * told to delete the file.) */ // NOTE: We no longer re-create files automatically because // new FileRep persistent objects will ensure files exist. // UNDONE: Can't remove this block of code yet until boot time calls to this routine are analyzed... { MirrorDataLossTrackingState mirrorDataLossTrackingState; int64 mirrorDataLossTrackingSessionNum; bool mirrorDataLossOccurred; // UNDONE: What about the persistent rel files table??? // UNDONE: This condition should not occur anymore. // UNDONE: segmentFileNum and AO? mirrorDataLossTrackingState = FileRepPrimary_GetMirrorDataLossTrackingSessionNum( &mirrorDataLossTrackingSessionNum); smgrcreate( res->reldata.rd_smgr, res->reldata.rd_isLocalBuf, /* relationName */ NULL, // Ok to be NULL -- we don't know the name here. mirrorDataLossTrackingState, mirrorDataLossTrackingSessionNum, /* ignoreAlreadyExists */ true, &mirrorDataLossOccurred); } } res->moreRecently = &(_xlrelarr[0]); res->lessRecently = _xlrelarr[0].lessRecently; _xlrelarr[0].lessRecently = res; res->lessRecently->moreRecently = res; Assert(&(res->reldata) != NULL); // Assert what it says in the interface -- we don't return NULL anymore. return &(res->reldata); }
bool PersistentFilespace_TryGetPrimaryAndMirrorUnderLock( Oid filespaceOid, /* The filespace OID to lookup. */ char **primaryFilespaceLocation, /* The primary filespace directory path. Return NULL for global and base. */ char **mirrorFilespaceLocation) /* The primary filespace directory path. Return NULL for global and base. * Or, returns NULL when mirror not configured. */ { FilespaceDirEntry filespaceDirEntry; int16 primaryDbId; char *primaryBlankPadded = NULL; char *mirrorBlankPadded = NULL; *primaryFilespaceLocation = NULL; *mirrorFilespaceLocation = NULL; #ifdef MASTER_MIRROR_SYNC /* * Can't rely on persistent tables or memory structures on the standby so * get it from the cache maintained by the master mirror sync code */ if (IsStandbyMode()) { return mmxlog_filespace_get_path( filespaceOid, primaryFilespaceLocation); } #endif /* * Important to make this call AFTER we check if we are the Standby Master. */ PersistentFilespace_VerifyInitScan(); filespaceDirEntry = PersistentFilespace_FindDirUnderLock( filespaceOid); if (filespaceDirEntry == NULL) return false; /* * The persistent_filespace_node_table contains the paths for both the * primary and mirror nodes, and the table is the same on both sides of the * mirror. When it was first created the primary put its location first, * but we don't know if we were the primary when it was created or not. To * determine which path corresponds to this node we compare our dbid to the * one stored in the table. */ primaryDbId = GpIdentity.dbid; if (filespaceDirEntry->dbId1 == primaryDbId) { /* dbid == dbid1 */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded1; mirrorBlankPadded = filespaceDirEntry->locationBlankPadded2; } else if (filespaceDirEntry->dbId2 == primaryDbId) { /* dbid == dbid2 */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded2; mirrorBlankPadded = filespaceDirEntry->locationBlankPadded1; } else { /* * The dbid check above does not work for the Master Node during * initial startup, because the master doesn't yet know its own dbid. * To handle this we special case for the master node the master * always considers the first entry as the correct location. * * Note: This design may need to be reconsidered to handle standby * masters! */ PrimaryMirrorMode mode; getPrimaryMirrorStatusCodes(&mode, NULL, NULL, NULL); if (mode == PMModeMaster) { /* Master node */ primaryBlankPadded = filespaceDirEntry->locationBlankPadded1; mirrorBlankPadded = filespaceDirEntry->locationBlankPadded2; } else { /* * Current dbid matches neither dbid in table and was not started * as a master node. */ ereport(FATAL, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Unable to determine dbid for filespace lookup"))); } } /* These should both have been populated by one of the cases above */ Assert(primaryBlankPadded); Assert(mirrorBlankPadded); PersistentFilespace_ConvertBlankPaddedLocation( primaryFilespaceLocation, primaryBlankPadded, /* isPrimary */ true); PersistentFilespace_ConvertBlankPaddedLocation( mirrorFilespaceLocation, mirrorBlankPadded, /* isPrimary */ false); return true; }