Join The Works program to have access to the most current content, and to be able to ask questions and get answers from Revelation staff and the Revelation community

At 30 DEC 2021 02:14:58AM Joshua Goddard wrote:

Could someone please explain how the java OEnginerServer/NETOI talks to an OpenEngine?


At 30 DEC 2021 03:16AM Andrew McAuley wrote:

Assuming I am understanding the question correctly, when OI 1 was launched it was intended to be middleware, allowing any external program to communicate via the engine to allow access to any database. To this end it introduced something called REVCAPI. There's some limited documentation here. Checkout also REVCAPI_EQUATES in the online help.

The Sprezzatura Group

The Sprezzatura Blog

World leaders in all things RevSoft


At 30 DEC 2021 09:22AM bob carten wrote:

Here are some simple examples of using revCapi to talk to an oengine.

These correlate to the Oengine documentation referenced by Sprezz.

C#

using System;

using System.Collections.Generic;

using System.Runtime.InteropServices;

using System.Collections.Specialized;

using System.Threading;

using System.Text;

using System.IO;





namespace ghIPSS_Console

{

    class RevCapiWrapper



	/// <summary>

	/// Summary description for RevCapiWrapper.

	/// This Class is an interop wrapper for RevCap32.dll

	///

	/// 24 March 2005    rjc  Created

	/// </summary>



{



	// Function Prototypes for RevCapi



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevInitializeApi();



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevTerminateApi();



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetApiError();



	// The old way to start the engine and open a queue

	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevStartLocalEngine(String Pathname, String Database);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevShutdownLocalEngine(byte bSuppressMsg);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevOpenQ(String Qname, String UserName, String Password,  out int Queue)            ;



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevCloseQ(int Queue);





	// The new way to start an engine and open queues

	const int  REV_CREATE_ENGINE_OPEN_EXISTING = 0 ;

	const int REV_CREATE_ENGINE_CREATE_NEW = 1;

	const int REV_CREATE_ENGINE_OPEN_ALWAYS = 2;

	const int  REV_CREATE_ENGINE_INDEXER = 16;

	const int REV_CREATE_ENGINE_WAIT_ON_CLOSE = 32;

	const int REV_CREATE_ENGINE_NO_UI = 64;



	const int  UNPROCESSED = 0;      // Server has not begun request.

	const int PROCESSING = 1;       // Server is processing request.

	const int DATA_AVAILABLE = 2;   // Server has data available.

	const int COMPLETED = 3;        // Server has completed request, status information is available.

	const int PROC_ERROR = 4;       // Server process failed, status information is available.

	const int INFO_AVAILABLE = 5;   // Server has intermediate status information available.

	const int INFO_REQUEST = 10 ;   // Server is requesting info



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevCreateEngine(String Server,

		String Database,

		int nFlags,

		int nShutdownSessions,

		out int Engine);







	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevCloseEngine( int Engine );





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevCreateQueue( int hEngine ,

		String pQueueName,

		String pDatabase,

		String pUserName,

		String pPassword,

		out int Queue );





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevCloseQueue( int Queue );



	//The rest of the api is the same

	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetEngine( int Queue, out int Engine)        ;



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetSizeOfQNames();



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetQNames(StringBuilder Buffer,

		long buffSize,

		char Delimiter)            ;



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetSizeOfQStatus(int Queue);



	//[ DllImport("REVCAP32.DLL")]

	//protected internal static extern int

	//        RevGetQStatus( int QUEUE, LPQSTATUS As Object)

	//        ;





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevSetScript( String Script, int ScriptSize);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevSetScriptArg(int PlaceNo, String Value, int dwSize);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevSendScript(int QUEUE, int hTransact,  out int Request );





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevSendImm(int Queue, String Script, int ScriptLen, int Transact, int Request, StringBuilder Result);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevSend(int Queue, String Script, int ScriptLen, int Priority, int Transact, out int Request);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevSendArg(int Request, int Position, String Value, int ValueLen) ;



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevEndSend_

		(int Request)

		;





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevPoll(int Request, out int Status);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevWait(int Request, out int Status);



	//[ DllImport("REVCAP32.DLL")]

	//protected internal static extern int

	//        RevWaitEx( int Request, DWORD, DWORD, UINT, UINT, LPINT) ;





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevEndRequest(int Request);





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetSizeOfRow( int Request);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetValueOfRow( int Request, StringBuilder Buffer, int BuffSize);





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetNumberOfColumns(int Request);





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetDataTypeOfColumn(int Request, int ColumnNr);





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetSizeOfColumn(int Request, int ColumnNr);





	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetValueOfColumn(int Request, int ColNo, StringBuilder Buffer, int BuffSize);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetSizeOfStatusText(int Request);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevGetStatusText(int Request, StringBuilder buffer, int bufferSize, char delimiter);



	[ DllImport("REVCAP32.DLL")]

	protected internal static extern int

		RevRespond(int Request, StringBuilder Buffer, int BufferSize);

	//

	//  * End function prototypes *

	//





	    // Fields

	    private static int m_instanceCount = 0;







	    // Setting Names



	    const string WORKING_DIRECTORY =     "WorkingDirectory";

	    const string OESERVER_NAME     =     "ServerName";

	    const string DATABASE_NAME     =     "DatabaseName";

	    const string CREATE_FLAGS      =     "CreateFlags";

	    const string SHUTDOWN_SESSIONS =     "ShutdownSessions";

	    const string QUEUE_NAME        =     "QueueName";

	    const string USER_NAME         =     "UserName";

	    const string USER_PASSWORD     =     "UserPassword";

	    const string PROCEDURE_NAME    =     "ProcedureName";





	    // Default values

	    const string DEFAULT_PROCEDURE_NAME = "RUN_MY_REQUEST";

	    const string DEFAULT_ENGINE_SECTION = "DefaultEngine";







	    // Mv Delimiters

	    const char RM =   '\u00FF';

	    const char FM =   '\u00FE';

	    const char VM =   '\u00FD';



	    // Engine Settings	

	    // The intent is to let you set a section to determine which engine to run



	    //private static string m_server = "";

	    private static string m_database = "MYAPP";

	    private static string m_username = "MYUSER";

	    private static string m_password = "MYPASSWORD";

	    private static string m_workingdirectory = "c:\\revsoft\\OINSIGHT";

	    //private static string m_queue_name = "";

	    private static int m_create_flags = 1;

        private static int m_shutdownsessions = 1;

        private static string m_procedure_name = DEFAULT_PROCEDURE_NAME;



        //private static int m_engine = 0;

        //private static int m_queue = 0;



        //private static string m_rowDelim = "\r\n";



        private string response = "";





	// * end fields  *





	public RevCapiWrapper()

	{



		// Default Section

		//m_iniSection = DEFAULT_ENGINE_SECTION;



		Initialise();

	}



	public RevCapiWrapper( string SectionName)

	{

		// Pass in Section

		//m_iniSection = "DefaultEngine";



		Initialise();

	}





	private void Initialise()

	{



		// Get Session Parameters from Ini File



		string strTest;



		/*

		* m_workingdirectory = oIniFile.IniReadValue(m_iniSection, WORKING_DIRECTORY);

		* m_server = oIniFile.IniReadValue(m_iniSection, OESERVER_NAME);

		* m_database = oIniFile.IniReadValue(m_iniSection, DATABASE_NAME);

		* m_username = oIniFile.IniReadValue(m_iniSection, USER_NAME);

		* m_password = oIniFile.IniReadValue(m_iniSection, USER_PASSWORD);

        */





		//strTest = oIniFile.IniReadValue(m_iniSection, CREATE_FLAGS) ;

        strTest = "1";

		switch ( strTest)

		{



			case "0" :

				m_create_flags = 2;

				break;

			case "1" :

				m_create_flags = 1;

				break;

			case "2" :

				m_create_flags = 2;

				break;

			case "64" :

				m_create_flags = 64;

				break;

			case "65" :

				m_create_flags = 65;

				break;

			default:

				m_create_flags = 1;

				break;



		}



		//strTest = oIniFile.IniReadValue(m_iniSection, SHUTDOWN_SESSIONS) ;

        strTest = "1";

		switch ( strTest)

		{



			case "0" :

				m_shutdownsessions = 2;

				break;

			case "1" :

				m_shutdownsessions = 1;

				break;

			default:

				m_shutdownsessions = 1;

				break;



		}





		//strTest = oIniFile.IniReadValue(m_iniSection, PROCEDURE_NAME) ;

        strTest = "TEST_ISO8583_MANAGER";

		if ( strTest  != "" )

		{

			m_procedure_name = strTest;

		}

		else

		{

			m_procedure_name = DEFAULT_PROCEDURE_NAME;

		}

		



		// Init Api for the first engine

		if ( m_instanceCount == 0 ) 

		{

			Environment.CurrentDirectory = m_workingdirectory;

			RevInitializeApi();

		}



		

	}



	~RevCapiWrapper()

	{



		this.Close();



	}

	public void Close()

	{

        //if ( m_queue != 0 ) 

        //{

        //    RevCloseQueue( m_queue ) ;

        //    m_queue = 0;

        //}





        //if ( m_engine != 0 ) 

        //{

        //    RevCloseEngine( m_engine ) ;

        //    m_engine = 0 ;

        //}



		// last engine out kills the api

        //m_instanceCount-- ;

		//if ( m_instanceCount == 0 ) 

			RevTerminateApi();



	}



        public string Response

        {

            get { return response; }

        }



	public string RunCommand( string strMethod, string request )

	{



		int lret = 0;

		bool bOK = true;

        string encoded = base64Encode(request);

        response = "";





        // bump the engine count

        m_instanceCount++;



        // set the engine name

        // Note: I use the "\\.\pipename" format for the server name

        // to get an external, i.e. out of process, engine

        // without this you can only start a single engine

        string server  = "\\\\.\\SK" + m_instanceCount.ToString("00");

        string queue_name = "QK" + m_instanceCount.ToString("00");

        int queue = 0;

        int engine = 0;



        //server="8084";

        //m_create_flags = 0;

        //m_shutdownsessions = 0;



        

        // Is there a queue?		

		if (bOK)		

		{			



			try

			{



				// Change the current directory.

				Environment.CurrentDirectory = (m_workingdirectory);				

				

				lret = RevCreateEngine(server, m_database, m_create_flags, m_shutdownsessions, out engine ) ;

				if (lret == 0 )

				{

					lret = RevCreateQueue(engine, queue_name, m_database, m_username, m_password,  out queue);

					if (lret != 0 )

					{

						this.Close();

					}				

				}

			}

			catch ( Exception ex )                

			{

                Console.WriteLine(ex.Message);

				lret = -1;

				this.Close();

			}

		}



			string strReturnValue = "";

			int myStatus = 0;





			if ( lret == 0 && bOK)



			{

				int rowCount = 0 ;



				int pollLen = 0;

				StringBuilder resultBuffer = new StringBuilder(""); 

				StringBuilder pollBuffer;

					

					

				string strFuncName = m_procedure_name;				

                string script = "RUN " + strFuncName + " '" + strMethod + "', " + " '" + encoded + "'";

                string statusText = "";

				int myRequest = 0;

				char chDelim = '\t';



                try

                {





                    lret = RevSetScript(script, script.Length);

                    if (lret == 0)

                    {

                        lret = RevSendScript(queue, 0, out myRequest);

                    }



                    if (myRequest != 0)

                    {



                        do

                        {

                            lret = RevPoll(myRequest, out myStatus);

                            switch (myStatus)

                            {

                                case UNPROCESSED:      // Server has not begun request.

                                    break;

                                case PROCESSING:       // Server is processing request.

                                    break;

                                case DATA_AVAILABLE:   // Server has data available.



                                    // add break between rows

                                    rowCount++;

                                    //if ( rowCount > 1) 

                                    //	resultBuffer.Append( m_rowDelim );



                                    int colCount = RevGetNumberOfColumns(myRequest);

                                    int wColNo;

                                    string this_val = "";

                                    for (wColNo = 1; wColNo <= colCount; wColNo++)

                                    {



                                        // Fieldmark between columns

                                        if (wColNo > 1)

                                            resultBuffer.Append(FM);



                                        // Get the data for this columns

                                        pollLen = RevGetSizeOfColumn(myRequest, wColNo);

                                        if (pollLen > 0)

                                        {

                                            pollBuffer = new StringBuilder(pollLen);

                                            lret = RevGetValueOfColumn(myRequest, 1, pollBuffer, pollLen);

                                            this_val = pollBuffer.ToString();







                                            // Append the column

                                            resultBuffer.Append(this_val);

                                        }



                                    }







                                    break;

                                case COMPLETED:        // Server has completed request, status information is available.



                                    // Get the status data

                                    pollLen = RevGetSizeOfStatusText(myRequest);

                                    if (pollLen > 0)

                                    {

                                        pollBuffer = new StringBuilder(pollLen);

                                        lret = RevGetStatusText(myRequest, pollBuffer, pollLen, chDelim);

                                        statusText = pollBuffer.ToString();

                                        resultBuffer.Append(statusText);

                                    }



                                    break;

                                case PROC_ERROR:       // Server process failed, status information is available.

                                    // Get the status data

                                    pollLen = RevGetSizeOfStatusText(myRequest);

                                    if (pollLen > 0)

                                    {

                                        pollBuffer = new StringBuilder(pollLen);

                                        lret = RevGetStatusText(myRequest, pollBuffer, pollLen, chDelim);



                                        statusText = pollBuffer.ToString();

                                        resultBuffer.Append(statusText);

                                    }



                                    break;

                                case INFO_AVAILABLE:   // Server has intermediate status information available.

                                    pollLen = RevGetSizeOfStatusText(myRequest);

                                    if (pollLen > 0)

                                    {

                                        pollBuffer = new StringBuilder(pollLen);

                                        lret = RevGetStatusText(myRequest, pollBuffer, pollLen, chDelim);

                                        statusText = pollBuffer.ToString();



                                        resultBuffer.Append(statusText);

                                    }

                                    break;

                                case INFO_REQUEST:   // Server is requesting info

                                    resultBuffer.Append(statusText);

                                    break;

                            }



                        }

                        while ((myStatus != COMPLETED) && (myStatus != PROC_ERROR));

                        strReturnValue = resultBuffer.ToString();

                    }

                    RevEndRequest(myRequest);





                }

                catch (Exception e)

                {

                    strReturnValue = " RunRequest Failed ...";

                    System.Console.WriteLine("{0} \n {1}", strReturnValue, e.Message);

                    if (myRequest != 0)

                        RevEndRequest(myRequest);





                }



                finally

                {

                    if (queue != 0)

                    {

                        RevCloseQueue(queue);

                        queue = 0;

                    }





                    if (engine != 0)

                    {

                        RevCloseEngine(engine);

                        engine = 0;

                    }





                    //m_instanceCount--;

                }

			}



            

			return strReturnValue;

		}



        public bool runRequest(string OiMethod, string request)

        {

            string encoded = base64Encode(request);            

            bool isOk = true;



            string result = RunCommand(OiMethod, request);

                if (isOk)

                {

                    response = base64Decode(result);

                }            

            

            return isOk;

        }



        public string base64Encode(string data)

        {

            try

            {

                byte[] encData_byte = new byte[data.Length];

                encData_byte = System.Text.Encoding.ASCII.GetBytes(data);

                string encodedData = Convert.ToBase64String(encData_byte);

                return encodedData;

            }

            catch (Exception e)

            {

                throw new Exception("Error in base64Encode" + e.Message);

            }

        }



        public string base64Decode(string data)

        {

            try

            {

                System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();

                System.Text.Decoder AsciiDecode = encoder.GetDecoder();



                byte[] todecode_byte = Convert.FromBase64String(data);

                int charCount = AsciiDecode.GetCharCount(todecode_byte, 0, todecode_byte.Length);

                char[] decoded_char = new char[charCount];

                AsciiDecode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);

                string result = new String(decoded_char);

                return result;

            }

            catch (Exception e)

            {

                throw new Exception("Error in base64Decode" + e.Message);

            }

        }

	}



}

Basic+ example

Function TEST_REVCAPI(method)

/*

**  Purpose:  Test calling revCapi

**    

**  Usage:



**  run TEST_REVCAPI 'SUB' to test callsubroutine

**  run TEST_REVCAPI 'FUNC' to test callFunction

**  run TEST_REVCAPI '' to test CreateRequest

**



* Notes:





*  rjc  12-07-10  Created

*/



Declare Function rti_createGuid



$Insert revcapi_equates

$Insert Msg_Equates



If Assigned(method) Else method = ''



* Connect to an oinsight



serverSpec = "\\.\":rti_createGuid()

databasename = @APPID<1>

flags = 0

shutdownSessions = 0

username = @username

password = @username  ;* assume password same as username

queueName = ''

path = drive()

If path[-1,1] = '\' Then path[-1,1] = ''





*

* revCapi will only start an OENGINE

* If don't need to start oi, use startflag = 1 or startflag = 65 for hidden engine

*



* For this example, I want to use Oi.

* That let's you run oipi or windows in the other copy.

* So, launch a child OI using a /sn parameter, then connect to it with startflag = 0

* 



*

cmd = "oinsight.exe"

params = ' /sn=':serverspec : ' /ap=' : databasename : ' /un=':username : ' /pw=':password: ' /dv=1'

Call shellExecute(0, 'Open':\00\, cmd:\00\, params:\00\, Drive():\00\, 0)



*

* 15 second delay to allow OI to start

*

elapsed = 0

max_elapsed = 15

loop

	started = time()

	Loop

		Call winyield()

	While time() = started

	Repeat

	

	elapsed +=1

	Call send_Info( 'delay ' : elapsed : ' of ' : max_elapsed : ' seconds')

Until elapsed ge max_elapsed

Repeat



engine = 0

queue = 0

error = 0

returnvalue = ''

statustext = ''

Error = CreateEngine(Engine, ServerSpec, DatabaseName,  Flags, ShutdownSessions)

If Not(error) then

	Error = CreateQueue(Queue, Engine, QueueName, DatabaseName, UserName, Password)

End





oiFuncName = 'TEST_REVCAPI_SUB'

oiParam = databasename



Begin Case

	Case error

		

	Case indexc(method, 'Func', 1)

		Call WinYield()

		Error = CallFunction(Queue, returnvalue, oiFuncName, oiParam)

		Call WinYield()

	Case indexc(method, 'Sub', 1)

		Call WinYield()

		Error = CallSubroutine(Queue, oiFuncName, oiParam)

		Call WinYield()

	Case 1

		script = "RUN " : oiFuncName : " '" : oiParam : "'";

		statusText = "";

		request = 0;

		Status = ''

		statusText = ''

		returnvalue = ''

		this_reply = ''

		

		Error = CreateRequest(request, Queue, Script, '')

		if ( request ne 0 )  then

			loop

				Error = PollForReply(Request, Status)

				begin case

					case Status eq UNPROCESSED$      // Server has not begun request.

						null

					case Status eq PROCESSING$       // Server is processing request.

						null

					case Status eq DATA_AVAILABLE$   // Server has data available.

						Error = GetReply(Request, this_reply)

						returnvalue := this_Reply

						

					case Status eq COMPLETED$        // Server has completed request, status information is available.						

						Error = GetStatusText(Request, @vm, StatusText)					

						

					case Status eq PROC_ERROR$       // Server process failed, status information is available.

						// Get the status data

						// Get the status data

						

						Error = GetStatusText(Request, @vm, StatusText)

						

						

						

					case Status eq INFO_AVAILABLE$   // Server has intermediate status information available.

						this_Text = ''

						Error = GetStatusText(Request, @vm, this_Text)

						Call send_dyn(this_text)

						

					case Status eq INFO_REQUEST$   // Server is requesting info

						this_Text = ''

						Error = GetStatusText(Request, @vm, this_Text)

						def = ''

						def<mType$> = 'RC'

						def<mCaption$> = 'Info Needed'

						def<mText$> = this_text

						ans = Msg(@window, def)

						

				end case

			while ( (Status ne COMPLETED$) and ( Status ne PROC_ERROR$) )

			repeat

			CloseRequest(Request)

		end

		

		

End case



// Clean Up - close queue and engine.  Becuase I used 0 for shutdoen sessions it will not close the OI

// 

if queue then   x = CloseQueue(Queue)

if engine then  x = CloseEngine(Engine)



Call Send_Dyn(' Response = ' : Quote(returnvalue))

Call Send_Dyn(' Status = ' : Quote(statustext))

Call Send_Dyn(' error = ' : Quote(error))





Return ''
Function TEST_REVCAPI_SUB(text)



If Assigned(text) Else text = ''

ans = 'you sent ' : quote(text)

Call Set_Status(1, 'Happy')

Return ans

At 30 DEC 2021 06:45PM Joshua Goddard wrote:

Thanks, but my question was more: how does revcapi talk to the OEngnie?


At 31 DEC 2021 09:52AM bob carten wrote:

Are you asking about the transport protocol? RevCapi uses named pipes or tcpip. RCL4. The ServerName parameter determines which protocol to use. The default is named pipe. If you specify a port number then revcapi uses tcpip. If you look at the engineinfo you can see the named pipe name or tcpip port that is being used.

For example

/SN=BOB will open a named pipe "BOB"

/SN= 18123 will connect on tcpip port 18123


At 04 JAN 2022 01:30AM Joshua Goddard wrote:

Thanks, that's what I wanted to know.

View this thread on the Works forum...

  • third_party_content/community/commentary/forums_works/fb5f9e7106d5cd469102a60c3c1d15ba.txt
  • Last modified: 2024/01/04 20:57
  • by 127.0.0.1