8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-26 08:03:03 +01:00
firebird-mirror/src/jrd/rdb.cpp
eku 0c1b55dd08 Code cleanup:
Since we already have the define ISC_STATUS_LENGTH for the the length of
the status vector, we should use it! Replaced 'status[20]' with
'status[ISC_STATUS_LENGTH]'.

Replaced the different symbolic names for the maximum length of a path
(MAX_PATH, MAX_PATH_LENGTH, MAXPATHLEN) with one uniq symbol MAXPATHLEN.
2002-10-24 09:01:44 +00:00

1444 lines
32 KiB
C++

/*
* PROGRAM: Rdb/GDS Access Method Interface
* MODULE: rdb.c
* DESCRIPTION: User visible entrypoints
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#include "firebird.h"
#include descrip
#include ssdef
#include "../jrd/gds.h"
#include "../jrd/rdb.h"
#include "../jrd/common.h"
#include "../jrd/mblr.h"
#include "../jrd/gds_proto.h"
#include "../jrd/map_proto.h"
#include "../jrd/mblr_proto.h"
#define RDB_IMAGE "RDBVMSSHR"
#define RDB_CALL(name) if (!name) find_symbol (&name,"name"); stat = (*name)
#define rdb$bad_req_handle 20480058
#define DBTYPE_ISC 37
/* Transaction element block */
typedef struct teb {
int *teb_database;
int teb_tpb_length;
SCHAR *teb_tpb;
} TEB;
typedef enum {
impl_rdb = 1,
impl_gds
} IMPL;
typedef struct handle {
IMPL implementation;
int *handle;
int *messages;
struct handle *parent;
struct handle *next;
} *HANDLE, *REQ, *DBB, *TRA, *BLB;
static TRA *dyn_tra_handle;
static STATUS status_vector[ISC_STATUS_LENGTH];
static UCHAR *temp_buffer;
static SLONG temp_buffer_length;
static int (*RDB$ATTACH_DATABASE) (),
(*RDB$COMMIT_TRANSACTION) (),
(*RDB$COMPILE_REQUEST) (),
(*RDB$CREATE_DATABASE) (),
(*RDB$DETACH_DATABASE) (),
(*RDB$PREPARE_TRANSACTION) (),
(*RDB$RECEIVE) (),
(*RDB$RELEASE_REQUEST) (),
(*RDB$ROLLBACK_TRANSACTION) (),
(*RDB$SEND) (),
(*RDB$START_AND_SEND) (),
(*RDB$START_REQUEST) (),
(*RDB$START_TRANSACTION) (),
(*RDB$UNWIND_REQUEST) (),
(*RDB$CREATE_SEGMENTED_STRING) (),
(*RDB$OPEN_SEGMENTED_STRING) (),
(*RDB$CLOSE_SEGMENTED_STRING) (),
(*RDB$CANCEL_SEGMENTED_STRING) (),
(*RDB$GET_SEGMENT) (),
(*RDB$PUT_SEGMENT) (),
(*RDB$SEGMENTED_STRING_INFO) (),
(*RDB$REQUEST_INFO) (),
(*RDB$DATABASE_INFO) (),
(*RDB$TRANSACTION_INFO) (),
(*RDB$RECONNECT_TRANSACTION) (), (*RDB$DDL) (), (*RDB$EXTENSION) ();
static HANDLE allocate_handle(IMPL, int *);
static UCHAR *allocate_temp(int);
static int condition_handler(int *, int *, int *);
static SSHORT dsc_length(struct dsc$descriptor *);
static int find_symbol(int *, UCHAR *);
static void make_desc(UCHAR *, int, struct dsc$descriptor *);
static void putmsg(struct dsc$descriptor *, SCHAR *);
static int set_status(int *, int);
static SLONG codes[] = {
#include "../jrd/rdbcodes.h"
};
int rdb$attach_database(
int *user_status,
struct dsc$descriptor *file,
DBB * handle,
SSHORT dpb_length, SCHAR * dpb, SSHORT db_type)
{
/**************************************
*
* r d b $ A T T A C H _ D A T A B A S E
*
**************************************
*
* Functional description
* Create a nice, squeeky clean database, uncorrupted by user data.
*
**************************************/
int *status, stat;
int len;
/* Try Rdb/VMS first. If it succeeds, everything is ducky */
if (RDB$ATTACH_DATABASE ||
find_symbol(&RDB$ATTACH_DATABASE, "RDB$ATTACH_DATABASE")) {
RDB_CALL(RDB$ATTACH_DATABASE) (user_status, file, handle, dpb_length,
dpb);
if (stat & 1) {
*handle = allocate_handle(impl_rdb, *handle);
return stat;
}
}
/* Try GDS next.
Rdb/VMS implemented a new dpb version number, not documented.
Sense it and ignore the dpb. */
if (dpb_length && (dpb[0] == 2))
len = 0;
else
len = dpb_length;
stat = gds__attach_database(status_vector, dsc_length(file),
file->dsc$a_pointer, handle, len, dpb,
db_type);
if (!stat) {
*handle = allocate_handle(impl_gds, *handle);
return MAP_status_to_rdb(status_vector, user_status);
}
/* Neither worked -- return Rdb/VMS status */
return user_status[1];
}
int rdb$cancel_segmented_string(int *user_status, BLB * blob_handle)
{
/**************************************
*
* r d b $ C A N C E L _ B L O B
*
**************************************
*
* Functional description
* Cancel a blob (surprise!)
*
**************************************/
int stat;
if (!*blob_handle) {
*user_status++ = 1;
*user_status++ = 1;
return 1;
}
if ((*blob_handle)->implementation == impl_gds) {
gds__cancel_blob(status_vector, &(*blob_handle)->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$CANCEL_SEGMENTED_STRING) (user_status,
&(*blob_handle)->handle);
}
if (stat & 1) {
gds__free(*blob_handle);
*blob_handle = NULL;
}
return stat;
}
int rdb$close_segmented_string(int *user_status, BLB * blob_handle)
{
/**************************************
*
* r d b $ _ C L O S E _ B L O B
*
**************************************
*
* Functional description
* Close a blob (surprise!)
*
**************************************/
int stat;
if (!*blob_handle)
return set_status(user_status, rdb$_bad_req_handle);
if ((*blob_handle)->implementation == impl_gds) {
gds__close_blob(status_vector, &(*blob_handle)->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$CLOSE_SEGMENTED_STRING) (user_status,
&(*blob_handle)->handle);
}
if (stat & 1) {
gds__free(*blob_handle);
*blob_handle = NULL;
}
return stat;
}
int rdb$commit_transaction(int *user_status, TRA * tra_handle)
{
/**************************************
*
* r d b $ C O M M I T
*
**************************************
*
* Functional description
* Commit a transaction.
*
**************************************/
int stat;
if (!*tra_handle)
return set_status(user_status, rdb$_bad_trans_handle);
if ((*tra_handle)->implementation == impl_gds) {
gds__commit_transaction(status_vector, &(*tra_handle)->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$COMMIT_TRANSACTION) (user_status,
&(*tra_handle)->handle);
}
if (stat & 1) {
gds__free(*tra_handle);
*tra_handle = NULL;
}
return stat;
}
int rdb$compile_request(
int *user_status,
DBB * db_handle,
REQ * req_handle, SSHORT blr_length, SCHAR * blr)
{
/**************************************
*
* r d b $ C O M P I L E
*
**************************************
*
* Functional description
*
**************************************/
STATUS stat;
int *messages;
REQ request;
DBB database;
USHORT temp_length;
UCHAR *temp;
SLONG max_length;
if (!*db_handle)
return set_status(user_status, rdb$_bad_db_handle);
messages = NULL;
database = *db_handle;
temp = allocate_temp(blr_length + 200);
if ((*db_handle)->implementation == impl_gds) {
if (messages =
MAP_parse_blr(blr, blr_length, temp, &temp_length, &max_length)) {
blr = temp;
blr_length = temp_length;
allocate_temp(max_length);
}
if (gds__compile_request(status_vector, &database->handle,
req_handle, blr_length, blr))
MAP_release(messages);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$COMPILE_REQUEST) (user_status, &database->handle,
req_handle, blr_length, blr);
}
if (stat & 1) {
*req_handle = request =
allocate_handle(database->implementation, *req_handle);
request->parent = database;
request->next = database->next;
database->next = request;
request->messages = messages;
}
return stat;
}
int rdb$create_database(
int *user_status,
struct dsc$descriptor *file,
DBB * handle,
USHORT dpb_length, UCHAR * dpb, USHORT db_type)
{
/**************************************
*
* r d b $ C R E A T E _ D A T A B A S E
*
**************************************
*
* Functional description
* Create a nice, squeeky clean database, uncorrupted by user data.
*
**************************************/
int stat;
if (db_type = DBTYPE_ISC) {
stat = gds__create_database(status_vector, dsc_length(file),
file->dsc$a_pointer, handle, dpb_length,
dpb, db_type);
if (stat & 1)
*handle = allocate_handle(impl_gds, *handle);
return MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$CREATE_DATABASE) (user_status, file, handle,
dpb_length, dpb, db_type);
if (stat & 1)
*handle = allocate_handle(impl_rdb, *handle);
return stat;
}
}
int rdb$create_segmented_string(
int *user_status,
HANDLE * db_handle,
HANDLE * tra_handle,
HANDLE * blob_handle, GDS__QUAD * blob_id)
{
/**************************************
*
* r d b $ _ C R E A T E _ B L O B
*
**************************************
*
* Functional description
* Get a segment from a blob (surprise!)
*
**************************************/
int stat;
if (!*db_handle)
return set_status(user_status, rdb$_bad_db_handle);
if ((*db_handle)->implementation == impl_gds) {
gds__create_blob(status_vector, &(*db_handle)->handle,
&(*tra_handle)->handle, blob_handle, blob_id);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$CREATE_SEGMENTED_STRING) (user_status,
&(*db_handle)->handle,
&(*tra_handle)->handle,
blob_handle, blob_id);
}
if (stat & 1)
*blob_handle =
allocate_handle((*db_handle)->implementation, *blob_handle);
return stat;
}
int rdb$database_info(
int *user_status,
DBB * handle,
SSHORT item_length,
SCHAR * items, SSHORT buffer_length, SCHAR * buffer)
{
/**************************************
*
* r d b $ d a t a b a s e _ i n f o
*
**************************************
*
* Functional description
* Get info on object.
*
**************************************/
int stat;
SCHAR item, *item_ptr, *end, *tmp_ptr, tmp_buff[32];
SSHORT len;
if (!*handle)
return set_status(user_status, rdb$_bad_db_handle);
if ((*handle)->implementation == impl_gds) {
/* Rdb implemented more info items (but didnt' document them)
and theirs overlap ours. So, force error on the ones
we don't know about. */
tmp_ptr = tmp_buff;
item_ptr = items;
end = item_ptr + item_length;
while (item_ptr < end) {
*tmp_ptr = item = *item_ptr++;
if (item > gds__info_limbo)
*tmp_ptr += 200;
tmp_ptr++;
}
gds__database_info(status_vector, &(*handle)->handle,
item_length, &tmp_buff, buffer_length, buffer);
/* Now clean the clumplets all back up again... */
item_ptr = buffer;
end = item_ptr + buffer_length;
while (item_ptr < end) {
item = *item_ptr++;
len = *item_ptr++;
len |= (*item_ptr++) << 8;
if (item == gds__info_error && *item_ptr > 200)
*item_ptr -= 200;
else if (item == gds__info_end || item == gds__info_truncated)
break;
item_ptr += len;
}
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$DATABASE_INFO) (user_status, &(*handle)->handle,
item_length, items, buffer_length,
buffer);
}
return stat;
}
int rdb$ddl(
int *user_status,
DBB * db_handle, UCHAR ddl_operation, int length, UCHAR * buffer)
{
/**************************************
*
* r d b $ d d l
*
**************************************
*
* Functional description
* Support RDB metadata BLR (MBLR) through
* translation to InterBase DYN, or pass
* it through as before to RDB.
*
**************************************/
int stat, dyn_length, gds_vector[32], *gds;
UCHAR *dyn_buffer;
if (!*db_handle)
return set_status(user_status, rdb$_bad_db_handle);
if (!dyn_tra_handle)
return set_status(user_status, rdb$_bad_trans_handle);
if ((*db_handle)->implementation == impl_gds) {
/* First see if we can in fact translate the MBLR string into a DYN string */
dyn_buffer = allocate_temp(2 * length);
if (!MBLR_translate_to_dyn((int) ddl_operation, length, buffer,
&dyn_length, dyn_buffer))
return set_status(user_status, rdb$_wish_list);
/* Finally we can ship off the DYN string built to be processed */
if (gds__ddl(status_vector, &(*db_handle)->handle,
&(*dyn_tra_handle)->handle, dyn_length, dyn_buffer));
{
stat = MAP_status_to_rdb(status_vector, user_status);
return stat;
}
}
else {
RDB_CALL(RDB$DDL) (user_status, &(*db_handle)->handle,
ddl_operation, length, buffer);
}
return stat;
}
int rdb$detach_database(int *user_status, DBB * handle)
{
/**************************************
*
* r d b $ D E T A C H
*
**************************************
*
* Functional description
* Close down a database.
*
**************************************/
DBB database;
REQ request;
int stat;
if (!(database = *handle))
return set_status(user_status, rdb$_bad_db_handle);
if (database->implementation == impl_gds) {
gds__detach_database(status_vector, &database->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$DETACH_DATABASE) (user_status, &database->handle);
}
if (stat & 1) {
while (request = database->next) {
database->next = request->next;
MAP_release(request->messages);
gds__free(request);
}
gds__free(database);
*handle = NULL;
}
return stat;
}
int rdb$extension(
int *user_status,
USHORT index,
HANDLE * handle,
UCHAR type,
USHORT input_length,
UCHAR * input, USHORT result_length, UCHAR * result)
{
/**************************************
*
* r d b $ e x t e n s i o n
*
**************************************
*
* Functional description
* Unimplemented function.
*
**************************************/
int stat;
if (!*handle)
return set_status(user_status, rdb$_bad_db_handle);
if ((*handle)->implementation == impl_gds)
return set_status(user_status, rdb$_wish_list);
else {
RDB_CALL(RDB$EXTENSION) (user_status,
index,
&(*handle)->handle,
type,
input_length, input, result_length, result);
}
return stat;
}
int rdb$get_segment(
int *user_status,
HANDLE * blob_handle,
SSHORT * length, SSHORT buffer_length, UCHAR * buffer)
{
/**************************************
*
* r d b $ _ G E T _ S E G M E N T
*
**************************************
*
* Functional description
* Get a segment from a blob (surprise!)
*
**************************************/
int stat;
if (!*blob_handle)
return set_status(user_status, rdb$_bad_segstr_handle);
if ((*blob_handle)->implementation == impl_gds) {
gds__get_segment(status_vector, &(*blob_handle)->handle,
length, buffer_length, buffer);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$GET_SEGMENT) (user_status, &(*blob_handle)->handle,
length, buffer_length, buffer);
}
return stat;
}
int rdb$open_segmented_string(
int *user_status,
HANDLE * db_handle,
HANDLE * tra_handle,
HANDLE * blob_handle, GDS__QUAD * blob_id)
{
/**************************************
*
* r d b $ _ O P E N _ B L O B
*
**************************************
*
* Functional description
* Get a segment from a blob (surprise!)
*
**************************************/
int stat;
if (!*db_handle)
return set_status(user_status, rdb$_bad_db_handle);
if ((*db_handle)->implementation == impl_gds) {
gds__open_blob(status_vector, &(*db_handle)->handle,
&(*tra_handle)->handle, blob_handle, blob_id);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$OPEN_SEGMENTED_STRING) (user_status,
&(*db_handle)->handle,
&(*tra_handle)->handle,
blob_handle, blob_id);
}
if (stat & 1)
*blob_handle =
allocate_handle((*db_handle)->implementation, *blob_handle);
return stat;
}
int rdb$put_segment(
int *user_status,
BLB * blob_handle, SSHORT buffer_length, UCHAR * buffer)
{
/**************************************
*
* r d b $ _ P U T _ S E G M E N T
*
**************************************
*
* Functional description
* Put a segment into a blob (surprise!)
*
**************************************/
int stat;
if (!*blob_handle)
return set_status(user_status, rdb$_bad_segstr_handle);
if ((*blob_handle)->implementation == impl_gds) {
gds__put_segment(status_vector, &(*blob_handle)->handle,
buffer_length, buffer);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$PUT_SEGMENT) (user_status, &(*blob_handle)->handle,
buffer_length, buffer);
}
return stat;
}
int rdb$prepare_transaction(int *user_status, TRA * tra_handle)
{
/**************************************
*
* r d b $ p r e p a r e
*
**************************************
*
* Functional description
* Prepare a transaction for commit. First phase of a two
* phase commit.
*
**************************************/
int stat;
if (!*tra_handle)
return set_status(user_status, rdb$_bad_trans_handle);
if ((*tra_handle)->implementation == impl_gds) {
gds__prepare_transaction(status_vector, &(*tra_handle)->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$PREPARE_TRANSACTION) (user_status,
&(*tra_handle)->handle);
}
return stat;
}
int rdb$receive(
int *user_status,
REQ * req_handle,
USHORT msg_type, USHORT msg_length, SCHAR * msg, SSHORT level)
{
/**************************************
*
* r d b $ R E C E I V E
*
**************************************
*
* Functional description
* Get a record from the host program.
*
**************************************/
STATUS stat;
REQ request;
UCHAR *temp;
int length;
if (!(request = *req_handle))
return set_status(user_status, rdb$_bad_req_handle);
if (request->implementation == impl_gds) {
if (length = MAP_rdb_length(msg_type, request->messages)) {
temp = allocate_temp(0);
gds__receive(status_vector, &request->handle,
msg_type, length, temp, level);
MAP_gds_to_rdb(msg_type, request->messages, temp, msg);
}
else
gds__receive(status_vector, &request->handle,
msg_type, msg_length, msg, level);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$RECEIVE) (user_status, &request->handle,
msg_type, msg_length, msg, level);
}
return stat;
}
int rdb$reconnect_transaction(
int *user_status,
DBB * db_handle,
TRA * tra_handle, SSHORT length, UCHAR * id)
{
/**************************************
*
* r d b $ r e c o n n e c t _ t r a n s a c t i o n
*
**************************************
*
* Functional description
* Reconnect to a transaction in limbo.
*
**************************************/
int stat;
if (!*db_handle)
return set_status(user_status, rdb$_bad_db_handle);
if ((*db_handle)->handle == impl_gds) {
gds__reconnect_transaction(status_vector,
(*db_handle)->handle,
(*tra_handle)->handle, length, id);
return MAP_status_to_rdb(status_vector, user_status);
}
RDB_CALL(RDB$RECONNECT_TRANSACTION) (user_status,
(*db_handle)->handle,
(*tra_handle)->handle, length, id);
return stat;
}
int rdb$request_info(
int *user_status,
REQ * handle,
SSHORT level,
SSHORT item_length,
SCHAR * items, SSHORT buffer_length, SCHAR * buffer)
{
/**************************************
*
* r d b $ r e q u e s t _ i n f o
*
**************************************
*
* Functional description
* Get info on object.
*
**************************************/
int stat;
if (!*handle)
return set_status(user_status, rdb$_bad_req_handle);
if ((*handle)->implementation == impl_gds) {
gds__request_info(status_vector, &(*handle)->handle,
item_length, items, buffer_length, buffer, level);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$REQUEST_INFO) (user_status, &(*handle)->handle,
item_length, items, buffer_length, buffer,
level);
}
return stat;
}
int rdb$release_request(int *user_status, REQ * req_handle)
{
/**************************************
*
* r d b $ R E L E A S E _ R E Q U E S T
*
**************************************
*
* Functional description
* Release a request.
*
**************************************/
REQ *ptr, request;
DBB database;
int stat;
if (!(request = *req_handle))
return set_status(user_status, rdb$_bad_req_handle);
if (request->implementation == impl_gds) {
gds__release_request(status_vector, &request->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$RELEASE_REQUEST) (user_status, &request->handle);
}
if (stat & 1) {
database = request->parent;
for (ptr = &database->next; *ptr; ptr = &(*ptr)->next)
if (*ptr == request) {
*ptr = request->next;
break;
}
MAP_release(request->messages);
gds__free(request);
*req_handle = NULL;
}
return stat;
}
int rdb$rollback_transaction(int *user_status, TRA * tra_handle)
{
/**************************************
*
* r d b $ R O L L B A C K
*
**************************************
*
* Functional description
* Abort a transaction.
*
**************************************/
int stat;
if (!*tra_handle)
return set_status(user_status, rdb$_bad_trans_handle);
if ((*tra_handle)->implementation == impl_gds) {
gds__rollback_transaction(status_vector, &(*tra_handle)->handle);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$ROLLBACK_TRANSACTION) (user_status,
&(*tra_handle)->handle);
}
if (stat & 1) {
gds__free(*tra_handle);
*tra_handle = NULL;
}
return stat;
}
int rdb$segmented_string_info(
int *user_status,
BLB * handle,
SSHORT item_length,
SCHAR * items,
SSHORT buffer_length, SCHAR * buffer)
{
/**************************************
*
* r d b $ b l o b _ i n f o
*
**************************************
*
* Functional description
* Get info on object.
*
**************************************/
int stat;
if (!*handle)
return set_status(user_status, rdb$_bad_segstr_handle);
if ((*handle)->implementation == impl_gds) {
gds__blob_info(status_vector, &(*handle)->handle,
item_length, items, buffer_length, buffer);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$SEGMENTED_STRING_INFO) (user_status, &(*handle)->handle,
item_length, items,
buffer_length, buffer);
}
return stat;
}
int rdb$send(
int *user_status,
REQ * req_handle,
USHORT msg_type, USHORT msg_length, SCHAR * msg, SSHORT level)
{
/**************************************
*
* r d b $ S E N D
*
**************************************
*
* Functional description
* Get a record from the host program.
*
**************************************/
int length, stat;
REQ request;
UCHAR *temp;
if (!(request = *req_handle))
return set_status(user_status, rdb$_bad_req_handle);
if (request->implementation == impl_gds) {
temp = allocate_temp(0);
if (length = MAP_rdb_to_gds(msg_type, request->messages, msg, temp)) {
msg_length = length;
msg = temp;
}
gds__send(status_vector, &request->handle,
msg_type, msg_length, msg, level);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$SEND) (user_status, &request->handle,
msg_type, msg_length, msg, level);
}
return stat;
}
int rdb$start_and_send(
int *user_status,
REQ * req_handle,
TRA * tra_handle,
USHORT msg_type,
USHORT msg_length, SCHAR * msg, SSHORT level)
{
/**************************************
*
* r d b $ S T A R T _ A N D _ S E N D
*
**************************************
*
* Functional description
* Get a record from the host program.
*
**************************************/
int length, stat;
REQ request;
UCHAR *temp;
if (!(request = *req_handle))
return set_status(user_status, rdb$_bad_req_handle);
if ((*req_handle)->implementation == impl_gds) {
temp = allocate_temp(0);
if (length = MAP_rdb_to_gds(msg_type, request->messages, msg, temp)) {
msg_length = length;
msg = temp;
}
gds__start_and_send(status_vector, &request->handle,
&(*tra_handle)->handle, msg_type, msg_length, msg,
level);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$START_AND_SEND) (user_status, &request->handle,
&(*tra_handle)->handle, msg_type,
msg_length, msg, level);
}
return stat;
}
int rdb$start_request(
int *user_status,
register REQ * req_handle,
register TRA * tra_handle, SSHORT level)
{
/**************************************
*
* r d b $ s t a r t _ r e q u e s t
*
**************************************
*
* Functional description
* Get a record from the host program.
*
**************************************/
int stat;
if (!*req_handle)
return set_status(user_status, rdb$_bad_req_handle);
if ((*req_handle)->implementation == impl_gds) {
gds__start_request(status_vector, &(*req_handle)->handle,
&(*tra_handle)->handle, level);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$START_REQUEST) (user_status, &(*req_handle)->handle,
&(*tra_handle)->handle, level);
}
return stat;
}
int rdb$start_multiple(
int *user_status,
TRA * tra_handle, SSHORT count, TEB * teb)
{
/**************************************
*
* r d b $ s t a r t _ m u l t i p l e
*
**************************************
*
* Functional description
* Start a transaction.
*
**************************************/
}
int rdb$start_transaction(
int *user_status,
TRA * tra_handle,
SSHORT count,
DBB * db_handle, SSHORT tpb_length, SCHAR * tpb)
{
/**************************************
*
* r d b $ s t a r t _ t r a n s a c t i o n
*
**************************************
*
* Functional description
* Start a transaction.
*
**************************************/
TEB *teb;
DBB database;
int stat, gds_vector[32], rdb_vector[32], *gds, *rdb, c;
if (*tra_handle)
return set_status(user_status, rdb$_bad_trans_handle);
gds = gds_vector;
*gds++ = 0;
*gds++ = user_status;
*gds++ = tra_handle;
*gds++ = 0;
rdb = rdb_vector;
*rdb++ = 0;
*rdb++ = status_vector;
*rdb++ = tra_handle;
*rdb++ = 0;
for (teb = &db_handle, c = 0; c < count; c++, teb++) {
database = *teb->teb_database;
if (!database)
return set_status(user_status, rdb$_bad_db_handle);
if (database->implementation == impl_gds) {
++gds_vector[3];
*gds++ = &database->handle;
*gds++ = teb->teb_tpb_length;
*gds++ = teb->teb_tpb;
}
else {
++rdb_vector[3];
*rdb++ = &database->handle;
*rdb++ = teb->teb_tpb_length;
*rdb++ = teb->teb_tpb;
}
}
if (gds_vector[3]) {
gds_vector[0] = gds - gds_vector - 1;
stat = lib$callg(gds_vector, gds__start_transaction);
if (!stat) {
*tra_handle = allocate_handle(impl_gds, *tra_handle);
dyn_tra_handle = *tra_handle;
}
stat = MAP_status_to_rdb(status_vector, user_status);
}
if (rdb_vector[3]) {
rdb_vector[0] = rdb - rdb_vector - 1;
find_symbol(&RDB$START_TRANSACTION, "RDB$START_TRANSACTION");
stat = lib$callg(rdb_vector, RDB$START_TRANSACTION);
if (stat & 1)
*tra_handle = allocate_handle(impl_rdb, *tra_handle);
}
return stat;
}
int rdb$transaction_info(
int *user_status,
TRA * handle,
SSHORT item_length,
SCHAR * items, SSHORT buffer_length, SCHAR * buffer)
{
/**************************************
*
* r d b $ t r a n s a c t i o n _ i n f o
*
**************************************
*
* Functional description
* Get info on object.
*
**************************************/
int stat;
if (!*handle)
return set_status(user_status, rdb$_bad_trans_handle);
if ((*handle)->implementation == impl_gds) {
gds__transaction_info(status_vector, &(*handle)->handle,
item_length, items, buffer_length, buffer);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$TRANSACTION_INFO) (user_status, &(*handle)->handle,
item_length, items, buffer_length,
buffer);
}
return stat;
}
int rdb$unwind_request(int *user_status, REQ * req_handle, SSHORT level)
{
/**************************************
*
* r d b $ U N W I N D _ r e q u e s t
*
**************************************
*
* Functional description
* Unwind a running request.
*
**************************************/
int stat;
if (!*req_handle)
return set_status(user_status, rdb$_bad_req_handle);
if ((*req_handle)->implementation == impl_gds) {
gds__unwind_request(status_vector, &(*req_handle)->handle, level);
stat = MAP_status_to_rdb(status_vector, user_status);
}
else {
RDB_CALL(RDB$UNWIND_REQUEST) (user_status, &(*req_handle)->handle,
level);
}
return stat;
}
static HANDLE allocate_handle(IMPL implementation, int *real_handle)
{
/**************************************
*
* a l l o c a t e _ h a n d l e
*
**************************************
*
* Functional description
* Allocate an indirect handle.
*
**************************************/
UCHAR *p, *end;
HANDLE handle;
handle = gds__alloc((SLONG) sizeof(struct handle));
/* FREE: unknown */
if (!handle) { /* NOMEM: crash here */
DEV_REPORT("allocate_handle: no memory");
/* NOMEM: not handled, crash here */
}
for (p = handle, end = p + sizeof(struct handle); p < end;)
*p++ = 0;
handle->implementation = implementation;
handle->handle = real_handle;
return handle;
}
static UCHAR *allocate_temp(int length)
{
/**************************************
*
* a l l o c a t e _ t e m p
*
**************************************
*
* Functional description
* Allocate a temp of at least a given size.
*
**************************************/
if (length && temp_buffer_length < length) {
if (temp_buffer)
gds__free(temp_buffer);
temp_buffer = gds__alloc((SLONG) length);
/* FREE: unknown - reallocation of buffer handled above */
/* NOMEM: caller must handle */
if (temp_buffer)
temp_buffer_length = length;
else
temp_buffer_length = 0;
}
return temp_buffer;
}
static int condition_handler(int *sig, int *mech, int *enbl)
{
/**************************************
*
* c o n d i t i o n _ h a n d l e r
*
**************************************
*
* Functional description
* Ignore signal from "lib$find_symbol".
*
**************************************/
return SS$_CONTINUE;
}
static SSHORT dsc_length(struct dsc$descriptor *d)
{
/**************************************
*
* d s c _ l e n g t h
*
**************************************
*
* Functional description
* Determine length of argument passed by descriptor
*
**************************************/
struct dsc$descriptor_a *a;
switch (d->dsc$b_class) {
case DSC$K_CLASS_A:
a = d;
return a->dsc$l_arsize;
default:
return d->dsc$w_length;
}
}
static int find_symbol(int *address, UCHAR * name)
{
/**************************************
*
* f i n d _ s y m b o l
*
**************************************
*
* Functional description
* Look up entrypoint into RDB image.
*
**************************************/
struct dsc$descriptor file, symbol;
VAXC$ESTABLISH(condition_handler);
make_desc(RDB_IMAGE, 0, &file);
make_desc(name, 0, &symbol);
lib$find_image_symbol(&file, &symbol, address);
return *address;
}
static void make_desc(
UCHAR * string, int length, struct dsc$descriptor *desc)
{
/**************************************
*
* m a k e _ d e s c
*
**************************************
*
* Functional description
* Fill in VMS descriptor.
*
**************************************/
desc->dsc$b_dtype = DSC$K_DTYPE_T;
desc->dsc$b_class = DSC$K_CLASS_S;
desc->dsc$a_pointer = string;
if (!(desc->dsc$w_length = length))
desc->dsc$w_length = strlen(string);
}
static void putmsg(struct dsc$descriptor_s *desc, SCHAR * arg)
{
/**************************************
*
* p u t m s g
*
**************************************
*
* Functional description
* Get a line of message.
*
**************************************/
}
static int set_status(int *status, int code)
{
/**************************************
*
* s e t _ s t a t u s
*
**************************************
*
* Functional description
* Generate an error for a bad handle.
*
**************************************/
*status++ = 1;
*status++ = code;
*status = 0;
return code;
}
#define DUMMY(name) name () {ib_printf ("name entered\n"); return 0;}
DUMMY(rdb$dummy1);