/*
// $Id$
// Farrago is an extensible data management system.
// Copyright (C) 2005-2006 The Eigenbase Project
// Copyright (C) 2005-2006 Disruptive Tech
// Copyright (C) 2005-2006 LucidEra, Inc.
// Portions Copyright (C) 2003-2006 John V. Sichi
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package net.sf.farrago.fennel;

import java.sql.*;

import net.sf.farrago.fem.fennel.*;

import org.eigenbase.util.*;


/**
 * FennelStorage is the JNI interface for calling Fennel from Farrago. Most
 * methods have package access only; other classes in this package expose public
 * wrapper methods.
 *
 * @author John V. Sichi
 * @version $Id$
 */
public class FennelStorage
{

    //~ Static fields/initializers ---------------------------------------------

    static {
        Util.loadLibrary("farrago");
    }

    static final int CLOSE_RESULT = 0;

    static final int CLOSE_ABORT = 1;

    static final int CLOSE_DEALLOCATE = 2;

    //~ Methods ----------------------------------------------------------------

    /**
     * Creates a native handle for a Java object for reference by XML commands.
     * After this, the Java object cannot be garbage collected until its owner
     * explicitly calls closeAllocation.
     *
     * @param obj object for which to create a handle, or null to create a
     * placeholder handle
     *
     * @return native handle
     */
    static native long newObjectHandle(Object obj);

    /**
     * Releases a handle obtained via newObjectHandle. This should only be
     * called from FennelJavaHandle.
     *
     * @param handle the handle to delete
     */
    static native void deleteObjectHandle(long handle);

    /**
     * Changes the object referenced by a handle.
     *
     * @param handle the handle to change
     * @param obj new object
     */
    static native void setObjectHandle(
        long handle,
        Object obj);

    /**
     * @return count of handles returned by Fennel which have not yet been
     * deleted
     */
    public static native int getHandleCount();

    /**
     * Constructs a FemTupleAccessor for a FemTupleDescriptor.
     *
     * @param tupleDesc source FemTupleDescriptor
     *
     * @return XMI string representation of FemTupleAccessor
     */
    static native String getAccessorXmiForTupleDescriptor(
        FemTupleDescriptor tupleDesc);

    /**
     * Executes a command represented as a Java object.
     *
     * @param cmd Java representation of object
     *
     * @return output object handle if any
     */
    static native long executeJavaCmd(FemCmd cmd)
        throws SQLException;

    /**
     * Opens a stream graph.
     *
     * @param hStream handle to stream
     * @param hTxn handle to txn in which stream is being opened
     * @param javaStreamMap optional FennelJavaStreamMap
     */
    static native void tupleStreamGraphOpen(
        long hStreamGraph,
        long hTxn,
        FennelJavaStreamMap javaStreamMap)
        throws SQLException;

    /**
     * Fetches a buffer of rows from a stream. If unpositioned, this fetches the
     * first rows.
     *
     * @param hStream handle to stream
     * @param byteArray output buffer receives complete tuples
     *
     * @return number of bytes fetched (at least one tuple should always be
     * fetched, so 0 indicates end of stream)
     */
    static native int tupleStreamFetch(
        long hStream,
        byte [] byteArray)
        throws SQLException;

    /**
     * Fetches a buffer of rows from a stream. Specifically, the stream must be
     * a JavaTransformExecStream. If unpositioned, this fetches the first rows.
     * Does not block if no data is available.
     *
     * @param hStream handle to stream
     * @param execStreamInputOrdinal ordinal of the input to fetch from
     * @param byteArray output buffer receives complete tuples
     *
     * @return number of bytes fetched (0 indicates end of stream, less than 0
     * indicates no data currently availble)
     */
    static native int tupleStreamTransformFetch(
        long hStream,
        int execSTreamInputOrdinal,
        byte [] byteArray)
        throws SQLException;

    /**
     * Restarts a stream.
     *
     * @param hStream handle to stream to restart
     */
    static native void tupleStreamRestart(
        long hStream)
        throws SQLException;

    /**
     * Closes a stream graph.
     *
     * @param hStream handle to stream graph
     * @param action CLOSE_XXX
     */
    static native void tupleStreamGraphClose(
        long hStreamGraph,
        int action)
        throws SQLException;
}

// End FennelStorage.java

@@ -1112,16 +1112,35 @@
 til.*;%0A%0A
+import java.awt.*;%0A
 %0A/**%0A * 
@@ -1390,16 +1390,55 @@
 torage%0A%7B
+%0A    private static Toolkit awtToolkit;
 %0A%0A    //
@@ -1509,24 +1509,24 @@
 ----------%0A%0A
-
     static %7B
@@ -1526,16 +1526,696 @@
 tatic %7B%0A
+        // REVIEW jvs 8-Sept-2006:  workaround upon workaround.  This%0A        // is required because in native code, we have to use%0A        // dlopen(%22libfarrago.so%22, RTLD_GLOBAL) in order for native plugins%0A        // to load correctly.  But the RTLD_GLOBAL causes trouble later%0A        // if someone tries to use AWT from within the same JVM.  So...%0A        // preload AWT here.%0A        try %7B%0A            awtToolkit = Toolkit.getDefaultToolkit();%0A        %7D catch (HeadlessException ex) %7B%0A            // I'm not sure if this can actually happen, but if it does,%0A            // just suppress it so that a headless server doesn't fail%0A            // on startup.%0A        %7D%0A        %0A
         

add workaround for problem of loading AWT from within same process as Farrago after Fennel has been loaded; this fixes a problem seen in the past with FarragoPlanVisualizer, as well as other scenarios such as embedding Farrago in an app server which does graphicky things such as chart rendering