/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.internal.pagemem; import org.apache.ignite.internal.util.typedef.internal.U; /** * Utility class for page ID parts manipulation. * * @see FullPageId */ public final class PageIdUtils { /** */ public static final int PAGE_IDX_SIZE = 32; /** */ public static final int PART_ID_SIZE = 16; /** */ public static final int FLAG_SIZE = 8; /** */ public static final int OFFSET_SIZE = 8; /** */ public static final int TAG_SIZE = 16; /** */ public static final long PAGE_IDX_MASK = ~(-1L << PAGE_IDX_SIZE); /** */ public static final long OFFSET_MASK = ~(-1L << OFFSET_SIZE); /** */ public static final long TAG_MASK = ~(-1L << TAG_SIZE); /** */ public static final long PART_ID_MASK = ~(-1L << PART_ID_SIZE); /** */ public static final long FLAG_MASK = ~(-1L << FLAG_SIZE); /** */ private static final long EFFECTIVE_PAGE_ID_MASK = ~(-1L << (PAGE_IDX_SIZE + PART_ID_SIZE)); /** */ private static final long PAGE_ID_MASK = ~(-1L << (PAGE_IDX_SIZE + PART_ID_SIZE + FLAG_SIZE)); /** Max itemid number. */ public static final int MAX_ITEMID_NUM = 0xFE; /** Maximum page number. */ public static final long MAX_PAGE_NUM = (1L << PAGE_IDX_SIZE) - 1; /** Maximum page number. */ public static final int MAX_PART_ID = (1 << PART_ID_SIZE) - 1; /** * */ private PageIdUtils() { // No-op. } /** * Constructs a page link by the given page ID and 8-byte words within the page. * * @param pageId Page ID. * @param itemId Item ID. * @return Page link. */ public static long link(long pageId, int itemId) { assert itemId >= 0 && itemId <= MAX_ITEMID_NUM: itemId; assert (pageId >> (FLAG_SIZE + PART_ID_SIZE + PAGE_IDX_SIZE)) == 0 : U.hexLong(pageId); return pageId | (((long)itemId) << (FLAG_SIZE + PART_ID_SIZE + PAGE_IDX_SIZE)); } /** * Extracts a page index from the given pageId. * * @param pageId Page id. * @return Page ID. */ public static int pageIndex(long pageId) { return (int)(pageId & PAGE_IDX_MASK); // 4 bytes } /** * Extracts a page ID from the given page link. * * @param link Page link. * @return Page ID. */ public static long pageId(long link) { return flag(link) == PageIdAllocator.FLAG_IDX ? link : link & PAGE_ID_MASK; } /** * @param link Page link. * @return Effective page id. */ public static long effectivePageId(long link) { return link & EFFECTIVE_PAGE_ID_MASK; } /** * @param pageId Page id. * @return {@code True} if page id is equal to effective page id. */ public static boolean isEffectivePageId(long pageId) { return (pageId & ~EFFECTIVE_PAGE_ID_MASK) == 0; } /** * Index of the item inside of data page. * * @param link Page link. * @return Offset in 8-byte words. */ public static int itemId(long link) { return (int)((link >> (PAGE_IDX_SIZE + PART_ID_SIZE + FLAG_SIZE)) & OFFSET_MASK); } /** * Tag of pageId * * @param link Page link. * @return tag - item id + flags */ public static int tag(long link) { return (int)((link >> (PAGE_IDX_SIZE + PART_ID_SIZE)) & TAG_MASK); } /** * @param partId Partition ID. * @return Part ID constructed from the given cache ID and partition ID. */ public static long pageId(int partId, byte flag, int pageIdx) { long pageId = flag & FLAG_MASK; pageId = (pageId << PART_ID_SIZE) | (partId & PART_ID_MASK); pageId = (pageId << (PAGE_IDX_SIZE)) | (pageIdx & PAGE_IDX_MASK); return pageId; } /** * @param pageId Page ID. * @return Flag. */ public static byte flag(long pageId) { return (byte)((pageId >>> (PART_ID_SIZE + PAGE_IDX_SIZE)) & FLAG_MASK); } /** * @param pageId Page ID. * @return Partition. */ public static int partId(long pageId) { return (int)((pageId >>> PAGE_IDX_SIZE ) & PART_ID_MASK); } /** * @param pageId Page ID. * @return New page ID. */ public static long rotatePageId(long pageId) { long updatedRotationId = (pageId >> PAGE_IDX_SIZE + PART_ID_SIZE + FLAG_SIZE) + 1; return (pageId & PAGE_ID_MASK) | (updatedRotationId << (PAGE_IDX_SIZE + PART_ID_SIZE + FLAG_SIZE)); } /** * Change page type. * * @param pageId Old page ID. * @param type New page type. * @return Changed page ID. */ public static long changeType(long pageId, byte type) { return pageId(partId(pageId), type, pageIndex(pageId)); } }