edu.umass.cs.gigapaxos.paxosutil.PaxosMessenger.java Source code

Java tutorial

Introduction

Here is the source code for edu.umass.cs.gigapaxos.paxosutil.PaxosMessenger.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.gigapaxos.paxosutil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;

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

import edu.umass.cs.gigapaxos.PaxosConfig.PC;
import edu.umass.cs.gigapaxos.PaxosManager;
import edu.umass.cs.gigapaxos.paxospackets.BatchedCommit;
import edu.umass.cs.gigapaxos.paxospackets.PaxosPacket;
import edu.umass.cs.gigapaxos.paxospackets.PaxosPacket.PaxosPacketType;
import edu.umass.cs.gigapaxos.paxospackets.RequestPacket;
import edu.umass.cs.nio.GenericMessagingTask;
import edu.umass.cs.nio.JSONMessenger;
import edu.umass.cs.nio.interfaces.InterfaceNIOTransport;
import edu.umass.cs.utils.Config;
import edu.umass.cs.utils.DelayProfiler;
import edu.umass.cs.utils.Util;

/**
 * @author V. Arun
 * @param <NodeIDType>
 * 
 *            This class is simply JSONMessenger adapted to use MessagingTask
 *            instead of GenericMessagingTask and to fix integer node IDs to
 *            NodeIDType as needed.
 * 
 *            It's a utility because there is nothing paxos specific here.
 */
@SuppressWarnings("javadoc")
public class PaxosMessenger<NodeIDType> extends JSONMessenger<NodeIDType> {

    private static final int NUM_MESSENGER_WORKERS = Config.getGlobalInt(PC.NUM_MESSENGER_WORKERS);

    public static final boolean ENABLE_INT_STRING_CONVERSION = true;// false;
    private final IntegerMap<NodeIDType> nodeMap;

    public PaxosMessenger(InterfaceNIOTransport<NodeIDType, JSONObject> niot, IntegerMap<NodeIDType> nodeMap) {
        this(niot, nodeMap, NUM_MESSENGER_WORKERS);
    }

    public PaxosMessenger(InterfaceNIOTransport<NodeIDType, JSONObject> niot, IntegerMap<NodeIDType> nodeMap,
            int numWorkers) {
        super(niot, numWorkers);
        this.nodeMap = nodeMap;
    }

    public PaxosMessenger(PaxosMessenger<NodeIDType> msgr) {
        this(msgr.getNIOTransport(), msgr.nodeMap, 0);
    }

    public void send(MessagingTask[] mtasks) throws JSONException, IOException {
        if (mtasks == null)
            return;
        for (MessagingTask mtask : mtasks)
            send(mtask);
    }

    // all send roads lead to here
    public void send(MessagingTask mtask) throws JSONException, IOException {
        if (mtask == null || mtask.isEmptyMessaging())
            return;
        // need to convert integers to NodeIDType.toString before sending
        super.send(toGeneric(mtask), useWorkers(mtask));
    }

    private boolean useWorkers(MessagingTask mtask) {
        return mtask != null && !mtask.isEmptyMessaging()
                && (mtask.msgs[0].getType() == PaxosPacketType.ACCEPT
                        || mtask.msgs[0].getType() == PaxosPacketType.DECISION
                        || mtask.msgs[0].getType() == PaxosPacketType.BATCHED_COMMIT);
    }

    private static boolean cacheStringifiedAccept() {
        return IntegerMap.allInt();
    }

    private Object toJSONObject(PaxosPacket msg) throws JSONException {
        if (cacheStringifiedAccept() && msg.getType() == PaxosPacketType.ACCEPT
                && ((RequestPacket) msg).getStringifiedSelf() != null)
            return ((RequestPacket) msg).getStringifiedSelf();

        JSONObject jsonified = fixNodeIntToString(msg.toJSONObject());
        String stringified = jsonified.toString();

        if (cacheStringifiedAccept() && msg.getType() == PaxosPacketType.ACCEPT)
            ((RequestPacket) msg).setStringifiedSelf(stringified);
        return stringified;
    }

    private static final boolean BYTEIFICATION = Config.getGlobalBoolean(PC.BYTEIFICATION);
    private static final boolean ENABLE_INSTRUMENTATION = Config.getGlobalBoolean(PC.ENABLE_INSTRUMENTATION);
    public static final boolean INSTRUMENT_SERIALIZATION = ENABLE_INSTRUMENTATION
            && Config.getGlobalBoolean(PC.INSTRUMENT_SERIALIZATION);

    private Object toJSONSmartObject(PaxosPacket msg) throws JSONException {
        if (cacheStringifiedAccept() && msg.getType() == PaxosPacketType.ACCEPT
                && ((RequestPacket) msg).getStringifiedSelf() != null)
            return ((RequestPacket) msg).getStringifiedSelf();

        // FIXME: to test byteable
        if (BYTEIFICATION && IntegerMap.allInt()
                && (msg.getType() == PaxosPacket.PaxosPacketType.REQUEST
                        || (msg.getType() == PaxosPacket.PaxosPacketType.ACCEPT))
                || msg.getType() == PaxosPacketType.BATCHED_COMMIT
                || msg.getType() == PaxosPacketType.BATCHED_ACCEPT_REPLY)
            return msg;

        long t = System.nanoTime();
        net.minidev.json.JSONObject jsonSmart = msg.toJSONSmart();
        assert (msg.getType() != PaxosPacketType.ACCEPT || jsonSmart != null);
        // fallback to JSONObject
        Object jsonified = jsonSmart == null ? fixNodeIntToString(msg.toJSONObject())
                : fixNodeIntToString(jsonSmart);
        String stringified = jsonified.toString();

        if (Util.oneIn(100) && INSTRUMENT_SERIALIZATION && ENABLE_INSTRUMENTATION)
            if (msg.getType() == PaxosPacketType.ACCEPT)
                DelayProfiler.updateDelayNano("acceptStringification", t, ((RequestPacket) msg).batchSize() + 1);
            else if (msg.getType() == PaxosPacketType.BATCHED_COMMIT)
                DelayProfiler.updateDelayNano("commitStringification", t, ((BatchedCommit) msg).size() + 1);

        if (cacheStringifiedAccept() && msg.getType() == PaxosPacketType.ACCEPT)
            ((RequestPacket) msg).setStringifiedSelf(stringified);
        return stringified;
    }

    // we explicitly
    private Object[] toObjects(PaxosPacket[] packets) throws JSONException {
        Object[] objects = new Object[packets.length];
        for (int i = 0; i < packets.length; i++) {
            objects[i] = USE_JSON_SMART ? toJSONSmartObject(packets[i]) : toJSONObject(packets[i]);
            assert (!cacheStringifiedAccept() || packets[i].getType() != PaxosPacketType.ACCEPT
                    || ((RequestPacket) packets[i]).getStringifiedSelf() != null || BYTEIFICATION);
        }
        return objects;
    }

    public static final boolean useJSONSmart() {
        return USE_JSON_SMART;
    }

    private static final boolean USE_JSON_SMART = !Config.getGlobalString(PC.JSON_LIBRARY).equals("org.json");

    private GenericMessagingTask<NodeIDType, ?> toGeneric(MessagingTask mtask) throws JSONException {
        Set<NodeIDType> nodes = this.nodeMap.getIntArrayAsNodeSet(mtask.recipients);
        return (new GenericMessagingTask<NodeIDType, String>(nodes.toArray(),
                // Util.intToIntegerArray(mtask.recipients)
                toObjects(mtask.msgs)));
    }

    // convert int to NodeIDType to String
    public JSONObject fixNodeIntToString(JSONObject json) throws JSONException {
        // long t = System.nanoTime();
        if (!ENABLE_INT_STRING_CONVERSION || IntegerMap.allInt())
            return json;
        if (json.has(PaxosPacket.NodeIDKeys.B.toString())) {
            // fix ballot string
            Ballot ballot = new Ballot(json.getString(PaxosPacket.NodeIDKeys.B.toString()));
            json.put(PaxosPacket.NodeIDKeys.B.toString(),
                    Ballot.getBallotString(ballot.ballotNumber, intToString(ballot.coordinatorID)));
        } else if (json.has(PaxosPacket.NodeIDKeys.GROUP.toString())) {
            // fix group JSONArray
            JSONArray jsonArray = json.getJSONArray(PaxosPacket.NodeIDKeys.GROUP.toString());
            for (int i = 0; i < jsonArray.length(); i++) {
                int member = jsonArray.getInt(i);
                jsonArray.put(i, intToString(member));
            }
            json.put(PaxosPacket.NodeIDKeys.GROUP.toString(), jsonArray);
        } else
            for (PaxosPacket.NodeIDKeys key : PaxosPacket.NodeIDKeys.values()) {
                if (json.has(key.toString())) {
                    // simple default int->string fix
                    int id = json.getInt(key.toString());
                    json.put(key.toString(), intToString(id));
                }
            }
        // if(Util.oneIn(100))
        // DelayProfiler.updateDelayNano("fixNodeIntToString", t);
        return json;
    }

    public net.minidev.json.JSONObject fixNodeIntToString(net.minidev.json.JSONObject jsonSmart) {
        // long t = System.nanoTime();
        if (!ENABLE_INT_STRING_CONVERSION || IntegerMap.allInt())
            return jsonSmart;
        if (jsonSmart.containsKey(PaxosPacket.NodeIDKeys.B.toString())) {
            // fix ballot string
            Ballot ballot = new Ballot((String) jsonSmart.get(PaxosPacket.NodeIDKeys.B.toString()));
            jsonSmart.put(PaxosPacket.NodeIDKeys.B.toString(),
                    Ballot.getBallotString(ballot.ballotNumber, intToString(ballot.coordinatorID)));
        } else if (jsonSmart.containsKey(PaxosPacket.NodeIDKeys.GROUP.toString())) {
            // fix group JSONArray
            Collection<?> jsonArray = (Collection<?>) jsonSmart.get(PaxosPacket.NodeIDKeys.GROUP.toString());
            ArrayList<String> nodes = new ArrayList<String>();
            for (Object element : jsonArray) {
                int member = (Integer) element;
                nodes.add(intToString(member));
                // jsonArray.put(i, intToString(member));
            }
            jsonSmart.put(PaxosPacket.NodeIDKeys.GROUP.toString(), nodes);
        } else
            for (PaxosPacket.NodeIDKeys key : PaxosPacket.NodeIDKeys.values()) {
                if (jsonSmart.containsKey(key.toString())) {
                    // simple default int->string fix
                    int id = (Integer) jsonSmart.get(key.toString());
                    jsonSmart.put(key.toString(), intToString(id));
                }
            }
        // if(Util.oneIn(100))
        // DelayProfiler.updateDelayNano("fixNodeIntToString", t);
        return jsonSmart;
    }

    private String intToString(int id) {
        return this.nodeMap.get(id).toString();
    }
}