File: xa.xml

package info (click to toggle)
virtuoso-opensource 7.2.5.1%2Bdfsg1-0.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 285,240 kB
  • sloc: ansic: 641,220; sql: 490,413; xml: 269,570; java: 83,893; javascript: 79,900; cpp: 36,927; sh: 31,653; cs: 25,702; php: 12,690; yacc: 10,227; lex: 7,601; makefile: 7,129; jsp: 4,523; awk: 1,697; perl: 1,013; ruby: 1,003; python: 326
file content (384 lines) | stat: -rw-r--r-- 11,803 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
<?xml version="1.0" encoding="UTF-8"?>
<!--
 -  
 -  This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
 -  project.
 -  
 -  Copyright (C) 1998-2018 OpenLink Software
 -  
 -  This project 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; only version 2 of the License, dated June 1991.
 -  
 -  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.,
 -  51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 -  
 -  
-->

<chapter label="xa.xml" id="xa">
<title>Using Virtuoso with Tuxedo</title>
<abstract>
	<para>
		BEA Tuxedo provides the framework, or middleware, for building scalable multi-tier client/server 
		applications in heterogeneous (dissimilar), distributed environments that extend from the Web to 
		the Enterprise. Using BEA Tuxedo, users can develop, manage, and deploy distributed applications 
		independently of the underlying hardware, operating system, network, and database environment.
	</para>
	<para>
		The current document covers linkage between Virtuoso server and Tuxedo by ATMI (Application-to-Transaction
		Monitor Interface) only.
	</para>
	<para>
		In contrast to classic 2-tier client/server configuration of SQL servers, the Tuxedo brings 3-tier paradigm
		(clients, services, resource managers).
	</para>
	<para>
		At the foundation of BEA Tuxedo ATMI is a proven, reliable transaction processor, also known as 
		a transaction processing (TP) monitor. A transaction processor is an example of a 3-tier client/server
		architecture, where the transaction processor supports the application logic (represented by "services"
		between the GUI front-end and the back-end resource managers. Examples of resource managers are SQL 
		databases, message queues, legacy applications, and other back-end services.
	</para>
	<para>
		This document explains how to build support binaries for Tuxedo and Virtuoso and how to write services which
		use the Virtuoso as resource manager.
	</para>
</abstract>
<sect1 id="xaBuildTMS">
	<title>Building the Transaction Manager Server</title>
	<para>
		First of all, the administrator needs to build Virtuoso Transaction Manager Server application in order 
		to use Virtuoso server as Resource Manager of global transactions operated by Tuxedo.
	</para>
	<para>
		Then, the following line needs to be put in the $TUXDIR/udataobj/RM file:
		<programlisting>
			Virtuoso:virt_xa_switch: libvirtxa.a -L${HOME}/lib  -lwic -ldk1t -lthrp -lutil2 -L${SSLDIR}/lib -lssl -lcrypto
		</programlisting>
		The libvirtxa.a library could be found in tuxedo/lib directory.
	</para>
	<para>
		This allows to build TP monitor with Virtuoso support (VirtTMS) and services which could use Virtuoso as resource manager.
		libvirtxa.a and other libraries must be accessible by the compiler. The following command builds the VirtTMS:
		<programlisting>
			buildtms -o ${TUXDIR}/bin/VirtTMS -r Virtuoso
		</programlisting>
	</para>
</sect1>
<sect1 id="xaUBBconf">
	<title>Configuration</title>
	<para>
		In order to use Virtuoso as resource manager the UBB config file (Tuxedo main configuration file) must contain reference
		to VirtTMS. The following example of UBB config file configures two services and two virtuoso servers (resource managers)
		behind them.
	</para>
		<programlisting><![CDATA[*RESOURCES
IPCKEY          52617
DOMAINID        qsample
MASTER          NODE
MODEL           SHM
#
*MACHINES
#
NODE
        LMID = NODE
        TUXDIR = "TUXEDODIR"
        TUXCONFIG = "SERVDIR/tuxconfig"
        TLOGDEVICE ="SERVDIR/tuxconfig"
        TLOGSIZE=10
        APPDIR = "SERVDIR"
        ULOGPFX = "SERVDIR/ULOG"
*GROUPS

DEFAULT:        TMSNAME=VirtTMS TMSCOUNT=2 LMID=NODE
GROUP1  GRPNO=1 OPENINFO = "Virtuoso:dba:dba@NODE:1111"
GROUP2  GRPNO=2 OPENINFO = "Virtuoso:dba@NODE:1112"

*SERVERS
#
DEFAULT:        CLOPT="-A"
VirtRMtest      SRVGRP=GROUP1 SRVID=1
# VirtRMtest    SRVGRP=GROUP2 SRVID=1


# VirtRMtest2   SRVGRP=GROUP1 SRVID=2
VirtRMtest2     SRVGRP=GROUP2 SRVID=2

#server         SRVGRP=GROUP1 SRVID=1
*SERVICES
DEFAULT:        LOAD=50
VRMTEST         PRIO=50
VRMTEST2        PRIO=50
]]></programlisting>
</sect1>

<sect1 id="xaServices">
	<title>Services</title>
	<sect2 id="xaServicesAbstract">
		<title>Introduction</title>
		<para>
			The services (in the Tuxedo's term) are special programs which implement business logic. The services could
			be in the context of a global XA transaction, in this case 2PC control will be set in motion. 
			Each service which uses Virtuoso as resource manager has hdbc connection to 
			the Virtuoso server. This connection is automatically opened when service activated. The connection string (OPENINFO)
			to the Virtuoso server is the connection string of the group of the service (see GROUPS section 
			in the sample config file). The OPENINFO has the following format: "Virtuoso:user:password@NODENAME:port".
			The user,password and port are optional.
		</para>
	</sect2>
	<sect2 id="xaServicesVQL">
		<title>VQL functions</title>
		<para>
			VQL functions are used to receive access to hdbc for further work with the Virtuoso server.
			Only HDBCs received by the VQL functions are operated in
			the context of the distributed transactions.
		</para>
		<para>
			<programlisting>
				int vql_get_connection (HDBC * hdbc, int type);
			</programlisting>
			returns result of setting hdbc to current hdbc connection. "type" argument indicates 
			which hdbc is to select, currently only VQL_CTX_TYPE  is supported, other values are 
			reserved.
		</para>
		<para>
			<programlisting>
			int vql_get_env (HENV * env);
			</programlisting>
			returns result of setting current ODBC environment.
		</para>
		<para>Header: vql_client.h</para>
		<para>Library: libvirtxa.a</para>
	</sect2>
	<sect2 id="xaServCon">
		<title>Services concept</title>
		<para>
			Each service has an entry point (some function), which is supposed to perform the application task. The result of
			whole transaction depends on result of the service's entry function. The scenario of typical workflow is as
			follows:
			<itemizedlist mark="bullet" spacing="compact">
				<listitem>client begins global transaction by ATMI tpbegin() call,</listitem>
				<listitem>client calls the service N1 to update some tables on the first Virtuoso server (resource manager),</listitem>
				<listitem>client calls the service N2 to update some tables on the second Virtuoso server (resource manager),</listitem>
				<listitem>client finishes global transaction by either tpcommit() or tpabort() call of ATMI.</listitem>
			</itemizedlist>
		</para>
		<para>
			The tx_* functions also could be used, See TUXEDO TxRPC related or ORACLE XA documentation.
			<itemizedlist mark="bullet" spacing="compact">
				<listitem>tx_begin()</listitem>
				<listitem>tx_commit()</listitem>
				<listitem>tx_open()</listitem>
			</itemizedlist>
		</para>
		<para>
			Services can be built with the following command:
			<programlisting>buildserver -v -f virt_service1.o -o VirtService1 -r Virtuoso -s VService1</programlisting>
			where "virt_service1.o" is the service object file which contains VService1 entry function.
			"-r Virtuoso" indicates that service must be assembled with Virtuoso XA support library.
		</para>
	</sect2>
	<sect2 id="xaServOpeninfo">
		<title>OPENINFO</title>
		<para>
			OPENINFO is necessary for services to connect to the certain Virtuoso server.
			OPENINFO for the services (see GROUPS section in the example) consists of 2 parts: 
			"Virtuoso" term and connection string. Connection string provides the service name, 
			password, server and port of Virtuoso server. Common format of connection string is
			[USER[:PASSWORD]]@SERVER[:PORT].
			Only the SERVER name is required, the others are optional.
		</para>
	</sect2>
</sect1>
<sect1 id="xaClients">
	<title>Clients</title>
	<para>
		There are no special requirements for the clients of services which use Virtuoso as resource manager.
		See Tuxedo 8.x documentation
	</para>	
</sect1>
<sect1 id="xaServExample">
	<title>Service example</title>
<programlisting><![CDATA[#include <stdio.h>
#include <time.h>


#include <xa.h>
#include <atmi.h>
#include <userlog.h>

#include "vql_client.h"

#include <libudbc.h>
#ifndef SQL_SUCCEEDED
#define SQL_SUCCEEDED(rc) (((rc)&(~1))==0)
#endif

#define MAXNAME SQL_MAX_DSN_LENGTH

int sql_exec (HDBC hdbc, char* text);


/* VirtRM test service */
int
tpsvrinit(int argc, char *argv[])
{
  if (tpopen () == -1)
    {
      userlog ("tpsrvinit: could not open RM, %s\n", tpstrerror (tperrno));
      return -1;
    }
  /* userlog writes to the central TUXEDO message log */
  userlog("Welcome to the VirtRMtest server");
  return 0;
}

int
tpsrvdone()
{
  if (tpclose () == -1)
    {
      userlog ("tpsrvinit: could not close RM, %s\n", tpstrerror (tperrno));
      return -1;
    }
  /* userlog writes to the central TUXEDO message log */
  userlog("By!! the VirtRMtest server");
  return 0;
}

static void
DoSQLError (HDBC hdbc, HSTMT hstmt);

#define CHECK_RC(rc) \
	if (!SQL_SUCCEEDED (rc)) { DoSQLError (hdbc, stmt); return -1; };

int sql_exec (HDBC hdbc, char* text)
{
  RETCODE rc;
  HSTMT stmt;

  rc = SQLAllocStmt (hdbc, &stmt);
  CHECK_RC(rc);

  rc = SQLExecDirect (stmt, text, SQL_NTS);
  CHECK_RC(rc);
  
  SQLFreeStmt (stmt, SQL_DROP);
  return 0;
}


void
VRMTEST(TPSVCINFO *rqst)
{
  HDBC hdbc;
  int rc;

  rc = vql_get_connection (&hdbc, VQL_CTX_TYPE);
  if (rc != VQL_SUCCESS)
    {
#ifdef TMS_TRACE
      userlog ("AP[%d]: vql_get_connection error %d\n", getpid(), rc);
#endif
      goto _fail;
    }
  rc = sql_exec (hdbc, "UPDATE sal set amount = amount + 10 where name = 'jfk'");
  if (rc == -1)
    {
#ifdef TMS_TRACE
      userlog ("AP[%d]: vql_get_connection error %d\n", getpid(), rc);
#endif
      goto _fail;
    }

  userlog ("AP[%d]: exec sql succ.\n", getpid());
  
  tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
  return;

 _fail:
  userlog ("FAILED: exec sql.\n");
  tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
  return;
}


void
VRMTEST2(TPSVCINFO *rqst)
{
  HDBC hdbc;
  int rc;


  rc = vql_get_connection (&hdbc, VQL_CTX_TYPE);
  if (rc != VQL_SUCCESS)
    goto _fail;

  rc = sql_exec (hdbc, "UPDATE sal set amount = amount - 10 where name = 'jfk'");
  if (rc == -1)
    goto _fail;

  userlog ("AP[%d]: exec sql succ.\n", getpid());
  
  tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
  return;

 _fail:
  userlog ("AP[%d]: service #2 error %d\n", getpid(), rc);
  tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
  return;


  tpreturn(TPSUCCESS, 0, rqst->data, 0L, 0);
}


#define MSG_BUF_SIZE 300

static void
DoSQLError (HDBC hdbc, HSTMT hstmt)
{
  UCHAR szSqlState[MSG_BUF_SIZE];
  UCHAR szErrorMsg[MSG_BUF_SIZE];

  SQLINTEGER fNativeError = 0;
  SWORD cbErrorMsg = MSG_BUF_SIZE;
  RETCODE rc;
  HENV env;
  
#ifndef TMS_TRACE
  return;
#else
  vql_get_env (&env);

  rc = SQLError (env,
      hdbc,
      hstmt,
      szSqlState, &fNativeError, szErrorMsg, MSG_BUF_SIZE, &cbErrorMsg);

  if (rc != SQL_NO_DATA_FOUND || rc != SQL_ERROR)
    {
      if (fNativeError != 0x1645)	// ignore change database to master context message
	{
	  userlog ("SqlState: %s, fNativeError: %x m=%s\n", szSqlState,
		   fNativeError, szErrorMsg);
	}
    }
  else
    {
      userlog ("SQLError() failed: %x, NO_DATA_FOUND OR SQL_ERROR\n", rc);
    }
  return;
#endif
}]]>
</programlisting>
</sect1>
</chapter>