se.sics.caracaldb.global.MaintenanceSerializer.java Source code

Java tutorial

Introduction

Here is the source code for se.sics.caracaldb.global.MaintenanceSerializer.java

Source

/*
 * This file is part of the CaracalDB distributed storage system.
 *
 * Copyright (C) 2009 Swedish Institute of Computer Science (SICS) 
 * Copyright (C) 2009 Royal Institute of Technology (KTH)
 *
 * This program 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 2
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package se.sics.caracaldb.global;

import com.google.common.base.Optional;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.sics.caracaldb.KeyRange;
import se.sics.caracaldb.ServerSerializer;
import se.sics.caracaldb.View;
import se.sics.caracaldb.replication.linearisable.ViewChange;
import se.sics.caracaldb.utils.CustomSerialisers;
import se.sics.kompics.network.netty.serialization.Serializer;
import se.sics.kompics.network.netty.serialization.SpecialSerializers;
import se.sics.kompics.network.netty.serialization.SpecialSerializers.BitBuffer;
import se.sics.kompics.network.netty.serialization.SpecialSerializers.MessageSerializationUtil.MessageFields;

/**
 *
 * @author lkroll
 */
public class MaintenanceSerializer implements Serializer {

    private static final Logger LOG = LoggerFactory.getLogger(MaintenanceSerializer.class);

    // 0
    private static final boolean MSG = false;
    private static final boolean OP = true;
    // 1&2
    private static final Boolean[] JOIN = new Boolean[] { false, false };
    private static final Boolean[] SYNCED = new Boolean[] { false, true };
    private static final Boolean[] RECONF = new Boolean[] { true, false };
    private static final Boolean[] UPDATE = new Boolean[] { true, true };

    @Override
    public int identifier() {
        return ServerSerializer.GLOBAL.id;
    }

    @Override
    public void toBinary(Object o, ByteBuf buf) {
        if (o instanceof MaintenanceMsg) {
            MaintenanceMsg msg = (MaintenanceMsg) o;
            int flagPos = buf.writerIndex();
            buf.writeByte(0); // reserve for flags
            BitBuffer flags = BitBuffer.create(MSG); // 0
            SpecialSerializers.MessageSerializationUtil.msgToBinary(msg, buf, false, false);
            toBinaryOp(msg.op, buf, flags);
            byte[] flagsB = flags.finalise();
            buf.setByte(flagPos, flagsB[0]);
            return;
        }
        if (o instanceof Maintenance) {
            int flagPos = buf.writerIndex();
            buf.writeByte(0); // reserve for flags
            BitBuffer flags = BitBuffer.create(OP); // 0
            toBinaryOp((Maintenance) o, buf, flags);
            byte[] flagsB = flags.finalise();
            buf.setByte(flagPos, flagsB[0]);
            return;
        }
        LOG.warn("Couldn't serialize {}: {}", o, o.getClass());
    }

    private void toBinaryOp(Maintenance op, ByteBuf buf, BitBuffer flags) {
        if (op instanceof NodeJoin) {
            NodeJoin m = (NodeJoin) op;
            flags.write(JOIN);
            flags.write(false, false); // reserve bits 3&4
            CustomSerialisers.serialiseView(m.view, buf);
            CustomSerialisers.serialiseKeyRange(m.responsibility, buf);
            flags.write(m.dataTransfer); // custom bit 5
            buf.writeInt(m.quorum);
            return;
        }
        if (op instanceof NodeSynced) {
            NodeSynced m = (NodeSynced) op;
            flags.write(SYNCED);
            flags.write(false, false); // reserve bits 3&4
            CustomSerialisers.serialiseView(m.view, buf);
            CustomSerialisers.serialiseKeyRange(m.responsibility, buf);
            return;
        }
        if (op instanceof Reconfiguration) {
            Reconfiguration m = (Reconfiguration) op;
            flags.write(RECONF);
            flags.write(false, false); // reserve bits 3&4
            CustomSerialisers.serialiseView(m.change.view, buf);
            buf.writeInt(m.change.quorum);
            CustomSerialisers.serialiseKeyRange(m.change.range, buf);
            return;
        }
        if (op instanceof LUTUpdate) {
            LUTUpdate m = (LUTUpdate) op;
            flags.write(UPDATE);
            flags.write(false, false); // reserve bits 3&4
            m.serialise(buf);
        }
    }

    @Override
    public Object fromBinary(ByteBuf buf, Optional<Object> hint) {
        byte[] flagsB = new byte[1];
        buf.readBytes(flagsB);
        boolean[] flags = BitBuffer.extract(8, flagsB);
        if (flags[0] == MSG) {
            MessageFields fields = SpecialSerializers.MessageSerializationUtil.msgFromBinary(buf);
            Maintenance op = fromBinaryOp(buf, flags);
            return new MaintenanceMsg(fields.src, fields.dst, op);
        }
        if (flags[0] == OP) {
            return fromBinaryOp(buf, flags);
        }
        return null; // no idea how it should get here^^
    }

    private Maintenance fromBinaryOp(ByteBuf buf, boolean[] flags) {
        if (matches(flags, JOIN)) {
            View view = CustomSerialisers.deserialiseView(buf);
            KeyRange respon = CustomSerialisers.deserialiseKeyRange(buf);
            boolean dataTransfer = flags[5];
            int quorum = buf.readInt();
            return new NodeJoin(view, quorum, respon, dataTransfer);
        }
        if (matches(flags, SYNCED)) {
            View view = CustomSerialisers.deserialiseView(buf);
            KeyRange respon = CustomSerialisers.deserialiseKeyRange(buf);
            return new NodeSynced(view, respon);
        }
        if (matches(flags, RECONF)) {
            View view = CustomSerialisers.deserialiseView(buf);
            int quorum = buf.readInt();
            KeyRange range = CustomSerialisers.deserialiseKeyRange(buf);
            return new Reconfiguration(new ViewChange(view, quorum, range));
        }
        if (matches(flags, UPDATE)) {
            try {
                return LUTUpdate.deserialise(buf);
            } catch (InstantiationException ex) {
                LOG.error("Could not deserialise LUTUpdate: \n   ", ex);
            } catch (IllegalAccessException ex) {
                LOG.error("Could not deserialise LUTUpdate: \n   ", ex);
            }
        }
        return null;
    }

    private boolean matches(boolean[] flags, Boolean[] type) {
        return (flags[1] == type[0]) && (flags[2] == type[1]);
    }

}