public unsafe void Commit() { if (Flags != (TransactionFlags.ReadWrite)) { return; // nothing to do } FlushAllMultiValues(); _freeSpaceRepository.FlushFreeState(this); foreach (var kvp in _treesInfo) { var txInfo = kvp.Value; var tree = kvp.Key; tree.DebugValidateTree(this, txInfo.RootPageNumber); txInfo.Flush(); if (string.IsNullOrEmpty(kvp.Key.Name)) { continue; } var treePtr = (TreeRootHeader *)_env.Root.DirectAdd(this, tree.Name, sizeof(TreeRootHeader)); tree.State.CopyTo(treePtr); } FlushFreePages(); // this is the the free space that is available when all concurrent transactions are done if (_rootTreeData != null) { _env.Root.DebugValidateTree(this, _rootTreeData.RootPageNumber); _rootTreeData.Flush(); } if (_fresSpaceTreeData != null) { _env.FreeSpaceRoot.DebugValidateTree(this, _fresSpaceTreeData.RootPageNumber); _fresSpaceTreeData.Flush(); } #if DEBUG if (_env.Root != null && _env.FreeSpaceRoot != null) { Debug.Assert(_env.Root.State.RootPageNumber != _env.FreeSpaceRoot.State.RootPageNumber); } #endif _env.NextPageNumber = NextPageNumber; // Because we don't know in what order the OS will flush the pages // we need to do this twice, once for the data, and then once for the metadata var sortedPagesToFlush = _dirtyPages.Select(x => x.Value).Distinct().ToList(); sortedPagesToFlush.Sort(); _pager.Flush(sortedPagesToFlush); if (_freeSpaceRepository != null) { _freeSpaceRepository.LastTransactionPageUsage(sortedPagesToFlush.Count); } WriteHeader(_pager.Get(this, _id & 1)); // this will cycle between the first and second pages _pager.Flush(_id & 1); // and now we flush the metadata as well _pager.Sync(); }