/* * 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.processors.cache.database.freelist.io; import java.util.Map; import org.apache.ignite.internal.pagemem.PageUtils; import org.apache.ignite.internal.processors.cache.database.freelist.PagesList; import org.apache.ignite.internal.processors.cache.database.tree.io.IOVersions; import org.apache.ignite.internal.processors.cache.database.tree.io.PageIO; import org.apache.ignite.internal.util.GridLongList; /** * */ public class PagesListMetaIO extends PageIO { /** */ private static final int CNT_OFF = COMMON_HEADER_END; /** */ private static final int NEXT_META_PAGE_OFF = CNT_OFF + 2; /** */ private static final int ITEMS_OFF = NEXT_META_PAGE_OFF + 8; /** */ private static final int ITEM_SIZE = 10; /** */ public static final IOVersions<PagesListMetaIO> VERSIONS = new IOVersions<>( new PagesListMetaIO(1) ); /** * @param ver Page format version. */ private PagesListMetaIO(int ver) { super(T_PAGE_LIST_META, ver); } /** {@inheritDoc} */ @Override public void initNewPage(long pageAddr, long pageId, int pageSize) { super.initNewPage(pageAddr, pageId, pageSize); setCount(pageAddr, 0); setNextMetaPageId(pageAddr, 0L); } /** * @param pageAddr Page address. * @return Stored items count. */ private int getCount(long pageAddr) { return PageUtils.getShort(pageAddr, CNT_OFF); } /** * @param pageAddr Page address. * @param cnt Stored items count. */ private void setCount(long pageAddr, int cnt) { assert cnt >= 0 && cnt <= Short.MAX_VALUE : cnt; PageUtils.putShort(pageAddr, CNT_OFF, (short)cnt); } /** * @param pageAddr Page address. * @return Next meta page ID. */ public long getNextMetaPageId(long pageAddr) { return PageUtils.getLong(pageAddr, NEXT_META_PAGE_OFF); } /** * @param pageAddr Page address. * @param metaPageId Next meta page ID. */ public void setNextMetaPageId(long pageAddr, long metaPageId) { PageUtils.putLong(pageAddr, NEXT_META_PAGE_OFF, metaPageId); } /** * @param pageAddr Page address. */ public void resetCount(long pageAddr) { setCount(pageAddr, 0); } /** * @param pageSize Page size. * @param pageAddr Page address. * @param bucket Bucket number. * @param tails Tails. * @param tailsOff Tails offset. * @return Number of items written. */ public int addTails(int pageSize, long pageAddr, int bucket, PagesList.Stripe[] tails, int tailsOff) { assert bucket >= 0 && bucket <= Short.MAX_VALUE : bucket; int cnt = getCount(pageAddr); int cap = getCapacity(pageSize, pageAddr); if (cnt == cap) return 0; int off = offset(cnt); int write = Math.min(cap - cnt, tails.length - tailsOff); for (int i = 0; i < write; i++) { PageUtils.putShort(pageAddr, off, (short)bucket); PageUtils.putLong(pageAddr, off + 2, tails[tailsOff].tailId); tailsOff++; off += ITEM_SIZE; } setCount(pageAddr, cnt + write); return write; } /** * @param pageAddr Page address. * @param res Results map. */ public void getBucketsData(long pageAddr, Map<Integer, GridLongList> res) { int cnt = getCount(pageAddr); assert cnt >= 0 && cnt <= Short.MAX_VALUE : cnt; if (cnt == 0) return; int off = offset(0); for (int i = 0; i < cnt; i++) { Integer bucket = (int)PageUtils.getShort(pageAddr, off); assert bucket >= 0 && bucket <= Short.MAX_VALUE : bucket; long tailId = PageUtils.getLong(pageAddr, off + 2); assert tailId != 0; GridLongList list = res.get(bucket); if (list == null) res.put(bucket, list = new GridLongList()); list.add(tailId); off += ITEM_SIZE; } } /** * @param pageAddr Page address. * @return Maximum number of items which can be stored in buffer. */ private int getCapacity(int pageSize, long pageAddr) { return (pageSize - ITEMS_OFF) / ITEM_SIZE; } /** * @param idx Item index. * @return Item offset. */ private int offset(int idx) { return ITEMS_OFF + ITEM_SIZE * idx; } }