Skip to content

Commit

Permalink
wire in support for compositebinarystores and unit test it
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed Apr 26, 2013
1 parent 6766daf commit 19d44cb
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 45 deletions.
Expand Up @@ -18,6 +18,9 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;
Expand All @@ -40,6 +43,7 @@
import org.infinispan.loaders.decorators.ChainingCacheStore;
import org.modeshape.jcr.value.BinaryKey;
import org.modeshape.jcr.value.binary.BinaryStore;
import org.modeshape.jcr.value.binary.CompositeBinaryStore;
import org.modeshape.jcr.value.binary.infinispan.InfinispanBinaryStore;
import org.slf4j.Logger;

Expand Down Expand Up @@ -88,14 +92,14 @@ public class LowLevelStorageService {
throws RepositoryException {
logger.debug("Checking resource: " + resource.getPath());

return transformBinaryBlobs(resource, ServiceHelpers
.getCheckCacheFixityFunction(digest, dsChecksum, dsSize));
return transformLowLevelCacheEntries(resource, ServiceHelpers
.getCheckCacheFixityFunction(digest, dsChecksum, dsSize));
}

public <T> Collection<T> transformBinaryBlobs(final Node resource,
final Function<LowLevelCacheEntry, T> transform)
public <T> Collection<T> transformLowLevelCacheEntries(final Node resource,
final Function<LowLevelCacheEntry, T> transform)
throws RepositoryException {
return transform(getBinaryBlobs(resource), transform);
return transform(getLowLevelCacheEntries(resource), transform);
}

/**
Expand All @@ -104,10 +108,10 @@ public <T> Collection<T> transformBinaryBlobs(final Node resource,
* @return a map of binary stores and input streams
* @throws RepositoryException
*/
public Set<LowLevelCacheEntry> getBinaryBlobs(final Node resource)
public Set<LowLevelCacheEntry> getLowLevelCacheEntries(final Node resource)
throws RepositoryException {

return getBinaryBlobs(getBinaryKey.apply(resource));
return getLowLevelCacheEntries(getBinaryKey.apply(resource));

}

Expand All @@ -116,49 +120,98 @@ public Set<LowLevelCacheEntry> getBinaryBlobs(final Node resource)
* @param key a Modeshape BinaryValue's key.
* @return a set of binary stores
*/
public Set<LowLevelCacheEntry> getBinaryBlobs(final BinaryKey key) {

final ImmutableSet.Builder<LowLevelCacheEntry> blobs = builder();
public Set<LowLevelCacheEntry> getLowLevelCacheEntries(final BinaryKey key) {

final BinaryStore store = getBinaryStore.apply(repo);

if (store == null) {
return blobs.build();
}
if (store == null) {
return new HashSet<LowLevelCacheEntry>();
}

// if we have an Infinispan store, it may have multiple stores (or cluster nodes)
if (store instanceof InfinispanBinaryStore) {
final InfinispanBinaryStore ispnStore =
(InfinispanBinaryStore) store;
return getLowLevelCacheEntriesFromStore(store, key);
}

//seems like we have to start it, not sure why.
ispnStore.start();
/**
*
* @param key a Modeshape BinaryValue's key.
* @return a set of binary stores
*/
public Set<LowLevelCacheEntry> getLowLevelCacheEntriesFromStore(final BinaryStore store, final BinaryKey key) {

for (final Cache<?, ?> c : ImmutableSet.copyOf(ispnStore
.getCaches())) {
if(store instanceof CompositeBinaryStore) {
return getLowLevelCacheEntriesFromStore((CompositeBinaryStore) store, key);

final CacheStore cacheStore = getCacheStore.apply(c);
} else if (store instanceof InfinispanBinaryStore) {
return getLowLevelCacheEntriesFromStore((InfinispanBinaryStore) store, key);

// A ChainingCacheStore indicates we (may) have multiple CacheStores at play
if (cacheStore instanceof ChainingCacheStore) {
final ChainingCacheStore chainingCacheStore =
(ChainingCacheStore) cacheStore;
// the stores are a map of the cache store and the configuration; i'm just throwing the configuration away..
for (final CacheStore s : chainingCacheStore.getStores()
.keySet()) {
blobs.add(new LowLevelCacheEntry(store, s, key));
}
} else {
// just a nice, simple infinispan cache.
blobs.add(new LowLevelCacheEntry(store, cacheStore, key));
}
}
} else {
blobs.add(new LowLevelCacheEntry(store, key));
}
} else {
final ImmutableSet.Builder<LowLevelCacheEntry> blobs = builder();
blobs.add(new LowLevelCacheEntry(store, key));
return blobs.build();
}

return blobs.build();
}
}

/**
*
* @param key a Modeshape BinaryValue's key.
* @return a set of binary stores
*/
protected Set<LowLevelCacheEntry> getLowLevelCacheEntriesFromStore(final CompositeBinaryStore compositeStore, final BinaryKey key) {

final ImmutableSet.Builder<LowLevelCacheEntry> blobs = builder();

Iterator<Map.Entry<String,BinaryStore>> it = compositeStore.getNamedStoreIterator();

while(it.hasNext()) {
BinaryStore bs = it.next().getValue();

if(bs.hasBinary(key)) {

final Set<LowLevelCacheEntry> binaryBlobs = getLowLevelCacheEntriesFromStore(bs, key);

for(LowLevelCacheEntry e : binaryBlobs) {
blobs.add(e);
}
}
}

return blobs.build();
}

/**
*
* @param key a Modeshape BinaryValue's key.
* @return a set of binary stores
*/
protected Set<LowLevelCacheEntry> getLowLevelCacheEntriesFromStore(final InfinispanBinaryStore ispnStore, final BinaryKey key) {

final ImmutableSet.Builder<LowLevelCacheEntry> blobs = builder();

//seems like we have to start it, not sure why.
ispnStore.start();

for (final Cache<?, ?> c : ImmutableSet.copyOf(ispnStore.getCaches())) {

final CacheStore cacheStore = getCacheStore.apply(c);

// A ChainingCacheStore indicates we (may) have multiple CacheStores at play
if (cacheStore instanceof ChainingCacheStore) {
final ChainingCacheStore chainingCacheStore =
(ChainingCacheStore) cacheStore;
// the stores are a map of the cache store and the configuration; i'm just throwing the configuration away..
for (final CacheStore s : chainingCacheStore.getStores()
.keySet()) {
blobs.add(new LowLevelCacheEntry(ispnStore, s, key));
}
} else {
// just a nice, simple infinispan cache.
blobs.add(new LowLevelCacheEntry(ispnStore, cacheStore, key));
}
}

return blobs.build();
}

@PostConstruct
public final void getSession() {
Expand Down
Expand Up @@ -87,7 +87,7 @@ public void testGetBinaryBlobs() throws Exception {
"testRepositoryContent");

final Iterator<LowLevelCacheEntry> inputStreamList =
lowLevelService.getBinaryBlobs(ds.getNode()).iterator();
lowLevelService.getLowLevelCacheEntries(ds.getNode()).iterator();

int i = 0;
while (inputStreamList.hasNext()) {
Expand Down
Expand Up @@ -88,7 +88,7 @@ private void tamperWithNode(final Node node) throws Exception {

logger.info("Tampering with node " + node.toString());
final Set<LowLevelCacheEntry> binaryBlobs =
lowLevelService.getBinaryBlobs(node);
lowLevelService.getLowLevelCacheEntries(node);

final Iterator<LowLevelCacheEntry> it = binaryBlobs.iterator();

Expand Down
Expand Up @@ -2,20 +2,25 @@
package org.fcrepo.services;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.spy;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.jcr.LoginException;
Expand All @@ -39,6 +44,7 @@
import org.junit.runner.RunWith;
import org.modeshape.jcr.value.BinaryKey;
import org.modeshape.jcr.value.binary.BinaryStore;
import org.modeshape.jcr.value.binary.CompositeBinaryStore;
import org.modeshape.jcr.value.binary.infinispan.InfinispanBinaryStore;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
Expand Down Expand Up @@ -105,7 +111,7 @@ public void testTransformBinaryBlobs() throws RepositoryException {
mock(Function.class);
when(testFunc.apply(any(LowLevelCacheEntry.class))).thenReturn("bar");
final Collection<String> actual =
testObj.transformBinaryBlobs(mockNode, testFunc);
testObj.transformLowLevelCacheEntries(mockNode, testFunc);
assertEquals("bar", actual.iterator().next());
verify(testFunc).apply(any(LowLevelCacheEntry.class));
}
Expand All @@ -125,7 +131,7 @@ public void testGetBinaryBlobs() throws RepositoryException {
testObj.setGetBinaryStore(mockStoreFunc);
testObj.setGetBinaryKey(mockKeyFunc);
testObj.setRepository(mockRepo);
final Set<LowLevelCacheEntry> actual = testObj.getBinaryBlobs(mockNode);
final Set<LowLevelCacheEntry> actual = testObj.getLowLevelCacheEntries(mockNode);
assertEquals("foo", actual.iterator().next().getExternalIdentifier());
}

Expand Down Expand Up @@ -168,6 +174,98 @@ public void testSetRepository() throws LoginException, RepositoryException {
verify(mockAnotherRepo).login();
}

@Test
public void shouldRetrieveLowLevelCacheEntryForDefaultBinaryStore() throws RepositoryException {
final BinaryKey key = new BinaryKey("key-123");
final GetBinaryStore mockStoreFunc = mock(GetBinaryStore.class);
final Repository mockRepo = mock(Repository.class);
final BinaryStore mockStore = mock(BinaryStore.class);
when(mockStoreFunc.apply(mockRepo)).thenReturn(mockStore);

final LowLevelStorageService testObj = spy(new LowLevelStorageService());
testObj.setRepository(mockRepo);
testObj.setGetBinaryStore(mockStoreFunc);
final Set<LowLevelCacheEntry> entries = testObj.getLowLevelCacheEntries(key);
verify(testObj, times(1)).getLowLevelCacheEntriesFromStore(mockStore, key);
}

@Test
public void shouldRetrieveLowLevelCacheStoresForBinaryKey() throws RepositoryException {

final BinaryStore mockStore = mock(BinaryStore.class);

final LowLevelStorageService testObj = new LowLevelStorageService();

final Set<LowLevelCacheEntry> entries = testObj.getLowLevelCacheEntriesFromStore(mockStore, new BinaryKey("key-123"));

assertEquals(1, entries.size());

assertTrue("does not contain our entry", entries.contains(new LowLevelCacheEntry(mockStore, new BinaryKey("key-123"))));
}


@Test
public void shouldRetrieveLowLevelCacheStoresForCompositeStore() throws RepositoryException {

final Cache ispnCache1 = mock(Cache.class);
final Cache ispnCache2 = mock(Cache.class);
final CacheStore ispnCacheStore1 = mock(CacheStore.class);
final CacheStore ispnCacheStore2 = mock(CacheStore.class);
final BinaryStore plainBinaryStore = mock(BinaryStore.class);
final BinaryStore plainBinaryStore2 = mock(BinaryStore.class);


final GetCacheStore mockCacheStoreFunc = mock(GetCacheStore.class);
when(mockCacheStoreFunc.apply(ispnCache1)).thenReturn(ispnCacheStore1);
when(mockCacheStoreFunc.apply(ispnCache2)).thenReturn(ispnCacheStore2);

final CompositeBinaryStore mockStore = mock(CompositeBinaryStore.class);

final HashMap<String, BinaryStore> map = new HashMap<String, BinaryStore>();
final List<Cache<?, ?>> caches = new ArrayList<Cache<?, ?>>();
caches.add(ispnCache1);
caches.add(ispnCache2);

map.put("default", plainBinaryStore);
map.put("a", plainBinaryStore2);
final InfinispanBinaryStore infinispanBinaryStore = mock(InfinispanBinaryStore.class);
when(infinispanBinaryStore.getCaches()).thenReturn(caches);
map.put("b", infinispanBinaryStore);
when(mockStore.getNamedStoreIterator()).thenReturn(map.entrySet().iterator());

final LowLevelStorageService testObj = new LowLevelStorageService();
testObj.setGetCacheStore(mockCacheStoreFunc);

final BinaryKey key = new BinaryKey("key-123");
when(plainBinaryStore.hasBinary(key)).thenReturn(true);
when(plainBinaryStore2.hasBinary(key)).thenReturn(false);
when(infinispanBinaryStore.hasBinary(key)).thenReturn(true);
final Set<LowLevelCacheEntry> entries = testObj.getLowLevelCacheEntriesFromStore(mockStore, key);

assertEquals(3, entries.size());

assertTrue(entries.contains(new LowLevelCacheEntry(plainBinaryStore, key)));
assertTrue(!entries.contains(new LowLevelCacheEntry(plainBinaryStore2, key)));
assertTrue(entries.contains(new LowLevelCacheEntry(infinispanBinaryStore, ispnCacheStore1, key)));
assertTrue(entries.contains(new LowLevelCacheEntry(infinispanBinaryStore, ispnCacheStore2, key)));


}

@Test
public void shouldReturnAnEmptySetForMissingBinaryStore() throws RepositoryException {

final GetBinaryStore mockStoreFunc = mock(GetBinaryStore.class);
final Repository mockRepo = mock(Repository.class);
when(mockStoreFunc.apply(mockRepo)).thenReturn(null);

final LowLevelStorageService testObj = new LowLevelStorageService();
testObj.setGetBinaryStore(mockStoreFunc);
final Set<LowLevelCacheEntry> entries = testObj.getLowLevelCacheEntries(new BinaryKey("key-123"));

assertEquals(0, entries.size());
}

@SuppressWarnings("unchecked")
@Test
public void testRunFixityAndFixProblems() throws RepositoryException,
Expand Down

0 comments on commit 19d44cb

Please sign in to comment.