Skip to content

Commit bc7e9fa

Browse files
author
Gabriel Einsdorf
authored
Merge pull request #489 from knime-ip/fix-cached-cell
KNIPGuavaCacheService: Switch to String based cache
2 parents f5492e2 + 39b7286 commit bc7e9fa

9 files changed

Lines changed: 96 additions & 100 deletions

File tree

org.knime.knip.base/src/org/knime/knip/base/data/img/ImgPlusCell.java

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,13 @@
6565
import org.knime.core.data.filestore.FileStoreCell;
6666
import org.knime.knip.base.KNIMEKNIPPlugin;
6767
import org.knime.knip.base.data.CachedObjectAccess;
68-
import org.knime.knip.base.data.CachedObjectAccess.StreamSkipper;
6968
import org.knime.knip.base.data.FileStoreCellMetadata;
7069
import org.knime.knip.base.data.IntervalValue;
7170
import org.knime.knip.base.renderer.ThumbnailRenderer;
7271
import org.knime.knip.core.KNIPGateway;
7372
import org.knime.knip.core.awt.AWTImageTools;
7473
import org.knime.knip.core.awt.Real2GreyColorRenderer;
7574
import org.knime.knip.core.data.img.DefaultImgMetadata;
76-
import org.knime.knip.core.io.externalization.BufferedDataInputStream;
7775
import org.knime.knip.core.io.externalization.ExternalizerManager;
7876
import org.knime.knip.core.util.MinimaUtils;
7977
import org.scijava.Named;
@@ -107,6 +105,8 @@
107105
public class ImgPlusCell<T extends RealType<T>> extends FileStoreCell
108106
implements ImgPlusValue<T>, StringValue, IntervalValue {
109107

108+
private static final String IMG_PLUS_CELL_KEY = "IP";
109+
110110
/**
111111
* Type
112112
*
@@ -122,7 +122,7 @@ public class ImgPlusCell<T extends RealType<T>> extends FileStoreCell
122122
/**
123123
* UID
124124
*/
125-
private static final long serialVersionUID = 1L;
125+
private static final long serialVersionUID = 2L;
126126

127127
private FileStoreCellMetadata m_fileMetadata;
128128

@@ -158,19 +158,19 @@ protected ImgPlusCell(final Img<T> img, final ImgPlusMetadata metadata, final Fi
158158
tmpImg = ((WrappedImg<T>)tmpImg).getImg();
159159
}
160160

161-
m_imgAccess = new CachedObjectAccess<Img<T>>(fileStore, tmpImg);
161+
m_imgAccess = new CachedObjectAccess<>(fileStore, tmpImg);
162162

163163
final long[] dimensions = new long[img.numDimensions()];
164164
img.dimensions(dimensions);
165165

166-
m_metadataAccess = new CachedObjectAccess<ImgPlusCellMetadata>(fileStore,
166+
m_metadataAccess = new CachedObjectAccess<>(fileStore,
167167
new ImgPlusCellMetadata(
168168
MetadataUtil.copyImgPlusMetadata(metadata, new DefaultImgMetadata(dimensions.length)),
169169
img.size(), getMinFromImg(img), dimensions, img.firstElement().getClass(), null));
170170

171171
m_fileMetadata = new FileStoreCellMetadata(-1, false, null);
172172

173-
CACHE.put(this, this);
173+
CACHE.put(this.stringHashCode(), this);
174174
}
175175

176176
/**
@@ -241,7 +241,14 @@ private BufferedImage createThumbnail(final double factor) {
241241
*/
242242
@Override
243243
protected boolean equalsDataCell(final DataCell dc) {
244-
return dc.hashCode() == hashCode();
244+
if (dc instanceof ImgPlusCell) {
245+
ImgPlusCell dc2 = (ImgPlusCell)dc;
246+
if (dc2.getFileStore().getFile().equals(this.getFileStore().getFile())
247+
&& dc2.m_fileMetadata.getOffset() == this.m_fileMetadata.getOffset()) {
248+
return true;
249+
}
250+
}
251+
return false;
245252
}
246253

247254
/**
@@ -308,7 +315,7 @@ public synchronized ImgPlus<T> getImgPlus() {
308315
@Override
309316
public synchronized ImgPlus<T> getImgPlusCopy() {
310317
final ImgPlus<T> source = getImgPlus();
311-
final ImgPlus<T> dest = new ImgPlus<T>(source.copy());
318+
final ImgPlus<T> dest = new ImgPlus<>(source.copy());
312319

313320
MetadataUtil.copyImgPlusMetadata(source, dest);
314321

@@ -461,7 +468,7 @@ public synchronized Image getThumbnail(final RenderingHints renderingHints) {
461468
tmp = new ImgPlusCellMetadata(tmp.getMetadata(), tmp.getSize(), tmp.getMinimum(),
462469
tmp.getDimensions(), tmp.getPixelType(), createThumbnail(height / fullHeight)));
463470
// update cached object
464-
CACHE.put(this, this);
471+
CACHE.put(this.stringHashCode(), this);
465472
}
466473
return tmp.getThumbnail();
467474
}
@@ -482,7 +489,11 @@ private int getThumbnailWidth(final int height) {
482489
*/
483490
@Override
484491
public int hashCode() {
485-
return (int)(getFileStore().getFile().hashCode() + (31 * m_fileMetadata.getOffset()));
492+
return stringHashCode().hashCode();
493+
}
494+
495+
private String stringHashCode() {
496+
return IMG_PLUS_CELL_KEY + getFileStore().getFile().getName() + m_fileMetadata.getOffset();
486497
}
487498

488499
/**
@@ -517,28 +528,20 @@ protected synchronized void load(final DataInput input) throws IOException {
517528
protected void postConstruct() {
518529

519530
@SuppressWarnings("unchecked")
520-
final ImgPlusCell<T> tmp = (ImgPlusCell<T>)CACHE.get(this);
531+
final ImgPlusCell<T> tmp = (ImgPlusCell<T>)CACHE.get(this.stringHashCode());
521532

522533
if (tmp == null) {
523-
m_metadataAccess =
524-
new CachedObjectAccess<ImgPlusCellMetadata>(getFileStore(), null, m_fileMetadata.getOffset(), null);
525-
526-
m_imgAccess = new CachedObjectAccess<Img<T>>(getFileStore(), null, m_fileMetadata.getOffset(),
527-
new StreamSkipper() {
528-
/**
529-
* {@inheritDoc}
530-
*/
531-
@Override
532-
public void skip(final BufferedDataInputStream in) {
533-
try {
534-
m_metadataAccess.setObject(ExternalizerManager.read(in));
535-
} catch (Exception e) {
536-
throw new RuntimeException(e);
537-
}
538-
}
539-
});
540-
541-
CACHE.put(this, this);
534+
m_metadataAccess = new CachedObjectAccess<>(getFileStore(), null, m_fileMetadata.getOffset(), null);
535+
536+
m_imgAccess = new CachedObjectAccess<>(getFileStore(), null, m_fileMetadata.getOffset(), in -> {
537+
try {
538+
m_metadataAccess.setObject(ExternalizerManager.read(in));
539+
} catch (Exception e) {
540+
throw new RuntimeException(e);
541+
}
542+
});
543+
544+
CACHE.put(this.stringHashCode(), this);
542545
} else {
543546
m_metadataAccess = tmp.m_metadataAccess;
544547
m_imgAccess = tmp.m_imgAccess;

org.knime.knip.base/src/org/knime/knip/base/data/labeling/LabelingCell.java

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
import org.knime.core.data.filestore.FileStoreCell;
6565
import org.knime.knip.base.KNIMEKNIPPlugin;
6666
import org.knime.knip.base.data.CachedObjectAccess;
67-
import org.knime.knip.base.data.CachedObjectAccess.StreamSkipper;
6867
import org.knime.knip.base.data.FileStoreCellMetadata;
6968
import org.knime.knip.base.data.IntervalValue;
7069
import org.knime.knip.base.renderer.ThumbnailRenderer;
@@ -75,7 +74,6 @@
7574
import org.knime.knip.core.awt.labelingcolortable.RandomMissingColorHandler;
7675
import org.knime.knip.core.data.LabelingView;
7776
import org.knime.knip.core.data.img.LabelingMetadata;
78-
import org.knime.knip.core.io.externalization.BufferedDataInputStream;
7977
import org.knime.knip.core.io.externalization.ExternalizerManager;
8078
import org.scijava.Named;
8179
import org.scijava.cache.CacheService;
@@ -102,6 +100,8 @@
102100
*/
103101
public class LabelingCell<L> extends FileStoreCell implements LabelingValue<L>, StringValue, IntervalValue {
104102

103+
private static final String LABELING_CELL_KEY = "LC";
104+
105105
/**
106106
* ObjectRepository
107107
*/
@@ -110,7 +110,7 @@ public class LabelingCell<L> extends FileStoreCell implements LabelingValue<L>,
110110
/**
111111
* UID
112112
*/
113-
private static final long serialVersionUID = 1L;
113+
private static final long serialVersionUID = 2L;
114114

115115
/**
116116
* Convenience access method for DataType.getType(ImageCell.class).
@@ -154,12 +154,12 @@ protected LabelingCell(final RandomAccessibleInterval<LabelingType<L>> labeling,
154154
super(fileStore);
155155
final long[] dimensions = new long[labeling.numDimensions()];
156156
labeling.dimensions(dimensions);
157-
m_metadataAccess = new CachedObjectAccess<LabelingCellMetadata>(fileStore,
157+
m_metadataAccess = new CachedObjectAccess<>(fileStore,
158158
new LabelingCellMetadata(metadata, Views.iterable(labeling).size(), dimensions, null));
159-
m_labelingAccess = new CachedObjectAccess<>(fileStore, new LabelingView<L>(labeling));
159+
m_labelingAccess = new CachedObjectAccess<>(fileStore, new LabelingView<>(labeling));
160160
m_fileMetadata = new FileStoreCellMetadata(-1, false, null);
161161

162-
CACHE.put(this, this);
162+
CACHE.put(this.stringHashCode(), this);
163163

164164
}
165165

@@ -173,7 +173,7 @@ private BufferedImage createThumbnail(final double factor) {
173173
}
174174

175175
// set the labeling mapping
176-
final ColorLabelingRenderer<L> rend = new ColorLabelingRenderer<L>();
176+
final ColorLabelingRenderer<L> rend = new ColorLabelingRenderer<>();
177177
rend.setLabelMapping(lab2d.randomAccess().get().getMapping());
178178
int i = 0;
179179
final long[] max = new long[lab2d.numDimensions()];
@@ -202,7 +202,14 @@ private BufferedImage createThumbnail(final double factor) {
202202
*/
203203
@Override
204204
protected boolean equalsDataCell(final DataCell dc) {
205-
return dc.hashCode() == hashCode();
205+
if (dc instanceof LabelingCell) {
206+
LabelingCell dc2 = (LabelingCell)dc;
207+
if (dc2.getFileStore().getFile().equals(this.getFileStore().getFile())
208+
&& dc2.m_fileMetadata.getOffset() == this.m_fileMetadata.getOffset()) {
209+
return true;
210+
}
211+
}
212+
return false;
206213
}
207214

208215
/**
@@ -356,17 +363,21 @@ public synchronized Image getThumbnail(final RenderingHints renderingHints) {
356363
fullHeight = tmp.getDimensions()[1];
357364
}
358365
if ((tmp.getThumbnail() == null) || (tmp.getThumbnail().getHeight() != height)) {
359-
m_metadataAccess = new CachedObjectAccess<LabelingCellMetadata>(getFileStore(),
366+
m_metadataAccess = new CachedObjectAccess<>(getFileStore(),
360367
tmp = new LabelingCellMetadata(tmp.getLabelingMetadata(), tmp.getSize(), tmp.getDimensions(),
361368
createThumbnail(height / fullHeight)));
362369
// update cached object
363-
CACHE.put(this, this);
370+
CACHE.put(this.stringHashCode(), this);
364371
}
365372
return tmp.getThumbnail();
366373
}
367374

368375
}
369376

377+
private String stringHashCode() {
378+
return LABELING_CELL_KEY + getFileStore().getFile().getName() + m_fileMetadata.getOffset();
379+
}
380+
370381
private int getThumbnailWidth(final int height) {
371382
final LabelingCellMetadata tmp = m_metadataAccess.get();
372383
if (tmp.getDimensions().length == 1) {
@@ -381,7 +392,7 @@ private int getThumbnailWidth(final int height) {
381392
*/
382393
@Override
383394
public int hashCode() {
384-
return (int)(getFileStore().getFile().hashCode() + (31 * m_fileMetadata.getOffset()));
395+
return stringHashCode().hashCode();
385396
}
386397

387398
/**
@@ -415,27 +426,20 @@ protected synchronized void load(final DataInput input) throws IOException {
415426
protected void postConstruct() {
416427

417428
@SuppressWarnings("unchecked")
418-
final LabelingCell<L> tmp = (LabelingCell<L>)CACHE.get(this);
429+
final LabelingCell<L> tmp = (LabelingCell<L>)CACHE.get(this.stringHashCode());
419430

420431
if (tmp == null) {
421432
// Creates empty CachedObjectAccesses which know how to reconstruct the managed objects.
422433
m_metadataAccess = new CachedObjectAccess<>(getFileStore(), null, m_fileMetadata.getOffset(), null);
423-
m_labelingAccess =
424-
new CachedObjectAccess<>(getFileStore(), null, m_fileMetadata.getOffset(), new StreamSkipper() {
425-
/**
426-
* {@inheritDoc}
427-
*/
428-
@Override
429-
public void skip(final BufferedDataInputStream in) {
430-
try {
431-
m_metadataAccess.setObject(ExternalizerManager.read(in));
432-
} catch (Exception e) {
433-
throw new RuntimeException(e);
434-
}
435-
}
436-
});
437-
438-
CACHE.put(this, this);
434+
m_labelingAccess = new CachedObjectAccess<>(getFileStore(), null, m_fileMetadata.getOffset(), in -> {
435+
try {
436+
m_metadataAccess.setObject(ExternalizerManager.read(in));
437+
} catch (Exception e) {
438+
throw new RuntimeException(e);
439+
}
440+
});
441+
442+
CACHE.put(this.stringHashCode(), this);
439443
} else {
440444
m_labelingAccess = tmp.m_labelingAccess;
441445
m_metadataAccess = tmp.m_metadataAccess;

org.knime.knip.core/src/org/knime/knip/core/KNIPGuavaCacheService.java

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,50 +66,44 @@
6666
/**
6767
* {@link CacheService} implementation wrapping a guava {@link Cache}.
6868
*/
69-
@Plugin(type = Service.class, priority = Priority.HIGH_PRIORITY)
69+
@Plugin(type = Service.class, priority = Priority.HIGH)
7070
public class KNIPGuavaCacheService extends AbstractService implements CacheService {
7171

7272
@Parameter
7373
private MemoryService ms;
7474

75-
private Cache<Integer, Object> cache;
75+
private Cache<String, Object> cache;
7676

7777
private final Semaphore gate = new Semaphore(1);
7878

7979
@Override
8080
public void initialize() {
8181
//FIXME: Make parameters accessible via image processing config at some point
82-
cache = CacheBuilder.newBuilder().maximumSize(1000).weakValues()
83-
.build();
84-
85-
ms.register(new MemoryAlertable() {
86-
87-
@Override
88-
public void memoryLow() {
89-
if (gate.tryAcquire()) {
90-
cache.invalidateAll();
91-
cache.cleanUp();
92-
gate.release();
93-
}
82+
cache = CacheBuilder.newBuilder().maximumSize(1000).weakValues().build();
9483

84+
ms.register(() -> {
85+
if (gate.tryAcquire()) {
86+
cache.invalidateAll();
87+
cache.cleanUp();
88+
gate.release();
9589
}
9690
});
9791
}
9892

9993
@Override
10094
public void put(final Object key, final Object value) {
101-
cache.put(key.hashCode(), value);
95+
cache.put(key.toString(), value);
10296
}
10397

10498
@Override
10599
public Object get(final Object key) {
106-
return cache.getIfPresent(key.hashCode());
100+
return cache.getIfPresent(key.toString());
107101
}
108102

109103
@SuppressWarnings("unchecked")
110104
@Override
111105
public <V> V get(final Object key, final Callable<V> valueLoader) throws ExecutionException {
112-
return (V)cache.get(key.hashCode(), valueLoader);
106+
return (V)cache.get(key.toString(), valueLoader);
113107
}
114108

115109
/**

org.knime.knip.core/src/org/knime/knip/core/ui/imgviewer/panels/providers/AWTImageProvider.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ public class AWTImageProvider extends HiddenViewerComponent {
9292

9393
private static final NodeLogger LOGGER = NodeLogger.getLogger(AWTImageProvider.class);
9494

95+
private static final String AWT_IMAGE_PROVIDE_KEY = "AP";
96+
9597
/**
9698
* Converts DoubleType to FloatType and preserves other types. This can be used to ensure that images (after calling
9799
* the method) are FloatType or smaller and thus can be normalized. However type safety is broken!
@@ -158,13 +160,13 @@ private void renderAndCacheImg() {
158160
Image awtImage = null;
159161
if (m_isCachingActive) {
160162

161-
final int hash = (31 + m_renderUnit.generateHashCode());
162-
awtImage = (Image)KNIPGateway.cache().get(hash);
163+
final String hashKey = AWT_IMAGE_PROVIDE_KEY + m_renderUnit.generateHashCode();
164+
awtImage = (Image)KNIPGateway.cache().get(hashKey);
163165

164166
if (awtImage == null) {
165167
awtImage = m_renderUnit.createImage();
166168

167-
KNIPGateway.cache().put(hash, awtImage);
169+
KNIPGateway.cache().put(hashKey, awtImage);
168170
LOGGER.info("Caching Image ...");
169171
} else {
170172
LOGGER.info("Image from Cache ...");

org.knime.knip.features/src/org/knime/knip/features/sets/optimizedfeatures/KNIPCachedOpEnvironment.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@
5959
*/
6060
public class KNIPCachedOpEnvironment extends CustomOpEnvironment {
6161

62-
@Parameter
63-
private CacheService cs;
6462
private Collection<Class<?>> ignored;
6563

6664
public KNIPCachedOpEnvironment(final OpEnvironment parent, final Collection<? extends OpInfo> prioritizedInfos,

0 commit comments

Comments
 (0)