es.bsc.amon.controller.AppsDBMapper.java Source code

Java tutorial

Introduction

Here is the source code for es.bsc.amon.controller.AppsDBMapper.java

Source

/*
 * Author: Mario Macias (Barcelona Supercomputing Center). 2014
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library 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 Lesser General Public License for more details:
 *
 * http://www.gnu.org/licenses/lgpl-2.1.html
 */

package es.bsc.amon.controller;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mongodb.*;
import com.mongodb.util.JSON;
import es.bsc.amon.DBManager;
import play.Logger;

import java.util.*;

/**
 * Created by mmacias on 08/06/14.
 */
public class AppsDBMapper {
    private static AppsDBMapper instance;
    private DBCollection colAppInstances;

    private AppsDBMapper() {
        // default table size to 64 MB
        Logger.info("Creating collection '" + COLL_NAME + "'...");
        Properties config = DBManager.instance.getConfig();
        DB database = DBManager.instance.getDatabase();

        try {

            int collectionSize = Integer.parseInt(config.getProperty("collection.size"));
            colAppInstances = database.createCollection(COLL_NAME, new BasicDBObject("capped", true) //enable round robin database
                    .append("size", collectionSize));

        } catch (MongoException cfe) {
            if (cfe.getCode() == DBManager.COLLECTION_ALREADY_EXISTS) {
                Logger.info("Collection '" + COLL_NAME + "' already exists. Continuing normally...");
            }
            colAppInstances = database.getCollection(COLL_NAME);
        }

        // compound index events by timestamp, appId and nodeId
        BasicDBObject indexInfo = new BasicDBObject();
        indexInfo.put(EventsDBMapper.TIMESTAMP, -1); // 1 for ascending, -1 for descending
        colAppInstances.createIndex(indexInfo);
    }

    public static AppsDBMapper getInstance() {
        if (instance == null) {
            instance = new AppsDBMapper();
        }
        return instance;
    }

    public void addAppInstance(String appInstanceJson) {
        BasicDBObject dbo = (BasicDBObject) JSON.parse(appInstanceJson);
        BasicDBObject data = ((BasicDBObject) dbo.get(FIELD_DATA));
        if (data == null || dbo.get(FIELD_APP_ID) == null || dbo.get(FIELD_INSTANCE_ID) == null
                || data.get(FIELD_DATA_START) == null || data.get(FIELD_DATA_END) == null
                || data.get(FIELD_DATA_POWER) == null) {
            throw new AppException("The App document must have the following structure:\n" + "{'appId' : ...\n"
                    + "'instanceId' : ...\n" + "'data' : {\n" + "\t'start' : ....\n" + "\t'end' : ....\n"
                    + "\t'power' : ....\n" + "}}");
        }
        long timestamp = System.currentTimeMillis();
        dbo.put(FIELD_TIMESTAMP, timestamp);
        colAppInstances.insert(dbo);
    }

    /**
     *
     * @param start
     * @param end
     * @param showInstances if true, shows instances information instead of nodes information
     * @return
     */
    public ObjectNode getAllApps(long start, long end, boolean showInstances) {
        DBObject query = (DBObject) JSON.parse("{ '$or' : [" + "{ '$and' : [ { timestamp : { '$gte' : " + start
                + " }}, { timestamp : {'$lte' : " + end + "}} ] }," + "{ '$and' : [ { endtime : { '$gte' : " + start
                + " }}, { endtime : {'$lte' : " + end + "}} ] }" + "]}");
        //DBObject orderby = new BasicDBObject("timestamp":-1);
        BasicDBList ret = DBManager.instance.find(EventsDBMapper.COLL_NAME, query);

        Map<String, Set<String>> appsInfo = new HashMap<>();

        Iterator<Object> iter = ret.iterator();
        while (iter.hasNext()) {
            DBObject event = (DBObject) iter.next();
            try {
                String appName = event.get(EventsDBMapper.APPID).toString();
                Object node = event.get(showInstances ? EventsDBMapper.INSTANCEID : EventsDBMapper.NODEID);
                String nodeName = node == null ? "" : node.toString();
                Set<String> appSet = appsInfo.get(appName);
                if (appSet == null) {
                    appSet = new TreeSet<String>();
                    appsInfo.put(appName, appSet);
                }
                appSet.add(nodeName);
            } catch (NullPointerException ex) {
                Logger.warn("This element did not parsed as an application: " + event.toString()
                        + ". Removing it from DB...");
                try {
                    EventsDBMapper.getInstance().remove(event);
                } catch (Exception e) {
                    Logger.error("Cannot remove it from database");
                }
            }
        }

        ObjectNode all = new ObjectNode(JsonNodeFactory.instance);
        for (Map.Entry<String, Set<String>> entry : appsInfo.entrySet()) {
            ArrayNode nodes = new ArrayNode(JsonNodeFactory.instance);
            for (String n : entry.getValue()) {
                nodes.add(n);
            }
            all.put(entry.getKey(), nodes);
        }
        return all;
    }

    public String getFinishedAppInstances(long start, long end, int limit) {
        DBObject query = (DBObject) JSON.parse("{ '$or' : [" + "{ '$and' : [ { timestamp : { '$gte' : " + start
                + " }}, { timestamp : {'$lte' : " + end + "}} ] }," + "{ '$and' : [ { endtime : { '$gte' : " + start
                + " }}, { endtime : {'$lte' : " + end + "}} ] }" + "]}");
        BasicDBList ret = DBManager.instance.find(COLL_NAME, query, null, limit);
        return ret.toString();
    }

    public static final String FIELD_TIMESTAMP = "timestamp";
    public static final String FIELD_APP_ID = "appId";
    public static final String FIELD_INSTANCE_ID = "instanceId";
    public static final String FIELD_DATA = "data";
    public static final String FIELD_DATA_START = "start";
    public static final String FIELD_DATA_END = "end";
    public static final String FIELD_DATA_POWER = "power";
    public static final String COLL_NAME = "appinstances";

    public class AppException extends RuntimeException {
        public AppException(String message) {
            super(message);
        }
    }
}