DeltaBaseCache.java
- /*
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- package org.eclipse.jgit.internal.storage.file;
- import java.lang.ref.SoftReference;
- import org.eclipse.jgit.storage.file.WindowCacheConfig;
- class DeltaBaseCache {
- private static final int CACHE_SZ = 1024;
- static final SoftReference<Entry> DEAD;
- private static int hash(long position) {
- return (((int) position) << 22) >>> 22;
- }
- private static volatile int defaultMaxByteCount;
- private final int maxByteCount;
- private final Slot[] cache;
- private Slot lruHead;
- private Slot lruTail;
- private int openByteCount;
- static {
- DEAD = new SoftReference<>(null);
- reconfigure(new WindowCacheConfig());
- }
- static void reconfigure(WindowCacheConfig cfg) {
- defaultMaxByteCount = cfg.getDeltaBaseCacheLimit();
- }
- DeltaBaseCache() {
- maxByteCount = defaultMaxByteCount;
- cache = new Slot[CACHE_SZ];
- }
- Entry get(Pack pack, long position) {
- Slot e = cache[hash(position)];
- if (e == null)
- return null;
- if (e.provider == pack && e.position == position) {
- final Entry buf = e.data.get();
- if (buf != null) {
- moveToHead(e);
- return buf;
- }
- }
- return null;
- }
- void store(final Pack pack, final long position,
- final byte[] data, final int objectType) {
- if (data.length > maxByteCount)
- return; // Too large to cache.
- Slot e = cache[hash(position)];
- if (e == null) {
- e = new Slot();
- cache[hash(position)] = e;
- } else {
- clearEntry(e);
- }
- openByteCount += data.length;
- releaseMemory();
- e.provider = pack;
- e.position = position;
- e.sz = data.length;
- e.data = new SoftReference<>(new Entry(data, objectType));
- moveToHead(e);
- }
- private void releaseMemory() {
- while (openByteCount > maxByteCount && lruTail != null) {
- final Slot currOldest = lruTail;
- final Slot nextOldest = currOldest.lruPrev;
- clearEntry(currOldest);
- currOldest.lruPrev = null;
- currOldest.lruNext = null;
- if (nextOldest == null)
- lruHead = null;
- else
- nextOldest.lruNext = null;
- lruTail = nextOldest;
- }
- }
- private void moveToHead(Slot e) {
- unlink(e);
- e.lruPrev = null;
- e.lruNext = lruHead;
- if (lruHead != null)
- lruHead.lruPrev = e;
- else
- lruTail = e;
- lruHead = e;
- }
- private void unlink(Slot e) {
- final Slot prev = e.lruPrev;
- final Slot next = e.lruNext;
- if (prev != null)
- prev.lruNext = next;
- if (next != null)
- next.lruPrev = prev;
- }
- private void clearEntry(Slot e) {
- openByteCount -= e.sz;
- e.provider = null;
- e.data = DEAD;
- e.sz = 0;
- }
- static class Entry {
- final byte[] data;
- final int type;
- Entry(byte[] aData, int aType) {
- data = aData;
- type = aType;
- }
- }
- private static class Slot {
- Slot lruPrev;
- Slot lruNext;
- Pack provider;
- long position;
- int sz;
- SoftReference<Entry> data = DEAD;
- }
- }