Java tutorial
/*------------------------------------------------------------------------------------------------- _______ __ _ _______ _______ ______ ______ |_____| | \ | | |______ | \ |_____] | | | \_| | ______| |_____/ |_____] Copyright (c) 2016, antsdb.com and/or its affiliates. All rights reserved. *-xguo0<@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License, version 3, as published by the Free Software Foundation. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt> -------------------------------------------------------------------------------------------------*/ package com.antsdb.saltedfish.sql.vdm; import org.apache.commons.lang.NotImplementedException; import com.antsdb.saltedfish.cpp.FishObject; import com.antsdb.saltedfish.cpp.Heap; import com.antsdb.saltedfish.cpp.KeyBytes; import com.antsdb.saltedfish.cpp.Unsafe; import com.antsdb.saltedfish.cpp.Value; import com.antsdb.saltedfish.nosql.Row; import com.antsdb.saltedfish.nosql.SlowRow; import com.antsdb.saltedfish.sql.meta.ColumnMeta; import com.antsdb.saltedfish.sql.meta.TableMeta; import com.antsdb.saltedfish.util.BytesUtil; /** * record is not thread safe * * @author xinyi * */ public abstract class Record { public final static long GROUP_END = Unsafe.allocateMemory(16); final static byte TYPE_RECORD = Value.FORMAT_RECORD; final static int OFFSET_SIZE = 2; final static int OFFSET_KEY = OFFSET_SIZE + 2; final static int OFFSET_FIELDS = OFFSET_KEY + 8; public abstract Object get(int field); public abstract Record set(int field, Object val); public abstract byte[] getKey(); public abstract int size(); static { Unsafe.putByte(GROUP_END, TYPE_RECORD); Unsafe.putShort(GROUP_END + OFFSET_SIZE, (short) 0); } public Object getString(int i) { return (String) get(i); } public boolean isEmpty() { return getKey() == null; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append('{'); for (int i = 0; i < this.size(); i++) { buf.append('"'); buf.append(i); buf.append('"'); buf.append(':'); Object value = get(i); if (value instanceof String) { buf.append('"'); buf.append(value); buf.append('"'); } else { buf.append(value); } buf.append(','); } if (this.size() > 0) { buf.deleteCharAt(buf.length() - 1); } buf.append('}'); return buf.toString(); } public final static long alloc(Heap heap, int nFields) { if (nFields >= Short.MAX_VALUE) { throw new IllegalArgumentException(); } int bytes = OFFSET_FIELDS + nFields * 8; long p = heap.alloc(bytes); Unsafe.putByte(p, TYPE_RECORD); Unsafe.putShort(p + OFFSET_SIZE, (short) nFields); reset(p); return p; } public static void reset(long pRecord) { checkType(pRecord); int bytes = 8 + size(pRecord) * 8; Unsafe.setMemory(pRecord + OFFSET_KEY, bytes, (byte) 0); } public final static long getValueAddress(long pRecord, int field) { long pValue = get(pRecord, field); return pValue; } public final static Object getValue(long pRecord, int field) { long pValue = get(pRecord, field); if (pValue == 0) { return null; } Object value = FishObject.get(null, pValue); return value; } public final static long get(long pRecord, int field) { checkType(pRecord); int size = size(pRecord); if ((field < 0) || (field >= size)) { return 0; } long pField = pRecord + OFFSET_FIELDS + field * 8; long pValue = Unsafe.getLong(pField); return pValue; } public final static void set(long pRecord, int field, long pValue) { checkType(pRecord); checkField(pRecord, field); long pField = pRecord + OFFSET_FIELDS + field * 8; Unsafe.putLong(pField, pValue); } public final static int size(long pRecord) { checkType(pRecord); long pSize = pRecord + OFFSET_SIZE; int size = Unsafe.getShort(pSize); return size; } public final static long getKey(long pRecord) { checkType(pRecord); long pKey = Unsafe.getLong(pRecord + OFFSET_KEY); return pKey; } public final static byte[] getKeyBytes(long pRecord) { long pKey = getKey(pRecord); if (pKey == 0) { return null; } return KeyBytes.create(pKey).get(); } public final static void setKey(long pRecord, long pKey) { checkType(pRecord); Unsafe.putLong(pRecord + OFFSET_KEY, pKey); } public static void setKey(Heap heap, long pRecord, byte[] bytes) { long pBytes = bytes != null ? KeyBytes.allocSet(heap, bytes).getAddress() : 0; setKey(pRecord, pBytes); } private final static void checkType(long pRecord) { if (pRecord == 0) { throw new IllegalArgumentException(); } byte type = Unsafe.getByte(pRecord); if (type != TYPE_RECORD) { throw new IllegalArgumentException(); } } private final static void checkField(long pRecord, int field) { int size = size(pRecord); if ((field < 0) || (field >= size)) { throw new IllegalArgumentException(); } } public static void set(Heap heap, long pRecord, Record rec) { for (int i = 0; i < rec.size(); i++) { Object value = rec.get(i); long pValue = FishObject.allocSet(heap, value); Record.set(pRecord, i, pValue); } } public final static boolean isGroupEnd(long pRecord) { return pRecord == GROUP_END; } public static boolean isEmpty(long pRecord) { return getKey(pRecord) == 0; } public static Record toRecord(long pRecord) { Record rec = new HashMapRecord(); int size = size(pRecord); for (int i = 0; i < size; i++) { Object value = getValue(pRecord, i); rec.set(i, value); } return rec; } public static long fromRow(Heap heap, TableMeta table, SlowRow row) { throw new NotImplementedException(); } public static long fromRow(Heap heap, TableMeta table, Row row) { long pRecord = alloc(heap, table.getColumns().size() + 2); int i = 0; setKey(pRecord, row.getKeyAddress()); set(pRecord, i++, row.getFieldAddress(-1)); set(pRecord, i++, row.getFieldAddress(0)); for (ColumnMeta column : table.getColumns()) { long pValue = row.getFieldAddress(column.getColumnId()); set(pRecord, i++, pValue); } return pRecord; } public static String dump(long pRecord) { if (pRecord == 0) { return "NULL"; } StringBuilder buf = new StringBuilder(); try { buf.append("size:"); buf.append(size(pRecord)); buf.append("\n"); buf.append("key:"); buf.append(BytesUtil.toHex(getKeyBytes(pRecord))); buf.append("\n"); for (int i = 0; i < size(pRecord); i++) { buf.append(i); buf.append(":"); buf.append(getValue(pRecord, i)); buf.append("\n"); } } catch (Exception x) { return "not a record"; } return buf.toString(); } }