Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor cache decorator #3056

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/main/java/org/apache/ibatis/cache/CacheDecorator.java
@@ -0,0 +1,72 @@
/*
* Copyright 2009-2024 the original author or 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
*
* https://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.apache.ibatis.cache;

import java.util.concurrent.locks.ReadWriteLock;

/**
* abstract cache decorator.
*
* @author wuwen
*/
public abstract class CacheDecorator implements Cache {

private final Cache delegate;

public CacheDecorator(Cache cache) {
this.delegate = cache;
}

@Override
public String getId() {
return delegate.getId();
}

@Override
public void putObject(Object key, Object value) {
delegate.putObject(key, value);
}

@Override
public Object getObject(Object key) {
return delegate.getObject(key);
}

@Override
public Object removeObject(Object key) {
return delegate.removeObject(key);
}

@Override
public void clear() {
delegate.clear();
}

@Override
public int getSize() {
return delegate.getSize();
}

@Override
public ReadWriteLock getReadWriteLock() {
return delegate.getReadWriteLock();
}

protected Cache getDelegate() {
return delegate;
}

}
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2023 the original author or authors.
* Copyright 2009-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@
import java.util.concurrent.TimeUnit;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheDecorator;
import org.apache.ibatis.cache.CacheException;

/**
Expand All @@ -34,31 +35,20 @@
*
* @author Eduardo Macarron
*/
public class BlockingCache implements Cache {
public class BlockingCache extends CacheDecorator {

private long timeout;
private final Cache delegate;
private final ConcurrentHashMap<Object, CountDownLatch> locks;

public BlockingCache(Cache delegate) {
this.delegate = delegate;
super(delegate);
this.locks = new ConcurrentHashMap<>();
}

@Override
public String getId() {
return delegate.getId();
}

@Override
public int getSize() {
return delegate.getSize();
}

@Override
public void putObject(Object key, Object value) {
try {
delegate.putObject(key, value);
super.putObject(key, value);
} finally {
releaseLock(key);
}
Expand All @@ -67,7 +57,7 @@ public void putObject(Object key, Object value) {
@Override
public Object getObject(Object key) {
acquireLock(key);
Object value = delegate.getObject(key);
Object value = super.getObject(key);
if (value != null) {
releaseLock(key);
}
Expand All @@ -81,11 +71,6 @@ public Object removeObject(Object key) {
return null;
}

@Override
public void clear() {
delegate.clear();
}

private void acquireLock(Object key) {
CountDownLatch newLatch = new CountDownLatch(1);
while (true) {
Expand All @@ -98,7 +83,7 @@ private void acquireLock(Object key) {
boolean acquired = latch.await(timeout, TimeUnit.MILLISECONDS);
if (!acquired) {
throw new CacheException(
"Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId());
"Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + super.getId());
}
} else {
latch.await();
Expand Down
28 changes: 9 additions & 19 deletions src/main/java/org/apache/ibatis/cache/decorators/FifoCache.java
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2023 the original author or authors.
* Copyright 2009-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,66 +19,56 @@
import java.util.LinkedList;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheDecorator;

/**
* FIFO (first in, first out) cache decorator.
*
* @author Clinton Begin
*/
public class FifoCache implements Cache {
public class FifoCache extends CacheDecorator {

private final Cache delegate;
private final Deque<Object> keyList;
private int size;

public FifoCache(Cache delegate) {
this.delegate = delegate;
super(delegate);
this.keyList = new LinkedList<>();
this.size = 1024;
}

@Override
public String getId() {
return delegate.getId();
}

@Override
public int getSize() {
return delegate.getSize();
}

public void setSize(int size) {
this.size = size;
}

@Override
public void putObject(Object key, Object value) {
cycleKeyList(key);
delegate.putObject(key, value);
super.putObject(key, value);
}

@Override
public Object getObject(Object key) {
return delegate.getObject(key);
return super.getObject(key);
}

@Override
public Object removeObject(Object key) {
keyList.remove(key);
return delegate.removeObject(key);
return super.removeObject(key);
}

@Override
public void clear() {
delegate.clear();
super.clear();
keyList.clear();
}

private void cycleKeyList(Object key) {
keyList.addLast(key);
if (keyList.size() > size) {
Object oldestKey = keyList.removeFirst();
delegate.removeObject(oldestKey);
super.removeObject(oldestKey);
}
}

Expand Down
39 changes: 7 additions & 32 deletions src/main/java/org/apache/ibatis/cache/decorators/LoggingCache.java
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2023 the original author or authors.
* Copyright 2009-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,43 +16,28 @@
package org.apache.ibatis.cache.decorators;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheDecorator;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;

/**
* @author Clinton Begin
*/
public class LoggingCache implements Cache {
public class LoggingCache extends CacheDecorator {

private final Log log;
private final Cache delegate;
protected int requests;
protected int hits;

public LoggingCache(Cache delegate) {
this.delegate = delegate;
super(delegate);
this.log = LogFactory.getLog(getId());
}

@Override
public String getId() {
return delegate.getId();
}

@Override
public int getSize() {
return delegate.getSize();
}

@Override
public void putObject(Object key, Object object) {
delegate.putObject(key, object);
}

@Override
public Object getObject(Object key) {
requests++;
final Object value = delegate.getObject(key);
final Object value = super.getObject(key);
if (value != null) {
hits++;
}
Expand All @@ -62,24 +47,14 @@ public Object getObject(Object key) {
return value;
}

@Override
public Object removeObject(Object key) {
return delegate.removeObject(key);
}

@Override
public void clear() {
delegate.clear();
}

@Override
public int hashCode() {
return delegate.hashCode();
return getDelegate().hashCode();
}

@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
return getDelegate().equals(obj);
}

private double getHitRatio() {
Expand Down
28 changes: 9 additions & 19 deletions src/main/java/org/apache/ibatis/cache/decorators/LruCache.java
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2023 the original author or authors.
* Copyright 2009-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,33 +19,23 @@
import java.util.Map;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheDecorator;

/**
* Lru (least recently used) cache decorator.
*
* @author Clinton Begin
*/
public class LruCache implements Cache {
public class LruCache extends CacheDecorator {

private final Cache delegate;
private Map<Object, Object> keyMap;
private Object eldestKey;

public LruCache(Cache delegate) {
this.delegate = delegate;
super(delegate);
setSize(1024);
}

@Override
public String getId() {
return delegate.getId();
}

@Override
public int getSize() {
return delegate.getSize();
}

public void setSize(final int size) {
keyMap = new LinkedHashMap<Object, Object>(size, .75F, true) {
private static final long serialVersionUID = 4267176411845948333L;
Expand All @@ -63,32 +53,32 @@ protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {

@Override
public void putObject(Object key, Object value) {
delegate.putObject(key, value);
super.putObject(key, value);
cycleKeyList(key);
}

@Override
public Object getObject(Object key) {
keyMap.get(key); // touch
return delegate.getObject(key);
return super.getObject(key);
}

@Override
public Object removeObject(Object key) {
keyMap.remove(key);
return delegate.removeObject(key);
return super.removeObject(key);
}

@Override
public void clear() {
delegate.clear();
super.clear();
keyMap.clear();
}

private void cycleKeyList(Object key) {
keyMap.put(key, key);
if (eldestKey != null) {
delegate.removeObject(eldestKey);
super.removeObject(eldestKey);
eldestKey = null;
}
}
Expand Down