共有メモリでAVCを実装

実は、SE-PostgreSQLはuserspace AVC相当のモノを自前で実装している。
エラーハンドリングの容易さとパフォーマンスが理由だが、これを共有メモリセグメント上に配置するように実装を変更した。

今までは、PostgreSQLインスタンス毎にAVCを持っていた。しかしこの実装では、ローカルのAVC上に十分にAVCエントリが蓄積されるまでの間はカーネルへの呼び出しが生じてしまうという問題が生じる。
共有メモリを利用することで、全てのPostgreSQLインスタンスが同一のAVCを参照することが可能になり、AVCエントリの構築のためにカーネルの呼び出しを行うことは最小限に抑えられる。

また、boolean値の変更などが発生した場合には直ちにAVCの内容をクリアしなければならないが、共有メモリを利用することでこの処理が単純化される。

以下、後学のために共有メモリセグメントを利用するためのメモ
1. 共有メモリセグメントサイズの加算
CreateSharedMemoryAndSemaphores()関数内で、全共有メモリサイズを計算している箇所があるので、SE-PostgreSQLで利用する分をここに加える。動的に増減させることはできない。

2. PostgreSQLインスタンスにアタッチ
void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);をコール。nameはセグメント名、sizeはセグメントの大きさ。foundPtrには共有メモリセグメントが既に作成されていれば true が返却される。

3. 共有メモリセグメント上のオブジェクトの参照
共有メモリがアタッチされるアドレスはプロセス毎に異なるので、全て先頭からのオフセットで表現し、ベースアドレスと加算することでアドレスを得る。
オフセットは SHMEM_OFFSET 型(実体は unsigned long)で表現
オフセット→アドレス変換は MAKE_PTR() マクロを利用
アドレス→オフセット変換は MAKE_OFFSET() マクロを利用

たまには役に立つことを書いてみよう。