edu.umass.cs.reconfiguration.reconfigurationpackets.CreateServiceName.java Source code

Java tutorial

Introduction

Here is the source code for edu.umass.cs.reconfiguration.reconfigurationpackets.CreateServiceName.java

Source

/* Copyright (c) 2015 University of Massachusetts
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * Initial developer(s): V. Arun */
package edu.umass.cs.reconfiguration.reconfigurationpackets;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import edu.umass.cs.nio.interfaces.Stringifiable;
import edu.umass.cs.nio.nioutils.StringifiableDefault;
import edu.umass.cs.reconfiguration.ReconfigurationConfig;
import edu.umass.cs.reconfiguration.reconfigurationpackets.BatchedCreateServiceName.BatchKeys;
import edu.umass.cs.reconfiguration.reconfigurationutils.ConsistentReconfigurableNodeConfig;
import edu.umass.cs.utils.Util;

/**
 * @author V. Arun
 * 
 *         This class has a field to specify the initial state in addition to
 *         the default fields in ClientReconfigurationPacket.
 */
public class CreateServiceName extends ClientReconfigurationPacket {

    /**
     *
     */
    public static enum Keys {
        /**
         * 
         */
        NAME,
        /**
        * 
        */
        STATE,
        /**
        * 
        */
        NAME_STATE_ARRAY,

        /**
         * Set of names in a batch create that could not be created or could not
         * be confirmed as having been successfully created (but could have gotten
         * created after all).
         */
        FAILED_CREATES,
    };

    /**
     * Unstringer needed to handle client InetSocketAddresses as opposed to
     * NodeIDType.
     */
    public static final Stringifiable<InetSocketAddress> unstringer = new StringifiableDefault<InetSocketAddress>(
            new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));

    /**
     * Initial state.
     */
    public final String initialState;

    /**
     * Map of name,state pairs for batched creates.
     */
    public final Map<String, String> nameStates;

    private final Set<String> failedCreates;

    /**
     * @param name
     * @param state
     */
    public CreateServiceName(String name, String state) {
        this(null, name, 0, state);
    }

    /**
     * @param initiator
     * @param name
     * @param epochNumber
     * @param state
     * @param nameStates
     */
    private CreateServiceName(InetSocketAddress initiator, String name, int epochNumber, String state,
            Map<String, String> nameStates, InetSocketAddress myReceiver) {
        super(initiator, ReconfigurationPacket.PacketType.CREATE_SERVICE_NAME, name, epochNumber, myReceiver);
        this.initialState = state;
        this.nameStates = nameStates;
        this.failedCreates = null;
    }

    private CreateServiceName(InetSocketAddress initiator, String name, int epochNumber, String state,
            Map<String, String> nameStates) {
        this(initiator, name, epochNumber, state, nameStates, null);
    }

    /**
     * @param initiator
     * @param name
     * @param epochNumber
     * @param state
     */
    public CreateServiceName(InetSocketAddress initiator, String name, int epochNumber, String state) {
        this(initiator, name, epochNumber, state, null, null);
    }

    /**
     * @param initiator
     * @param name
     * @param epochNumber
     * @param state
     * @param myReceiver
     */
    public CreateServiceName(InetSocketAddress initiator, String name, int epochNumber, String state,
            InetSocketAddress myReceiver) {
        this(initiator, name, epochNumber, state, null, myReceiver);
    }

    /**
     * @param initiator
     * @param nameStates
     */
    public CreateServiceName(InetSocketAddress initiator, Map<String, String> nameStates) {
        this(initiator, nameStates.keySet().iterator().next(), 0, nameStates.values().iterator().next(),
                nameStates);
    }

    /**
     * FIXME: need to document the reliance on the consistent ordering of the
     * head element in nameStates.
     * 
     * @param nameStates
     * @param create
     */
    public CreateServiceName(Map<String, String> nameStates, CreateServiceName create) {
        this(nameStates, null, create);
    }

    /**
     * @param nameStates
     * @param failedCreates
     * @param create
     */
    public CreateServiceName(Map<String, String> nameStates, Set<String> failedCreates, CreateServiceName create) {
        super(nameStates.keySet().iterator().next(), create);
        this.setSender(create.getSender());
        this.nameStates = nameStates;
        this.initialState = nameStates.get(nameStates.keySet().iterator().next());
        this.failedCreates = failedCreates;
    }

    /**
     * @return {@code this}with only head name and state.
     */
    public CreateServiceName getHeadOnly() {
        this.nameStates.clear();
        return this;
    }

    /**
     * @param json
     * @param unstringer
     * @throws JSONException
     */
    public CreateServiceName(JSONObject json, Stringifiable<?> unstringer) throws JSONException {
        super(json, CreateServiceName.unstringer); // ignores unstringer
        // may not be true for String packet demultiplexers
        // assert (this.getSender() != null);
        this.initialState = json.optString(Keys.STATE.toString(), null);
        this.nameStates = getNameStateMap(json);
        JSONArray jsonArray = json.has(Keys.FAILED_CREATES.toString())
                ? json.getJSONArray(Keys.FAILED_CREATES.toString())
                : null;
        if (jsonArray != null && jsonArray.length() > 0) {
            this.failedCreates = new HashSet<String>();
            for (int i = 0; i < jsonArray.length(); i++)
                this.failedCreates.add(jsonArray.getString(i));
        } else
            this.failedCreates = null;
    }

    /**
     * @param json
     * @throws JSONException
     */
    public CreateServiceName(JSONObject json) throws JSONException {
        this(json, unstringer);
    }

    @Override
    public JSONObject toJSONObjectImpl() throws JSONException {
        JSONObject json = super.toJSONObjectImpl();
        if (initialState != null)
            json.put(Keys.STATE.toString(), initialState);

        json.putOpt(BatchKeys.NAME_STATE_ARRAY.toString(), getNameStateJSONArray(this.nameStates));

        if (this.failedCreates != null && !this.failedCreates.isEmpty())
            json.put(Keys.FAILED_CREATES.toString(), this.failedCreates);
        return json;
    }

    /**
     * @return True if this is a batched create request or response.
     */
    public boolean isBatched() {
        return this.nameStates != null && !this.nameStates.isEmpty();
    }

    protected static JSONArray getNameStateJSONArray(Map<String, String> nameStates) throws JSONException {
        if (nameStates != null && !nameStates.isEmpty()) {
            JSONArray jsonArray = new JSONArray();
            for (String name : nameStates.keySet()) {
                JSONObject nameState = new JSONObject();
                nameState.put(Keys.NAME.toString(), name);
                nameState.put(Keys.STATE.toString(), nameStates.get(name));
                jsonArray.put(nameState);
            }
            return jsonArray;
        }
        return null;
    }

    protected static Map<String, String> getNameStateMap(JSONObject json) throws JSONException {
        if (!json.has(BatchKeys.NAME_STATE_ARRAY.toString()))
            return null;
        JSONArray nameStateArray = json.getJSONArray(BatchKeys.NAME_STATE_ARRAY.toString());
        Map<String, String> nameStates = new HashMap<String, String>();
        for (int i = 0; i < nameStateArray.length(); i++) {
            JSONObject nameState = nameStateArray.getJSONObject(i);
            String name = nameState.getString(Keys.NAME.toString());
            String state = nameState.has(Keys.STATE.toString()) ? nameState.getString(Keys.STATE.toString()) : null;
            if (name == null)
                throw new JSONException("Parsed null name in batched request");
            nameStates.put(name, state);
        }
        return nameStates;
    }

    /**
     * @return Initial state.
     */
    public String getInitialState() {
        return initialState;
    }

    /**
     * @return Name, state tuple map.
     */
    public Map<String, String> getNameStates() {
        return this.nameStates;
    }

    /**
     * @return Number of creates in this request or respose.
     */
    public int size() {
        return this.isBatched() ? this.nameStates.size() : 1;
    }

    public String getSummary() {
        return super.getSummary() + (this.isBatched() ? ":|batched|=" + this.size() : "");
    }

    /**
     * @param nameStates
     * @param batchSize
     * @return Array of batched CreateServiceName requests.
     */
    public static CreateServiceName[] makeCreateNameRequest(Map<String, String> nameStates, int batchSize) {
        return ReconfigurationConfig.makeCreateNameRequest(nameStates, batchSize);
    }

    /**
     * @param nameStates
     * @param batchSize
     * @param reconfigurators
     * @return Array of batched CreateServiceName requests.
     */
    public static CreateServiceName[] makeCreateNameRequest(Map<String, String> nameStates, int batchSize,
            Set<String> reconfigurators) {
        return ReconfigurationConfig.makeCreateNameRequest(nameStates, batchSize, reconfigurators);
    }

    public static void main(String[] args) {
        try {
            Util.assertAssertionsEnabled();
            InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName("localhost"), 2345);
            int numNames = 1000;
            String[] reconfigurators = { "RC43", "RC22", "RC78", "RC21", "RC143" };
            String namePrefix = "someName";
            String defaultState = "default_initial_state";
            String[] names = new String[numNames];
            String[] states = new String[numNames];
            for (int i = 0; i < numNames; i++) {
                names[i] = namePrefix + i;
                states[i] = defaultState + i;
            }
            CreateServiceName bcreate1 = new CreateServiceName(isa, "random0", 0, "hello");
            HashMap<String, String> nameStates = new HashMap<String, String>();
            for (int i = 0; i < names.length; i++)
                nameStates.put(names[i], states[i]);
            CreateServiceName bcreate2 = new CreateServiceName(isa, names[0], 0, states[0], nameStates);
            System.out.println(bcreate1.toString());
            System.out.println(bcreate2.toString());

            // translate a batch into consistent constituent batches
            Collection<Set<String>> batches = ConsistentReconfigurableNodeConfig.splitIntoRCGroups(
                    new HashSet<String>(Arrays.asList(names)), new HashSet<String>(Arrays.asList(reconfigurators)));
            int totalSize = 0;
            int numBatches = 0;
            for (Set<String> batch : batches)
                System.out.println("batch#" + numBatches++ + " of size " + batch.size() + " (totalSize = "
                        + (totalSize += batch.size()) + ")" + " = " + batch);
            assert (totalSize == numNames);
            System.out.println(bcreate2.getSummary());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}