Archived
0

optimize berkeleyDB

This commit is contained in:
iMoHax
2015-08-18 11:49:12 +03:00
parent 7ecdd03727
commit 3b9bbd3fbe
10 changed files with 135 additions and 36 deletions

View File

@@ -26,7 +26,7 @@ public class VendorsIterator implements Iterator<Vendor> {
if (places.hasNext()){ if (places.hasNext()){
Place place = places.next(); Place place = places.next();
Collection<Vendor> v = place.get(); Collection<Vendor> v = place.get();
if (place.count() > 0){ if (!v.isEmpty()){
vendors = v.iterator(); vendors = v.iterator();
nextVendor(); nextVendor();
} else { } else {

View File

@@ -102,6 +102,11 @@ public class BDBMarket extends AbstractMarket {
buyItems.remove(item); buyItems.remove(item);
} }
@Override
public Place get(String name) {
return store.getPlaceAccessor().get(name);
}
@Override @Override
public Collection<Place> get() { public Collection<Place> get() {
return store.getPlaceAccessor().getAll(); return store.getPlaceAccessor().getAll();
@@ -112,11 +117,25 @@ public class BDBMarket extends AbstractMarket {
return store.getGroupAccessor().getAll(); return store.getGroupAccessor().getAll();
} }
@Override
public Item getItem(String name) {
return store.getItemAccessor().get(name);
}
@Override @Override
public Collection<Item> getItems() { public Collection<Item> getItems() {
return store.getItemAccessor().getAll(); 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 @Override
public ItemStat getStat(OFFER_TYPE type, Item item) { public ItemStat getStat(OFFER_TYPE type, Item item) {
ItemStat entry = getItemCache(type).get(item); ItemStat entry = getItemCache(type).get(item);

View File

@@ -29,7 +29,7 @@ public class BDBStore {
EnvironmentConfig envConfig = new EnvironmentConfig(); EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true); envConfig.setAllowCreate(true);
envConfig.setSharedCache(true); envConfig.setSharedCache(true);
envConfig.setTransactional(true); envConfig.setTransactional(false);
dbEnvironment = new Environment(new File(path), envConfig); dbEnvironment = new Environment(new File(path), envConfig);
try { try {

View File

@@ -6,16 +6,19 @@ import ru.trader.store.berkeley.entities.BDBPlace;
import ru.trader.store.berkeley.entities.BDBVendor; import ru.trader.store.berkeley.entities.BDBVendor;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
public class PlaceProxy extends AbstractPlace { public class PlaceProxy extends AbstractPlace {
private final BDBPlace place; private final BDBPlace place;
private BDBStore store; private BDBStore store;
private long count; private Collection<Vendor> vendors;
private final ReentrantLock lock = new ReentrantLock();
public PlaceProxy(BDBPlace place, BDBStore store) { public PlaceProxy(BDBPlace place, BDBStore store) {
this.place = place; this.place = place;
this.store = store; this.store = store;
count = -1; vendors = null;
} }
public PlaceProxy(BDBPlace place, BDBMarket market, BDBStore store) { public PlaceProxy(BDBPlace place, BDBMarket market, BDBStore store) {
@@ -51,13 +54,25 @@ public class PlaceProxy extends AbstractPlace {
@Override @Override
protected void addVendor(Vendor vendor) { protected void addVendor(Vendor vendor) {
store.getVendorAccessor().put(((VendorProxy)vendor).getEntity()); store.getVendorAccessor().put(((VendorProxy)vendor).getEntity());
if (count != -1) count++; if (vendors != null || lock.isLocked()) {
unsafe( (v) -> {
if (vendors != null){
vendors.add(vendor);
}
});
}
} }
@Override @Override
protected void removeVendor(Vendor vendor) { protected void removeVendor(Vendor vendor) {
store.getVendorAccessor().delete(((VendorProxy)vendor).getEntity()); store.getVendorAccessor().delete(((VendorProxy)vendor).getEntity());
if (count != -1) count--; if (vendors != null || lock.isLocked()) {
unsafe( (v) -> {
if (vendors != null){
vendors.remove(vendor);
}
});
}
} }
@Override @Override
@@ -82,21 +97,28 @@ public class PlaceProxy extends AbstractPlace {
@Override @Override
public Collection<Vendor> get() { 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 @Override
public long count() { public long count() {
if (count == -1){ if (vendors != null){
count = store.getVendorAccessor().count(place.getId()); return vendors.size();
} }
return count; return get().size();
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
if (count > -1){ if (vendors != null){
return count == 0; return vendors.isEmpty();
} }
return !store.getVendorAccessor().contains(place.getId()); return !store.getVendorAccessor().contains(place.getId());
} }
@@ -117,4 +139,13 @@ public class PlaceProxy extends AbstractPlace {
public int hashCode() { public int hashCode() {
return place.hashCode(); return place.hashCode();
} }
private void unsafe(Consumer<Void> operation){
lock.lock();
try {
operation.accept(null);
} finally {
lock.unlock();
}
}
} }

View File

@@ -7,6 +7,8 @@ import ru.trader.store.berkeley.entities.BDBVendor;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
public class VendorProxy extends AbstractVendor { public class VendorProxy extends AbstractVendor {
private final BDBVendor vendor; private final BDBVendor vendor;
@@ -14,6 +16,7 @@ public class VendorProxy extends AbstractVendor {
private Place place; private Place place;
protected Map<Long, Offer> sell; protected Map<Long, Offer> sell;
protected Map<Long, Offer> buy; protected Map<Long, Offer> buy;
private final ReentrantLock lock = new ReentrantLock();
public VendorProxy(BDBVendor vendor, BDBStore store) { public VendorProxy(BDBVendor vendor, BDBStore store) {
this.vendor = vendor; this.vendor = vendor;
@@ -21,28 +24,38 @@ public class VendorProxy extends AbstractVendor {
} }
private void initSellCache(){ 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)) { for (Offer offer : store.getOfferAccessor().getAllByType(vendor.getId(), OFFER_TYPE.SELL)) {
sell.put(((ItemProxy)offer.getItem()).getId(), offer); sell.put(((ItemProxy)offer.getItem()).getId(), offer);
} }
this.sell = sell;
} }
private void initBuyCache(){ 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)) { for (Offer offer : store.getOfferAccessor().getAllByType(vendor.getId(), OFFER_TYPE.BUY)) {
buy.put(((ItemProxy)offer.getItem()).getId(), offer); buy.put(((ItemProxy)offer.getItem()).getId(), offer);
} }
this.buy = buy;
} }
private Map<Long, Offer> getCache(OFFER_TYPE type){ private Map<Long, Offer> getCache(OFFER_TYPE type){
if (type == OFFER_TYPE.SELL){ if (type == OFFER_TYPE.SELL){
if (sell == null){ if (sell == null){
initSellCache(); unsafe((v) -> {
if (sell == null){
initSellCache();
}
});
} }
return sell; return sell;
} else { } else {
if (buy == null){ if (buy == null){
initBuyCache(); unsafe((v) -> {
if (buy == null){
initBuyCache();
}
});
} }
return buy; return buy;
} }
@@ -120,7 +133,11 @@ public class VendorProxy extends AbstractVendor {
@Override @Override
public Place getPlace() { public Place getPlace() {
if (place == null){ if (place == null){
place = store.getPlaceAccessor().get(vendor.getPlaceId()); unsafe((v) -> {
if (place == null){
place = store.getPlaceAccessor().get(vendor.getPlaceId());
}
});
} }
return place; return place;
} }
@@ -166,4 +183,14 @@ public class VendorProxy extends AbstractVendor {
public int hashCode() { public int hashCode() {
return vendor.hashCode(); return vendor.hashCode();
} }
private void unsafe(Consumer<Void> operation){
lock.lock();
try {
operation.accept(null);
} finally {
lock.unlock();
}
}
} }

View File

@@ -4,6 +4,7 @@ package ru.trader.store.berkeley.dao;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate;
import com.sleepycat.persist.EntityCursor; import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityIndex; import com.sleepycat.persist.EntityIndex;
@@ -12,34 +13,52 @@ import com.sleepycat.persist.SecondaryIndex;
public class DAUtils { public class DAUtils {
public static <T, K, E> T get(EntityIndex<K, E> index, K key, Function<E, T> convertFunc){ 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){ 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<>(); Collection<T> res = new LinkedList<>();
try (EntityCursor<E> cursor = index.entities(from, true, to, true)){ try (EntityCursor<E> cursor = index.entities(from, true, to, true)){
for(E entity : cursor){ for(E entity : cursor){
res.add(convertFunc.apply(entity)); if (filter == null || filter.test(entity)){
res.add(convertFunc.apply(entity));
}
} }
} }
return res; return res;
} }
public static <T, E> Collection<T> getAll(EntityIndex<?, E> index, Function<E, T> convertFunc){ 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<>(); Collection<T> res = new LinkedList<>();
try (EntityCursor<E> cursor = index.entities()){ try (EntityCursor<E> cursor = index.entities()){
for(E entity : cursor){ for(E entity : cursor){
res.add(convertFunc.apply(entity)); if (filter == null || filter.test(entity)){
res.add(convertFunc.apply(entity));
}
} }
} }
return res; return res;
} }
public static <T, K, E> Collection<T> getAll(SecondaryIndex<K, ?, E> index, K key, Function<E, T> convertFunc){ 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<>(); Collection<T> res = new LinkedList<>();
try (EntityCursor<E> cursor = index.subIndex(key).entities()){ try (EntityCursor<E> cursor = index.subIndex(key).entities()){
for(E entity : cursor){ for(E entity : cursor){
res.add(convertFunc.apply(entity)); if (filter == null || filter.test(entity)){
res.add(convertFunc.apply(entity));
}
} }
} }
return res; return res;

View File

@@ -23,6 +23,11 @@ public class ItemDA<T> {
return DAUtils.get(indexById, id, convertFunc); 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(){ public Collection<T> getAll(){
return DAUtils.getAll(indexById, convertFunc); return DAUtils.getAll(indexById, convertFunc);
} }

View File

@@ -1,23 +1,23 @@
package ru.trader.store.berkeley.dao; package ru.trader.store.berkeley.dao;
import com.sleepycat.persist.EntityCursor;
import com.sleepycat.persist.EntityStore; import com.sleepycat.persist.EntityStore;
import com.sleepycat.persist.PrimaryIndex; import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.SecondaryIndex; import com.sleepycat.persist.SecondaryIndex;
import ru.trader.store.berkeley.entities.BDBPlace; import ru.trader.store.berkeley.entities.BDBPlace;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList;
import java.util.function.Function; import java.util.function.Function;
public class PlaceDA<T> { public class PlaceDA<T> {
private final PrimaryIndex<Long, BDBPlace> indexById; private final PrimaryIndex<Long, BDBPlace> indexById;
private final SecondaryIndex<String, Long, BDBPlace> indexByName;
private final SecondaryIndex<Double, Long, BDBPlace> indexByDistance; private final SecondaryIndex<Double, Long, BDBPlace> indexByDistance;
private Function<BDBPlace,T> convertFunc; private Function<BDBPlace,T> convertFunc;
public PlaceDA(EntityStore store, Function<BDBPlace, T> convertFunc) { public PlaceDA(EntityStore store, Function<BDBPlace, T> convertFunc) {
this.convertFunc = convertFunc; this.convertFunc = convertFunc;
this.indexById = store.getPrimaryIndex(Long.class, BDBPlace.class); this.indexById = store.getPrimaryIndex(Long.class, BDBPlace.class);
this.indexByName = store.getSecondaryIndex(indexById, String.class, "name");
this.indexByDistance = store.getSecondaryIndex(indexById, Double.class, "distance"); this.indexByDistance = store.getSecondaryIndex(indexById, Double.class, "distance");
} }
@@ -29,22 +29,20 @@ public class PlaceDA<T> {
return DAUtils.get(indexById, id, convertFunc); return DAUtils.get(indexById, id, convertFunc);
} }
public T get(String name){
return DAUtils.get(indexByName, name, convertFunc);
}
public Collection<T> getAll(){ public Collection<T> getAll(){
return DAUtils.getAll(indexById, convertFunc); return DAUtils.getAll(indexById, convertFunc);
} }
public Collection<T> getAll(double x, double y, double z, double radius){ 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)); double center = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
Collection<T> res = new LinkedList<>(); return DAUtils.get(indexByDistance, center < radius? 0 : center - radius, center + radius, convertFunc, entity -> {
try (EntityCursor<BDBPlace> cursor = indexByDistance.entities(center < radius? 0 : center - radius, true, center + radius, true)) 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;
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;
} }
public BDBPlace put(BDBPlace place){ public BDBPlace put(BDBPlace place){

View File

@@ -4,7 +4,6 @@ import com.sleepycat.persist.*;
import ru.trader.store.berkeley.entities.BDBVendor; import ru.trader.store.berkeley.entities.BDBVendor;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList;
import java.util.function.Function; import java.util.function.Function;
public class VendorDA<T> { public class VendorDA<T> {

View File

@@ -5,7 +5,7 @@ import com.sleepycat.persist.model.PrimaryKey;
import com.sleepycat.persist.model.Relationship; import com.sleepycat.persist.model.Relationship;
import com.sleepycat.persist.model.SecondaryKey; import com.sleepycat.persist.model.SecondaryKey;
@Entity(version = 1) @Entity(version = 2)
public class BDBPlace { public class BDBPlace {
@PrimaryKey(sequence = "P_ID") @PrimaryKey(sequence = "P_ID")
@@ -14,6 +14,7 @@ public class BDBPlace {
@SecondaryKey(relate = Relationship.MANY_TO_ONE) @SecondaryKey(relate = Relationship.MANY_TO_ONE)
private double distance; private double distance;
@SecondaryKey(relate = Relationship.MANY_TO_ONE)
private String name; private String name;
private double x; private double x;
private double y; private double y;