Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/db/ChunkCache.java')
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/db/ChunkCache.java139
1 files changed, 139 insertions, 0 deletions
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/db/ChunkCache.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/db/ChunkCache.java
new file mode 100644
index 000000000..1cd3736d8
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/db/ChunkCache.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2016 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Markus Schorn - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.nd.db;
+
+public final class ChunkCache {
+ private static ChunkCache sSharedInstance= new ChunkCache();
+
+ private Chunk[] fPageTable;
+ private boolean fTableIsFull;
+ private int fPointer;
+
+ public static ChunkCache getSharedInstance() {
+ return sSharedInstance;
+ }
+
+ public ChunkCache() {
+ this(5 * 1024 * 1024);
+ }
+
+ public ChunkCache(long maxSize) {
+ this.fPageTable= new Chunk[computeLength(maxSize)];
+ }
+
+ public synchronized void add(Chunk chunk, boolean locked) {
+ if (locked) {
+ chunk.fLocked= true;
+ }
+ if (chunk.fCacheIndex >= 0) {
+ chunk.fCacheHitFlag= true;
+ return;
+ }
+ if (this.fTableIsFull) {
+ evictChunk();
+ chunk.fCacheIndex= this.fPointer;
+ this.fPageTable[this.fPointer]= chunk;
+ } else {
+ chunk.fCacheIndex= this.fPointer;
+ this.fPageTable[this.fPointer]= chunk;
+
+ this.fPointer++;
+ if (this.fPointer == this.fPageTable.length) {
+ this.fPointer= 0;
+ this.fTableIsFull= true;
+ }
+ }
+ }
+
+ /**
+ * Evicts a chunk from the page table and the chunk table.
+ * After this method returns, {@link #fPointer} will contain
+ * the index of the evicted chunk within the page table.
+ */
+ private void evictChunk() {
+ /*
+ * Use the CLOCK algorithm to determine which chunk to evict.
+ * i.e., if the chunk in the current slot of the page table has been
+ * recently referenced (i.e. the reference flag is set), unset the
+ * reference flag and move to the next slot. Otherwise, evict the
+ * chunk in the current slot.
+ */
+ while (true) {
+ Chunk chunk = this.fPageTable[this.fPointer];
+ if (chunk.fCacheHitFlag) {
+ chunk.fCacheHitFlag= false;
+ this.fPointer= (this.fPointer + 1) % this.fPageTable.length;
+ } else {
+ chunk.fDatabase.releaseChunk(chunk);
+ chunk.fCacheIndex= -1;
+ this.fPageTable[this.fPointer] = null;
+ return;
+ }
+ }
+ }
+
+ public synchronized void remove(Chunk chunk) {
+ final int idx= chunk.fCacheIndex;
+ if (idx >= 0) {
+ if (this.fTableIsFull) {
+ this.fPointer= this.fPageTable.length-1;
+ this.fTableIsFull= false;
+ } else {
+ this.fPointer--;
+ }
+ chunk.fCacheIndex= -1;
+ final Chunk move= this.fPageTable[this.fPointer];
+ this.fPageTable[idx]= move;
+ move.fCacheIndex= idx;
+ this.fPageTable[this.fPointer]= null;
+ }
+ }
+
+ /**
+ * Returns the maximum size of the chunk cache in bytes.
+ */
+ public synchronized long getMaxSize() {
+ return (long) this.fPageTable.length * Database.CHUNK_SIZE;
+ }
+
+ /**
+ * Clears the page table and changes it to hold chunks with
+ * maximum total memory of <code>maxSize</code>.
+ * @param maxSize the total size of the chunks in bytes.
+ */
+ public synchronized void setMaxSize(long maxSize) {
+ final int newLength= computeLength(maxSize);
+ final int oldLength= this.fTableIsFull ? this.fPageTable.length : this.fPointer;
+ if (newLength > oldLength) {
+ Chunk[] newTable= new Chunk[newLength];
+ System.arraycopy(this.fPageTable, 0, newTable, 0, oldLength);
+ this.fTableIsFull= false;
+ this.fPointer= oldLength;
+ this.fPageTable= newTable;
+ } else {
+ for (int i= newLength; i < oldLength; i++) {
+ final Chunk chunk= this.fPageTable[i];
+ chunk.fDatabase.releaseChunk(chunk);
+ chunk.fCacheIndex= -1;
+ }
+ Chunk[] newTable= new Chunk[newLength];
+ System.arraycopy(this.fPageTable, 0, newTable, 0, newLength);
+ this.fTableIsFull= true;
+ this.fPointer= 0;
+ this.fPageTable= newTable;
+ }
+ }
+
+ private int computeLength(long maxSize) {
+ long maxLength= Math.min(maxSize / Database.CHUNK_SIZE, Integer.MAX_VALUE);
+ return Math.max(1, (int) maxLength);
+ }
+}

Back to the top