/*------------------------------------------------------------------------------------------------- _______ __ _ _______ _______ ______ ______ |_____| | \ | | |______ | \ |_____] | | | \_| | ______| |_____/ |_____] 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 GNU Lesser 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/lgpl-3.0.en.html> -------------------------------------------------------------------------------------------------*/ package com.antsdb.saltedfish.nosql; import org.apache.commons.lang.StringUtils; 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.util.BytesUtil; /** * VaporizingRow is a transient row. It lives in the specified heap. It is * vaporized when the heap is gone. This class is mostly used in updating data * in Humpback. It is friendly with EA. * * @author wgu0 */ public final class VaporizingRow { Heap heap; int maxColumnId; long pValueArray; long pKey; long version; int size = 0; public VaporizingRow(Heap heap, int maxColumnId) { this.heap = heap; this.maxColumnId = maxColumnId; init(); } VaporizingRow(Heap heap, SlowRow from) { if (from.getMaxColumnId() < 0) { throw new IllegalArgumentException(); } this.heap = heap; this.maxColumnId = from.getMaxColumnId(); init(); this.version = from.getTrxTimestamp(); byte[] key = from.getKey(); long pKey = (key != null) ? KeyBytes.allocSet(heap, key).getAddress() : 0; setKey(pKey); for (int i = 0; i <= this.maxColumnId; i++) { Object value = from.get(i); set(i, value); } } private void init() { int len = (maxColumnId + 1) * 8; this.pValueArray = this.heap.alloc(len); Unsafe.setMemory(this.pValueArray, len, (byte) 0); } public int getMaxColumnId() { return maxColumnId; } public void setKey(byte[] key) { long pKey = (key != null) ? KeyBytes.allocSet(heap, key).getAddress() : 0; setKey(pKey); } public void setKey(long pNewKey) { if (this.pKey != 0) { size -= FishObject.getSize(this.pKey); } this.pKey = pNewKey; size += FishObject.getSize(pKey); } public void set(int field, Object value) { long pValue = FishObject.allocSet(heap, value); setFieldAddress(field, pValue); } public long getFieldAddress(int index) { long ppValue = this.pValueArray + index * 8; long pValue = Unsafe.getLong(ppValue); return pValue; } public void setFieldAddress(int n, long pValue) { if ((n < 0) || (n > this.maxColumnId)) { throw new IllegalArgumentException(); } long ppValue = this.pValueArray + n * 8; long pOldValue = Unsafe.getLong(ppValue); if (pOldValue != 0) { size -= FishObject.getSize(pOldValue); } size += FishObject.getSize(pValue); Unsafe.putLong(ppValue, pValue); } public long getKeyAddress() { return this.pKey; } public Object get(int index) { long pValue = getFieldAddress(index); Object value = FishObject.get(heap, pValue); return value; } /** * number of bytes * * @return */ public int getSize() { return this.size + Row.getHeaderSize(this.maxColumnId); } public long getTrxTimestamp() { return this.version; } public long getVersion() { return this.version; } public void setVersion(long version) { this.version = version; } @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("version:"); buf.append(this.version); buf.append('\n'); buf.append("max column id:"); buf.append(getMaxColumnId()); buf.append('\n'); buf.append("trx timestamp:"); buf.append(getTrxTimestamp()); buf.append('\n'); buf.append("key:"); buf.append(BytesUtil.toHex8(getKey())); for (int i = 0; i <= getMaxColumnId(); i++) { Object value = get(i); if (value != null) { buf.append('\n'); buf.append(i); buf.append(":"); String output; if (value instanceof byte[]) { output = BytesUtil.toHex((byte[]) value); } else { output = value.toString(); } if (output.length() >= 80) { output = StringUtils.left(output, 80) + "..."; } buf.append(output); } } return buf.toString(); } public byte[] getKey() { long pKey = getKeyAddress(); byte[] key = (byte[]) FishObject.get(heap, pKey); return key; } public static VaporizingRow from(Heap heap, int maxColumnId, Row raw) { VaporizingRow row = new VaporizingRow(heap, maxColumnId); row.setKey(raw.getKeyAddress()); row.setVersion(raw.getTrxTimestamp()); for (int i = 0; i <= raw.getMaxColumnId(); i++) { row.setFieldAddress(i, raw.getFieldAddress(i)); } return row; } public final String getKeySpec(int tableId) { String result = String.valueOf(tableId) + ":" + KeyBytes.toString(getKeyAddress()); return result; } }