2 * Copyright (C) 2008 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org
.spearce
.jgit
.lib
;
19 import java
.lang
.ref
.SoftReference
;
21 class UnpackedObjectCache
{
22 private static final int CACHE_SZ
= 256;
24 private static final int MB
= 1024 * 1024;
26 private static final SoftReference
<Entry
> DEAD
;
28 private static int hash(final WindowedFile pack
, final long position
) {
29 int h
= pack
.hash
+ (int) position
;
35 private static int maxByteCount
;
37 private static final Slot
[] cache
;
39 private static Slot lruHead
;
41 private static Slot lruTail
;
43 private static int openByteCount
;
46 DEAD
= new SoftReference
<Entry
>(null);
47 maxByteCount
= 10 * MB
;
49 cache
= new Slot
[CACHE_SZ
];
50 for (int i
= 0; i
< CACHE_SZ
; i
++)
51 cache
[i
] = new Slot();
54 static synchronized void reconfigure(final int dbLimit
) {
55 if (maxByteCount
!= dbLimit
) {
56 maxByteCount
= dbLimit
;
61 static synchronized Entry
get(final WindowedFile pack
, final long position
) {
62 final Slot e
= cache
[hash(pack
, position
)];
63 if (e
.provider
== pack
&& e
.position
== position
) {
64 final Entry buf
= e
.data
.get();
73 static synchronized void store(final WindowedFile pack
,
74 final long position
, final byte[] data
, final int objectType
) {
75 if (data
.length
> maxByteCount
)
76 return; // Too large to cache.
78 final Slot e
= cache
[hash(pack
, position
)];
81 openByteCount
+= data
.length
;
85 e
.position
= position
;
86 e
.data
= new SoftReference
<Entry
>(new Entry(data
, objectType
));
90 private static void releaseMemory() {
91 while (openByteCount
> maxByteCount
&& lruTail
!= null) {
92 final Slot currOldest
= lruTail
;
93 final Slot nextOldest
= currOldest
.lruPrev
;
95 clearEntry(currOldest
);
96 currOldest
.lruPrev
= null;
97 currOldest
.lruNext
= null;
99 if (nextOldest
== null)
102 nextOldest
.lruNext
= null;
103 lruTail
= nextOldest
;
107 static synchronized void purge(final WindowedFile file
) {
108 for (final Slot e
: cache
) {
109 if (e
.provider
== file
) {
116 private static void moveToHead(final Slot e
) {
127 private static void unlink(final Slot e
) {
128 final Slot prev
= e
.lruPrev
;
129 final Slot next
= e
.lruNext
;
136 private static void clearEntry(final Slot e
) {
137 final Entry old
= e
.data
.get();
139 openByteCount
-= old
.data
.length
;
144 private UnpackedObjectCache() {
145 throw new UnsupportedOperationException();
153 Entry(final byte[] aData
, final int aType
) {
159 private static class Slot
{
164 WindowedFile provider
;
168 SoftReference
<Entry
> data
= DEAD
;