/* * 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.geode.internal.offheap; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; /** * A fragment is a block of memory that can have chunks allocated from it. The allocations are * always from the front so the free memory is always at the end. The freeIdx keeps track of the * first byte of free memory in the fragment. The base memory address and the total size of a * fragment never change. During defragmentation fragments go away and are recreated. * * */ public class Fragment implements MemoryBlock { private static final byte FILL_BYTE = OffHeapStoredObject.FILL_BYTE; private final long baseAddr; private final int size; @SuppressWarnings("unused") private volatile int freeIdx; private static AtomicIntegerFieldUpdater<Fragment> freeIdxUpdater = AtomicIntegerFieldUpdater.newUpdater(Fragment.class, "freeIdx"); public Fragment(long addr, int size) { MemoryAllocatorImpl.validateAddress(addr); this.baseAddr = addr; this.size = size; freeIdxUpdater.set(this, 0); } public int freeSpace() { return getSize() - getFreeIndex(); } public boolean allocate(int oldOffset, int newOffset) { return freeIdxUpdater.compareAndSet(this, oldOffset, newOffset); } public int getFreeIndex() { return freeIdxUpdater.get(this); } public int getSize() { return this.size; } public long getAddress() { return this.baseAddr; } @Override public State getState() { return State.UNUSED; } @Override public MemoryBlock getNextBlock() { throw new UnsupportedOperationException(); } @Override public int getBlockSize() { return freeSpace(); } @Override public int getSlabId() { throw new UnsupportedOperationException(); } @Override public int getFreeListId() { return -1; } @Override public int getRefCount() { return 0; } @Override public String getDataType() { return "N/A"; } @Override public boolean isSerialized() { return false; } @Override public boolean isCompressed() { return false; } @Override public Object getDataValue() { return null; } public void fill() { AddressableMemoryManager.fill(this.baseAddr, this.size, FILL_BYTE); } @Override public boolean equals(Object o) { if (o instanceof Fragment) { return getAddress() == ((Fragment) o).getAddress(); } return false; } @Override public int hashCode() { long value = this.getAddress(); return (int) (value ^ (value >>> 32)); } @Override public String toString() { return "Fragment [baseAddr=" + baseAddr + ", size=" + size + ", freeIdx=" + freeIdx + "]"; } }