001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.io.hfile.bucket; 019 020import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.BucketEntry; 021import org.apache.hadoop.hbase.util.UnsafeAccess; 022import org.apache.yetus.audience.InterfaceAudience; 023 024import sun.misc.Unsafe; 025 026@InterfaceAudience.Private 027public class UnsafeSharedMemoryBucketEntry extends BucketEntry { 028 private static final long serialVersionUID = 707544024564058801L; 029 030 // We are just doing what AtomicInteger doing for the Atomic incrementAndGet/decrementAndGet. 031 // We are avoiding the need to have a field of AtomicIneger type and have it as just int type. 032 // We would like to reduce the head overhead per object of this type as much as possible. 033 // Doing this direct Unsafe usage save us 16 bytes per Object. 034 // ie Just using 4 bytes for int type than 20 bytes requirement for an AtomicInteger (16 bytes) 035 // and 4 bytes reference to it. 036 private static final Unsafe unsafe = UnsafeAccess.theUnsafe; 037 private static final long refCountOffset; 038 039 static { 040 try { 041 refCountOffset = unsafe 042 .objectFieldOffset(UnsafeSharedMemoryBucketEntry.class.getDeclaredField("refCount")); 043 } catch (Exception ex) { 044 throw new Error(ex); 045 } 046 } 047 048 // Set this when we were not able to forcefully evict the block 049 private volatile boolean markedForEvict; 050 private volatile int refCount = 0; 051 052 public UnsafeSharedMemoryBucketEntry(long offset, int length, long accessCounter, 053 boolean inMemory) { 054 super(offset, length, accessCounter, inMemory); 055 } 056 057 @Override 058 protected int getRefCount() { 059 return this.refCount; 060 } 061 062 @Override 063 protected int incrementRefCountAndGet() { 064 return unsafe.getAndAddInt(this, refCountOffset, 1) + 1; 065 } 066 067 @Override 068 protected int decrementRefCountAndGet() { 069 return unsafe.getAndAddInt(this, refCountOffset, -1) - 1; 070 } 071 072 @Override 073 protected boolean isMarkedForEvict() { 074 return this.markedForEvict; 075 } 076 077 @Override 078 protected void markForEvict() { 079 this.markedForEvict = true; 080 } 081}