org.cloudata.core.tablet.ColumnValue.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudata.core.tablet.ColumnValue.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.cloudata.core.tablet;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudata.core.client.Cell;
import org.cloudata.core.client.Row;
import org.cloudata.core.client.ScanCell;
import org.cloudata.core.common.Constants;
import org.cloudata.core.common.io.CWritable;
import org.cloudata.core.common.io.CWritableUtils;

/**
 * ? Cell? ? ??(ValueObject)<br>
 * ??? API Tablet Server ? ?? ?  ?.<br>
 * @author 
 *
 */
public class ColumnValue implements CWritable, Comparable<ColumnValue>, org.apache.hadoop.io.Writable {
    public static final Log LOG = LogFactory.getLog(ColumnValue.class.getName());

    public static final String ARRAY_CLASS_NAME = (new ColumnValue[0]).getClass().getName();
    public static final int ARRAY_CLASS_LENGTH = ARRAY_CLASS_NAME.getBytes().length;
    public static long NANO_TIME = 0;
    /**
     * ? Row.Key
     */
    protected Row.Key rowKey;

    /**
     * Cell.Key
     */
    protected Cell.Key cellKey;

    /**
     * Value
     */
    protected byte[] value;

    /**
     * timestamp (columnkey ??  timestamp? desc  ?.)
     */
    protected long timestamp;

    /**
     *  (? ?? compaction   ? ?.
     */
    protected boolean deleted;

    /**
     *  Cell.Key?  ? ?? (read ? )
     */
    private int numOfValues;

    public ColumnValue() {
        rowKey = new Row.Key();
        cellKey = new Cell.Key();
    }

    public ColumnValue(Row.Key rowKey, Cell.Key cellKey, byte[] value) {
        this(rowKey, cellKey, value, false, System.currentTimeMillis());
    }

    public ColumnValue(Row.Key rowKey, Cell.Key cellKey, byte[] value, boolean deleted) {
        this(rowKey, cellKey, value, deleted, System.currentTimeMillis());
    }

    public ColumnValue(Row.Key rowKey, Cell.Key cellKey, byte[] value, long timestamp) {
        this(rowKey, cellKey, value, false, timestamp);
    }

    public ColumnValue(Row.Key rowKey, Cell.Key cellKey, byte[] value, boolean deleted, long timestamp) {
        this.rowKey = rowKey;
        this.cellKey = cellKey;
        this.value = value;
        this.deleted = deleted;
        this.timestamp = timestamp;
    }

    public ColumnValue copyColumnValue() {
        try {
            ColumnValue columnValue = new ColumnValue();

            byte[] buf = new byte[columnValue.size()];

            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            DataOutputStream out = new DataOutputStream(bout);
            this.write(out);

            buf = bout.toByteArray();
            DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf));

            columnValue.readFields(in);

            out.close();
            in.close();
            return columnValue;
        } catch (Exception e) {
            LOG.error(e);
            return null;
        }
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }

    public Row.Key getRowKey() {
        return rowKey;
    }

    public void setRowKey(Row.Key rowKey) {
        this.rowKey = rowKey;
    }

    public Cell.Key getCellKey() {
        return cellKey;
    }

    public void setCellKey(Cell.Key cellKey) {
        this.cellKey = cellKey;
    }

    public byte[] getValue() {
        return value;
    }

    public void setValue(byte[] value) {
        this.value = value;
    }

    public String getValueAsString() {
        if (value == null)
            return null;
        return new String(value);
    }

    public CWritable getValue(CWritable writable) throws IOException {
        if (value == null)
            return null;

        DataInputStream din = new DataInputStream(new ByteArrayInputStream(value));
        writable.readFields(din);
        return writable;
    }

    public String toString() {
        return "[Row.Key=" + rowKey + ", CellKey=" + cellKey + ", value=" + getValueAsString() + ", timestamp="
                + timestamp + ", deleted=" + deleted + "]";
    }

    public void readFields(DataInput in) throws IOException {
        //long startNano = System.nanoTime();
        rowKey.readFields(in);
        cellKey.readFields(in);
        int opCode = in.readInt();
        if (opCode == Constants.DELETEED) {
            deleted = true;
        } else if (opCode == Constants.INSERTED) {
            deleted = false;
        } else {
            throw new IOException("Wrong record operation code(DELETEED or INSERTED): " + opCode);
        }
        timestamp = in.readLong();
        numOfValues = in.readInt();
        int valueLength = in.readInt();
        //System.out.println(">>>>>" + valueLength);
        value = valueLength < 0 ? null : new byte[valueLength];
        if (value != null) {
            in.readFully(value);
        }
    }

    public void write(DataOutput out) throws IOException {
        rowKey.write(out);

        cellKey.write(out);

        //write operation
        if (deleted) {
            out.writeInt(Constants.DELETEED);
        } else {
            out.writeInt(Constants.INSERTED);
        }

        //write timestame
        out.writeLong(timestamp);

        //write numOfValues
        out.writeInt(numOfValues);

        //write value
        int valueLength = (value == null ? -1 : value.length);

        out.writeInt(valueLength);

        if (valueLength > 0) {
            out.write(value);
        }
    }

    public int size() throws IOException {
        //columnKey + deleted + timestamp + valueSize + value
        return rowKey.getByteSize() + cellKey.getByteSize() + CWritableUtils.getIntByteSize()
                + CWritableUtils.getLongByteSize() + CWritableUtils.getIntByteSize()
                + CWritableUtils.getIntByteSize() + (value == null ? 0 : value.length);
    }

    public int getAllocatedSize() {
        return 40 + rowKey.getAllocatedSize() + cellKey.getAllocatedSize() + (value == null ? 0 : value.length);
    }

    /**
     * ?: ?? columnKey? time desc ??? .( ??  ? ?) 
     */
    public int compareTo(ColumnValue obj) {
        //FIXME Timestamp  ??  ? ??  ?   ? 
        //ColumnValue must be desc
        if (rowKey == null)
            return -1;
        if (obj.rowKey == null)
            return 1;
        int compare = rowKey.compareTo(obj.rowKey);
        if (compare != 0) {
            return compare;
        }

        if (cellKey == null)
            return -1;
        if (obj.cellKey == null)
            return 1;

        //timestamp ? ?  1, ?  -1? .
        //? ValueCollection? version  ?  ?  ?   ?.
        if ((compare = cellKey.compareTo(obj.cellKey)) == 0) {
            if (timestamp == obj.timestamp) {
                if (deleted == obj.deleted)
                    return 0;
                else
                    return deleted ? -1 : 1;
            } else
                return timestamp > obj.timestamp ? -1 : 1;
        } else
            return compare;
    }

    public boolean equals(Object obj) {
        if (!(obj instanceof ColumnValue)) {
            return false;
        }

        ColumnValue that = (ColumnValue) obj;

        if (this.rowKey == that.rowKey || (this.rowKey != null && this.rowKey.equals(that.rowKey))) {
            if (this.cellKey == that.cellKey || (this.cellKey != null && this.cellKey.equals(that.cellKey))) {

                return this.timestamp == that.timestamp && this.deleted == that.deleted
                        && this.numOfValues == that.numOfValues;

                // Not compare the value due to performance reason
                // It seems ok to compare all the members except value
                // in order to determine the equivalence of the two objects

                // && Arrays.equals(this.value, that.value);
            }
        }

        return false;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }

    public String getPrintValue(String encoding) {
        try {
            String keyStr = null;
            if (cellKey != null || cellKey.getBytes() != null) {
                keyStr = new String(cellKey.getBytes(), 0, cellKey.getLength(), encoding);
            }

            String valueStr = null;
            if (value != null) {
                valueStr = new String(value, 0, value.length, encoding);
            }

            if (numOfValues > 1) {
                return keyStr + ":" + valueStr + "(" + numOfValues + ")";
            } else {
                return keyStr + ":" + valueStr;
            }
        } catch (UnsupportedEncodingException e) {
            return "Error:" + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public String getPrintValue() {
        return getPrintValue("utf-8");
    }

    public boolean equalsKey(ColumnValue columnValue) {
        return rowKey.equals(columnValue.rowKey) && cellKey.equals(columnValue.cellKey);
    }

    public int getNumOfValues() {
        return numOfValues;
    }

    public void setNumOfValues(int numOfValues) {
        this.numOfValues = numOfValues;
    }

    public long getValueAsLong() {
        return Long.parseLong(new String(value));
    }

    public int getValueAsInt() {
        return Integer.parseInt(new String(value));
    }

    public Cell.Value copyToCellValue() {
        Cell.Value cellValue = new Cell.Value();

        cellValue.setBytes(value);
        cellValue.setTimestamp(timestamp);
        cellValue.setDeleted(deleted);
        cellValue.setNumOfValues(numOfValues);

        return cellValue;
    }

    public ScanCell copyToScanCell(String columnName) {

        ScanCell scannerCell = new ScanCell();
        scannerCell.setRowKey(rowKey);
        scannerCell.setColumnName(columnName);

        scannerCell.setCellKey(cellKey);
        scannerCell.setCellValue(copyToCellValue());

        return scannerCell;
    }
}