Package org.nustaq.offheap.structs

Source Code of org.nustaq.offheap.structs.FSTStruct

package org.nustaq.offheap.structs;

import org.nustaq.offheap.bytez.Bytez;
import org.nustaq.offheap.bytez.onheap.HeapBytez;
import org.nustaq.offheap.structs.unsafeimpl.FSTStructFactory;

import java.io.*;

/**
* Copyright (c) 2012, Ruediger Moeller. All rights reserved.
* <p/>
* 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.
* <p/>
* 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.
* <p/>
* 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
* <p/>
* Date: 01.07.13
* Time: 20:20
* To change this template use File | Settings | File Templates.
*/
/**
* Base class of all structs. Inherit this to define your own structs.
* Refer to the documentation in the wiki regarding limitations of struct classes/members
*/
public class FSTStruct implements Serializable {

    transient public long ___offset;
    transient public Bytez ___bytes;
    transient public FSTStructFactory ___fac;
    transient public int ___elementSize;
    transient public FSTStructChange tracker;

    /**
     * must include bytearray offset in case of unsafe use
     * @param off
     */
    protected void setAbsoluteOffset(long off) {
        ___offset = off;
    }

    /**
     * @return internal offset, use getIndexInBase to get the start index of the struct within the base byte array
     */
    protected long getAbsoluteOffset() {
        return ___offset;
    }

    /**
     * @return the start index of this struct within the underlying byte array. getByteSize returns len
     */
    public long getOffset() {
        return (___offset);
    }

    /**
     * @deprecated use getOffset
     * see getOffset
     */
    public long getIndexInBase() {
        return (___offset);
    }

    /**
     * @return the number of bytes used by the struct pointed to
     */
    public int getByteSize() {
        if ( !isOffHeap() ) {
            return 0;
        }
        return ___bytes.getInt( ___offset);
    }

    public Class getPointedClass() {
        if ( ! isOffHeap() )
            throw new RuntimeException("cannot call on heap");
        Class clazz = ___fac.getClazz(getClzId());
        if ( clazz == null ) {
            return FSTStruct.class;
        }
        return clazz;
    }

    public int getClzId() {
        if ( ! isOffHeap() )
            throw new RuntimeException("cannot call on heap");
        return ___bytes.getInt(___offset+4);
    }

    public boolean pointsToNull() {
        return getClzId() <= 0;
    }

    protected void addOffset(long off) {
        ___offset+=off;
    }

    protected void setBase(Bytez base) {
        ___bytes = base;
    }

    /**
     * @return the underlying byte array.
     */
    public Bytez getBase() {
        return ___bytes;
    }

    public FSTStructFactory getFac() {
        return ___fac;
    }

    /**
     * set this struct pointer to base array at given offset (=bufoff+index)
     * @param base
     * @param offset direct offset to byte array element (=FSTStruct.bufoff+array index)
     */
    public void baseOn( byte base[], long offset, FSTStructFactory fac) {
        ___bytes = new HeapBytez(base); ___offset = offset; ___fac = fac;
    }

     public void baseOn( Bytez base, long offset, FSTStructFactory fac) {
         ___bytes = base; ___offset = offset; ___fac = fac;
     }

    /**
     * set this struct pointer to base array at given index
     * @param base
     * @param index
     */
    public void baseOn( byte base[], int index ) {
        ___bytes = new HeapBytez(base); ___offset = index;
        if ( ___fac == null )
            ___fac = FSTStructFactory.getInstance();
    }

     public void baseOn( Bytez base, int index ) {
         ___bytes = base; ___offset = index;
         if ( ___fac == null )
             ___fac = FSTStructFactory.getInstance();
     }

    public boolean isIdenticTo(FSTStruct other) {
        return other.getBase().equals(___bytes) && other.getAbsoluteOffset() == ___offset;
    }

     public int hashCode() {
         if ( !isOffHeap() )
             return onHeapHashcode();
        return ___bytes.getInt(___offset)^___bytes.getInt(___offset+getByteSize()-4);
     }

     public int onHeapHashcode() {
         return super.hashCode();
     }

     @Override
     public boolean equals(Object obj) {
         if (obj instanceof FSTStruct) {
             FSTStruct other = (FSTStruct) obj;
             final int len = getByteSize();
             if (other.getByteSize() == len) {
                 long ix = getOffset();
                 long ox = other.getOffset();
                 for ( int i=0; i < len; i++) {
                     if ( ___bytes.get(i+ix) != other.___bytes.get(i+ox) )
                         return false;
                 }
                 return true;
             } else
                return false;
         }
         return super.equals(obj);
     }

     public boolean isOffHeap() {
        return ___fac != null;
    }

    public int getElementInArraySize() {
        return ___elementSize;
    }

    public boolean isStructArrayPointer() {
        return ___elementSize > 0;
    }

    public boolean isNull() {
        return getClzId() <= 0;
    }

    /**
     * important: iterators, array access and access to substructures of a struct always return
     * pointers, which are cached per thread. To keep a pointer to a struct (e.g. search struct array and find an
     * element which should be kept as result) you need to detach it (removed from cache). Cost of detach is like an
     * object creation in case it is in the cache.
     */
    public FSTStruct detach() {
        if ( isOffHeap() ) {
            ___fac.detach(this);
        }
        return this;
    }

    /**
     *  Warning: no bounds checking. Moving the pointer outside the underlying Bytez will cause access violations
     */
    public final void next() {
        if ( ___elementSize > 0 )
            ___offset += ___elementSize;
        else
            throw new RuntimeException("not pointing to a struct array");
    }

    /**
     *  Warning: no bounds checking. Moving the pointer outside the underlying Bytez will cause access violations
     */
    public final void next(int offset) {
        ___offset += offset;
    }

    /**
     *  Warning: no bounds checking. Moving the pointer outside the underlying Bytez will cause access violations
     */
    public final void previous() {
        if ( ___elementSize > 0 )
            ___offset -= ___elementSize;
        else
            throw new RuntimeException("not pointing to a struct array");
    }

    public <T extends FSTStruct> T cast( Class<T> to ) {
        int clzId = ___fac.getClzId(to);
        if ( this.getClass().getSuperclass() == to )
            return (T) this;
        FSTStruct res = ___fac.createStructPointer(___bytes, (int) (___offset), clzId);
        res.___elementSize = ___elementSize;
        return (T) res;
    }

    /**
     * @return a volatile pointer of the exact type this points to
     */
    public FSTStruct cast() {
        int clzId = getClzId();
        if ( ___fac.getClazz(clzId) == getClass().getSuperclass() )
            return this;
        FSTStruct res = (FSTStruct) ___fac.getStructPointerByOffset(___bytes, ___offset);
        res.___elementSize = ___elementSize;
        return res;
    }

    public byte getByte() {
        return ___bytes.get(___offset);
    }

    public void setByte(byte i) {
        ___bytes.put(___offset,i);
    }

    public char getChar() {
        return ___bytes.getChar(___offset);
    }

    public short getShort() {
        return ___bytes.getShort(___offset);
    }

    public void setShort(short i) {
        ___bytes.putShort(___offset,i);
    }

    public int getInt() {
        return ___bytes.getInt(___offset);
    }

    public void setInt(int i) {
        ___bytes.putInt(___offset,i);
    }

    public long getLong() {
        return ___bytes.getLong(___offset);
    }

    public void setLong(long i) {
        ___bytes.putLong(___offset, i);
    }

    public float getFloat() {
        return ___bytes.getFloat(___offset);
    }

    public double getDouble() {
        return ___bytes.getDouble(___offset);
    }

    public void getBytes(byte[] target, int startIndexInTarget, int len) {
        if ( ! isOffHeap() ) {
            throw new RuntimeException("must be offheap to call this");
        }
        ___bytes.getArr(___offset,target,startIndexInTarget,len);
    }

    public void getBytes(Bytez target, int startIndexInTarget) {
        if ( ! isOffHeap() ) {
            throw new RuntimeException("must be offheap to call this");
        }
        if ( target.length() < startIndexInTarget+getByteSize() ) {
            throw new RuntimeException("ArrayIndexOutofBounds byte len:"+target.length()+" start+size:"+(startIndexInTarget+getByteSize()));
        }
//        unsafe.copyMemory(___bytes,___offset, target, bufoff+startIndexInTarget, getByteSize());
        ___bytes.copyTo(target,startIndexInTarget,___offset, getByteSize());
    }

     public void setBytes(byte[] source, int sourceIndex, int len ) {
         if ( ! isOffHeap() ) {
             throw new RuntimeException("must be offheap to call this");
         }
         ___bytes.set(___offset,source,sourceIndex,len);
     }

    public void setBytes(Bytez source, int sourceIndex, int len ) {
        if ( ! isOffHeap() ) {
            throw new RuntimeException("must be offheap to call this");
        }
//        unsafe.copyMemory(source, bufoff+sourceIndex, ___bytes, ___offset, len);
        source.copyTo(___bytes, ___offset, sourceIndex, len);
    }

    /**
     * returns a complete copy of this object allocating a new Bytez capable of holding the data.
     * @return
     */
    public FSTStruct createCopy() {
        if ( ! isOffHeap() ) {
            throw new RuntimeException("must be offheap to call this");
        }
        byte b[] = new byte[getByteSize()];
        HeapBytez res = new HeapBytez(b);
        getBytes(res,0);
        return ___fac.createStructWrapper(res,0);
    }

    /**
     * works only if change tracking is enabled
     */
    public FSTStruct startChangeTracking() {
        tracker = new FSTStructChange();
        return this;
    }

    /**
     * works only if change tracking is enabled
     */
    public FSTStructChange finishChangeTracking() {
        tracker.snapshotChanges((int) getOffset(),getBase());
        FSTStructChange res = tracker;
        tracker = null;
        return res;
    }

     public boolean isChangeTracking() {
         return tracker != null;
     }

     public FSTStruct toOffHeap() {
         if ( isOffHeap() )
             return this;
         return FSTStructFactory.getInstance().toStruct(this);
     }

     //////////////////////////////////////////////
     // helper to support stringy web protocols

     public Object getFieldValues() {
         throw new RuntimeException("only supported for structs");
     }
}
TOP

Related Classes of org.nustaq.offheap.structs.FSTStruct

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.