On Sat Mar 16 09:57:58 2024 +0000, Jinoh Kang wrote:
`grow_file` corrupts the file if we the size decreases, so other callers of `grow_file()` explicitly guards against this condition. I think we should do it here too:
assert(size > session_mapping->size);
Note that the "size ↔ capacity" translation is not a round-trip, and going from capacity back to size may actually result in the size decreasing if the element size becomes sufficiently greater than page size (plus certain overhead accounting for existing mapping size): $$ \newcommand{\NP}{\mathsf{NewPages}} \newcommand{\OP}{\mathsf{OldPages}} \newcommand{\Ps}{\mathsf{PageSize}} \newcommand{\Hs}{\mathsf{HeadSize}} \newcommand{\Es}{\mathsf{EltSize}} \newcommand{\ceil}[1]{\mathopen{}\left\lceil#1\right\rceil\mathclose{}} \newcommand{\floor}[1]{\mathopen{}\left\lfloor#1\right\rfloor\mathclose{}} \newcommand{\paren}[1]{\mathopen{}\left(#1\right)\mathclose{}} \displaystyle \[1ex] \begin{align*} \NP&=\ceil{\paren{\tfrac32\floor{{\paren{\OP\cdot\Ps - \Hs}}/{\Es}}\cdot\Es + \Hs}/{\Ps}}\ &=\ceil{\paren{\tfrac32\paren{{\paren{\OP\cdot\Ps - \Hs}}/{\Es} - k}\cdot\Es + \Hs}/{\Ps}}\ &=\ceil{\OP - \paren{k\cdot\Es - \tfrac13\paren{\OP\cdot\Ps - \Hs}}/\paren{\tfrac23\cdot\Ps}}\ &<\OP \end{align*} $$ where $$ \newcommand{\NP}{\mathsf{NewPages}} \newcommand{\OP}{\mathsf{OldPages}} \newcommand{\Ps}{\mathsf{PageSize}} \newcommand{\Hs}{\mathsf{HeadSize}} \newcommand{\Es}{\mathsf{EltSize}} \begin{align*} \mathbb{N}\ni\NP&=\text{New \texttt{session_mapping->size / page_size}}\ \mathbb{N}\ni\OP&=\text{Old \texttt{session_mapping->size / page_size}}\ \mathbb{N}\ni\Ps&=\text{\texttt{page_size}}>0\ \mathbb{N}\ni\Hs&=\text{\texttt{offsetof(session_shm_t, objects[0])}}>0\ \mathbb{N}\ni\Es&=\text{\texttt{sizeof(session_obj_t)}}>0\ 0&\leq k< 1&\text{(truncated fractional part)}\ k\cdot\Es &> \tfrac23\cdot\Ps + \tfrac13\left(\OP\cdot\Ps - \Hs\right) \ \left\lfloor\cdot\right\rfloor&=\mathrm{floor}!\left(\cdot\right)\ \left\lceil\cdot\right\rceil&=\mathrm{ceil}!\left(\cdot\right)\ \end{align*} $$
I don't think this holds if we can guarantee capacity ≥ 3:
*E = EltSize, P = PageSize, O = OldPages, H = HeadSize, C = (Old)Capacity*
``` C > 0 in N O = ⌈(C⋅E + H) / P⌉ ≥ C⋅E + H / P ```
Back to your condition for this:
``` k⋅E > 2/3⋅P + 1/3⋅(O⋅P - H) ⇔ 3⋅k⋅E > 2⋅P + O⋅P - H ⇒ 3⋅k⋅E > 2⋅P + C⋅E ⇒ 3⋅k > C ⇒ 3 > C ```
Which means that `C ≥ 3 ⇒ k⋅E ≤ 2/3⋅P + 1/3⋅(O⋅P - H)`, and then we're safe.
I think it's unlikely to ever not be the case and we would then have bigger issues, but I'll change the initial size to depend on the element size, and enforce at least 3 elements.
so other callers of `grow_file()` explicitly guards against this condition.
I don't see what you mean by that, where is this guarded exactly?