package com.cloudera.fraud.example.service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.cloudera.fraud.example.model.ItemSaleEvent;
import com.cloudera.fraud.example.model.ProfilePojo;
public class LocalCacheFraudService extends AbstractCacheFraudService{
public LocalCacheFraudService(AbstractFraudHBaseService hbaseService) {
super(hbaseService);
}
static ConcurrentMap<Long, ProfilePojo> localCache = new ConcurrentHashMap<Long, ProfilePojo>();
public static int maxCacheSize = 50000;
public static int cacheWaterMark = 30000;
protected ProfilePurchasePar getProfile(ItemSaleEvent event) throws IOException {
ProfilePojo buyer = localCache.get(event.getBuyingId());
ProfilePojo seller = localCache.get(event.getSellingId());
if (buyer == null || seller == null) {
ArrayList<Long> userIdToFetch = new ArrayList<Long>();
if (buyer == null) { userIdToFetch.add(event.getBuyingId()); }
if (seller == null) { userIdToFetch.add(event.getSellingId()); }
ProfilePojo[] profilesFromHBase = getProfilesFromHBase(userIdToFetch);
int counter = 0;
if (buyer == null) {
buyer = profilesFromHBase[counter++];
localCache.putIfAbsent(event.getBuyingId(), buyer);
}
if (seller == null) {
seller = profilesFromHBase[counter++];
localCache.putIfAbsent(event.getSellingId(), seller);
}
}
trimCache();
return new ProfilePurchasePar(buyer, seller);
}
@Override
protected void updateProfileCountsForSale(Long buyerId, Long sellerId,
ItemSaleEvent event) throws IOException, InterruptedException {
ProfilePojo buyer = localCache.get(buyerId);
buyer.incrementCurrentLogInPurchasesValue(event.getItemValue());
buyer.incrementTotalPurchases(1);
ProfilePojo seller = localCache.get(sellerId);
seller.incrementCurrentLogInSellsValue(event.getItemValue());
seller.incrementTotalSells(1);
updateProfileCountsForSaleInHBase(buyerId, sellerId, event);
}
@Override
protected void logInProfile(long userId, String ipAddress) throws Exception {
logInProfileInHBase(userId, ipAddress);
}
protected void trimCache() {
while (localCache.size() > cacheWaterMark) {
synchronized(localCache) {
long currentTime = System.currentTimeMillis();
ArrayList<Long> deleteList = new ArrayList<Long>();
for (Entry<Long, ProfilePojo> entry: localCache.entrySet()) {
if (currentTime - entry.getValue().getCreatedTimeStamp() > 10000) {
deleteList.add(entry.getKey());
}
}
for (Long rowKey: deleteList) {
localCache.remove(rowKey);
}
}
}
while (localCache.size() > maxCacheSize) {
synchronized(localCache) {
Iterator<Long> it = localCache.keySet().iterator();
ArrayList<Long> deleteList = new ArrayList<Long>();
for (int i = 0; i < localCache.size()-maxCacheSize; i++) {
deleteList.add(it.next());
}
for (Long rowKey: deleteList) {
localCache.remove(rowKey);
}
}
}
}
}