-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #386 from LiUSemWeb/385-optimized-persisted-cache-…
…for-cardinality-queries 385 optimized persisted cache for cardinality queries
- Loading branch information
Showing
19 changed files
with
1,957 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 29 additions & 1 deletion
30
...-base/src/main/java/se/liu/ida/hefquin/base/datastructures/impl/cache/CacheEntryBase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,45 @@ | ||
package se.liu.ida.hefquin.base.datastructures.impl.cache; | ||
|
||
public class CacheEntryBase<ObjectType> implements CacheEntry<ObjectType> | ||
import java.io.Serializable; | ||
import java.time.Instant; | ||
|
||
public class CacheEntryBase<ObjectType> implements CacheEntry<ObjectType>, Serializable | ||
{ | ||
private static final long serialVersionUID = 1L; | ||
protected final ObjectType obj; | ||
protected final long creationTime; | ||
|
||
public CacheEntryBase( final ObjectType obj ) { | ||
this( obj, Instant.now().toEpochMilli() ); | ||
} | ||
|
||
public CacheEntryBase( final ObjectType obj, final long creationTime ) { | ||
assert obj != null; | ||
this.obj = obj; | ||
this.creationTime = creationTime; | ||
} | ||
|
||
@Override | ||
public ObjectType getObject() { | ||
return obj; | ||
} | ||
|
||
@Override | ||
public long createdAt() { | ||
return creationTime; | ||
} | ||
|
||
@Override | ||
public boolean equals( final Object obj ) { | ||
if ( this == obj ) | ||
return true; | ||
if ( obj == null || getClass() != obj.getClass() ) | ||
return false; | ||
return this.getObject().equals(((CacheEntryBase<?>) obj).getObject()); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return getObject().hashCode(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
.../se/liu/ida/hefquin/base/datastructures/impl/cache/CacheInvalidationPolicyTimeToLive.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package se.liu.ida.hefquin.base.datastructures.impl.cache; | ||
|
||
import java.time.Instant; | ||
|
||
public class CacheInvalidationPolicyTimeToLive<EntryType extends CacheEntry<ObjectType>, ObjectType> | ||
implements CacheInvalidationPolicy<EntryType, ObjectType> | ||
{ | ||
protected final long timeToLive; | ||
|
||
public CacheInvalidationPolicyTimeToLive( final long timeToLive ){ | ||
this.timeToLive = timeToLive; | ||
} | ||
|
||
/** | ||
* Returns <code>true</code> if the given cache entry has not reached | ||
* the time to live considered by this policy. | ||
*/ | ||
public boolean isStillValid( final EntryType e ) { | ||
return e.createdAt() + timeToLive > Instant.now().toEpochMilli(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
217 changes: 217 additions & 0 deletions
217
...a/hefquin/engine/federation/access/impl/FederationAccessManagerWithChronicleMapCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
package se.liu.ida.hefquin.engine.federation.access.impl; | ||
|
||
import java.io.IOException; | ||
import java.util.Date; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutorService; | ||
|
||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheEntry; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheEntryFactory; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheInvalidationPolicy; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheInvalidationPolicyTimeToLive; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CachePolicies; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheReplacementPolicy; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheReplacementPolicyFactory; | ||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheReplacementPolicyLRU; | ||
import se.liu.ida.hefquin.engine.federation.BRTPFServer; | ||
import se.liu.ida.hefquin.engine.federation.SPARQLEndpoint; | ||
import se.liu.ida.hefquin.engine.federation.TPFServer; | ||
import se.liu.ida.hefquin.engine.federation.access.BRTPFRequest; | ||
import se.liu.ida.hefquin.engine.federation.access.CardinalityResponse; | ||
import se.liu.ida.hefquin.engine.federation.access.DataRetrievalResponse; | ||
import se.liu.ida.hefquin.engine.federation.access.FederationAccessException; | ||
import se.liu.ida.hefquin.engine.federation.access.FederationAccessManager; | ||
import se.liu.ida.hefquin.engine.federation.access.SPARQLRequest; | ||
import se.liu.ida.hefquin.engine.federation.access.TPFRequest; | ||
import se.liu.ida.hefquin.engine.federation.access.impl.cache.CardinalityCacheEntry; | ||
import se.liu.ida.hefquin.engine.federation.access.impl.cache.CardinalityCacheEntryFactory; | ||
import se.liu.ida.hefquin.engine.federation.access.impl.cache.CardinalityCacheKey; | ||
import se.liu.ida.hefquin.engine.federation.access.impl.cache.ChronicleMapCardinalityCache; | ||
import se.liu.ida.hefquin.engine.federation.access.impl.response.CachedCardinalityResponseImpl; | ||
|
||
/** | ||
* A FederationAccessManager implementation that incorporates persistent disk | ||
* caching of cardinality requests. | ||
*/ | ||
public class FederationAccessManagerWithChronicleMapCache extends FederationAccessManagerWithCache | ||
{ | ||
protected final ChronicleMapCardinalityCache cardinalityCache; | ||
protected final static int defaultCacheCapacity = 1000; | ||
|
||
public FederationAccessManagerWithChronicleMapCache( final FederationAccessManager fedAccMan, | ||
final int cacheCapacity, | ||
final CachePolicies<Key, CompletableFuture<? extends DataRetrievalResponse>, ? extends CacheEntry<CompletableFuture<? extends DataRetrievalResponse>>> cachePolicies, | ||
final CachePolicies<CardinalityCacheKey, Integer, CardinalityCacheEntry> cardinalityCachePolicies ) | ||
throws IOException | ||
{ | ||
super( fedAccMan, cacheCapacity, cachePolicies ); | ||
cardinalityCache = new ChronicleMapCardinalityCache( cardinalityCachePolicies, cacheCapacity ); | ||
} | ||
|
||
public FederationAccessManagerWithChronicleMapCache( final FederationAccessManager fedAccMan, | ||
final int cacheCapacity, | ||
final long timeToLive ) | ||
throws IOException | ||
{ | ||
this( fedAccMan, | ||
cacheCapacity, | ||
new MyDefaultCachePolicies(), | ||
new MyDefaultCardinalityCachePolicies( timeToLive ) ); | ||
} | ||
|
||
/** | ||
* Creates a {@link FederationAccessManagerWithChronicleMapCache} with the default configuration. | ||
*/ | ||
public FederationAccessManagerWithChronicleMapCache( final ExecutorService execService ) throws IOException | ||
{ | ||
this( new AsyncFederationAccessManagerImpl( execService ), | ||
defaultCacheCapacity, | ||
new MyDefaultCachePolicies(), | ||
new MyDefaultCardinalityCachePolicies() ); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<CardinalityResponse> issueCardinalityRequest( final SPARQLRequest req, | ||
final SPARQLEndpoint fm ) | ||
throws FederationAccessException | ||
{ | ||
final CardinalityCacheKey key = new CardinalityCacheKey( req, fm ); | ||
final Date requestStartTime = new Date(); | ||
final CardinalityCacheEntry cachedEntry = cardinalityCache.get( key ); | ||
final Date requestEndTime = new Date(); | ||
if ( cachedEntry != null ) { | ||
cacheHitsSPARQLCardinality++; | ||
final CardinalityResponse cr = new CachedCardinalityResponseImpl( fm, | ||
req, | ||
cachedEntry.getObject(), | ||
requestStartTime, | ||
requestEndTime ); | ||
return CompletableFuture.completedFuture( cr ); | ||
} | ||
|
||
final CompletableFuture<CardinalityResponse> newResponse = fedAccMan.issueCardinalityRequest( req, fm ); | ||
newResponse.thenAccept( value -> { | ||
cardinalityCache.put( key, value.getCardinality() ); | ||
} ); | ||
return newResponse; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<CardinalityResponse> issueCardinalityRequest( final TPFRequest req, | ||
final TPFServer fm ) | ||
throws FederationAccessException | ||
{ | ||
final CardinalityCacheKey key = new CardinalityCacheKey( req, fm ); | ||
final Date requestStartTime = new Date(); | ||
final CardinalityCacheEntry cachedEntry = cardinalityCache.get( key ); | ||
final Date requestEndTime = new Date(); | ||
if ( cachedEntry != null ) { | ||
cacheHitsTPFCardinality++; | ||
final CardinalityResponse cr = new CachedCardinalityResponseImpl( fm, | ||
req, | ||
cachedEntry.getObject(), | ||
requestStartTime, | ||
requestEndTime ); | ||
return CompletableFuture.completedFuture( cr ); | ||
} | ||
|
||
final CompletableFuture<CardinalityResponse> newResponse = fedAccMan.issueCardinalityRequest( req, fm ); | ||
newResponse.thenAccept( value -> { | ||
cardinalityCache.put( key, value.getCardinality() ); | ||
} ); | ||
return newResponse; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<CardinalityResponse> issueCardinalityRequest( final TPFRequest req, | ||
final BRTPFServer fm ) | ||
throws FederationAccessException | ||
{ | ||
final CardinalityCacheKey key = new CardinalityCacheKey( req, fm ); | ||
final Date requestStartTime = new Date(); | ||
final CardinalityCacheEntry cachedEntry = cardinalityCache.get( key ); | ||
final Date requestEndTime = new Date(); | ||
if ( cachedEntry != null ) { | ||
cacheHitsTPFCardinality++; | ||
final CardinalityResponse cr = new CachedCardinalityResponseImpl( fm, | ||
req, | ||
cachedEntry.getObject(), | ||
requestStartTime, | ||
requestEndTime ); | ||
return CompletableFuture.completedFuture( cr ); | ||
} | ||
|
||
final CompletableFuture<CardinalityResponse> newResponse = fedAccMan.issueCardinalityRequest( req, fm ); | ||
newResponse.thenAccept( value -> { | ||
cardinalityCache.put( key, value.getCardinality() ); | ||
} ); | ||
return newResponse; | ||
} | ||
|
||
@Override | ||
public CompletableFuture<CardinalityResponse> issueCardinalityRequest( final BRTPFRequest req, | ||
final BRTPFServer fm ) | ||
throws FederationAccessException | ||
{ | ||
final CardinalityCacheKey key = new CardinalityCacheKey( req, fm ); | ||
final Date requestStartTime = new Date(); | ||
final CardinalityCacheEntry cachedEntry = cardinalityCache.get( key ); | ||
final Date requestEndTime = new Date(); | ||
if ( cachedEntry != null ) { | ||
cacheHitsTPFCardinality++; | ||
final CardinalityResponse cr = new CachedCardinalityResponseImpl( fm, | ||
req, | ||
cachedEntry.getObject(), | ||
requestStartTime, | ||
requestEndTime ); | ||
return CompletableFuture.completedFuture( cr ); | ||
} | ||
|
||
final CompletableFuture<CardinalityResponse> newResponse = fedAccMan.issueCardinalityRequest( req, fm ); | ||
newResponse.thenAccept( value -> { | ||
cardinalityCache.put( key, value.getCardinality() ); | ||
} ); | ||
return newResponse; | ||
} | ||
|
||
/** | ||
* Clears the persisted cardinality cache map. | ||
*/ | ||
public void clearCardinalityCache() { | ||
cardinalityCache.clear(); | ||
} | ||
|
||
protected static class MyDefaultCardinalityCachePolicies implements CachePolicies<CardinalityCacheKey, Integer, CardinalityCacheEntry> | ||
{ | ||
protected final long timeToLive; | ||
protected final static long defaultTimeToLive = 300_000; // 5 minutes | ||
|
||
public MyDefaultCardinalityCachePolicies() { | ||
this( defaultTimeToLive ); | ||
} | ||
|
||
public MyDefaultCardinalityCachePolicies( final long timeToLive ) { | ||
this.timeToLive = timeToLive; | ||
} | ||
|
||
@Override | ||
public CacheEntryFactory<CardinalityCacheEntry, Integer> getEntryFactory() { | ||
return new CardinalityCacheEntryFactory(); | ||
} | ||
|
||
@Override | ||
public CacheReplacementPolicyFactory<CardinalityCacheKey, Integer, CardinalityCacheEntry> getReplacementPolicyFactory() { | ||
return new CacheReplacementPolicyFactory<>() { | ||
@Override | ||
public CacheReplacementPolicy<CardinalityCacheKey, Integer, CardinalityCacheEntry> create() { | ||
return new CacheReplacementPolicyLRU<>(); | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
public CacheInvalidationPolicy<CardinalityCacheEntry, Integer> getInvalidationPolicy() { | ||
return new CacheInvalidationPolicyTimeToLive<>( timeToLive ); | ||
} | ||
} // end of MyDefaultCachePolicies | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
...in/java/se/liu/ida/hefquin/engine/federation/access/impl/cache/CardinalityCacheEntry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package se.liu.ida.hefquin.engine.federation.access.impl.cache; | ||
|
||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheEntryBase; | ||
|
||
/** | ||
* An entry used when caching cardinality requests. | ||
*/ | ||
public class CardinalityCacheEntry extends CacheEntryBase<Integer> | ||
{ | ||
private static final long serialVersionUID = 1L; | ||
|
||
public CardinalityCacheEntry( final Integer cardinality, final long entryCreatedAt ) { | ||
super( cardinality, entryCreatedAt ); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "CardinalityCacheEntry{cardinality='" + getObject() + "'}"; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
.../se/liu/ida/hefquin/engine/federation/access/impl/cache/CardinalityCacheEntryFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package se.liu.ida.hefquin.engine.federation.access.impl.cache; | ||
|
||
import java.time.Instant; | ||
|
||
import se.liu.ida.hefquin.base.datastructures.impl.cache.CacheEntryFactory; | ||
|
||
/** | ||
* An entry used when caching cardinality requests. | ||
*/ | ||
public class CardinalityCacheEntryFactory implements CacheEntryFactory<CardinalityCacheEntry, Integer> | ||
{ | ||
@Override | ||
public CardinalityCacheEntry createCacheEntry( final Integer cardinality ) { | ||
return new CardinalityCacheEntry( cardinality, Instant.now().toEpochMilli() ); | ||
} | ||
} |
Oops, something went wrong.