#include "postgres.h"
#include "access/cbfsmpage.h"
+#include "access/cbindexpage.h"
#include "access/cbmetapage.h"
#include "access/cbmetapage_format.h"
* will be set to the segment number of the newest index segment, or
* CB_INVALID_SEGMENT if there is none.
*
- * If the return value is CBM_INSERT_OK, there is an unfilled payload segment,
- * and *blkno will be set to the block number of the first unused page in that
+ * If the return value is CBM_INSERT_OK, *blkno will be set to the block number
+ * of the first unused page in the unfilled payload segment.
+ *
+ * If the return value is CBM_INSERT_NEEDS_INDEX_ENTRIES_RELOCATED, *blkno
+ * will be set to the first not-entirely-filled page in the newest index
* segment.
*/
CBMInsertState
* metapage that now precede the logical truncation point, but that would
* require a cleanup lock on the metapage, and it normally isn't going to
* be possible, because typically the last truncate operation will have
- * afterward done any such work that is possible. We might miss an
+ * afterwards done any such work that is possible. We might miss an
* opportunity in the case where the last truncate operation didn't clean
* up fully, but hopefully that's rare enough that we don't need to stress
* about it.
*
* If the newest index segment is already full, then a new index segment
* will need to be created. Otherwise, some entries can be copied into the
- * existing index segment. To make things easier for the caller, there is
- * a metapage flag to tell us which situation prevails.
+ * existing index segment.
*/
if (relp >= CB_METAPAGE_INDEX_ENTRIES * meta->cbm_pages_per_segment)
{
- if ((meta->cbm_flags & CBM_FLAG_INDEX_SEGMENT_FULL) != 0)
+ unsigned entries;
+ unsigned maxentries;
+
+ entries = meta->cbm_entries_in_newest_index_segment;
+ maxentries = CB_INDEXPAGE_INDEX_ENTRIES * meta->cbm_pages_per_segment;
+
+ if (entries > maxentries)
+ elog(ERROR,
+ "newest index segment listed as using %u of %u entries",
+ entries, maxentries);
+ else if (entries == maxentries)
return CBM_INSERT_NEEDS_INDEX_SEGMENT;
else
+ {
+ /* Figure out which block should be targeted. */
+ *blkno = cb_segment_to_block(meta->cbm_pages_per_segment,
+ meta->cbm_newest_index_segment,
+ entries / CB_INDEXPAGE_INDEX_ENTRIES);
+
return CBM_INSERT_NEEDS_INDEX_ENTRIES_RELOCATED;
+ }
}
/* Compute current insertion segment and offset. */
meta->cbm_index_metapage_start +=
count * meta->cbm_pages_per_segment;
if (relocating)
+ {
meta->cbm_index_start = meta->cbm_index_metapage_start;
+ meta->cbm_entries_in_newest_index_segment += count;
+ }
}
/*
cb_metapage_add_index_segment(CBMetapageData *meta, CBSegNo segno)
{
meta->cbm_newest_index_segment = segno;
+ meta->cbm_entries_in_newest_index_segment = 0;
if (meta->cbm_oldest_index_segment == CB_INVALID_SEGMENT)
meta->cbm_oldest_index_segment = segno;
}
* larger reduces the number of index and freespace map segments required
* and decreases fragmentation at the storage level, but it also increases
* the granularity of space reuse.
- *
- * cbm_flags stores flags. Currently, the only flag is
- * CBM_FLAG_INDEX_SEGMENT_FULL.
*/
uint32 cbm_magic;
uint32 cbm_version;
uint16 cbm_pages_per_segment;
- uint16 cbm_flags;
/*
* Logical start and end of the conveyor belt.
* cbm_oldest_index_segment and cbm_newest_index_segment are the oldest
* and newest index segments that exist. Both values will be
* CB_INVALID_SEGMENT if there are no index segments. Otherwise, the
- * mapping for cbm_oldest_logical_page is stored in the first entry in the
+ * mapping for cbm_index_start is stored in the first entry in the
* first page of cbm_oldest_index_segment.
*
- * Note that the end of the newest index segment will often be unused, and
- * its contents undefined. That's because new index entries are always
- * inserted directly into the metapage, and later moved into index
- * segments in bulk.
+ * cbm_entries_in_newest_index_segment is the number of index entries
+ * in the newest index segment, or 0 if there are no index segments.
*
* cbm_index_segments_moved is the total number of times in the history
* of this conveyor belt that an index segment has been physically
CBPageNo cbm_index_metapage_start;
CBSegNo cbm_oldest_index_segment;
CBSegNo cbm_newest_index_segment;
+ unsigned cbm_entries_in_newest_index_segment;
uint64 cbm_index_segments_moved;
CBSegNo cbm_next_segment;
uint8 cbm_freespace_map[CB_METAPAGE_FREESPACE_BYTES];
};
-/*
- * Conveyor belt metapage flags.
- *
- * CBM_FLAG_INDEX_SEGMENT_FULL indicates that there is no room in the
- * newest index segment for any more index entries.
- */
-#define CBM_FLAG_INDEX_SEGMENT_FULL 0x0001
-
#endif