Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2017 JanusGraph Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.janusgraph.diskstorage.cache;
import org.janusgraph.diskstorage.BackendException;
import org.janusgraph.diskstorage.Entry;
import org.janusgraph.diskstorage.EntryList;
import org.janusgraph.diskstorage.StaticBuffer;
import org.janusgraph.diskstorage.keycolumnvalue.*;
import org.janusgraph.diskstorage.keycolumnvalue.cache.CacheTransaction;
import org.janusgraph.diskstorage.keycolumnvalue.cache.KCVSCache;
import org.janusgraph.diskstorage.keycolumnvalue.inmemory.InMemoryStoreManager;
import org.janusgraph.diskstorage.util.BufferUtil;
import org.janusgraph.diskstorage.util.StandardBaseTransactionConfig;
import org.janusgraph.diskstorage.util.StaticArrayEntry;
import org.janusgraph.diskstorage.util.WriteByteBuffer;
import org.janusgraph.diskstorage.util.time.TimestampProvider;
import org.janusgraph.diskstorage.util.time.TimestampProviders;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Matthias Broecheler ([email protected])
*/
public abstract class KCVSCacheTest {
public static final String STORE_NAME = "store";
public static final TimestampProvider times = TimestampProviders.MICRO;
public static final Duration MAX_WRITE_TIME = Duration.ofMillis(100);
public KeyColumnValueStoreManager storeManager;
public CounterKCVS store;
public KCVSCache cache;
@BeforeEach
public void setup() throws Exception {
storeManager = new InMemoryStoreManager();
store = new CounterKCVS(storeManager.openDatabase(STORE_NAME));
cache = getCache(store);
}
public abstract KCVSCache getCache(KeyColumnValueStore store);
public StoreTransaction getStoreTx() {
try {
return storeManager.beginTransaction(StandardBaseTransactionConfig.of(times));
} catch (BackendException se) {
throw new RuntimeException(se);
}
}
public CacheTransaction getCacheTx() {
return new CacheTransaction(getStoreTx(), storeManager, 1024, MAX_WRITE_TIME, false);
}
@AfterEach
public void shutdown() throws Exception {
cache.close();
storeManager.close();
}
public void loadStore(int numKeys, int numCols) {
StoreTransaction tx = getStoreTx();
try {
for (int i=1;i<=numKeys;i++) {
final List adds = new ArrayList<>(numCols);
for (int j=1;j<=numCols;j++) adds.add(getEntry(j,j));
store.mutate(BufferUtil.getIntBuffer(i),adds,KeyColumnValueStore.NO_DELETIONS,tx);
}
tx.commit();
} catch (BackendException e) {
throw new RuntimeException(e);
}
}
@Test
public void testSmallCache() throws Exception {
final int numKeys = 100, numCols = 10; //numCols must be greater than or equal to 10 as it is assummed below
final int repeats = 100, clearEvery = 20, numMulti = 10;
loadStore(numKeys,numCols);
//Repeatedly read from cache and clear in between
int calls = 0;
assertEquals(calls,store.getSliceCalls());
for (int t=0;t keys = new ArrayList<>();
for (int i=10;i<10+numMulti;i++) keys.add(BufferUtil.getIntBuffer(i));
Map result = cache.getSlice(keys,getQuery(4,9),tx);
assertEquals(keys.size(),result.size());
for (StaticBuffer key : keys) assertTrue(result.containsKey(key));
for (EntryList r : result.values()) {
assertEquals(5,r.size());
}
tx.commit();
assertEquals(calls,store.getSliceCalls());
}
store.resetCounter();
//Check invalidation
StaticBuffer key = BufferUtil.getIntBuffer(23);
final List keys = new ArrayList<>();
keys.add(key);
keys.add(BufferUtil.getIntBuffer(12));
keys.add(BufferUtil.getIntBuffer(5));
//Read
CacheTransaction tx = getCacheTx();
assertEquals(numCols,cache.getSlice(new KeySliceQuery(key,getQuery(0,numCols+1)),tx).size());
Map result = cache.getSlice(keys,getQuery(2,8),tx);
assertEquals(keys.size(),result.size());
assertEquals(6,result.get(key).size());
//Update
final List deletions = new ArrayList<>(numCols/2);
for (int j=1;j<=numCols;j=j+2) deletions.add(getEntry(j,j));
cache.mutateEntries(key, KeyColumnValueStore.NO_ADDITIONS, deletions, tx);
tx.commit();
assertEquals(2,store.getSliceCalls());
//Ensure updates are correctly read
tx = getCacheTx();
assertEquals(numCols/2,cache.getSlice(new KeySliceQuery(key,getQuery(0,numCols+1)),tx).size());
result = cache.getSlice(keys,getQuery(2,8),tx);
assertEquals(keys.size(),result.size());
assertEquals(3,result.get(key).size());
tx.commit();
assertEquals(4,store.getSliceCalls());
}
public static KeySliceQuery getQuery(int key, int startCol, int endCol) {
return new KeySliceQuery(BufferUtil.getIntBuffer(key),getQuery(startCol, endCol));
}
public static SliceQuery getQuery(int startCol, int endCol) {
return new SliceQuery(BufferUtil.getIntBuffer(startCol),BufferUtil.getIntBuffer(endCol));
}
public static Entry getEntry(int col, int val) {
return new StaticArrayEntry(new WriteByteBuffer(4 * 2).putInt(col).putInt(val).getStaticBuffer(), 4);
}
public static class CounterKCVS implements KeyColumnValueStore {
private final KeyColumnValueStore store;
private final AtomicLong getSliceCounter;
public CounterKCVS(KeyColumnValueStore store) {
this.store = store;
getSliceCounter = new AtomicLong(0);
}
public long getSliceCalls() {
return getSliceCounter.get();
}
public void resetCounter() {
getSliceCounter.set(0);
}
@Override
public EntryList getSlice(KeySliceQuery query, StoreTransaction txh) throws BackendException {
getSliceCounter.incrementAndGet();
return store.getSlice(query,txh);
}
@Override
public Map getSlice(List keys, SliceQuery query, StoreTransaction txh) throws BackendException {
getSliceCounter.incrementAndGet();
return store.getSlice(keys,query,txh);
}
@Override
public void mutate(StaticBuffer key, List additions, List deletions, StoreTransaction txh) throws BackendException {
store.mutate(key,additions,deletions,txh);
}
@Override
public void acquireLock(StaticBuffer key, StaticBuffer column, StaticBuffer expectedValue, StoreTransaction txh) throws BackendException {
store.acquireLock(key,column,expectedValue,txh);
}
@Override
public KeyIterator getKeys(KeyRangeQuery query, StoreTransaction txh) throws BackendException {
return store.getKeys(query,txh);
}
@Override
public KeyIterator getKeys(SliceQuery query, StoreTransaction txh) throws BackendException {
return store.getKeys(query,txh);
}
@Override
public String getName() {
return store.getName();
}
@Override
public void close() throws BackendException {
store.close();
}
}
}