话说调用 InitPostgres 方法给 portgres 服务进程做相关初始化,这个方法里初始化了 relcache 和 catcache ,初始化了执行查询计划的 portal 的管理器,填充本进程 PGPROC 结构相关部分成员等,这一节讨论这个方法。
1
先看 InitPostgres 方法的调用序列梗概图
InitPostgres 方法的调用序列梗概图
InitPostgres 方法为初始化这个 postgres 服务进程做了一系列的工作,具体如下:
( 1 )调用 InitProcessPhas e2 方法,把本进程的 PGPROC 结构注册到 PGPROC 数组,就是让 共享内存里的 PGPROC 数组( 初始化 PGPROC 数组的文章见《 PostgreSQL 启动过程中的那些事七:初始化共享内存和信号十一: shmem 中初始化 SharedProcArray 》 )的第一个空元素指向这个 PGPROC 结构 ,并注册退出时做内存清理的函数。
( 2 )调用 SharedInvalBackendInit 方法,在该后台进程数据的 共享失效管理器数组获取一个 ProcState 结构(相关数据结果见《 PostgreSQL 启动过程中的那些事七:初始化共享内存和信号十三: shmem 中初始化 SharedInvalidationState 》)给该进程并初始化相关项,并注册退出方法以在退出时标记本进程的项非活跃。
( 3 )调用 ProcSignalInit 方法, 在 ProcSignalSlot 结构 数组(关于 ProcSignalSlot 结构 数组参见《 PostgreSQL 启动过程中的那些事七:初始化共享内存和信号十四: shmem 中初始化 PMSignal 》) ProcSignalSlot s 里给当前进程获取一个元素,元素下标是 MyBackendId-1 ,并注册以在进程退出时释放这个槽。
( 4 )为访问 XLOG ,调用 RecoveryInProgress 方法做共享内存相关初始化。
( 5 )调用 RelationCacheInitlisze 方法做管理 relcache 的环境的初始化。
( 6 )调用 InitCatalogCache 方法做管理 catcache 的环境的初始化。
( 7 )调用 EnablePortalManager 方法初始化 portal 管理器。
( 8 )调用 RelationCacheInitializePhase2 方法初始化共享系统表。
( 9 )调用 GetTransactionSnapshot 方法获取一个事务快照。这个方法在后面讨论简单查询时再讨论。
( 10 )调用 PerformAuthentication 方法根据 hba 文件设置进行客户端认证。
( 11 )调用 GetDatabaseTuple 方法根据数据库名字从 pg_database 系统表获取要访问的数据库对应的元组。
( 12 )调用 RelationCacheInitializePhase3 方法完成 relcache 初始化。
( 13 )调用 CheckMyDatabase 方法检查当前用户的数据库访问权限,从 cache 里的 pg_database 取当前数据库的相关属性字段。
( 14 )调用 InitializeClientEncoding 方法初始化客户端字符编码。
( 15 )调用 pgstat_bestart 方法在 PgBackendStatus 设置本进程状态。
2
下面讨论第( 5 )步, RelationCacheInitialize 方法初始化管理 relcache 相关对象。 Relcache 是存放用户定义表的模式信息的地方 。 为了图能大一点, PostgresMain 以前的调用流程序列就从下面的图中省略了,要回顾可以参考上面的“ InitPostgres 方法的调用序列梗概图 ”。
RelationCacheInitialize 方法的调用序列图
在 RelationCacheInitialize 方法里首先调用 CreateCacheMemoryContext 方法创建了内存上下文 "CacheMemoryContext" 。然后调用 hash_create 方法先创建了内存上下文 "Relcache by OID" ,然后在该内存上下文里创建了管理 relcache 里个关系 schema 的同名哈西表 "Relcache by OID" 。
下面是管理 relcache 的哈西表 "Relcache by OID" 的图和相关结构定义:
管理 relcache 的哈西表 ”Relcache by OID”
typedef struct relidcacheent
{
Oid reloid ;
Relation reldesc ;
} RelIdCacheEnt ;
接着调用 RelationMapInitlize 方法将记录关系和对应的文件节点的 RelMapFile 类型各变量初始化为 0 ,因为现在我们不能访问数据库,还没有加载数据库相关的基础设施。这些变量包括:
static RelMapFile shared_map ;
static RelMapFile local_map;
static RelMapFile active_shared_updates;
static RelMapFile active_local_updates;
static RelMapFile pending_shared_updates;
static RelMapFile pending_local_updates;
相关结构和图形见下面:
typedef struct RelMapping
{
Oid mapoid ; /* OID of a catalog */
Oid mapfilenode ; /* its filenode number */
} RelMapping ;
typedef struct RelMapFile
{
int32 magic ; /* always RELMAPPER_FILEMAGIC 总是文件映射器版本 */
int32 num_mappings ; /* number of valid RelMapping entries */
RelMapping mappings [MAX_MAPPINGS];
int32 crc ; /* CRC of all above */
int32 pad ; /* to make the struct size be 512 exactly */
} RelMapFile ;
RelMapFile 结构图
就到这儿吧,下接接着讨论 postgres 访问进程的后续初始化 catcache 、 portalManager 等操作。
------------
转载请著明出处,来自博客:
blog.csdn.net/beiigang
beigang.iteye.com