Commit 3b05f756 authored by chiaming2000's avatar chiaming2000
Browse files

Java simulator:

1. Media scan now supports SHA1 and SHA2 algorithm. 
parent 2e3a2835
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -40,12 +40,12 @@ import com.seagate.kinetic.common.lib.Hmac;
import com.seagate.kinetic.common.lib.Hmac.HmacException;
import com.seagate.kinetic.common.lib.KineticMessage;
import com.seagate.kinetic.proto.Kinetic.Command;
import com.seagate.kinetic.proto.Kinetic.Message;
import com.seagate.kinetic.proto.Kinetic.Message.AuthType;
import com.seagate.kinetic.proto.Kinetic.Message.Builder;
import com.seagate.kinetic.proto.Kinetic.Command.Header;
import com.seagate.kinetic.proto.Kinetic.Command.MessageType;
import com.seagate.kinetic.proto.Kinetic.Command.Range;
import com.seagate.kinetic.proto.Kinetic.Message;
import com.seagate.kinetic.proto.Kinetic.Message.AuthType;
import com.seagate.kinetic.proto.Kinetic.Message.Builder;


/**
@@ -594,11 +594,21 @@ public class ClientProxy {
         */
        if (header.getMessageType() == MessageType.PUT) {
            if (commandBuilder.getBodyBuilder().getKeyValueBuilder().hasTag() == false) {
                // calculate value Hmac
                ByteString tag = Hmac.calcTag(kineticMessage, this.myKey);

                // calculate value message digest
                // ByteString tag = Hmac.calcTag(kineticMessage, this.myKey);

                // ByteString tag =
                // MessageDigestUtil.calculateTag(Algorithm.SHA1,
                // kineticMessage.getValue());
                //
                // set tag
                commandBuilder.getBodyBuilder().getKeyValueBuilder()
                        .setTag(tag);
                // commandBuilder.getBodyBuilder().getKeyValueBuilder()
                // .setTag(tag);
                //
                // Algorithm algo = Algorithm.SHA1;
                // commandBuilder.getBodyBuilder().getKeyValueBuilder()
                // .setAlgorithm(algo);
            }
        }

+94 −0
Original line number Diff line number Diff line
/**
 * Copyright (C) 2014 Seagate Technology.
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package com.seagate.kinetic.common.lib;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.protobuf.ByteString;
import com.seagate.kinetic.proto.Kinetic.Command.Algorithm;

/**
 * 
 * @author chiaming
 *
 */
public class MessageDigestUtil {

    private final static Logger logger = Logger
            .getLogger(MessageDigestUtil.class.getName());

    public static ByteString calculateTag(Algorithm algo, byte[] value) {

        byte[] digest = null;

        // get md instance
        MessageDigest md = getInstance(algo);

        if (value == null) {
            value = new byte[0];
        }

        // calculate and return digest
        digest = md.digest(value);

        return ByteString.copyFrom(digest);

    }

    public static boolean isSupportedForKineticJava(Algorithm algo) {

        switch (algo) {
        case SHA1:
            return true;
        case SHA2:
            return true;
        default:
            return false;
        }
    }

    public static MessageDigest getInstance(Algorithm algo) {

        switch (algo) {
        case SHA1:
            return getDigestInstance("SHA-1");
        case SHA2:
            return getDigestInstance("SHA-256");
        default:
            throw new java.lang.UnsupportedOperationException(
                    "unsupported algorithm., name = " + algo.name());
        }
    }

    public static MessageDigest getDigestInstance(String algoName) {

        MessageDigest md = null;

        try {
            md = MessageDigest.getInstance(algoName);
        } catch (NoSuchAlgorithmException e) {
            logger.log(Level.WARNING, e.getMessage(), e);
        }

        return md;
    }

}
+166 −0
Original line number Diff line number Diff line
@@ -19,16 +19,23 @@
 */
package com.seagate.kinetic.simulator.internal;

import java.util.logging.Level;
import java.util.logging.Logger;

import kinetic.client.KineticException;
import kinetic.simulator.SimulatorConfiguration;

import com.google.protobuf.ByteString;
import com.seagate.kinetic.common.lib.KineticMessage;
import com.seagate.kinetic.common.lib.MessageDigestUtil;
import com.seagate.kinetic.proto.Kinetic.Command;
import com.seagate.kinetic.proto.Kinetic.Command.Algorithm;
import com.seagate.kinetic.proto.Kinetic.Command.MessageType;
import com.seagate.kinetic.proto.Kinetic.Command.Security.ACL.Permission;
import com.seagate.kinetic.proto.Kinetic.Command.Status.StatusCode;
import com.seagate.kinetic.simulator.persist.KVValue;
import com.seagate.kinetic.simulator.persist.Store;
import com.seagate.kinetic.simulator.persist.memory.KeyComparator;

/**
 * 
@@ -45,10 +52,13 @@ public abstract class BackGroundOpHandler {
    private final static Logger logger = Logger.getLogger(BackGroundOpHandler.class
            .getName());
    
    @SuppressWarnings({ "rawtypes" })
    public static void mediaScan(KineticMessage request,
            KineticMessage respond, SimulatorEngine engine)
            throws KVStoreException, KineticException {

        KeyComparator comparator = new KeyComparator();

        Command.Builder commandBuilder = (Command.Builder) respond.getCommand();

        // set reply type
@@ -59,13 +69,33 @@ public abstract class BackGroundOpHandler {
        commandBuilder.getHeaderBuilder().setAckSequence(
                request.getCommand().getHeader().getSequence());

        // max return key count
        int maxReturned = request.getCommand().getBody().getRange()
                .getMaxReturned();
        
        int MaxSupported = SimulatorConfiguration.getMaxSupportedKeyRangeSize();

        try {
            
            // if not set, set to default
            if (maxReturned <= 0) {
                maxReturned = MaxSupported;
            } else if (maxReturned > MaxSupported) {
                throw new InvalidRequestException(
                        "Exceed max returned key range., max allowed="
                                + SimulatorConfiguration
                                        .getMaxSupportedKeyRangeSize()
                                + ", request=" + maxReturned);
            }
            
            // check message type
            checkIsMessageValid (request);
            
            // check permission
            checkPermission (request, engine);  
            
            Store store = engine.getStore();

            /**
             *  XXX 09/09/2014 chiaming:
             *  framework to start background operation
@@ -75,6 +105,116 @@ public abstract class BackGroundOpHandler {
             *  The following statements are for testing purpose only
             */
            
            // get start key
            ByteString startKey = request.getCommand().getBody().getRange()
                    .getStartKey();

            // get end key
            ByteString endKey = request.getCommand().getBody().getRange()
                    .getEndKey();

            byte[] endKeybytes = endKey.toByteArray();

            // if scan to the end of the map
            boolean toEndOfMap = false;
            if (endKey.isEmpty()) {
                toEndOfMap = true;
            }

            // finish scan flag
            boolean done = false;

            // kv entry
            KVValue kv = null;

            // check if start key inclusive
            if (request.getCommand().getBody().getRange()
                    .getStartKeyInclusive()) {
                // include start key
                kv = get(store, startKey);
                if (kv == null) {
                    kv = getNext(store, startKey);
                }

            } else {
                // get next key
                kv = getNext(store, startKey);
            }

            // scan the drive
            long index = 0;
            while (done == false) {

                if (kv != null) {
                    // get algo
                    Algorithm algo = kv.getAlgorithm();
                    // get tag
                    ByteString tag = kv.getTag();

                    // compare tag
                    logger.info((index++) + ": scan media for key: "
                            + kv.getKeyOf()
                            + ", algo: " + algo);

                    if ((tag != null)
                            && (tag.isEmpty() == false)
                            && MessageDigestUtil
                                    .isSupportedForKineticJava(algo)) {

                        ByteString ctag = MessageDigestUtil.calculateTag(algo,
                                kv.getData()
                                .toByteArray());

                        if (tag.equals(ctag) == false) {

                            logger.info("tag does not match for key: "
                                    + kv.getKeyOf() + ", algo: " + algo);

                            if (commandBuilder.getBodyBuilder()
                                    .getRangeBuilder().getKeysCount() < maxReturned) {
                                // add bad key
                                commandBuilder.getBodyBuilder()
                                        .getRangeBuilder()
                                        .addKeys(kv.getKeyOf());
                            } else {
                                // reached max returned keys
                                // set endkey in response
                                commandBuilder.getBodyBuilder()
                                        .getRangeBuilder()
                                        .setEndKey(kv.getKeyOf());

                                // finished scan
                                return;
                            }
                        } else {
                            logger.info("tag validated for key: "
                                    + kv.getKeyOf() + ", algo: " + algo);
                        }
                    }

                    // read next key
                    kv = getNext(store, kv.getKeyOf());

                    if (kv == null) {
                        // reached to end of map
                        done = true;
                    } else if (toEndOfMap == false) {

                        /**
                         * check if passed end key
                         */
                        if (comparator.compare(endKeybytes, kv.getKeyOf()
                                .toByteArray()) < 0) {
                            done = true;
                        }
                    }

                } else {
                    logger.info(index + ": scan media reached end of map");
                    done = true;
                }
            }

            // set endkey in response
            commandBuilder
                    .getBodyBuilder()
@@ -182,4 +322,30 @@ public abstract class BackGroundOpHandler {
                Permission.RANGE);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static KVValue get(Store store, ByteString key) {
        KVValue kv = null;

        try {
            kv = (KVValue) store.get(key);
        } catch (Exception e) {
            logger.info(e.getMessage());
        }

        return kv;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static KVValue getNext(Store store, ByteString key) {
        KVValue kv = null;

        try {
            kv = (KVValue) store.getNext(key);
        } catch (Exception e) {
            logger.log(Level.WARNING, e.getMessage(), e);
        }

        return kv;
    }

}
+1 −1
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ public class BatchOperationHandler {
        }
    }

    public void checkBatchMode(KineticMessage kmreq)
    public synchronized void checkBatchMode(KineticMessage kmreq)
            throws InvalidRequestException {

        if (kmreq.getIsInvalidBatchMessage()) {
+9 −1
Original line number Diff line number Diff line
@@ -32,4 +32,12 @@ public class KVStoreNotFound extends KVStoreException{
	 */
	private static final long serialVersionUID = 335206057367584819L;

    public KVStoreNotFound() {
        super();
    }

    public KVStoreNotFound(String msg) {
        super(msg);
    }

}