org.peerfact.impl.overlay.dht.kademlia.base.WorkloadGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.peerfact.impl.overlay.dht.kademlia.base.WorkloadGenerator.java

Source

/*
 * Copyright (c) 2012-2013 Open Source Community - <http://www.peerfact.org>
 * Copyright (c) 2011-2012 University of Paderborn - UPB
 * Copyright (c) 2005-2011 KOM - Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package org.peerfact.impl.overlay.dht.kademlia.base;

import java.math.BigInteger;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;

import org.apache.commons.math.random.RandomAdaptor;
import org.apache.log4j.Logger;
import org.peerfact.api.overlay.dht.DHTObject;
import org.peerfact.api.scenario.Configurable;
import org.peerfact.impl.overlay.dht.kademlia.base.components.AbstractNodeFactory;
import org.peerfact.impl.overlay.dht.kademlia.base.components.KademliaOverlayKey;
import org.peerfact.impl.overlay.dht.kademlia.base.components.Node;
import org.peerfact.impl.overlay.dht.kademlia.hkademlia.components.HKademliaOverlayID;
import org.peerfact.impl.simengine.Simulator;
import org.peerfact.impl.util.logging.SimLogger;

/**
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * This part of the Simulator is not maintained in the current version of
 * PeerfactSim.KOM. There is no intention of the authors to fix this
 * circumstances, since the changes needed are huge compared to overall benefit.
 * 
 * If you want it to work correctly, you are free to make the specific changes
 * and provide it to the community.
 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * 
 * Generates work that has to be carried out by the nodes in the overlay
 * network. For instance, this class generates data items and random lookup keys
 * for these items.
 * 
 * @author Tobias Lauinger <tl1003@rbg.informatik.tu-darmstadt.de>
 * @version 05/06/2011
 */
public class WorkloadGenerator implements Configurable {

    private final static Logger log = SimLogger.getLogger(WorkloadGenerator.class);

    /**
     * A Collection that contains all data items that are available in the
     * overlay network.
     */
    private final Map<KademliaOverlayKey, DHTObject> dataItems;

    /**
     * An array that contains the keys from <code>dataItems</code>.
     */
    private KademliaOverlayKey[] dataKeys;

    /**
     * The random generator that is used in this simulation - a copy of
     * {@link Simulator#getRandom()}.
     */
    private final Random rnd;

    /**
     * Configuration values ("constants").
     */
    private final Config config;

    /**
     * Constructs a new WorkloadGenerator and gets the configuration information
     * from {@link KademliaSetup}. The remainder of this constructor works as
     * {@link #WorkloadGenerator(Config)}.
     */
    public WorkloadGenerator() {
        this(KademliaSetup.getConfig());
    }

    /**
     * Constructs a new WorkloadGenerator and builds
     * {@link WorkloadConfig#NUMBER_OF_DATA_ITEMS} random data items.
     * 
     * @param conf
     *            the Config that contains Kademlia-wide configuration
     *            constants.
     */
    public WorkloadGenerator(final Config conf) {
        config = conf;
        rnd = new RandomAdaptor(Simulator.getRandom());
        dataItems = new LinkedHashMap<KademliaOverlayKey, DHTObject>(
                (int) Math.ceil(config.getNumberOfDataItems() * 1.002), 0.999f);
        buildDataItems();
    }

    /**
     * "Callback" to notify this WorkloadGenerator that all Nodes have been
     * constructed and the NodeFactory has been registered in
     * {@link KademliaSetup}, to store the data items at the nodes.
     * 
     * @param nf
     *            (not used)
     */
    public final void setNodeFactory(final AbstractNodeFactory nf) {
        storeDataItemsAtNodes();
    }

    /**
     * Determines with global knowledge whether the data lookup result as
     * indicated by the parameters is accurate.
     * 
     * @param key
     *            the KademliaOverlayKey that has been looked up.
     * @param result
     *            the DHTObject that has been found (or <code>null</code> if no
     *            data item has been found).
     * @return true if this class has <code>result</code> as data item for
     *         <code>key</code> (or if <code>result==null</code> and there is no
     *         data item for <code>key</code>).
     */
    public final boolean isDataLookupResultCorrect(final KademliaOverlayKey key, final DHTObject result) {
        if (result == null && !dataItems.containsKey(key)) {
            return true;
        } else if (result != null && dataItems.containsKey(key) && dataItems.get(key).equals(result)) {
            return true;
        }
        return false;
    }

    /**
     * @return a random KademliaOverlayKey of an existing data item from the
     *         overlay network.
     */
    public final KademliaOverlayKey getRandomKeyForLookup() {
        return dataKeys[rnd.nextInt(dataKeys.length)];
    }

    /**
     * Builds the data items to be stored in the overlay network (but does not
     * actually store them on the peers).
     */
    private final void buildDataItems() {
        KademliaOverlayKey key;
        DHTObject data;
        while (dataItems.size() < config.getNumberOfDataItems()) {
            key = constructRandomKademliaOverlayKey();
            data = new DHTObject() {
                @Override
                public long getTransmissionSize() {
                    return 0;
                }
                // no implementation...
            };
            dataItems.put(key, data);
        }
        // store the keys in an extra array to allow (efficient) random access
        dataKeys = dataItems.keySet().toArray(new KademliaOverlayKey[] {});
        log.info("Built " + config.getNumberOfDataItems() + " data items for the Kademlia overlay network.");
    }

    /**
     * @return a new, random KademliaOverlayKey.
     */
    private final KademliaOverlayKey constructRandomKademliaOverlayKey() {
        final int bits = config.getIDLength();
        final BigInteger id = new BigInteger(bits, rnd);
        return new KademliaOverlayKey(id, config);
    }

    /**
     * Stores all data items at the nodes that are responsible to save them.
     * This method should be executed if all Nodes have been constructed because
     * it needs knowledge of all nodes in order to calculate which peer is
     * responsible to store a given data item. That is, responsibility is
     * calculated by taking into account the overall list of all existing peers
     * (no matter their online status).
     */
    private final void storeDataItemsAtNodes() {
        Collection<Node<HKademliaOverlayID>> kClosestNodes;
        log.info("Storing data items at responsible nodes...");

        for (final Map.Entry<KademliaOverlayKey, DHTObject> item : dataItems.entrySet()) {
            // fetch nodes that are responsible to save entry.getValue()
            kClosestNodes = KademliaSetup.getNodeFactory().getKClosestNodes(item.getKey());
            // store data on these nodes
            for (final Node<HKademliaOverlayID> currentNode : kClosestNodes) {
                currentNode.getLocalIndex().putInitialDataItem(item.getKey(), item.getValue());
            }
        }
        log.info("All data items have been stored at the responsible nodes.");
    }
}