1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-10 09:22:49 +00:00

Base AI, new Cache system, DAO changes and better geometry handling

Signed-off-by: Rogiel <rogiel@rogiel.com>
This commit is contained in:
2011-05-27 02:49:15 -03:00
parent aabe375b49
commit 73f51e53c0
95 changed files with 3079 additions and 1884 deletions

View File

@@ -0,0 +1,113 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* l2jserver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.l2jserver.service.cache.SoftCacheService.SoftCache;
import com.l2jserver.util.factory.CollectionFactory;
import com.sun.beans.WeakCache;
/**
* Base class for {@link WeakCache} and {@link SoftCache}
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <K>
* the key type
* @param <V>
* the value type
*/
abstract class AbstractReferenceCache<K, V> implements Cache<K, V> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The cache name
*/
protected final String cacheName;
/**
* Map storing references to cached objects
*/
protected final Map<K, Reference<V>> cacheMap = CollectionFactory.newMap();
/**
* The reference queue
*/
protected final ReferenceQueue<V> refQueue = CollectionFactory
.newReferenceQueue();
/**
* @param cacheName
* the cache name
*/
protected AbstractReferenceCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public void put(K key, V value) {
cleanQueue();
Reference<V> entry = newReference(key, value, refQueue);
cacheMap.put(key, entry);
log.debug("{}: added for key: {}", cacheName, key);
}
@Override
public V get(K key) {
cleanQueue();
Reference<V> reference = cacheMap.get(key);
if (reference == null)
return null;
V res = reference.get();
if (res != null)
log.debug("{}: obtained for key: {}", cacheName, key);
return res;
}
@Override
public boolean contains(K key) {
cleanQueue();
return cacheMap.containsKey(key);
}
protected abstract void cleanQueue();
@Override
public void remove(K key) {
cacheMap.remove(key);
log.debug("{}: removed for key: {}", cacheName, key);
}
@Override
public void clear() {
cacheMap.clear();
log.debug("{}: cleared", cacheName);
}
protected abstract Reference<V> newReference(K key, V value,
ReferenceQueue<V> queue);
}

View File

@@ -0,0 +1,64 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* l2jserver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
/**
* This interface represents a Map structure for cache usage.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface Cache<K, V> {
/**
* Adds a pair <key,value> to cache.<br>
* <br>
*
* <font color='red'><b>NOTICE:</b> </font> if there is already a value with
* given id in the map, {@link IllegalArgumentException} will be thrown.
*
* @param key
* @param value
*/
void put(K key, V value);
/**
* Returns cached value correlated to given key.
*
* @param key
* @return
*/
V get(K key);
/**
* Checks whether this map contains a value related to given key.
*
* @param key
* @return
*/
boolean contains(K key);
/**
* Removes an entry from the map, that has given key.
*
* @param key
*/
void remove(K key);
/**
* Clears this cache
*/
void clear();
}

View File

@@ -16,8 +16,6 @@
*/
package com.l2jserver.service.cache;
import net.sf.ehcache.Cache;
import com.l2jserver.service.Service;
/**
@@ -31,7 +29,6 @@ import com.l2jserver.service.Service;
* {@link IgnoreCaching}
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface CacheService extends Service {
/**
@@ -50,39 +47,60 @@ public interface CacheService extends Service {
/**
* Creates a new cache with default configurations. Eviction mode is LRU
* (Last Recently Used). If you wish more customization, you should manually
* create the cache and register it using {@link #register(Cache)}.
* (Last Recently Used). The size is only a guarantee that you can store
* <b>at least</b> <tt>n</tt> items.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param name
* the cache name
* @size the maximum cache size
* @return the created cache
*/
Cache createCache(String name, int size);
<K, V> Cache<K, V> createCache(String name, int size);
/**
* Creates a new eternal cache with default configurations. An eternal cache
* is guaranteed to never automatically expire items. The size is only a
* guarantee that you can store <b>at least</b> <tt>n</tt> items.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param name
* the cache name
* @size the maximum cache size
* @return the created cache
*/
<K, V> Cache<K, V> createEternalCache(String name, int size);
/**
* Creates a new cache with default configurations. The default cache size
* is 200.
* is 200. The size is only a guarantee that you can store <b>at least</b>
* 200 items.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param name
* the cache name
* @return the created cache
*/
Cache createCache(String name);
<K, V> Cache<K, V> createCache(String name);
/**
* Registers a new cache
* Disposes the cache. Once the cache is disposed it cannot be used anymore.
*
* @param <K>
* the cache key type
* @param <V>
* the cache value type
* @param cache
* the cache
*/
void register(Cache cache);
/**
* Unregisters an already registered cache
*
* @param cache
* the cache
*/
void unregister(Cache cache);
<K, V> void dispose(Cache<K, V> cache);
}

View File

@@ -20,9 +20,7 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
@@ -48,7 +46,7 @@ public class EhCacheService extends AbstractService implements CacheService {
/**
* The interface cache
*/
private Cache interfaceCache;
private Cache<MethodInvocation, Object> interfaceCache;
@Override
protected void doStart() throws ServiceStartException {
@@ -76,10 +74,7 @@ public class EhCacheService extends AbstractService implements CacheService {
return method.invoke(instance, args);
final MethodInvocation invocation = new MethodInvocation(
method, args);
Element element = interfaceCache.get(invocation);
if (element == null)
return doInvoke(invocation, proxy, method, args);
Object result = element.getObjectValue();
Object result = interfaceCache.get(invocation);
if (result == null)
return doInvoke(invocation, proxy, method, args);
return result;
@@ -90,43 +85,94 @@ public class EhCacheService extends AbstractService implements CacheService {
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object result = method.invoke(instance, args);
interfaceCache.put(new Element(invocation, result));
interfaceCache.put(invocation, result);
return result;
}
});
return proxy;
}
// @Override
// public Cache createCache(String name, int size) {
// Preconditions.checkNotNull(name, "name");
// Preconditions.checkArgument(size > 0, "size <= 0");
//
// Cache cache = new Cache(new CacheConfiguration(name, size)
// .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
// .overflowToDisk(true).eternal(false).timeToLiveSeconds(60)
// .timeToIdleSeconds(30).diskPersistent(false)
// .diskExpiryThreadIntervalSeconds(0));
// register(cache);
// return cache;
// }
//
// @Override
// public Cache createCache(String name) {
// Preconditions.checkNotNull(name, "name");
// return createCache(name, 200);
// }
//
// @Override
// public void register(Cache cache) {
// Preconditions.checkNotNull(cache, "cache");
// manager.addCache(cache);
// }
//
// @Override
// public void unregister(Cache cache) {
// Preconditions.checkNotNull(cache, "cache");
// manager.removeCache(cache.getName());
// }
@Override
public Cache createCache(String name, int size) {
public <K, V> Cache<K, V> createCache(String name, int size) {
Preconditions.checkNotNull(name, "name");
Preconditions.checkArgument(size > 0, "size <= 0");
Cache cache = new Cache(new CacheConfiguration(name, size)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(false).timeToLiveSeconds(60)
.timeToIdleSeconds(30).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
register(cache);
return cache;
}
@Override
public Cache createCache(String name) {
Preconditions.checkNotNull(name, "name");
return createCache(name, 200);
}
@Override
public void register(Cache cache) {
Preconditions.checkNotNull(cache, "cache");
net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(
new CacheConfiguration(name, size)
.memoryStoreEvictionPolicy(
MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(false)
.timeToLiveSeconds(60).timeToIdleSeconds(30)
.diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
manager.addCache(cache);
return new EhCacheFacade<K, V>(cache);
}
@Override
public void unregister(Cache cache) {
Preconditions.checkNotNull(cache, "cache");
manager.removeCache(cache.getName());
public <K, V> Cache<K, V> createEternalCache(String name, int size) {
Preconditions.checkNotNull(name, "name");
Preconditions.checkArgument(size > 0, "size <= 0");
net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(
new CacheConfiguration(name, size)
.memoryStoreEvictionPolicy(
MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true)
.diskExpiryThreadIntervalSeconds(0));
manager.addCache(cache);
return new EhCacheFacade<K, V>(cache);
}
@Override
public <K, V> Cache<K, V> createCache(String name) {
net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(
new CacheConfiguration(name, 200)
.memoryStoreEvictionPolicy(
MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true)
.diskExpiryThreadIntervalSeconds(0));
manager.addCache(cache);
return new EhCacheFacade<K, V>(cache);
}
@Override
public <K, V> void dispose(Cache<K, V> cache) {
if (cache instanceof EhCacheFacade) {
manager.removeCache(((EhCacheFacade<K, V>) cache).cache.getName());
}
}
@Override
@@ -136,42 +182,40 @@ public class EhCacheService extends AbstractService implements CacheService {
interfaceCache = null;
}
private static class MethodInvocation {
private final Method method;
private final Object[] args;
private class EhCacheFacade<K, V> implements Cache<K, V> {
private final net.sf.ehcache.Cache cache;
public MethodInvocation(Method method, Object[] args) {
this.method = method;
this.args = args;
public EhCacheFacade(net.sf.ehcache.Cache cache) {
this.cache = cache;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(args);
result = prime * result
+ ((method == null) ? 0 : method.hashCode());
return result;
public void put(K key, V value) {
cache.put(new Element(key, value));
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MethodInvocation other = (MethodInvocation) obj;
if (!Arrays.equals(args, other.args))
return false;
if (method == null) {
if (other.method != null)
return false;
} else if (!method.equals(other.method))
return false;
return true;
@SuppressWarnings("unchecked")
public V get(K key) {
final Element element = cache.get(key);
if (element == null)
return null;
return (V) element.getValue();
}
@Override
public boolean contains(K key) {
return cache.get(key) != null;
}
@Override
public void remove(K key) {
cache.remove(key);
}
@Override
public void clear() {
cache.removeAll();
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* l2jserver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.l2jserver.util.factory.CollectionFactory;
/**
* Cache class for an eternal cache
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
* @param <K>
* the key type
* @param <V>
* the value type
*/
class EternalCache<K, V> implements Cache<K, V> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The cache name
*/
protected final String cacheName;
/**
* Map storing references to cached objects
*/
protected final Map<K, V> cacheMap = CollectionFactory.newMap();
/**
* @param cacheName
* the cache name
*/
protected EternalCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public void put(K key, V value) {
cacheMap.put(key, value);
log.debug("{}: added for key: {}", cacheName, key);
}
@Override
public V get(K key) {
V obj = cacheMap.get(key);
if (obj != null)
log.debug("{}: obtained for key: {}", cacheName, key);
return obj;
}
@Override
public boolean contains(K key) {
return cacheMap.containsKey(key);
}
@Override
public void remove(K key) {
cacheMap.remove(key);
log.debug("{}: removed for key: {}", cacheName, key);
}
@Override
public void clear() {
cacheMap.clear();
log.debug("{}: cleared", cacheName);
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* l2jserver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* Simple class used to store method invocations for the proxied cache.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
class MethodInvocation {
/**
* The invoked method
*/
private final Method method;
/**
* The invocation arguments
*/
private final Object[] args;
public MethodInvocation(Method method, Object[] args) {
this.method = method;
this.args = args;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(args);
result = prime * result + ((method == null) ? 0 : method.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MethodInvocation other = (MethodInvocation) obj;
if (!Arrays.equals(args, other.args))
return false;
if (method == null) {
if (other.method != null)
return false;
} else if (!method.equals(other.method))
return false;
return true;
}
}

View File

@@ -0,0 +1,164 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* l2jserver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.google.common.base.Preconditions;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
/**
* This {@link Cache} service implementation uses a {@link SoftReference} to
* store values.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class SoftCacheService extends AbstractService implements CacheService {
/**
* The interface cache
*/
private Cache<MethodInvocation, Object> interfaceCache;
@Override
protected void doStart() throws ServiceStartException {
interfaceCache = createCache("interface-cache");
}
@Override
public <T extends Cacheable> T decorate(final Class<T> interfaceType,
final T instance) {
Preconditions.checkNotNull(interfaceType, "interfaceType");
Preconditions.checkNotNull(instance, "instance");
if (!interfaceType.isInterface())
return null;
@SuppressWarnings("unchecked")
final T proxy = (T) Proxy.newProxyInstance(this.getClass()
.getClassLoader(), new Class[] { interfaceType },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.isAnnotationPresent(IgnoreCaching.class))
return method.invoke(instance, args);
final MethodInvocation invocation = new MethodInvocation(
method, args);
Object result = interfaceCache.get(invocation);
if (result == null)
return doInvoke(invocation, proxy, method, args);
return result;
}
private Object doInvoke(MethodInvocation invocation,
Object proxy, Method method, Object[] args)
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object result = method.invoke(instance, args);
interfaceCache.put(invocation, result);
return result;
}
});
return proxy;
}
@Override
public <K, V> Cache<K, V> createCache(String name, int size) {
return new SoftCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createEternalCache(String name, int size) {
return new EternalCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createCache(String name) {
return new SoftCache<K, V>(name);
}
@Override
public <K, V> void dispose(Cache<K, V> cache) {
cache.clear();
}
@Override
protected void doStop() throws ServiceStopException {
dispose(interfaceCache);
interfaceCache = null;
}
/**
* This class is a simple map implementation for cache usage.<br>
* <br>
* Value may be stored in map really long, but it for sure will be removed
* if there is low memory (and of course there isn't any strong reference to
* value object)
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class SoftCache<K, V> extends AbstractReferenceCache<K, V> implements
Cache<K, V> {
/**
* This class is a {@link SoftReference} with additional responsibility
* of holding key object
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
private class SoftEntry extends SoftReference<V> {
private K key;
SoftEntry(K key, V referent, ReferenceQueue<? super V> q) {
super(referent, q);
this.key = key;
}
K getKey() {
return key;
}
}
public SoftCache(String cacheName) {
super(cacheName);
}
@Override
@SuppressWarnings("unchecked")
protected synchronized void cleanQueue() {
SoftEntry en = null;
while ((en = (SoftEntry) refQueue.poll()) != null) {
K key = en.getKey();
if (log.isDebugEnabled())
log.debug("{} : cleaned up {} for key: {}", cacheName, key);
cacheMap.remove(key);
}
}
@Override
protected Reference<V> newReference(K key, V value,
ReferenceQueue<V> vReferenceQueue) {
return new SoftEntry(key, value, vReferenceQueue);
}
}
}

View File

@@ -0,0 +1,164 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* l2jserver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* l2jserver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.cache;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.google.common.base.Preconditions;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
/**
* This {@link Cache} service implementation uses a {@link SoftReference} to
* store values.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class WeakCacheService extends AbstractService implements CacheService {
/**
* The interface cache
*/
private Cache<MethodInvocation, Object> interfaceCache;
@Override
protected void doStart() throws ServiceStartException {
interfaceCache = createCache("interface-cache");
}
@Override
public <T extends Cacheable> T decorate(final Class<T> interfaceType,
final T instance) {
Preconditions.checkNotNull(interfaceType, "interfaceType");
Preconditions.checkNotNull(instance, "instance");
if (!interfaceType.isInterface())
return null;
@SuppressWarnings("unchecked")
final T proxy = (T) Proxy.newProxyInstance(this.getClass()
.getClassLoader(), new Class[] { interfaceType },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.isAnnotationPresent(IgnoreCaching.class))
return method.invoke(instance, args);
final MethodInvocation invocation = new MethodInvocation(
method, args);
Object result = interfaceCache.get(invocation);
if (result == null)
return doInvoke(invocation, proxy, method, args);
return result;
}
private Object doInvoke(MethodInvocation invocation,
Object proxy, Method method, Object[] args)
throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object result = method.invoke(instance, args);
interfaceCache.put(invocation, result);
return result;
}
});
return proxy;
}
@Override
public <K, V> Cache<K, V> createCache(String name, int size) {
return new WeakCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createEternalCache(String name, int size) {
return new EternalCache<K, V>(name);
}
@Override
public <K, V> Cache<K, V> createCache(String name) {
return new WeakCache<K, V>(name);
}
@Override
public <K, V> void dispose(Cache<K, V> cache) {
cache.clear();
}
@Override
protected void doStop() throws ServiceStopException {
dispose(interfaceCache);
interfaceCache = null;
}
/**
* This class is a simple map implementation for cache usage.<br>
* <br>
* Values from the map will be removed after the first garbage collector run
* if there isn't any strong reference to the value object.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
private class WeakCache<K, V> extends AbstractReferenceCache<K, V>
implements Cache<K, V> {
/**
* This class is a {@link WeakReference} with additional responsibility
* of holding key object
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
private class Entry extends WeakReference<V> {
private K key;
Entry(K key, V referent, ReferenceQueue<? super V> q) {
super(referent, q);
this.key = key;
}
K getKey() {
return key;
}
}
WeakCache(String cacheName) {
super(cacheName);
}
@Override
@SuppressWarnings("unchecked")
protected synchronized void cleanQueue() {
Entry en = null;
while ((en = (Entry) refQueue.poll()) != null) {
K key = en.getKey();
if (log.isDebugEnabled())
log.debug("{}: cleaned up for key: {}", cacheName, key);
cacheMap.remove(key);
}
}
@Override
protected Reference<V> newReference(K key, V value,
ReferenceQueue<V> vReferenceQueue) {
return new Entry(key, value, vReferenceQueue);
}
}
}

View File

@@ -28,11 +28,6 @@ import java.util.List;
import javax.sql.DataSource;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
@@ -53,6 +48,7 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.cache.Cache;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.core.LoggingService;
@@ -105,7 +101,7 @@ public class JDBCDatabaseService extends AbstractService implements
/**
* An cache object
*/
private Cache objectCache;
private Cache<Object, Object> objectCache;
@Inject
public JDBCDatabaseService(ConfigurationService configService,
@@ -125,12 +121,8 @@ public class JDBCDatabaseService extends AbstractService implements
// cache must be large enough for all world objects, to avoid
// duplication... this would endanger non-persistent states
objectCache = new Cache(new CacheConfiguration("database-service",
IDAllocator.ALLOCABLE_IDS)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
cacheService.register(objectCache);
objectCache = cacheService.createEternalCache("database-service",
IDAllocator.ALLOCABLE_IDS);
}
@Override
@@ -186,21 +178,18 @@ public class JDBCDatabaseService extends AbstractService implements
public Object getCachedObject(Object id) {
Preconditions.checkNotNull(id, "id");
final Element element = objectCache.get(id);
if (element == null)
return null;
return element.getObjectValue();
return objectCache.get(id);
}
public boolean hasCachedObject(Object id) {
Preconditions.checkNotNull(id, "id");
return objectCache.get(id) != null;
return objectCache.contains(id);
}
public void updateCache(Object key, Object value) {
Preconditions.checkNotNull(key, "key");
Preconditions.checkNotNull(value, "value");
objectCache.put(new Element(key, value));
objectCache.put(key, value);
}
public void removeCache(Object key) {
@@ -210,8 +199,7 @@ public class JDBCDatabaseService extends AbstractService implements
@Override
protected void doStop() throws ServiceStopException {
if (objectCache != null)
objectCache.dispose();
cacheService.dispose(objectCache);
objectCache = null;
try {

View File

@@ -18,7 +18,7 @@ package com.l2jserver.service.game.ai;
import com.l2jserver.model.world.Actor;
import com.l2jserver.service.Service;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* This service executes AI operations

View File

@@ -27,7 +27,7 @@ import com.l2jserver.service.game.template.TemplateService;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* Default implementation for {@link AIService}.

View File

@@ -18,7 +18,7 @@ package com.l2jserver.service.game.ai.script;
import com.l2jserver.model.world.PositionableObject;
import com.l2jserver.service.game.ai.AIScript;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.geometry.Coordinate;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a

View File

@@ -23,8 +23,8 @@ import com.l2jserver.service.game.npc.NotAttackableNPCServiceException;
import com.l2jserver.service.game.spawn.AlreadySpawnedServiceException;
import com.l2jserver.service.game.spawn.NotSpawnedServiceException;
import com.l2jserver.service.game.spawn.SpawnPointNotFoundServiceException;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* This service manages {@link L2Character} instances
@@ -132,7 +132,7 @@ public interface CharacterService extends Service {
* @param point
* the validated point
*/
void validate(L2Character character, Point point);
void validate(L2Character character, Point3D point);
/**
* Called when received the validation of the position of an character
@@ -142,7 +142,7 @@ public interface CharacterService extends Service {
* @param point
* the validated point
*/
void receivedValidation(L2Character character, Point point);
void receivedValidation(L2Character character, Point3D point);
/**
* Set the character to walking mode

View File

@@ -74,8 +74,8 @@ import com.l2jserver.service.game.world.filter.impl.IDFilter;
import com.l2jserver.service.game.world.filter.impl.KnownListFilter;
import com.l2jserver.service.game.world.filter.impl.KnownListUpdateFilter;
import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* Default implementation for {@link CharacterService}.
@@ -417,21 +417,21 @@ public class CharacterServiceImpl extends AbstractService implements
}
@Override
public void validate(L2Character character, Point point) {
public void validate(L2Character character, Point3D point) {
Preconditions.checkNotNull(character, "character");
Preconditions.checkNotNull(point, "point");
// TODO implement position validation
}
@Override
public void receivedValidation(L2Character character, Point point) {
public void receivedValidation(L2Character character, Point3D point) {
Preconditions.checkNotNull(character, "character");
Preconditions.checkNotNull(point, "point");
if (character.isTeleporting())
// ignore while teleporting, for some reason the client sends a
// validation just before teleport packet
return;
final Point old = character.getPoint();
final Point3D old = character.getPoint();
character.setPoint(point);
eventDispatcher.dispatch(new CharacterMoveEvent(character, old));

View File

@@ -37,8 +37,8 @@ import com.l2jserver.service.game.character.CharacterService;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.game.world.event.TypedWorldListener;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* <h1>This implementation does not validate pathing!</h1>
@@ -97,7 +97,7 @@ public class MapperPathingService extends AbstractService implements
CharacterMoveEvent.class) {
@Override
protected boolean dispatch(CharacterMoveEvent e) {
final Point point = e.getPoint();
final Point3D point = e.getPoint();
final CoordinateStruct struct = CoordinateStruct
.fromCoordinate(point.getCoordinate());
try {

View File

@@ -24,8 +24,8 @@ import com.l2jserver.model.world.event.SpawnEvent;
import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
import com.l2jserver.model.world.player.event.PlayerTeleportingEvent;
import com.l2jserver.service.Service;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* This service is responsible for spawning monsters, npcs and players.
@@ -50,7 +50,7 @@ public interface SpawnService extends Service {
* @throws AlreadySpawnedServiceException
* if the object is already spawned in the world
*/
void spawn(PositionableObject object, Point point)
void spawn(PositionableObject object, Point3D point)
throws SpawnPointNotFoundServiceException,
AlreadySpawnedServiceException;

View File

@@ -37,8 +37,8 @@ import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.network.NetworkService;
import com.l2jserver.util.dimensional.Coordinate;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
/**
* Default implementation for {@link SpawnService}
@@ -69,7 +69,7 @@ public class SpawnServiceImpl extends AbstractService implements SpawnService {
}
@Override
public void spawn(PositionableObject object, Point point)
public void spawn(PositionableObject object, Point3D point)
throws SpawnPointNotFoundServiceException {
Preconditions.checkNotNull(object, "object");
// sanitize

View File

@@ -96,11 +96,6 @@ public class ScriptTemplateService extends AbstractService implements
// TODO templates.remove(t);
}
@Override
public void reload() {
context.reload();
}
@Override
protected void doStop() throws ServiceStopException {
if (context.isInitialized())

View File

@@ -31,9 +31,4 @@ public interface TemplateService extends Service {
* @return the template
*/
<T extends Template<?>> T getTemplate(TemplateID<T, ?> id);
/**
* Reload the template list.
*/
void reload();
}

View File

@@ -19,7 +19,6 @@ package com.l2jserver.service.game.template;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -46,22 +45,25 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.cache.Cache;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.core.LoggingService;
import com.l2jserver.service.core.vfs.VFSService;
import com.l2jserver.util.factory.CollectionFactory;
import com.l2jserver.util.jaxb.CharacterTemplateIDAdapter;
import com.l2jserver.util.jaxb.ItemTemplateIDAdapter;
import com.l2jserver.util.jaxb.NPCTemplateIDAdapter;
import com.l2jserver.util.jaxb.TeleportationTemplateIDAdapter;
import com.l2jserver.util.vfs.ExtensionFileSelector;
@Depends({ LoggingService.class, VFSService.class, ConfigurationService.class })
@Depends({ LoggingService.class, VFSService.class, CacheService.class,
ConfigurationService.class })
public class XMLTemplateService extends AbstractService implements
TemplateService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final VFSService vfsService;
private final CacheService cacheService;
private final XMLTemplateServiceConfiguration config;
private final NPCTemplateIDAdapter npcTemplateIdAdapter;
@@ -73,16 +75,17 @@ public class XMLTemplateService extends AbstractService implements
private Unmarshaller unmarshaller;
@SuppressWarnings("rawtypes")
private Map<TemplateID, Template> templates = CollectionFactory.newMap();
private Cache<TemplateID, Template> templates;
@Inject
public XMLTemplateService(final VFSService vfsService,
ConfigurationService configService,
CacheService cacheService, ConfigurationService configService,
NPCTemplateIDAdapter npcTemplateIdAdapter,
ItemTemplateIDAdapter itemTemplateIdAdapter,
CharacterTemplateIDAdapter charIdTemplateAdapter,
TeleportationTemplateIDAdapter teleportationIdTemplateAdapter) {
this.vfsService = vfsService;
this.cacheService = cacheService;
this.config = configService.get(XMLTemplateServiceConfiguration.class);
this.npcTemplateIdAdapter = npcTemplateIdAdapter;
this.itemTemplateIdAdapter = itemTemplateIdAdapter;
@@ -92,6 +95,7 @@ public class XMLTemplateService extends AbstractService implements
@Override
protected void doStart() throws ServiceStartException {
templates = cacheService.createEternalCache("templates", 100 * 1000);
try {
log.debug("Creating JAXBContext instance");
context = JAXBContext.newInstance(CharacterTemplate.class,
@@ -112,9 +116,9 @@ public class XMLTemplateService extends AbstractService implements
final FileObject root = vfsService.resolve(config
.getTemplateDirectory());
log.info("Scanning {} for XML templates", root);
FileObject[] files = root.findFiles(ExtensionFileSelector
.ext("xml"));
@@ -167,15 +171,10 @@ public class XMLTemplateService extends AbstractService implements
templates.remove(template.getID());
}
@Override
public void reload() {
// TODO Auto-generated method stub
}
@Override
protected void doStop() throws ServiceStopException {
templates.clear();
cacheService.dispose(templates);
templates = null;
unmarshaller = null;
context = null;
}

View File

@@ -18,11 +18,6 @@ package com.l2jserver.service.game.world;
import java.util.Collection;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.l2jserver.db.dao.CharacterDAO;
@@ -35,6 +30,7 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.ServiceStartException;
import com.l2jserver.service.ServiceStopException;
import com.l2jserver.service.cache.Cache;
import com.l2jserver.service.cache.CacheService;
import com.l2jserver.service.database.DatabaseService;
@@ -73,7 +69,7 @@ public class CachedWorldIDService extends AbstractService implements
/**
* The ID cache
*/
private Cache cache;
private Cache<Integer, ObjectID<?>> cache;
/**
* The loaded state
@@ -94,12 +90,8 @@ public class CachedWorldIDService extends AbstractService implements
@Override
protected void doStart() throws ServiceStartException {
// we allocate an cache which can fit all ids
cache = new Cache(new CacheConfiguration("id-cache",
IDAllocator.ALLOCABLE_IDS)
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU)
.overflowToDisk(true).eternal(true).diskPersistent(false)
.diskExpiryThreadIntervalSeconds(0));
cacheService.register(cache);
cache = cacheService.createEternalCache("id-cache",
IDAllocator.ALLOCABLE_IDS);
}
@Override
@@ -112,7 +104,7 @@ public class CachedWorldIDService extends AbstractService implements
@Override
public void unload() {
cache.removeAll();
cache.clear();
}
/**
@@ -137,17 +129,13 @@ public class CachedWorldIDService extends AbstractService implements
// ignore resolving before all IDs are loaded
return null;
}
final Element element = cache.get(id);
if (element == null)
return null;
return (I) element.getObjectValue();
return (I) cache.get(id);
}
@Override
public <I extends ObjectID<?>> void add(I id) {
Preconditions.checkNotNull(id, "id");
cache.put(new Element(id.getID(), id));
cache.put(id.getID(), id);
}
@Override
@@ -158,7 +146,7 @@ public class CachedWorldIDService extends AbstractService implements
@Override
protected void doStop() throws ServiceStopException {
cacheService.unregister(cache);
cacheService.dispose(cache);
cache = null;
allocator.clear();
}

View File

@@ -20,7 +20,7 @@ import com.l2jserver.model.world.PositionableObject;
import com.l2jserver.model.world.WorldObject;
import com.l2jserver.service.game.world.filter.AndFilter;
import com.l2jserver.service.game.world.filter.NotFilter;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* This filter will only accept {@link WorldObject} which are in vision of
@@ -32,7 +32,7 @@ public class KnownListUpdateFilter extends AndFilter<PositionableObject> {
public static final int KNOWNLIST_RANGE = 2000;
@SuppressWarnings("unchecked")
public KnownListUpdateFilter(PositionableObject object, Point old) {
public KnownListUpdateFilter(PositionableObject object, Point3D old) {
super(new KnownListFilter(object), new NotFilter<PositionableObject>(
new RangePointFilter(old, KNOWNLIST_RANGE)));
}

View File

@@ -19,7 +19,7 @@ package com.l2jserver.service.game.world.filter.impl;
import com.google.common.base.Preconditions;
import com.l2jserver.model.world.PositionableObject;
import com.l2jserver.service.game.world.filter.WorldObjectFilter;
import com.l2jserver.util.dimensional.Point;
import com.l2jserver.util.geometry.Point3D;
/**
* Filter objects that are in the <tt>range</tt> of <tt>coordinate</tt>
@@ -30,7 +30,7 @@ public class RangePointFilter implements WorldObjectFilter<PositionableObject> {
/**
* The coordinate point
*/
private final Point point;
private final Point3D point;
/**
* The desired maximum distance of the object
*/
@@ -44,7 +44,7 @@ public class RangePointFilter implements WorldObjectFilter<PositionableObject> {
* @param range
* the desired maximum distance of the object
*/
public RangePointFilter(final Point point, final int range) {
public RangePointFilter(final Point3D point, final int range) {
Preconditions.checkNotNull(point, "point");
Preconditions.checkState(range >= 0, "range < 0");
this.point = point;