Skip to content

Commit

Permalink
CHM removed from OByteBufferPool
Browse files Browse the repository at this point in the history
  • Loading branch information
andrii0lomakin committed Dec 6, 2018
1 parent dc6fc2e commit 23e878d
Show file tree
Hide file tree
Showing 16 changed files with 680 additions and 650 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
*
* @see ODirectMemoryAllocator
*/
public class OByteBufferPool implements OByteBufferPoolMXBean {
public final class OByteBufferPool implements OByteBufferPoolMXBean {
/**
* Whether we should track memory leaks during application execution
*/
Expand All @@ -56,7 +56,6 @@ public class OByteBufferPool implements OByteBufferPoolMXBean {

/**
* @return Singleton instance
* @param contextConfiguration
*/
public static OByteBufferPool instance(OContextConfiguration contextConfiguration) {
final OByteBufferPool instance = INSTANCE_HOLDER.get();
Expand All @@ -71,7 +70,7 @@ public static OByteBufferPool instance(OContextConfiguration contextConfiguratio
bufferSize = OGlobalConfiguration.DISK_CACHE_PAGE_SIZE.getValueAsInteger();
}

final OByteBufferPool newInstance = new OByteBufferPool(bufferSize * 1024);
final OByteBufferPool newInstance = new OByteBufferPool(bufferSize * 1024);
if (INSTANCE_HOLDER.compareAndSet(null, newInstance)) {
return newInstance;
}
Expand All @@ -87,7 +86,7 @@ public static OByteBufferPool instance(OContextConfiguration contextConfiguratio
/**
* {@link ByteBuffer}s can not be extended, so to keep mapping between pointers and buffers we use concurrent hash map.
*/
private final ConcurrentHashMap<ByteBufferHolder, PointerHolder> bufferPointerMapping = new ConcurrentHashMap<>();
private final ConcurrentHashMap<OPointer, PointerTracker> pointerMapping = new ConcurrentHashMap<>();

/**
* Pool of already allocated pages.
Expand Down Expand Up @@ -133,7 +132,7 @@ public OByteBufferPool(int pageSize, ODirectMemoryAllocator allocator, int poolS
*
* @return Direct memory buffer instance.
*/
public ByteBuffer acquireDirect(boolean clear) {
public final OPointer acquireDirect(boolean clear) {
OPointer pointer;

pointer = pointersPool.poll();
Expand All @@ -151,39 +150,39 @@ public ByteBuffer acquireDirect(boolean clear) {
final ByteBuffer buffer = pointer.getNativeByteBuffer();
buffer.position(0);

bufferPointerMapping.put(wrapBuffer(buffer), wrapPointer(pointer));
return buffer;
if (TRACK) {
pointerMapping.put(pointer, generatePointer());
}

return pointer;
}

/**
* Put buffer which is not used any more back to the pool or frees direct memory if pool is full.
*
* @param buffer Not used instance of buffer.
* @param pointer Not used instance of buffer.
*
* @see OGlobalConfiguration#DIRECT_MEMORY_POOL_LIMIT
*/
public void release(ByteBuffer buffer) {
final PointerHolder holder = bufferPointerMapping.remove(wrapBuffer(buffer));

if (holder == null) {
throw new IllegalArgumentException(String.format("Buffer %X is not acquired", System.identityHashCode(buffer)));
public final void release(OPointer pointer) {
if (TRACK) {
pointerMapping.remove(pointer);
}

long poolSize = pointersPoolSize.incrementAndGet();
if (poolSize > this.poolSize) {
pointersPoolSize.decrementAndGet();
allocator.deallocate(holder.pointer);
allocator.deallocate(pointer);
} else {
pointersPool.add(holder.pointer);
pointersPool.add(pointer);
}

}

/**
* @inheritDoc
*/
@Override
public int getPoolSize() {
public final int getPoolSize() {
return pointersPoolSize.get();
}

Expand All @@ -193,10 +192,10 @@ public int getPoolSize() {
public void checkMemoryLeaks() {
boolean detected = false;
if (TRACK) {
for (Map.Entry<ByteBufferHolder, PointerHolder> entry : bufferPointerMapping.entrySet()) {
for (Map.Entry<OPointer, PointerTracker> entry : pointerMapping.entrySet()) {
OLogManager.instance()
.errorNoDb(this, "DIRECT-TRACK: unreleased direct memory buffer `%X` detected.", entry.getValue().allocation,
System.identityHashCode(entry.getKey().byteBuffer));
.errorNoDb(this, "DIRECT-TRACK: unreleased direct memory pointer `%X` detected.", entry.getValue().allocation,
System.identityHashCode(entry.getKey()));
detected = true;
}
}
Expand All @@ -215,68 +214,25 @@ public void clear() {
pointersPool.clear();
pointersPoolSize.set(0);

if (!TRACK && !bufferPointerMapping.isEmpty()) {
final String message =
"There are not released allocations in " + "ByteBufferPool which may indicate presence of memory leaks in database!!"
+ "Start JVM with system property" + OGlobalConfiguration.DIRECT_MEMORY_TRACK_MODE.getKey()
+ " = true for more details";

OLogManager.instance().warnNoDb(this, message);
}

for (PointerHolder holder : bufferPointerMapping.values()) {
allocator.deallocate(holder.pointer);
}

bufferPointerMapping.clear();
}

/**
* Holder which is used to compare byte buffers by object's identity not by content
*/
private static final class ByteBufferHolder {
private final ByteBuffer byteBuffer;

ByteBufferHolder(ByteBuffer byteBuffer) {
this.byteBuffer = byteBuffer;
}

@Override
public int hashCode() {
return System.identityHashCode(byteBuffer);
for (OPointer pointer : pointerMapping.keySet()) {
allocator.deallocate(pointer);
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof ByteBufferHolder))
return false;

return ((ByteBufferHolder) obj).byteBuffer == this.byteBuffer;
}
pointerMapping.clear();
}

/**
* Holder which contains direct memory pointer and if memory tracking is enabled stack trace for the first allocation.
* Holder which contains if memory tracking is enabled stack trace for the first allocation.
*/
private static final class PointerHolder {
private final OPointer pointer;
private static final class PointerTracker {
private final Exception allocation;

PointerHolder(OPointer pointer, Exception allocation) {
this.pointer = pointer;
PointerTracker(Exception allocation) {
this.allocation = allocation;
}
}

private ByteBufferHolder wrapBuffer(ByteBuffer byteBuffer) {
return new ByteBufferHolder(byteBuffer);
}

private PointerHolder wrapPointer(OPointer pointer) {
if (TRACK) {
return new PointerHolder(pointer, new Exception());
} else {
return new PointerHolder(pointer, null);
}
private PointerTracker generatePointer() {
return new PointerTracker(new Exception());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
import java.nio.ByteBuffer;
import java.util.Objects;

public class OPointer {
private final Pointer pointer;
private final int size;
public final class OPointer {
private final Pointer pointer;
private final int size;
private ByteBuffer byteBuffer;

public OPointer(Pointer pointer, int size) {
OPointer(Pointer pointer, int size) {
this.pointer = pointer;
this.size = size;
}
Expand All @@ -19,7 +20,12 @@ public void clear() {
}

public ByteBuffer getNativeByteBuffer() {
return pointer.getByteBuffer(0, size);
if (byteBuffer != null) {
return byteBuffer;
}

byteBuffer = pointer.getByteBuffer(0, size);
return byteBuffer;
}

Pointer getNativePointer() {
Expand Down
38 changes: 38 additions & 0 deletions core/src/main/java/com/orientechnologies/common/util/OQuarto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.orientechnologies.common.util;

import java.util.Objects;

public final class OQuarto<T1, T2, T3, T4> {
public final T1 one;
public final T2 two;
public final T3 three;
public final T4 four;

public OQuarto(T1 one, T2 two, T3 three, T4 four) {
this.one = one;
this.two = two;
this.three = three;
this.four = four;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
OQuarto<?, ?, ?, ?> oQuarto = (OQuarto<?, ?, ?, ?>) o;
return Objects.equals(one, oQuarto.one) && Objects.equals(two, oQuarto.two) && Objects.equals(three, oQuarto.three) && Objects
.equals(four, oQuarto.four);
}

@Override
public int hashCode() {
return Objects.hash(one, two, three, four);
}

@Override
public String toString() {
return "OQuarto{" + "one=" + one + ", two=" + two + ", three=" + three + ", four=" + four + '}';
}
}
Loading

0 comments on commit 23e878d

Please sign in to comment.