optimize berkeleyDB
This commit is contained in:
@@ -26,7 +26,7 @@ public class VendorsIterator implements Iterator<Vendor> {
|
||||
if (places.hasNext()){
|
||||
Place place = places.next();
|
||||
Collection<Vendor> v = place.get();
|
||||
if (place.count() > 0){
|
||||
if (!v.isEmpty()){
|
||||
vendors = v.iterator();
|
||||
nextVendor();
|
||||
} else {
|
||||
|
||||
@@ -102,6 +102,11 @@ public class BDBMarket extends AbstractMarket {
|
||||
buyItems.remove(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Place get(String name) {
|
||||
return store.getPlaceAccessor().get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Place> get() {
|
||||
return store.getPlaceAccessor().getAll();
|
||||
@@ -112,11 +117,25 @@ public class BDBMarket extends AbstractMarket {
|
||||
return store.getGroupAccessor().getAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getItem(String name) {
|
||||
return store.getItemAccessor().get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Item> getItems() {
|
||||
return store.getItemAccessor().getAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Vendor> getVendors(boolean includeTransit) {
|
||||
Collection<Vendor> vendors = store.getVendorAccessor().getAll();
|
||||
if (includeTransit){
|
||||
store.getPlaceAccessor().getAll().stream().map(Place::asTransit).forEach(vendors::add);
|
||||
}
|
||||
return vendors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStat getStat(OFFER_TYPE type, Item item) {
|
||||
ItemStat entry = getItemCache(type).get(item);
|
||||
|
||||
@@ -29,7 +29,7 @@ public class BDBStore {
|
||||
EnvironmentConfig envConfig = new EnvironmentConfig();
|
||||
envConfig.setAllowCreate(true);
|
||||
envConfig.setSharedCache(true);
|
||||
envConfig.setTransactional(true);
|
||||
envConfig.setTransactional(false);
|
||||
dbEnvironment = new Environment(new File(path), envConfig);
|
||||
|
||||
try {
|
||||
|
||||
@@ -6,16 +6,19 @@ import ru.trader.store.berkeley.entities.BDBPlace;
|
||||
import ru.trader.store.berkeley.entities.BDBVendor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PlaceProxy extends AbstractPlace {
|
||||
private final BDBPlace place;
|
||||
private BDBStore store;
|
||||
private long count;
|
||||
private Collection<Vendor> vendors;
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public PlaceProxy(BDBPlace place, BDBStore store) {
|
||||
this.place = place;
|
||||
this.store = store;
|
||||
count = -1;
|
||||
vendors = null;
|
||||
}
|
||||
|
||||
public PlaceProxy(BDBPlace place, BDBMarket market, BDBStore store) {
|
||||
@@ -51,13 +54,25 @@ public class PlaceProxy extends AbstractPlace {
|
||||
@Override
|
||||
protected void addVendor(Vendor vendor) {
|
||||
store.getVendorAccessor().put(((VendorProxy)vendor).getEntity());
|
||||
if (count != -1) count++;
|
||||
if (vendors != null || lock.isLocked()) {
|
||||
unsafe( (v) -> {
|
||||
if (vendors != null){
|
||||
vendors.add(vendor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeVendor(Vendor vendor) {
|
||||
store.getVendorAccessor().delete(((VendorProxy)vendor).getEntity());
|
||||
if (count != -1) count--;
|
||||
if (vendors != null || lock.isLocked()) {
|
||||
unsafe( (v) -> {
|
||||
if (vendors != null){
|
||||
vendors.remove(vendor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,21 +97,28 @@ public class PlaceProxy extends AbstractPlace {
|
||||
|
||||
@Override
|
||||
public Collection<Vendor> get() {
|
||||
return store.getVendorAccessor().getAllByPlace(place.getId());
|
||||
if (vendors == null){
|
||||
unsafe( (v) -> {
|
||||
if (vendors == null){
|
||||
vendors = store.getVendorAccessor().getAllByPlace(place.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
return vendors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
if (count == -1){
|
||||
count = store.getVendorAccessor().count(place.getId());
|
||||
if (vendors != null){
|
||||
return vendors.size();
|
||||
}
|
||||
return count;
|
||||
return get().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if (count > -1){
|
||||
return count == 0;
|
||||
if (vendors != null){
|
||||
return vendors.isEmpty();
|
||||
}
|
||||
return !store.getVendorAccessor().contains(place.getId());
|
||||
}
|
||||
@@ -117,4 +139,13 @@ public class PlaceProxy extends AbstractPlace {
|
||||
public int hashCode() {
|
||||
return place.hashCode();
|
||||
}
|
||||
|
||||
private void unsafe(Consumer<Void> operation){
|
||||
lock.lock();
|
||||
try {
|
||||
operation.accept(null);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import ru.trader.store.berkeley.entities.BDBVendor;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class VendorProxy extends AbstractVendor {
|
||||
private final BDBVendor vendor;
|
||||
@@ -14,6 +16,7 @@ public class VendorProxy extends AbstractVendor {
|
||||
private Place place;
|
||||
protected Map<Long, Offer> sell;
|
||||
protected Map<Long, Offer> buy;
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public VendorProxy(BDBVendor vendor, BDBStore store) {
|
||||
this.vendor = vendor;
|
||||
@@ -21,28 +24,38 @@ public class VendorProxy extends AbstractVendor {
|
||||
}
|
||||
|
||||
private void initSellCache(){
|
||||
sell = new ConcurrentHashMap<>(20, 0.9f, 2);
|
||||
Map<Long, Offer> sell = new ConcurrentHashMap<>(20, 0.9f, 2);
|
||||
for (Offer offer : store.getOfferAccessor().getAllByType(vendor.getId(), OFFER_TYPE.SELL)) {
|
||||
sell.put(((ItemProxy)offer.getItem()).getId(), offer);
|
||||
}
|
||||
this.sell = sell;
|
||||
}
|
||||
|
||||
private void initBuyCache(){
|
||||
buy = new ConcurrentHashMap<>(20, 0.9f, 2);
|
||||
Map<Long, Offer> buy = new ConcurrentHashMap<>(20, 0.9f, 2);
|
||||
for (Offer offer : store.getOfferAccessor().getAllByType(vendor.getId(), OFFER_TYPE.BUY)) {
|
||||
buy.put(((ItemProxy)offer.getItem()).getId(), offer);
|
||||
}
|
||||
this.buy = buy;
|
||||
}
|
||||
|
||||
private Map<Long, Offer> getCache(OFFER_TYPE type){
|
||||
if (type == OFFER_TYPE.SELL){
|
||||
if (sell == null){
|
||||
initSellCache();
|
||||
unsafe((v) -> {
|
||||
if (sell == null){
|
||||
initSellCache();
|
||||
}
|
||||
});
|
||||
}
|
||||
return sell;
|
||||
} else {
|
||||
if (buy == null){
|
||||
initBuyCache();
|
||||
unsafe((v) -> {
|
||||
if (buy == null){
|
||||
initBuyCache();
|
||||
}
|
||||
});
|
||||
}
|
||||
return buy;
|
||||
}
|
||||
@@ -120,7 +133,11 @@ public class VendorProxy extends AbstractVendor {
|
||||
@Override
|
||||
public Place getPlace() {
|
||||
if (place == null){
|
||||
place = store.getPlaceAccessor().get(vendor.getPlaceId());
|
||||
unsafe((v) -> {
|
||||
if (place == null){
|
||||
place = store.getPlaceAccessor().get(vendor.getPlaceId());
|
||||
}
|
||||
});
|
||||
}
|
||||
return place;
|
||||
}
|
||||
@@ -166,4 +183,14 @@ public class VendorProxy extends AbstractVendor {
|
||||
public int hashCode() {
|
||||
return vendor.hashCode();
|
||||
}
|
||||
|
||||
private void unsafe(Consumer<Void> operation){
|
||||
lock.lock();
|
||||
try {
|
||||
operation.accept(null);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package ru.trader.store.berkeley.dao;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.sleepycat.persist.EntityCursor;
|
||||
import com.sleepycat.persist.EntityIndex;
|
||||
@@ -12,34 +13,52 @@ import com.sleepycat.persist.SecondaryIndex;
|
||||
public class DAUtils {
|
||||
|
||||
public static <T, K, E> T get(EntityIndex<K, E> index, K key, Function<E, T> convertFunc){
|
||||
return convertFunc.apply(index.get(key));
|
||||
E entry = index.get(key);
|
||||
return entry != null ? convertFunc.apply(entry) : null;
|
||||
}
|
||||
|
||||
public static <T, K, E> Collection<T> get(EntityIndex<K, E> index, K from, K to, Function<E, T> convertFunc){
|
||||
return get(index, from, to, convertFunc, null);
|
||||
}
|
||||
|
||||
public static <T, K, E> Collection<T> get(EntityIndex<K, E> index, K from, K to, Function<E, T> convertFunc, Predicate<E> filter){
|
||||
Collection<T> res = new LinkedList<>();
|
||||
try (EntityCursor<E> cursor = index.entities(from, true, to, true)){
|
||||
for(E entity : cursor){
|
||||
res.add(convertFunc.apply(entity));
|
||||
if (filter == null || filter.test(entity)){
|
||||
res.add(convertFunc.apply(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static <T, E> Collection<T> getAll(EntityIndex<?, E> index, Function<E, T> convertFunc){
|
||||
return getAll(index, convertFunc, null);
|
||||
}
|
||||
|
||||
public static <T, E> Collection<T> getAll(EntityIndex<?, E> index, Function<E, T> convertFunc, Predicate<E> filter){
|
||||
Collection<T> res = new LinkedList<>();
|
||||
try (EntityCursor<E> cursor = index.entities()){
|
||||
for(E entity : cursor){
|
||||
res.add(convertFunc.apply(entity));
|
||||
if (filter == null || filter.test(entity)){
|
||||
res.add(convertFunc.apply(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static <T, K, E> Collection<T> getAll(SecondaryIndex<K, ?, E> index, K key, Function<E, T> convertFunc){
|
||||
return getAll(index, key, convertFunc, null);
|
||||
}
|
||||
|
||||
public static <T, K, E> Collection<T> getAll(SecondaryIndex<K, ?, E> index, K key, Function<E, T> convertFunc, Predicate<E> filter){
|
||||
Collection<T> res = new LinkedList<>();
|
||||
try (EntityCursor<E> cursor = index.subIndex(key).entities()){
|
||||
for(E entity : cursor){
|
||||
res.add(convertFunc.apply(entity));
|
||||
if (filter == null || filter.test(entity)){
|
||||
res.add(convertFunc.apply(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
@@ -23,6 +23,11 @@ public class ItemDA<T> {
|
||||
return DAUtils.get(indexById, id, convertFunc);
|
||||
}
|
||||
|
||||
public T get(String name){
|
||||
Collection<T> items = DAUtils.getAll(indexById, convertFunc, item -> item.getName().equals(name));
|
||||
return items.isEmpty() ? null : items.iterator().next();
|
||||
}
|
||||
|
||||
public Collection<T> getAll(){
|
||||
return DAUtils.getAll(indexById, convertFunc);
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package ru.trader.store.berkeley.dao;
|
||||
|
||||
import com.sleepycat.persist.EntityCursor;
|
||||
import com.sleepycat.persist.EntityStore;
|
||||
import com.sleepycat.persist.PrimaryIndex;
|
||||
import com.sleepycat.persist.SecondaryIndex;
|
||||
import ru.trader.store.berkeley.entities.BDBPlace;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PlaceDA<T> {
|
||||
private final PrimaryIndex<Long, BDBPlace> indexById;
|
||||
private final SecondaryIndex<String, Long, BDBPlace> indexByName;
|
||||
private final SecondaryIndex<Double, Long, BDBPlace> indexByDistance;
|
||||
private Function<BDBPlace,T> convertFunc;
|
||||
|
||||
public PlaceDA(EntityStore store, Function<BDBPlace, T> convertFunc) {
|
||||
this.convertFunc = convertFunc;
|
||||
this.indexById = store.getPrimaryIndex(Long.class, BDBPlace.class);
|
||||
this.indexByName = store.getSecondaryIndex(indexById, String.class, "name");
|
||||
this.indexByDistance = store.getSecondaryIndex(indexById, Double.class, "distance");
|
||||
}
|
||||
|
||||
@@ -29,22 +29,20 @@ public class PlaceDA<T> {
|
||||
return DAUtils.get(indexById, id, convertFunc);
|
||||
}
|
||||
|
||||
public T get(String name){
|
||||
return DAUtils.get(indexByName, name, convertFunc);
|
||||
}
|
||||
|
||||
public Collection<T> getAll(){
|
||||
return DAUtils.getAll(indexById, convertFunc);
|
||||
}
|
||||
|
||||
public Collection<T> getAll(double x, double y, double z, double radius){
|
||||
double center = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
|
||||
Collection<T> res = new LinkedList<>();
|
||||
try (EntityCursor<BDBPlace> cursor = indexByDistance.entities(center < radius? 0 : center - radius, true, center + radius, true))
|
||||
{
|
||||
for(BDBPlace entity : cursor){
|
||||
double distance = Math.sqrt(Math.pow(x - entity.getX(), 2) + Math.pow(y - entity.getY(), 2) + Math.pow(z - entity.getZ(), 2));
|
||||
if (distance <= radius)
|
||||
res.add(convertFunc.apply(entity));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
return DAUtils.get(indexByDistance, center < radius? 0 : center - radius, center + radius, convertFunc, entity -> {
|
||||
double distance = Math.sqrt(Math.pow(x - entity.getX(), 2) + Math.pow(y - entity.getY(), 2) + Math.pow(z - entity.getZ(), 2));
|
||||
return distance <= radius;
|
||||
});
|
||||
}
|
||||
|
||||
public BDBPlace put(BDBPlace place){
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.sleepycat.persist.*;
|
||||
import ru.trader.store.berkeley.entities.BDBVendor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class VendorDA<T> {
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.sleepycat.persist.model.PrimaryKey;
|
||||
import com.sleepycat.persist.model.Relationship;
|
||||
import com.sleepycat.persist.model.SecondaryKey;
|
||||
|
||||
@Entity(version = 1)
|
||||
@Entity(version = 2)
|
||||
public class BDBPlace {
|
||||
|
||||
@PrimaryKey(sequence = "P_ID")
|
||||
@@ -14,6 +14,7 @@ public class BDBPlace {
|
||||
@SecondaryKey(relate = Relationship.MANY_TO_ONE)
|
||||
private double distance;
|
||||
|
||||
@SecondaryKey(relate = Relationship.MANY_TO_ONE)
|
||||
private String name;
|
||||
private double x;
|
||||
private double y;
|
||||
|
||||
Reference in New Issue
Block a user