All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alachisoft.ncache.client.internal.command.Command Maven / Gradle / Ivy

There is a newer version: 5.3.0
Show newest version
/*
 * Command.java
 *
 * Created on September 8, 2006, 12:37 PM
 *
 * Copyright 2005 Alachisoft, Inc. All rights reserved.
 * ALACHISOFT PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.alachisoft.ncache.client.internal.command;

import Alachisoft.NCache.Common.DataStructures.BridgeOperation;
import Alachisoft.NCache.Common.Net.Address;

import com.alachisoft.ncache.client.internal.communication.Broker;
import com.alachisoft.ncache.client.internal.communication.Connection;
import com.alachisoft.ncache.client.internal.communication.Request;
import com.alachisoft.ncache.client.internal.communication.SendError;
import com.alachisoft.ncache.common.protobuf.NamedTagInfoProtocol;
import com.alachisoft.ncache.common.protobuf.QueryInfoProtocol;
import com.alachisoft.ncache.common.protobuf.TagInfoProtocol;
import com.alachisoft.ncache.runtime.exceptions.CommandException;
import com.alachisoft.ncache.runtime.util.HelperFxn;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.*;

public abstract class Command {

    // region Fields

    protected byte[] value = null;
    protected byte[] commandBytes = null;
    protected byte[] internalCommandSize = null;
    private long requestId = -1;
    private String[] bulkKeys;
    private BridgeOperation[] bridgeOperations;
    private CommandResponse result = null;
    private String _cacheId;
    static String NC_NULL_VAL = "NLV";
    static String VERSION = "4200";
    protected String name;
    private long clientLastViewId = -1;
    private String intendedRecipient;
    protected String key;
    public boolean isAsync = false ;
    public boolean asyncCallbackSpecified = false;
    private String ip = "";
    protected boolean inquiryEnabled;
    protected com.alachisoft.ncache.common.protobuf.CommandProtocol.Command _command;
    protected int _commandID = 0;

    private byte[] serialized;
    private Address _finalDestinationAddress;
    private boolean isSurrogationSupported;
    private boolean isRetry;
    private Request _parent;
    private boolean supportsAcknowledgement;
    private long acknowledgmentId;
    public boolean pulseOnSend;
    public boolean sentOverWire;
    private SendError sendError;


    // endregion

    // region Properties

    public int getCommandID() {
        return _commandID;
    }
    public void setCommandID(int value) {
        _commandID = value;
    }

    public byte[] getSerialized()
    {
        return serialized;
    }
    public void setSerialized(byte[] value)
    {
        serialized = value;
    }

    public Address getFinalDestinationAddress() {
        return _finalDestinationAddress;
    }
    public void setFinalDestinationAddress(Address finalDestinationAddress) {
        this._finalDestinationAddress = finalDestinationAddress;
    }

    public boolean getSupportsSurrogation() {
        return isSurrogationSupported;
    }
    public void setSupportsSurrogation(boolean surrogationSupported) {
        isSurrogationSupported = surrogationSupported;
    }

    public boolean getIsRetry() {
        return isRetry;
    }
    public void setIsRetry(boolean retry) {
        isRetry = retry;
    }

    public Request getParent() {
        return _parent;
    }
    public void setParent(Request _parent) {
        this._parent = _parent;
    }

    public boolean getIsInternalCommand() {
        return getCommandRequestType() == RequestType.InternalCommand;
    }

    public abstract RequestType getCommandRequestType();

    public abstract CommandType getCommandType();

    public com.alachisoft.ncache.common.protobuf.CommandProtocol.Command.Type getType()
    {
        return _command.getType();
    }

    public long getRequestId() {
        return requestId;
    }
    public void setRequestId(long value) {
        requestId = value;
    }


    public boolean getSupportsAacknowledgement() {
        return supportsAcknowledgement;
    }
    public void setSupportsAacknowledgement(boolean supportsAcknowledgement) {
        this.supportsAcknowledgement = supportsAcknowledgement;
    }

    public long getClientLastViewId() {
        return clientLastViewId;
    }
    public void setClientLastViewId(long clientLastViewId) {
        this.clientLastViewId = clientLastViewId;
    }

    public String getIntendedRecipient() {
        return intendedRecipient;
    }
    public void setIntendedRecipient(String intendedRecipient) {
        this.intendedRecipient = intendedRecipient;
    }

    public CommandResponse getResponse() {
        return result;
    }
    public void setResponse(CommandResponse res) {
        this.result = res;
    }

    public String getKey() {
        return key;
    }

    public String[] getBulkKeys() {
        return bulkKeys;
    }
    public void setBulkKeys(String[] bulkKeys) {
        this.bulkKeys = bulkKeys;
    }

    public Object getValue() {
        return value;
    }
    public void setValue(byte[] bytes){ value = bytes; }

    public BridgeOperation[] getBridgeOperations() {
        return bridgeOperations;
    }
    public void setBridgeOperations(BridgeOperation[] bridgeOperations) {
        this.bridgeOperations = bridgeOperations;
    }

    public String getCommandName() {
        return name;
    }

    public boolean getIsSafe() {
        return true;
    }

    protected boolean getIsKeyBased() {
        return true;
    }

    public long getAcknowledgmentId() {
        return acknowledgmentId;
    }
    public void setAcknowledgmentId(long acknowledgmentId) {
        this.acknowledgmentId = acknowledgmentId;
    }

    public boolean getPulseOnSend() {
        return pulseOnSend;
    }
    public void setPulseOnSend(boolean pulseOnSend) {
        this.pulseOnSend = pulseOnSend;
    }

    public boolean getSentOverWire() {
        return sentOverWire;
    }
    public void setSentOverWire(boolean sentOverWire) {
        this.sentOverWire = sentOverWire;
    }

    public SendError getSendError() {
        return sendError;
    }
    public void setSendError(SendError sendError) {
        this.sendError = sendError;
    }

    public String getCacheId() {
        return _cacheId;
    }
    public void setCacheId(String _cacheId) {
        this._cacheId = _cacheId;
    }

    // endregion

    //region Methods

    protected byte[] constructCommand(byte[] serializedCommand) throws IOException
    {

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            ///Copy discarding buffer for server
            byte[] discardingBuffer = new byte[20];
            stream.write(discardingBuffer);

            ///Copy size of data in 10 bytes
            byte[] size = new byte[CommandOptions.COMMAND_SIZE];
            byte[] commandSize = String.valueOf(serializedCommand.length).getBytes(StandardCharsets.UTF_8);
            System.arraycopy(commandSize, 0, size, 0, commandSize.length);
            stream.write(size);

            ///Copy actual data
            stream.write(serializedCommand);

            ///Return the packet
            return stream.toByteArray();
        } finally {
            stream.close();
        }
    }

    protected abstract void createCommand() throws CommandException;
    public int getAcknowledgementOffset()
    {
        return 0;
    }
    public byte[] toByte(long acknowledgement, boolean requestInquiryEnabled) throws CommandException, IOException {
        synchronized (this) {
            if (commandBytes == null || inquiryEnabled != requestInquiryEnabled) {
                inquiryEnabled = requestInquiryEnabled;
                this.createCommand();
                this.serializeCommand();
            }
            if (getSupportsAacknowledgement() && inquiryEnabled) {
                byte[] acknowledgementBuffer = String.valueOf(acknowledgement).getBytes(StandardCharsets.UTF_8);
                System.arraycopy(acknowledgementBuffer, 0, commandBytes, getAcknowledgementOffset(), acknowledgementBuffer.length);
            }
        return commandBytes;
        }
    }

    protected void serializeCommandInternal(ByteArrayOutputStream stream) throws IOException
    {
        _command.writeTo(stream);
    }

    protected short getCommandHandle()
    {
        return 0;
    }

    protected void serializeCommand() throws IOException {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();

        //Writes a section for acknowledgment buffer.
        byte[] acknowledgementBuffer = (getSupportsAacknowledgement() && inquiryEnabled) ? new byte[20] : new byte[0];
        stream.write(acknowledgementBuffer, 0, acknowledgementBuffer.length);

        // Write command type, write 0 for base Command.
        byte[] commandType = HelperFxn.writeShort(getCommandHandle());
        stream.write(commandType, 0, commandType.length);

        // Writes a section for the command size.
        byte[] size = new byte[Connection.CmdSizeHolderBytesCount];
        stream.write(size, 0, size.length);

        serializeCommandInternal(stream);

        //All buffers acknowledgement/discarded/size will be using byte[] commandBytes
        // As stream in java has no way to set its Position
        commandBytes = stream.toByteArray();

        //lenght calculation of command
        int messageLen;
        messageLen = stream.size() - (size.length + acknowledgementBuffer.length + commandType.length);
        size = String.valueOf(messageLen).getBytes(StandardCharsets.UTF_8);

        //Command size setting copy length at position filled dummy previously
        int offset=acknowledgementBuffer.length + commandType.length;
        System.arraycopy(size, 0, commandBytes, offset, size.length );

        stream.close();
    }

    public void resetCommand()
    {
        if (_parent != null) {
            this.commandBytes = null;
            this._commandID = this._parent.getNextCommandID();
        }
    }

    public static Command getDedicatedCommand(Collection commands, String address)
    {
        /*
         * usama@30092014
         * This function will be called only for bulk commands
         * If commands are non-key commands, each command in passed commands will be the same,
         * If commands are key based bulk command, each command will have seperate set of keys. Need to merge all keys to create a dedicated command.
         */
        Command dedicatedCommand = null;
        List commandsList = new ArrayList<>(commands);
        dedicatedCommand = commandsList.get(0).getMergedCommand(commandsList);
        dedicatedCommand.commandBytes = null;
        dedicatedCommand.setClientLastViewId(Broker.ForcedViewId);
        dedicatedCommand.getParent().getCommands().clear();
        dedicatedCommand.getParent().addCommand(new Address(address, 9800), dedicatedCommand);
        return dedicatedCommand;

    }

    public byte[] getSerializedSurrogateCommand() throws IOException, CommandException {
        byte[] serializedbytes = null;
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        this.createCommand();
        if (_command != null)
        {
            _command.writeTo(stream);
        }
        serializedbytes = stream.toByteArray();
        return serializedbytes;
    }

    protected Command getMergedCommand(List commands)
    {
        return commands != null && commands.size() > 0 ? commands.get(0) : null;
    }

    protected String rebuildCommandWithTagInfo(HashMap tagInfo)
    {
        StringBuilder cmdString = new StringBuilder();
        cmdString.append(tagInfo.get("type") + "\"");
        Object obj = tagInfo.get("tags-list");
        if (obj instanceof ArrayList) {
            ArrayList tagsList = (ArrayList) obj;
            cmdString.append(tagsList.size() + "\"");

            Iterator tagsEnum = tagsList.iterator();
            while (tagsEnum.hasNext()) {
                Object current = tagsEnum.next();
                if (current != null) {
                    cmdString.append(current.toString() + "\"");
                } else {
                    cmdString.append(NC_NULL_VAL+"\"");
                }
            }
        }
        return cmdString.toString();
    }

    protected String rebuildCommandWithQueryInfo(HashMap queryInfo)
    {
        Map.Entry entry;
        StringBuilder cmdString = new StringBuilder();
        Iterator hashmapIt = queryInfo.entrySet().iterator();
        while (hashmapIt.hasNext()) {
            entry = (Map.Entry) hashmapIt.next();
            cmdString.append(entry.getKey()).append("\"");
            ArrayList values = (ArrayList) entry.getValue();
            cmdString.append(values.size()).append("\"");
            //New implementation involves a check here
            for (int i = 0; i < values.size(); i++) {
                cmdString.append(values.get(i)).append("\"");
            }

        }
        return cmdString.toString();
    }

    @Override
    public String toString()
    {
        return name + " : " + requestId;
    }

    //endregion

    //region Not Used in .Net

    protected int asyncCallbackId = -1;
    public static QueryInfoProtocol.QueryInfo getQueryInfoObj(HashMap queryInfoDic) {
        if (queryInfoDic == null) {
            return null;
        }
        if (queryInfoDic.size() == 0) {
            return null;
        }

        QueryInfoProtocol.QueryInfo.Builder builder = QueryInfoProtocol.QueryInfo.newBuilder();

        Iterator queryInfoEnum = queryInfoDic.keySet().iterator();
        while (queryInfoEnum.hasNext()) {
            builder = builder.setHandleId((Integer) queryInfoEnum.next());

            ArrayList values = (ArrayList) queryInfoDic.get(builder.getHandleId());

            int valuesListSize = values.size();
            for (int i = 0; i < valuesListSize; i++) {
                Object val = values.get(i);
                if (val != null) {
                    if (val instanceof Date) {
                        val = HelperFxn.getTicks((Date) val);
                    }
                    builder = builder.addAttributes(val.toString());
                } else //[Asad] as per fix mentioned in .net client by [salman] we need to send null values too as a special placeholder
                {
                    builder = builder.addAttributes("NCNULL");
                }
            }

        }
        return builder.build();
    }
    public static TagInfoProtocol.TagInfo getTagInfo(HashMap tagInfoDic) {
        if (tagInfoDic == null || tagInfoDic.size() == 0) {
            return null;
        }

        TagInfoProtocol.TagInfo.Builder builder = TagInfoProtocol.TagInfo.newBuilder();
        builder = builder.setType(String.valueOf(tagInfoDic.get("type")));

        Object obj = tagInfoDic.get("tags-list");
        if (obj instanceof ArrayList) {
            Iterator tagsEnum = ((ArrayList) obj).iterator();
            while (tagsEnum.hasNext()) {
                Object current = tagsEnum.next();
                if (current != null) {
                    builder = builder.addTags(current.toString());
                }
            }
        }

        return builder.build();
    }
    public static NamedTagInfoProtocol.NamedTagInfo GetNamedTagInfoObj(HashMap namedTagInfoDic) {

        if (namedTagInfoDic == null || namedTagInfoDic.size() == 0) {
            return null;
        }

        NamedTagInfoProtocol.NamedTagInfo.Builder builder = NamedTagInfoProtocol.NamedTagInfo.newBuilder();
        builder = builder.setType(String.valueOf(namedTagInfoDic.get("type")));

        HashMap tagsList = (HashMap) namedTagInfoDic.get("named-tags-list");
        Iterator namedTagEnumerator = tagsList.keySet().iterator();
        while (namedTagEnumerator.hasNext()) {
            Object current = namedTagEnumerator.next();
            if (current != null) {
                Object val = tagsList.get(current);
                builder = builder.addNames(current.toString());
                builder = builder.addTypes(val.getClass().getCanonicalName());
                if (val instanceof Date) {
                    val = HelperFxn.getTicks((Date) val);
                }
                builder = builder.addVals(val.toString());

            }
        }


        return builder.build();
    }

    //endregion
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy