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()){
Place place = places.next();
Collection<Vendor> v = place.get();
if (place.count() > 0){
if (!v.isEmpty()){
vendors = v.iterator();
nextVendor();
} else {

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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){

View File

@@ -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> {

View File

@@ -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;