diff options
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.java | 139 |
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); + } +} |