com.nokia.mole.DynamoDB.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.mole.DynamoDB.java

Source

/*
 * 
 * Mole - Mobile Organic Localisation Engine
 * Copyright (C) 2010 Nokia Corporation.  All rights reserved.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.nokia.mole;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodb.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodb.model.AttributeValue;
import com.amazonaws.services.dynamodb.model.DeleteItemRequest;
import com.amazonaws.services.dynamodb.model.GetItemRequest;
import com.amazonaws.services.dynamodb.model.GetItemResult;
import com.amazonaws.services.dynamodb.model.Key;
import com.amazonaws.services.dynamodb.model.PutItemRequest;
import com.amazonaws.services.dynamodb.model.ScanRequest;
import com.amazonaws.services.dynamodb.model.ScanResult;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.nokia.nrcc.TransientMapCache;

public class DynamoDB extends AbstractDB implements DB {

    static Logger log = Logger.getLogger(DynamoDB.class);
    AmazonDynamoDBClient client;
    Gson gson;
    static String loc2fpTable = "loc2fp";
    static String locAttr = "Location";
    static String fpAttr = "Fingerprint";

    static String mac2locsTable = "mac2locs";
    static String macAttr = "Mac";
    static String locsAttr = "Locations";
    Type locationListType = new TypeToken<ArrayList<Location>>() {
    }.getType();
    Type fingerprintType = new TypeToken<Fingerprint>() {
    }.getType();

    TransientMapCache<Location, Fingerprint> loc2fpCache;
    TransientMapCache<Mac, Set<Location>> mac2locCache;
    final boolean useCache;

    public DynamoDB(int cachePeriod) {
        log.info("Starting Dynamo DB");

        GsonBuilder gBuilder = new GsonBuilder();
        gBuilder.registerTypeAdapter(Mac.class, new Mac().new MacDeserializer()).create();
        gson = gBuilder.create();
        String key = MoleWS.getProperty("moleWS.aws_key");
        String secret = MoleWS.getProperty("moleWS.aws_secret");
        if (key == null || secret == null) {
            log.fatal("aws_key or aws_secret not found");
        }
        AWSCredentials credentials = new BasicAWSCredentials(key, secret);
        client = new AmazonDynamoDBClient(credentials);

        if (cachePeriod > 0) {
            useCache = true;
            loc2fpCache = new TransientMapCache<Location, Fingerprint>(cachePeriod);
            mac2locCache = new TransientMapCache<Mac, Set<Location>>(cachePeriod);
        } else {
            useCache = false;
        }

    }

    // Map<Location,Fingerprint> operations

    @Override
    boolean containsKey(Location location) {
        Fingerprint fingerprint = get(location);
        if (fingerprint != null) {
            return true;
        }
        return false;
    }

    @Override
    Fingerprint get(Location location) {
        if (useCache) {
            Fingerprint cachedFP = loc2fpCache.get(location);
            if (cachedFP != null) {
                log.warn("found cached fp");
                return cachedFP;
            }
        }

        String locationJson = gson.toJson(location);
        GetItemRequest getItemRequest = new GetItemRequest().withTableName(loc2fpTable)
                .withKey(new Key().withHashKeyElement(new AttributeValue().withS(locationJson)))
                .withAttributesToGet(fpAttr);

        GetItemResult result = client.getItem(getItemRequest);
        Map<String, AttributeValue> results = result.getItem();

        if (results != null && results.containsKey(fpAttr)) {
            AttributeValue value = results.get(fpAttr);
            String json = value.getS();
            assert (json.length() > 2);
            Fingerprint fingerprint = gson.fromJson(json, fingerprintType);
            if (useCache) {
                loc2fpCache.put(location, fingerprint);
            }
            return fingerprint;
        }
        return null;
    }

    @Override
    void put(Location location, Fingerprint fp) {
        Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
        String locationJson = gson.toJson(location);
        String fpJson = gson.toJson(fp, fingerprintType);
        item.put(locAttr, new AttributeValue().withS(locationJson));
        item.put(fpAttr, new AttributeValue().withS(fpJson));
        PutItemRequest itemRequest = new PutItemRequest().withTableName(loc2fpTable).withItem(item);
        client.putItem(itemRequest);
        if (useCache) {
            loc2fpCache.put(location, fp);
        }
    }

    @Override
    void remove(Location location) {
        String locationJson = gson.toJson(location);
        Key key = new Key().withHashKeyElement(new AttributeValue().withS(locationJson));
        DeleteItemRequest deleteItemRequest = new DeleteItemRequest().withTableName(loc2fpTable).withKey(key);
        client.deleteItem(deleteItemRequest);
        if (useCache) {
            loc2fpCache.remove(location);
        }
    }

    void clearTable(String tableName, String keyName) {
        int deleteCount = 0;
        try {
            ScanRequest scan = new ScanRequest().withTableName(tableName);
            ScanResult result = client.scan(scan);
            for (Map<String, AttributeValue> item : result.getItems()) {
                log.warn("item" + item);
                AttributeValue value = item.get(keyName);
                Key key = new Key().withHashKeyElement(value);
                DeleteItemRequest deleteItemRequest = new DeleteItemRequest().withTableName(tableName).withKey(key);
                client.deleteItem(deleteItemRequest);
                deleteCount++;
            }
        } catch (Exception ex) {
            log.fatal("clear exception= " + ex);
            System.exit(-1);
        }
        log.warn("finished clear table=" + tableName + " deleted=" + deleteCount);
    }

    @Override
    void clearLocations() {
        clearTable(loc2fpTable, locAttr);
        if (useCache) {
            loc2fpCache.clear();
        }
    }

    // Map<Mac,Set<Location>> operations

    @Override
    boolean containsKey(Mac mac) {
        Set<Location> locations = get(mac);
        if (locations != null) {
            return true;
        }
        return false;
    }

    @Override
    Set<Location> get(Mac mac) {
        if (useCache) {
            Set<Location> cachedLocations = mac2locCache.get(mac);
            if (cachedLocations != null) {
                log.warn("found cached locations");
                return cachedLocations;
            }
        }

        String macJson = gson.toJson(mac);
        GetItemRequest getItemRequest = new GetItemRequest().withTableName(mac2locsTable)
                .withKey(new Key().withHashKeyElement(new AttributeValue().withS(macJson)))
                .withAttributesToGet(locsAttr);

        GetItemResult result = client.getItem(getItemRequest);
        Map<String, AttributeValue> results = result.getItem();
        // we receive null if it's not found
        if (results != null && results.containsKey(locsAttr)) {
            AttributeValue value = results.get(locsAttr);
            String locationsJson = value.getS();
            assert (locationsJson.length() > 2);
            List<Location> locationList = gson.fromJson(locationsJson, locationListType);
            Set<Location> locations = new HashSet<Location>(locationList);
            if (useCache) {
                mac2locCache.put(mac, locations);
            }
            return locations;
        }
        return null;
    }

    @Override
    void put(Mac mac, Set<Location> locations) {
        Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
        String macJson = gson.toJson(mac);
        String locationsJson = gson.toJson(locations, locationListType);
        item.put(macAttr, new AttributeValue().withS(macJson));
        item.put(locsAttr, new AttributeValue().withS(locationsJson));
        PutItemRequest itemRequest = new PutItemRequest().withTableName(mac2locsTable).withItem(item);
        client.putItem(itemRequest);
        if (useCache) {
            mac2locCache.put(mac, locations);
        }
    }

    @Override
    void remove(Mac mac) {
        String macJson = gson.toJson(mac);
        Key key = new Key().withHashKeyElement(new AttributeValue().withS(macJson));
        DeleteItemRequest deleteItemRequest = new DeleteItemRequest().withTableName(mac2locsTable).withKey(key);
        client.deleteItem(deleteItemRequest);
        if (useCache) {
            mac2locCache.remove(mac);
        }
    }

    @Override
    void clearMacs() {
        clearTable(mac2locsTable, macAttr);
        mac2locCache.clear();
    }

    // Map<Location, Scans>.... not implemented -- we may want to do something different

    @Override
    public Map<Location, List<Scan>> getLocationScans() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    void put(Location location, List<Scan> scans) {
        // TODO Auto-generated method stub

    }

}