相关代码的路径如下所示:/src/backend/storage/smgr。外存管理负责处理数据库与外存介质(在PostgreSQL中只实现了磁盘的管理操作)的交互过程。在PostgreSQL中,外存管理由SMGR(主要代码在smgr.c中)提供对外存操作的统一接口。SMGR负责统管各种介质管理器,会根据上层的请求选择具体的截止管理器进行操作。这里介绍磁盘管理器,每个表文件在磁盘中都以一定的结构进行存储,针对磁盘,外存管理模块提供了磁盘管理器和VFD机制。在PG 8.4.1版本中,还为每个表文件创建了两个附属文件,即空闲空间映射表文件(FSM)和可见性映射表文件(VM)。另外,对于大数据存储,PG也提供了两种处理机制。
- smgr.c public interface routines to storage manager switch 存储管理器切换公共接口
- smgrtype.c storage manager type 存储管理器类型
- md.c manages relations that reside on magnetic disk 管理驻留在磁盘上的关系
存储管理器类型
1 typedef struct smgrid
2 {
3 const char *smgr_name;
4 } smgrid;
5
6 /*
7 * StorageManager[] -- List of defined storage managers.
8 */
9 static const smgrid StorageManager[] = {
10 {"magnetic disk"}
11 };
12 static const int NStorageManagers = lengthof(StorageManager);
smgrid结构体包含const char指针,storageManager是smgrid的数组,NStorageMangers是storageManager中smgrid结构体元素的个数。目前只实现了磁盘管理器magnetic disk。
smgr文件函数的参数Datum smgrin(PG_FUNCTION_ARGS) --> unsigned long smgrin(struct FunctionCallInfoData * fcinfo)。
PG_GETARG_CSTRING(n)预定义为DatumGetCString(PG_GETARG_DATUM(n))、DatumGetCString(x)预定义为((char ) DatumGetPointer(x))、DatumGetPointer(x)预定义为((Pointer)(x))、typedef char Pointer。PG_GETARG_DATUM(n)预定义为(fcinfo->arg[n])。PG_GETARG_CSTRING(0)–>DatumGetCString(PG_GETARG_DATUM(0))–>((char *) DatumGetPointer(PG_GETARG_DATUM(0)))–>((char *) ((Pointer)(PG_GETARG_DATUM(0))))–>((char ) ((char)(PG_GETARG_DATUM(0))))–>((char ) ((char)((fcinfo->arg[0]))))。
PG_RETURN_INT16(x)预定义为return Int16GetDatum(x),Int16GetDatum(x)预定义为((Datum)SET_2_BYTES(x))、SET_2_BYTES(value)预定义为((Datum)(value)&0x0000ffff)。PG_RETURN_INT16(0)–>return Int16GetDatum(0)–>return ((Datum)SET_2_BYTES(x))–>return ((unsigned long)((unsigned long)(0)&0x0000ffff))。
smgrin函数用于查找输入参数中指定存储管理器在存储管理器数组中的序号
#define
typedef struct FunctionCallInfoData *FunctionCallInfo;
1 Datum smgrin(PG_FUNCTION_ARGS)
2 {
3 char *s = PG_GETARG_CSTRING(0);
4 int16 i;
5
6 for (i = 0; i < NStorageManagers; i++)
7 {
8 if (strcmp(s, StorageManager[i].smgr_name) == 0)
9 PG_RETURN_INT16(i);
10 }
11 elog(ERROR, "unrecognized storage manager name \"%s\"", s);
12 PG_RETURN_INT16(0);
13 }
PG_GETARG_INT16(n)预定义为DatumGetInt16(PG_GETARG_DATUM(n))、DatumGetInt16(x)预定义为((int16)GET_2_BYTES(x))、GET_2_BYTES(datum)预定义为(((Datum)(datum))&0x0000ffff)、PG_GETARG_DATUM(n)预定义为(fcinfo->arg[n])。
PG_GETARG_INT16(0)–>DatumGetInt16(PG_GETARG_DATUM(0))–>((int16)GET_2_BYTES(PG_GETARG_DATUM(0)))–>((int16)(((unsigned long)(PG_GETARG_DATUM(0)))&0x0000ffff))–>((int16)(((unsigned long)((fcinfo->arg[0])))&0x0000ffff))
PG_RETURN_CSTRING(x)预定义为return CStringGetDatum(x)、CStringGetDatum(x)预定义为PointerGetDatum(x)、PointerGetDatum(x)预定义为((Datum)(x))
PG_RETURN_CSTRING(x)–>return CStringGetDatum(x)–>return PointerGetDatum(x)–>return ((Datum)(x))–>return ((unsigned long)(x))
smgrout函数用于提取输入参数中指定存储管理器序号的管理器名并返回
1 Datum smgrout(PG_FUNCTION_ARGS)
2 {
3 int16 i = PG_GETARG_INT16(0);
4 char *s;
5
6 if (i >= NStorageManagers || i < 0)
7 elog(ERROR, "invalid storage manager id: %d", i);
8
9 s = pstrdup(StorageManager[i].smgr_name);
10 PG_RETURN_CSTRING(s);
11 }
PG_RETURN_BOOL(x)–>return BoolGetDatum(x)–>return ((Datum)((x)?1:0))–>return ((unsigned long)((x)?1:0))
smgreq和smgrne用于判别输入参数的arg[0]和arg[1]是否相同或不同
1 Datum smgreq(PG_FUNCTION_ARGS)
2 {
3 int16 a = PG_GETARG_INT16(0);
4 int16 b = PG_GETARG_INT16(1);
5 PG_RETURN_BOOL(a == b);
6 }
7
8 Datum smgrne(PG_FUNCTION_ARGS)
9 {
10 int16 a = PG_GETARG_INT16(0);
11 int16 b = PG_GETARG_INT16(1);
12 PG_RETURN_BOOL(a != b);
13 }
存储管理器切换公共接口
此函数指针结构体定义了smgr.c与任何单独的存储管理器模块之间的API。 请注意,通常期望smgr子功能通过elog(ERROR)报告问题。 一个例外是smgr_unlink应该使用elog(WARNING)而不是erroring out,因为我们通常在提交后/中止清理期间取消链接的关系,因此raise error为时已晚。 另外,在bootstrap和/或WAL恢复期间应允许通常是错误的各种条件-有关详细信息,请参见md.c中的注释。
1 typedef struct f_smgr
2 {
3 void (*smgr_init) (void); /* may be NULL */
4 void (*smgr_shutdown) (void); /* may be NULL */
5 void (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
6 void (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
7 bool isRedo);
8 bool (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
9 void (*smgr_unlink) (RelFileNode rnode, ForkNumber forknum,
10 bool isRedo);
11 void (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
12 BlockNumber blocknum, char *buffer, bool isTemp);
13 void (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
14 BlockNumber blocknum);
15 void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
16 BlockNumber blocknum, char *buffer);
17 void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
18 BlockNumber blocknum, char *buffer, bool isTemp);
19 BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
20 void (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
21 BlockNumber nblocks, bool isTemp);
22 void (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
23 void (*smgr_pre_ckpt) (void); /* may be NULL */
24 void (*smgr_sync) (void); /* may be NULL */
25 void (*smgr_post_ckpt) (void); /* may be NULL */
26 } f_smgr;
27 static const f_smgr smgrsw[] = {
28 /* magnetic disk */ //这里的函数定义在md.c中
29 {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend,
30 mdprefetch, mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync,
31 mdpreckpt, mdsync, mdpostckpt
32 }
33 };
34 // NSmgr是smgrsw数组中f_smgr结构体元素个数
35 static const int NSmgr = lengthof(smgrsw);
1 void smgrinit(void)
2 {
3 int i;
4
5 for (i = 0; i < NSmgr; i++)
6 {
7 if (smgrsw[i].smgr_init)
8 (*(smgrsw[i].smgr_init)) ();
9 }
10
11 /* register the shutdown proc */
12 on_proc_exit(smgrshutdown, 0);
13 }
1 static void smgrshutdown(int code, Datum arg)
2 {
3 int i;
4 for (i = 0; i < NSmgr; i++)
5 {
6 if (smgrsw[i].smgr_shutdown)
7 (*(smgrsw[i].smgr_shutdown)) ();
8 }
9 }