| /* |
| * 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 org.apache.geode.internal.cache.CachedDeserializableFactory; |
| import org.apache.geode.internal.cache.InternalCache; |
| import org.apache.geode.internal.offheap.annotations.Released; |
| import org.apache.geode.internal.offheap.annotations.Unretained; |
| |
| /** |
| * Utility class that provides static method to do some common tasks for off-heap references. |
| * |
| * @since Geode 1.0 |
| */ |
| public class OffHeapHelper { |
| private OffHeapHelper() { |
| // no instances allowed |
| } |
| |
| /** |
| * If o is off-heap then return its heap form; otherwise return o since it is already on the heap. |
| */ |
| public static Object getHeapForm(Object o) { |
| if (o instanceof StoredObject) { |
| return ((StoredObject) o).getValueAsDeserializedHeapObject(); |
| } else { |
| return o; |
| } |
| } |
| |
| /** |
| * Just like {@link #copyIfNeeded(Object, InternalCache)} except that if off-heap is copied it is |
| * also released. |
| * |
| * @param v If this value is off-heap then the caller must have already retained it. |
| * @return the heap copy to use in place of v |
| */ |
| public static Object copyAndReleaseIfNeeded(@Released Object v, InternalCache cache) { |
| if (v instanceof StoredObject) { |
| @Unretained |
| StoredObject ohv = (StoredObject) v; |
| try { |
| if (ohv.isSerialized()) { |
| return CachedDeserializableFactory.create(ohv.getSerializedValue(), cache); |
| } else { |
| // it is a byte[] |
| return ohv.getDeserializedForReading(); |
| } |
| } finally { |
| release(ohv); |
| } |
| } else { |
| return v; |
| } |
| } |
| |
| /** |
| * If v is on heap then just return v; no copy needed. Else v is off-heap so copy it to heap and |
| * return a reference to the heap copy. Note that unlike {@link #getHeapForm(Object)} if v is a |
| * serialized off-heap object it will be copied to the heap as a CachedDeserializable. If you |
| * prefer to have the serialized object also deserialized and copied to the heap use |
| * {@link #getHeapForm(Object)}. |
| * |
| * @param v possible OFF_HEAP_REFERENCE |
| * @return v or a heap copy of v |
| */ |
| public static Object copyIfNeeded(@Unretained Object v, InternalCache cache) { |
| if (v instanceof StoredObject) { |
| @Unretained |
| StoredObject ohv = (StoredObject) v; |
| if (ohv.isSerialized()) { |
| v = CachedDeserializableFactory.create(ohv.getSerializedValue(), cache); |
| } else { |
| // it is a byte[] |
| v = ohv.getDeserializedForReading(); |
| } |
| } |
| return v; |
| } |
| |
| /** |
| * @return true if release was done |
| */ |
| public static boolean release(@Released Object o) { |
| if (o instanceof StoredObject) { |
| ((StoredObject) o).release(); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * Just like {@link #release(Object)} but also disable debug tracking of the release. |
| * |
| * @return true if release was done |
| */ |
| public static boolean releaseWithNoTracking(@Released Object o) { |
| if (o instanceof StoredObject) { |
| StoredObject so = (StoredObject) o; |
| if (!so.hasRefCount()) { |
| so.release(); |
| return true; |
| } |
| ReferenceCountHelper.skipRefCountTracking(); |
| so.release(); |
| ReferenceCountHelper.unskipRefCountTracking(); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * Just like {@link #release(Object)} but also set the owner for debug tracking of the release. |
| * |
| * @return true if release was done |
| */ |
| public static boolean releaseAndTrackOwner(@Released final Object o, final Object owner) { |
| if (o instanceof StoredObject) { |
| StoredObject so = (StoredObject) o; |
| if (!so.hasRefCount()) { |
| so.release(); |
| return true; |
| } |
| ReferenceCountHelper.setReferenceCountOwner(owner); |
| so.release(); |
| ReferenceCountHelper.setReferenceCountOwner(null); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| } |