mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 19:23:03 +01:00
Remove PLSERVER (page lock server).
This commit is contained in:
parent
17a9c20884
commit
3e05f5b931
@ -199,16 +199,6 @@ int PIO_connection(TEXT * file_name, USHORT * file_length)
|
||||
**************************************/
|
||||
int node;
|
||||
|
||||
#ifdef PLSERVER
|
||||
|
||||
/* Analyze the file name to see if a remote connection is required. If not,
|
||||
quietly (sic) return. */
|
||||
|
||||
if (node = analyze(file_name, *file_length))
|
||||
return PLS_connection(node);
|
||||
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
449
src/lock/pls.cpp
449
src/lock/pls.cpp
@ -1,449 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Lock Manager
|
||||
* MODULE: pls.c
|
||||
* DESCRIPTION: Page lock server interface
|
||||
*
|
||||
* 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 "lock.h"
|
||||
#include "plserver.h"
|
||||
|
||||
#include "/sys/ins/streams.ins.c"
|
||||
#include "/sys/ins/ms.ins.c"
|
||||
#include "/sys/ins/name.ins.c"
|
||||
#include "/sys/ins/proc2.ins.c"
|
||||
#include "/sys/ins/ipc.ins.c"
|
||||
|
||||
#define ALLOC pls_alloc
|
||||
#define DATAGRAM_RETRY 10
|
||||
|
||||
/* Connection block for page/lock server */
|
||||
|
||||
typedef struct plc {
|
||||
struct blk plc_header;
|
||||
struct pld *plc_next; /* Next connection */
|
||||
int plc_node; /* Node id of connection */
|
||||
int plc_send_sequence; /* Next available packet sequence number */
|
||||
int plc_recv_sequence; /* Sequence number of last packet received */
|
||||
UCHAR plc_socket[20]; /* Apollo socket handle */
|
||||
UCHAR plc_socket2[20]; /* Our socket handle */
|
||||
int plc_connection_handle;
|
||||
int plc_file_handle;
|
||||
USHORT plc_length; /* Length of file name */
|
||||
UCHAR plc_file[1]; /* Socket file name */
|
||||
} *PLC;
|
||||
|
||||
static int connect(int, ipc_$socket_handle_t *);
|
||||
static int error(UCHAR *, UCHAR *, status_$t);
|
||||
static UCHAR *pls_alloc(USHORT);
|
||||
static void pls_release(UCHAR *);
|
||||
static void move(SCHAR *, SCHAR *, SSHORT);
|
||||
|
||||
static PLC connections;
|
||||
|
||||
#define NODE_MASK 0xFFFFF
|
||||
|
||||
|
||||
/* Asknode Stuff */
|
||||
|
||||
std_$call void asknode_$info();
|
||||
|
||||
typedef SSHORT enum {
|
||||
ask_who, who_r,
|
||||
ask_time, time_r,
|
||||
ask_node_root, node_root_r
|
||||
} asknode_$kind_t;
|
||||
|
||||
#define asknode_$version 2
|
||||
|
||||
typedef struct {
|
||||
pinteger version;
|
||||
asknode_$kind_t kind;
|
||||
status_$t status;
|
||||
uid_$t uid;
|
||||
SCHAR stuff[256]; /* Random and various */
|
||||
} asknode_$reply_t;
|
||||
|
||||
/* name_$ stuff */
|
||||
|
||||
std_$call void name_$gpath_dir();
|
||||
|
||||
SSHORT enum name_$namtyp_t {
|
||||
name_$junk_flag,
|
||||
name_$wdir_flag,
|
||||
name_$ndir_flag,
|
||||
name_$node_flag,
|
||||
name_$root_flag,
|
||||
name_$node_data_flag
|
||||
};
|
||||
|
||||
|
||||
PLC PLS_connection(int node, USHORT server_flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P L S _ c o n n e c t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Establish a connection to a page/lock server on a given node.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
PHD header, reply;
|
||||
UCHAR socket_name[32];
|
||||
USHORT length;
|
||||
uid_$t uid;
|
||||
status_$t status;
|
||||
ipc_$socket_handle_t handle, local_handle;
|
||||
asknode_$reply_t node_info;
|
||||
|
||||
if (connect(node, &handle))
|
||||
return NULL;
|
||||
|
||||
if (connect(NULL, &local_handle))
|
||||
return NULL;
|
||||
|
||||
/* We seem to have a socket -- time to make a connection block */
|
||||
|
||||
connection = ALLOC(sizeof(struct plc) + length);
|
||||
connection->plc_length = length;
|
||||
connection->plc_node = node;
|
||||
strcpy(connection->plc_file, socket_name);
|
||||
move(&handle, connection->plc_socket, sizeof(handle));
|
||||
move(&local_handle, connection->plc_socket2, sizeof(handle));
|
||||
|
||||
/* We at least have a socket handle. See if anybody is really there */
|
||||
|
||||
header.phd_type = PL_CONNECT;
|
||||
proc2_$who_am_i(uid);
|
||||
header.phd_misc = uid.low & NODE_MASK;
|
||||
header.phd_flags = (server_flag) ? PHD_SERVER : 0;
|
||||
status.all =
|
||||
PLS_request(connection, &header, sizeof(header), &reply,
|
||||
sizeof(reply), NULL, 0, 0);
|
||||
|
||||
if (status.all) {
|
||||
PLS_disconnect(connection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
connection->plc_connection_handle = reply.phd_handle;
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
||||
PLC PLS_find_connection(int node, USHORT server_flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P L S _ f i n d _ c o n n e c t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Find a connection if it exists, otherwise create it.
|
||||
* Note: This is used only by the page/lock server to
|
||||
* avoid problems of dirty statics in Apollo installed images.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
|
||||
/* See if connection exits */
|
||||
|
||||
for (connection = connections; connection;
|
||||
connection = connection->plc_next) if (connection->plc_node == node)
|
||||
return connection;
|
||||
|
||||
/* Connection doesn't exist -- try to make it */
|
||||
|
||||
if (!(connection = PLS_connection(node, server_flag)))
|
||||
return NULL;
|
||||
|
||||
connection->plc_next = connections;
|
||||
connections = connection;
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
||||
int PLS_request(
|
||||
PLC connection,
|
||||
PHD * header,
|
||||
USHORT header_len,
|
||||
PHD * reply,
|
||||
USHORT reply_len,
|
||||
UCHAR * data, USHORT send_len, USHORT receive_len)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P L S _ r e q u e s t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Send a page/lock request and get response.
|
||||
*
|
||||
**************************************/
|
||||
USHORT send, wait, count, receive_length, header_length, next;
|
||||
status_$t status;
|
||||
ipc_$socket_handle_t handle;
|
||||
|
||||
/* Send the request until we get something back */
|
||||
|
||||
header->phd_connection = connection->plc_connection_handle;
|
||||
BUMP_SEQUENCE(connection->plc_send_sequence);
|
||||
header->phd_sequence = connection->plc_send_sequence;
|
||||
send = TRUE;
|
||||
wait = 10 * 4;
|
||||
|
||||
for (count = 0; count < DATAGRAM_RETRY; count++) {
|
||||
if (send) {
|
||||
header->phd_ack = connection->plc_recv_sequence;
|
||||
ipc_$send(connection->plc_socket,
|
||||
connection->plc_socket2,
|
||||
*header, header_len, *data, send_len, status);
|
||||
if (status.all)
|
||||
return status.all;
|
||||
}
|
||||
|
||||
/* Wait for and read reply */
|
||||
|
||||
ipc_$wait(connection->plc_socket2, wait, status);
|
||||
if (status.all == ipc_$timeout)
|
||||
continue;
|
||||
if (status.all)
|
||||
return status.all;
|
||||
ipc_$rcv(connection->plc_socket2, header_len, /* out-hdr-buflen */
|
||||
receive_len, /* out-data-buflen */
|
||||
handle, *reply, /* out-hdr-buf */
|
||||
reply_len, /* out-hdr-length */
|
||||
*data, /* out-data-buf */
|
||||
receive_length, /* out-data-length */
|
||||
status); /* status */
|
||||
if (status.all)
|
||||
return status.all;
|
||||
|
||||
connection->plc_recv_sequence = reply->phd_sequence;
|
||||
|
||||
/* If the packet acknowleges something other than the one sent, re-transmit */
|
||||
|
||||
if (reply->phd_ack != connection->plc_send_sequence) {
|
||||
send = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If this is something other than an acknowlegement, be patient */
|
||||
|
||||
if (reply->phd_type != PL_ACK)
|
||||
return FB_SUCCESS;
|
||||
|
||||
/* If we got an acknowlegement, the other guy has at least received the packet.
|
||||
We should be more patient, but still probe looking for death */
|
||||
|
||||
wait = 30 * 4;
|
||||
send = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PLS_disconnect( PLC connection)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P L S _ d i s c o n n e c t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Break a remote connection.
|
||||
*
|
||||
**************************************/
|
||||
status_$t status;
|
||||
|
||||
ipc_$close(connection->plc_file, connection->plc_length, status);
|
||||
if (status.all)
|
||||
error_$print(&status);
|
||||
|
||||
ipc_$delete(connection->plc_file, connection->plc_length, status);
|
||||
if (status.all)
|
||||
error_$print(&status);
|
||||
|
||||
/* Close a client channel */
|
||||
|
||||
pls_release(connection);
|
||||
}
|
||||
|
||||
|
||||
static int connect( int node, ipc_$socket_handle_t * handle)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* c o n n e c t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Try to establish a physical connection to the page
|
||||
* lock server on a given node.
|
||||
*
|
||||
**************************************/
|
||||
PHD header, reply;
|
||||
UCHAR socket_name[32], root_name[256], *p;
|
||||
USHORT length;
|
||||
status_$t status;
|
||||
asknode_$reply_t node_info;
|
||||
|
||||
/* If no node id was given, create a connection for ourselves */
|
||||
|
||||
if (!node) {
|
||||
strcpy(socket_name, "gds.pl_server_XXXXXX");
|
||||
mktemp(socket_name);
|
||||
length = strlen(socket_name);
|
||||
ipc_$create(socket_name, length, status);
|
||||
if (status.all)
|
||||
return error("ipc_$create", socket_name, status);
|
||||
ipc_$open(socket_name, length, 4, *handle, status);
|
||||
if (status.all)
|
||||
return error("ipc_$open", socket_name, status);
|
||||
unlink(socket_name);
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
/* File is open by another node. Sigh. Make up a nice filename */
|
||||
|
||||
asknode_$info(ask_node_root, node, 0, node_info, status);
|
||||
if (status.all)
|
||||
return error("asknode_$info", " ", status);
|
||||
|
||||
if (node_info.status.all)
|
||||
return error("asknode_$info", "remote site", node_info.status);
|
||||
|
||||
name_$gpath_dir(node_info.uid, name_$root_flag, root_name, length,
|
||||
status);
|
||||
if (status.all)
|
||||
return error("name_$gpath_dir", "", status);
|
||||
|
||||
root_name[length] = 0;
|
||||
sprintf(socket_name, "%s/sys/gds.plserver_%x", root_name, node);
|
||||
length = strlen(socket_name);
|
||||
|
||||
/* See if we can get a socket for the server. If not, don't bother
|
||||
continuing this non-sense */
|
||||
|
||||
ipc_$resolve(socket_name, length, *handle, status);
|
||||
if (status.all) {
|
||||
for (p = socket_name + 2; *p && *p != '/'; p++)
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p = *p - 'A' + 'a';
|
||||
ipc_$resolve(socket_name, length, *handle, status);
|
||||
}
|
||||
|
||||
if (status.all)
|
||||
return error("ipc_$resolve", socket_name, status);
|
||||
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int error( UCHAR * operation, UCHAR * object, status_$t status)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* e r r o r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* A system service error has occurred.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
ib_printf("Page/lock service error occurred during %s on \"%s\"\n",
|
||||
operation, object);
|
||||
error_$print(status);
|
||||
|
||||
return status.all;
|
||||
}
|
||||
|
||||
|
||||
static UCHAR *pls_alloc( USHORT size)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p l s _ a l l o c
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Allocate a block.
|
||||
*
|
||||
**************************************/
|
||||
UCHAR *blk, *p, *end;
|
||||
|
||||
blk = p = gds__alloc(size);
|
||||
end = p + size;
|
||||
|
||||
while (p < end)
|
||||
*p++ = 0;
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
||||
static void pls_release( UCHAR * blk)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p l s _ r e l e a s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release a block.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
gds__free(blk);
|
||||
}
|
||||
|
||||
|
||||
static void move(
|
||||
SCHAR * from,
|
||||
SCHAR * to, SSHORT length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m o v e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Move a byte string as fast as possible.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
if (length)
|
||||
do
|
||||
*to++ = *from++;
|
||||
while (--length);
|
||||
}
|
@ -1,684 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Remote Interface/Server
|
||||
* MODULE: plserver.c
|
||||
* DESCRIPTION: Page/lock server
|
||||
*
|
||||
* 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 "../jrd/ib_stdio.h"
|
||||
|
||||
#include "../jrd/common.h"
|
||||
#include "plserver.h"
|
||||
|
||||
#include "/sys/ins/base.ins.c"
|
||||
#include "/sys/ins/ipc.ins.c"
|
||||
#include "/sys/ins/error.ins.c"
|
||||
#include "/sys/ins/proc2.ins.c"
|
||||
#include "/sys/ins/ms.ins.c"
|
||||
|
||||
/* Block used to manage connections */
|
||||
|
||||
typedef struct plc {
|
||||
struct plc *plc_next;
|
||||
int plc_send_sequence; /* Next available packet sequence number */
|
||||
int plc_recv_sequence; /* Sequence number of last packet received */
|
||||
UCHAR plc_socket[20]; /* Apollo socket handle */
|
||||
struct fat *plc_attachments;
|
||||
struct blk *plc_server; /* Server connection on client node */
|
||||
} *PLC;
|
||||
|
||||
/* File attachment blocks */
|
||||
|
||||
typedef struct fat {
|
||||
struct plc *fat_connection; /* Connection block for file */
|
||||
struct file *fat_file; /* File block for attachment */
|
||||
struct fat *fat_next_connection; /* Next FAT in connections list */
|
||||
struct fat *fat_next_file; /* Next FAT in file list */
|
||||
} *FAT;
|
||||
|
||||
/* File window and file blocks */
|
||||
|
||||
typedef struct fwin {
|
||||
struct pag *fwin_address; /* Address of mapped region */
|
||||
SLONG fwin_length; /* Length of mapped region */
|
||||
SLONG fwin_offset; /* Offset in bytes of region */
|
||||
SLONG fwin_activity; /* Accesses since window turn */
|
||||
} FWIN;
|
||||
|
||||
#define WINDOWS 3
|
||||
#define WINDOW_LENGTH 32768
|
||||
|
||||
typedef struct fil {
|
||||
struct file *fil_next; /* Next file in server */
|
||||
FAT fil_attachments; /* List of attachments to file */
|
||||
USHORT fil_count; /* Number of window */
|
||||
FWIN fil_windows[WINDOWS]; /* File windows */
|
||||
USHORT fil_length; /* File name length */
|
||||
UCHAR fil_name[1]; /* File name */
|
||||
} *FIL;
|
||||
|
||||
static UCHAR *alloc(USHORT);
|
||||
static int client_error(PLC, UCHAR *, status_$t);
|
||||
static PLC connect(PHD *, UCHAR *);
|
||||
static void detach(FAT);
|
||||
static void disconnect(PHD *);
|
||||
static void ipc_error(status_$t, UCHAR *);
|
||||
static UCHAR *map_file(PLC, FIL, ULONG);
|
||||
static void move(UCHAR *, UCHAR *, USHORT);
|
||||
static void open(PHD *, UCHAR *);
|
||||
static void page_read(PHD *);
|
||||
static void page_write(PHD *, UCHAR *);
|
||||
static void release(UCHAR *);
|
||||
static void reply(PLC, PHD *, USHORT, UCHAR *, USHORT);
|
||||
static int socket_eql(UCHAR *, UCHAR *);
|
||||
|
||||
static PLC connections, servers;
|
||||
static FIL files;
|
||||
static ipc_$socket_handle_t server_handle;
|
||||
|
||||
static PLC connect();
|
||||
|
||||
|
||||
void main( int argc, char **argv)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m a i n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Apollo specific page/lock server. The page and lock functions
|
||||
* are independent (sigh), but there is no reason to have multiple
|
||||
* servers.
|
||||
*
|
||||
**************************************/
|
||||
UCHAR file[32], header_buffer[128], data_buffer[1024];
|
||||
USHORT header_length, data_length;
|
||||
PHD *header;
|
||||
PLC connection;
|
||||
status_$t status;
|
||||
uid_$t process_uid;
|
||||
ipc_$socket_handle_t client_handle;
|
||||
|
||||
/* Open the socket for activity */
|
||||
|
||||
proc2_$who_am_i(process_uid);
|
||||
sprintf(file, "/sys/gds.plserver_%x", process_uid.low & 0xFFFFF);
|
||||
data_length = strlen(file);
|
||||
|
||||
ipc_$create(file, data_length, status);
|
||||
|
||||
ipc_$open(file, data_length, 4, server_handle, status);
|
||||
if (status.all)
|
||||
ipc_error(status, "ipc_$open");
|
||||
|
||||
/* Process messages */
|
||||
|
||||
header = header_buffer;
|
||||
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
ipc_$wait(server_handle, 4 * 10, status);
|
||||
if (!status.all)
|
||||
break;
|
||||
if (status.all != ipc_$timeout)
|
||||
ipc_error(status, "ipc_$wait");
|
||||
for (connection = connections; connection;
|
||||
connection = connection->plc_next) {
|
||||
}
|
||||
}
|
||||
ipc_$rcv(server_handle,
|
||||
sizeof(header_buffer),
|
||||
sizeof(data_buffer),
|
||||
client_handle,
|
||||
header_buffer,
|
||||
header_length, data_buffer, data_length, status);
|
||||
if (status.all)
|
||||
ipc_error(status, "ipc_$rcv");
|
||||
|
||||
if (!(connection = header->phd_connection))
|
||||
connection = connect(header, &client_handle);
|
||||
|
||||
/* Get rid of duplicate packet */
|
||||
|
||||
if (header->phd_sequence == connection->plc_recv_sequence)
|
||||
continue;
|
||||
connection->plc_recv_sequence = header->phd_sequence;
|
||||
|
||||
switch (header->phd_type) {
|
||||
case PL_CONNECT:
|
||||
break;
|
||||
|
||||
case PL_DISCONNECT:
|
||||
disconnect(header);
|
||||
break;
|
||||
|
||||
case PL_PAGE_OPEN:
|
||||
open(header, data_buffer);
|
||||
break;
|
||||
|
||||
case PL_PAGE_READ:
|
||||
page_read(header);
|
||||
break;
|
||||
|
||||
case PL_PAGE_WRITE:
|
||||
page_write(header, data_buffer);
|
||||
break;
|
||||
|
||||
default:
|
||||
ib_fprintf(ib_stderr, "packet type %d not understood\n",
|
||||
header->phd_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static UCHAR *alloc( USHORT size)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* a l l o c
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Allocate a zero filled block.
|
||||
*
|
||||
**************************************/
|
||||
UCHAR *blk, *p, *end;
|
||||
|
||||
blk = p = gds__alloc(size);
|
||||
do
|
||||
*p++ = 0;
|
||||
while (--size);
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
||||
static int client_error( PLC connection, UCHAR * string, status_$t status)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* c l i e n t _ e r r o r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Report an error to the client.
|
||||
*
|
||||
**************************************/
|
||||
PHD packet;
|
||||
|
||||
packet.phd_type = PL_ERROR;
|
||||
packet.phd_length = 0;
|
||||
packet.phd_misc = status.all;
|
||||
strcpy(packet.phd_string, string);
|
||||
reply(connection, &packet, sizeof(packet), NULL, 0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static PLC connect( PHD * header, UCHAR * socket)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* c o n n e c t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Accept incoming connection.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
|
||||
/* Check for connection already active */
|
||||
|
||||
for (connection = connections; connection;
|
||||
connection =
|
||||
connection->plc_next) if (socket_eql(connection->plc_socket, socket))
|
||||
break;
|
||||
|
||||
if (!connection) {
|
||||
connection = alloc(sizeof(struct plc));
|
||||
connection->plc_next = connections;
|
||||
connections = connection;
|
||||
}
|
||||
|
||||
header->phd_handle = connection;
|
||||
connection->plc_recv_sequence = header->phd_sequence;
|
||||
move(socket, connection->plc_socket, sizeof(connection->plc_socket));
|
||||
reply(connection, header, sizeof(struct phd), NULL, 0);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
||||
static void detach( FAT attachment)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d e t a c h
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Detach from a file segment.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
FIL file, *file_ptr;
|
||||
FAT *fat;
|
||||
FWIN *win, *end;
|
||||
status_$t status;
|
||||
|
||||
connection = attachment->fat_connection;
|
||||
file = attachment->fat_file;
|
||||
|
||||
/* Disconnect attachment from connection. */
|
||||
|
||||
for (fat = &connection->plc_attachments; *fat;
|
||||
fat = &(*fat)->fat_next_connection) if (*fat == attachment) {
|
||||
*fat = attachment->fat_next_connection;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disconnect attachment from file. If file loses its last attachment,
|
||||
release the file */
|
||||
|
||||
for (fat = &file->fil_attachments; *fat; fat = &(*fat)->fat_next_file)
|
||||
if (*fat == attachment) {
|
||||
*fat = attachment->fat_next_file;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!file->fil_attachments) {
|
||||
for (win = file->fil_windows, end = win + file->fil_count; win < end;
|
||||
win++)
|
||||
ms_$unmap(win->fwin_address, win->fwin_length, status);
|
||||
for (file_ptr = &files; *file_ptr; file_ptr = &(*file_ptr)->fil_next)
|
||||
if (*file_ptr = file) {
|
||||
*file_ptr = file->fil_next;
|
||||
break;
|
||||
}
|
||||
release(file);
|
||||
}
|
||||
|
||||
release(attachment);
|
||||
}
|
||||
|
||||
|
||||
static void disconnect( PHD * packet)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d i s c o n n e c t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Break a connection.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection, *ptr;
|
||||
|
||||
connection = packet->phd_connection;
|
||||
packet->phd_type = PL_REPLY;
|
||||
reply(connection, packet, sizeof(struct phd), NULL, 0);
|
||||
|
||||
/* Get rid of file segments */
|
||||
|
||||
while (connection->plc_attachments)
|
||||
detach(connection->plc_attachments);
|
||||
|
||||
/* Get rid of connection block */
|
||||
|
||||
for (ptr = &connections; *ptr; ptr = &(*ptr)->plc_next)
|
||||
if (*ptr == connection) {
|
||||
*ptr = connection->plc_next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ipc_error( status_$t status, UCHAR * string)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* i p c _ e r r o r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* A more or less fatal error occurred. Seppicu time.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
ib_fprintf(ib_stderr, "Error during %s operation\n", string);
|
||||
error_$print(status);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
static UCHAR *map_file( PLC connection, FIL file, ULONG offset)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m a p _ f i l e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Map a page in a file.
|
||||
*
|
||||
**************************************/
|
||||
FWIN *window, *win, *end;
|
||||
SLONG section;
|
||||
status_$t status;
|
||||
USHORT i, length;
|
||||
UCHAR *address;
|
||||
|
||||
win = NULL;
|
||||
|
||||
/* Search for a window that is already mapped. */
|
||||
|
||||
for (window = file->fil_windows, end = window + file->fil_count;
|
||||
window < end; window++) {
|
||||
if (offset >= window->fwin_offset &&
|
||||
offset < window->fwin_offset + window->fwin_length) goto exit;
|
||||
if (!win || window->fwin_activity < win->fwin_activity)
|
||||
win = window;
|
||||
}
|
||||
|
||||
/* If not all windows have been used, use another */
|
||||
|
||||
section = offset & ~(WINDOW_LENGTH - 1);
|
||||
|
||||
if (file->fil_count < WINDOWS) {
|
||||
address = ms_$mapl(file->fil_name, file->fil_length, section,
|
||||
(SLONG) WINDOW_LENGTH, ms_$cowriters, ms_$wr,
|
||||
(SSHORT) - 1, window->fwin_length, status);
|
||||
|
||||
if (status.all)
|
||||
return client_error(connection, "ms_$mapl", status);
|
||||
++file->fil_count;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Window not found, remap it. */
|
||||
|
||||
window = win;
|
||||
address = ms_$remap(window->fwin_address, section,
|
||||
(SLONG) WINDOW_LENGTH, window->fwin_length, status);
|
||||
|
||||
if (status.all)
|
||||
return client_error(connection, "ms_$remap", status);
|
||||
|
||||
/* Down grade activity after window shift */
|
||||
|
||||
for (win = file->fil_windows; win < end; win++)
|
||||
win->fwin_activity >>= 2;
|
||||
|
||||
finish:
|
||||
|
||||
window->fwin_address = address;
|
||||
window->fwin_offset = section;
|
||||
window->fwin_activity = 0;
|
||||
|
||||
exit:
|
||||
|
||||
++window->fwin_activity;
|
||||
return (SCHAR *) window->fwin_address + offset - window->fwin_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void move( UCHAR * from, UCHAR * to, USHORT length)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m o v e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Move a fixed length string.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
if (length)
|
||||
do
|
||||
*to++ = *from++;
|
||||
while (--length);
|
||||
}
|
||||
|
||||
|
||||
static void open( PHD * packet, UCHAR * data)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* o p e n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Open a file.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
FIL file;
|
||||
FAT attachment;
|
||||
FWIN *window;
|
||||
status_$t status;
|
||||
|
||||
data[packet->phd_length] = 0;
|
||||
connection = packet->phd_connection;
|
||||
|
||||
/* Check to see if file is already known */
|
||||
|
||||
for (file = files; file; file = file->fil_next)
|
||||
if (!strcmp(data, file->fil_name))
|
||||
break;
|
||||
|
||||
/* If file doesn't exist, create it now */
|
||||
|
||||
if (!file) {
|
||||
file = alloc(sizeof(struct fil) + packet->phd_length);
|
||||
file->fil_length = packet->phd_length;
|
||||
strcpy(file->fil_name, data);
|
||||
file->fil_next = files;
|
||||
files = file;
|
||||
file->fil_count = 1;
|
||||
|
||||
/* Map the file as appropriate */
|
||||
|
||||
window = file->fil_windows;
|
||||
window->fwin_address = ms_$mapl(file->fil_name, file->fil_length,
|
||||
window->fwin_offset,
|
||||
(SLONG) WINDOW_LENGTH, ms_$cowriters,
|
||||
ms_$wr, (SSHORT) - 1,
|
||||
window->fwin_length, status);
|
||||
if (status.all)
|
||||
client_error(connection, "ms_$mapl", status);
|
||||
file->fil_count = 1;
|
||||
}
|
||||
|
||||
/* Connect file and connection block */
|
||||
|
||||
attachment = alloc(sizeof(struct fat));
|
||||
attachment->fat_connection = connection;
|
||||
attachment->fat_file = file;
|
||||
attachment->fat_next_file = file->fil_attachments;
|
||||
file->fil_attachments = attachment;
|
||||
attachment->fat_next_connection = connection->plc_attachments;
|
||||
connection->plc_attachments = attachment;
|
||||
|
||||
/* Send a reply */
|
||||
|
||||
packet->phd_handle = attachment;
|
||||
packet->phd_type = PL_REPLY;
|
||||
reply(connection, packet, sizeof(struct phd), NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static void page_read( PHD * packet)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a g e _ r e a d
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Read a database page.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
FIL file;
|
||||
FAT attachment;
|
||||
UCHAR *ptr;
|
||||
status_$t status;
|
||||
|
||||
connection = packet->phd_connection;
|
||||
attachment = packet->phd_handle;
|
||||
file = attachment->fat_file;
|
||||
|
||||
/* Map appropriate part of file */
|
||||
|
||||
ptr = map_file(connection, file, packet->phd_misc);
|
||||
if (ptr == -1)
|
||||
return;
|
||||
|
||||
/* Send a reply */
|
||||
|
||||
packet->phd_handle = attachment;
|
||||
packet->phd_type = PL_REPLY;
|
||||
reply(connection, packet, sizeof(struct phd), ptr, packet->phd_length);
|
||||
}
|
||||
|
||||
|
||||
static void page_write( PHD * packet, UCHAR * data)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a g e _ w r i t e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Write a database page.
|
||||
*
|
||||
**************************************/
|
||||
PLC connection;
|
||||
FIL file;
|
||||
FAT attachment;
|
||||
UCHAR *ptr;
|
||||
status_$t status;
|
||||
|
||||
attachment = packet->phd_handle;
|
||||
connection = packet->phd_connection;
|
||||
file = attachment->fat_file;
|
||||
|
||||
/* Map appropriate part of file */
|
||||
|
||||
ptr = map_file(connection, file, packet->phd_misc);
|
||||
if (ptr == -1)
|
||||
return;
|
||||
|
||||
move(data, ptr, packet->phd_length);
|
||||
|
||||
/* Send a reply */
|
||||
|
||||
packet->phd_handle = attachment;
|
||||
packet->phd_type = PL_REPLY;
|
||||
reply(connection, packet, sizeof(struct phd), NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static void release( UCHAR * blk)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* r e l e a s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release a block.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
gds__free(blk);
|
||||
}
|
||||
|
||||
|
||||
static void reply(
|
||||
PLC connection,
|
||||
PHD * header,
|
||||
USHORT header_len, UCHAR * data, USHORT data_len)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* r e p l y
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Reply to a request.
|
||||
*
|
||||
**************************************/
|
||||
status_$t status;
|
||||
|
||||
BUMP_SEQUENCE(connection->plc_send_sequence);
|
||||
header->phd_sequence = connection->plc_send_sequence;
|
||||
header->phd_ack = connection->plc_recv_sequence;
|
||||
|
||||
ipc_$send(connection->plc_socket, server_handle,
|
||||
*header, header_len, *data, data_len, status);
|
||||
if (status.all)
|
||||
ipc_error(status, "icp_$send");
|
||||
}
|
||||
|
||||
|
||||
static int socket_eql( UCHAR * socket1, UCHAR * socket2)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* s o c k e t _ e q l
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Compare two sockets for equality.
|
||||
*
|
||||
**************************************/
|
||||
UCHAR *end;
|
||||
|
||||
end = socket1 + sizeof(struct ipc_$socket_handle);
|
||||
|
||||
while (socket1 < end)
|
||||
if (*socket1++ != socket2++)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Remote Interface/Server
|
||||
* MODULE: plserver.h
|
||||
* DESCRIPTION: Page/lock server
|
||||
*
|
||||
* 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): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef _ISC_LOCK_PLSERVER_H_
|
||||
#define _ISC_LOCK_PLSERVER_H_
|
||||
|
||||
/* General usage packet types */
|
||||
|
||||
#define PL_CONNECT 1 /* Establish connection */
|
||||
#define PL_DISCONNECT 2 /* Break connection */
|
||||
#define PL_ACK 3 /* Acknowledge message */
|
||||
#define PL_ERROR 4 /* An error occurred */
|
||||
#define PL_REPLY 5 /* Generic reply */
|
||||
|
||||
/* Packet types for page operations */
|
||||
|
||||
#define PL_PAGE_OPEN 10 /* Open existing file */
|
||||
#define PL_PAGE_CREATE 11 /* Create new file */
|
||||
#define PL_PAGE_READ 12 /* Read file data */
|
||||
#define PL_PAGE_WRITE 13 /* Write file data */
|
||||
|
||||
/* Packet types for lock operations */
|
||||
|
||||
#define PL_LOCK_ENQ 20 /* Enqueue on lock */
|
||||
#define PL_LOCK_CVT 21 /* Convert existing lock */
|
||||
#define PL_LOCK_DEQ 22 /* Dequeue lock */
|
||||
#define PL_LOCK_GRANT 23 /* Grant lock */
|
||||
#define PL_LOCK_DENY 24 /* Deny lock */
|
||||
#define PL_LOCK_BLOCK 25 /* Existing lock is blocking another process */
|
||||
|
||||
/* Generate packet format */
|
||||
|
||||
typedef struct phd {
|
||||
UCHAR phd_type; /* Packet type */
|
||||
UCHAR phd_flags; /* Misc flags */
|
||||
USHORT phd_sequence; /* Packet sequence number */
|
||||
USHORT phd_ack; /* Acknowleding packet */
|
||||
int *phd_connection; /* Connection handle */
|
||||
int *phd_handle; /* Internal handle */
|
||||
USHORT phd_length; /* Miscellaneous usage */
|
||||
int phd_misc; /* Also miscellaneous usage */
|
||||
UCHAR phd_string[16]; /* Associated string */
|
||||
} PHD;
|
||||
|
||||
#define PHD_SERVER 1 /* Connection is from a server */
|
||||
|
||||
#define BUMP_SEQUENCE(n) n = (++n == 10000) ? 1 : n;
|
||||
|
||||
#endif /* _ISC_LOCK_PLSERVER_H_ */
|
Loading…
Reference in New Issue
Block a user