8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 19:23:02 +01:00
firebird-mirror/src/lock/driver.cpp

390 lines
9.2 KiB
C++

/*
* PROGRAM: JRD Lock Manager
* MODULE: driver.cpp
* DESCRIPTION: Stand alone test driver
*
* 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 <stdio.h>
#include "../jrd/common.h"
#include "../jrd/ibase.h"
#include "../jrd/isc.h"
#include "../lock/lock.h"
#ifdef WIN_NT
#include <process.h>
#endif
static int ast(void*);
static int lookup_agg(UCHAR *);
static int lookup_lock(UCHAR *);
static void print_help(void);
static struct tbl {
const char* tbl_string;
SSHORT tbl_code;
} types[] = {
{"null", LCK_null},
{"pr", LCK_PR},
{"sr", LCK_SR},
{"pw", LCK_PW},
{"sw", LCK_SW},
{"ex", LCK_EX},
{NULL, LCK_none}
};
static struct tagg {
const char* tagg_string;
SSHORT tagg_code;
} aggs[] = {
{"min", LCK_MIN},
{"max", LCK_MAX},
{"cnt", LCK_CNT},
{"sum", LCK_SUM},
{"avg", LCK_AVG},
{"any", LCK_ANY},
{NULL, NULL}
};
static int wait, sw_release, locks[100], levels[100];
static SLONG lck_owner_handle = 0;
void main( int argc, char **argv)
{
/**************************************
*
* m a i n
*
**************************************
*
* Functional description
* Test driver for lock manager.
*
**************************************/
UCHAR op[500], arg[500];
SSHORT type, n, agg;
SLONG lock, data;
ISC_STATUS_ARRAY status_vector;
printf("\nStand alone Lock Manager driver program.\n");
printf("****************************************\n\n");
printf("pid = %d\n\n", getpid());
printf("\n");
if (LOCK_init(status_vector, true,
getpid(), 1, &lck_owner_handle)) {
printf("LOCK_init failed\n");
isc_print_status(status_vector);
exit(0);
}
wait = 1;
sw_release = 1;
SSHORT slot = 0;
/* Force a dummy parent lock to test query data functionality */
SLONG parent = LOCK_enq(NULL, /* prior request */
NULL, /* parent request */
0, /* series */
"parent", /* value */
strlen("parent"), /* length of key */
LCK_SR, /* lock type */
NULL, NULL, /* AST and argument */
0, wait, status_vector, lck_owner_handle);
while (true) {
printf("Request: ");
ISC_STATUS status = scanf("%s%s", op, arg);
if (status == EOF)
continue;
if (!strcmp(op, "rel")) {
n = atoi(arg);
if (n < slot && (lock = locks[n])) {
LOCK_deq(lock);
locks[n] = 0;
}
else
printf("*** BAD LOCK\n");
continue;
}
else if (!strcmp(op, "ar")) {
sw_release = atoi(arg);
continue;
}
else if (!strcmp(op, "w")) {
wait = atoi(arg);
continue;
}
else if (!strcmp(op, "q"))
exit(0);
else if (!strcmp(op, "rd")) {
n = atoi(arg);
if (n >= slot || !(lock = locks[n])) {
printf("bad lock\n");
continue;
}
data = LOCK_read_data(lock);
printf("lock data = %d\n", data);
continue;
}
else if (!strcmp(op, "wd")) {
n = atoi(arg);
if (n >= slot || !(lock = locks[n])) {
printf("bad lock\n");
continue;
}
scanf("%s", arg);
data = atoi(arg);
LOCK_write_data(lock, data);
continue;
}
else if (!strcmp(op, "qd")) {
if (!(agg = lookup_agg(arg))) {
printf("bad query aggregate\n");
continue;
}
data = LOCK_query_data(parent, 0, agg);
if (agg == LCK_ANY)
printf("%s = %s\n", arg, ((data) ? "true" : "false"));
else
printf("%s = %d\n", arg, data);
continue;
}
else if (!strcmp(op, "cvt")) {
n = atoi(arg);
scanf("%s", op);
if (!(type = lookup_lock(op))) {
printf("bad lock type\n");
continue;
}
if (n >= slot || !(lock = locks[n])) {
printf("bad lock\n");
continue;
}
if (!LOCK_convert(lock, type, wait, NULL, 0, status_vector))
{
printf("*** CONVERSION FAILED: status_vector[1] = %d",
status_vector[1]);
switch (status_vector[1])
{
case isc_lock_timeout:
printf(" (isc_lock_timeout)\n");
break;
case isc_lock_conflict:
printf(" (isc_lock_conflict)\n");
break;
case isc_deadlock:
printf(" (isc_deadlock)\n");
break;
default:
printf("\n");
break;
}
}
continue;
}
else if (type = lookup_lock(op)) {
lock = LOCK_enq(NULL, /* prior request */
parent, /* parent request */
0, /* series */
arg, /* value */
strlen(arg), /* length of key */
type, /* lock type */
(sw_release ? ast : NULL), slot, /* AST and argument */
0, wait, status_vector, lck_owner_handle);
if (lock) {
printf("lock# %d = %d\n", slot, lock);
levels[slot] = type;
locks[slot++] = lock;
}
else {
printf("*** LOCK REJECTED: status_vector[1] = %d",
status_vector[1]);
if (status_vector[1] == isc_lock_timeout)
printf(" (isc_lock_timeout)\n");
else if (status_vector[1] == isc_lock_conflict)
printf(" (isc_lock_conflict)\n");
else if (status_vector[1] == isc_deadlock)
printf(" (isc_deadlock)\n");
else
printf("\n");
}
}
else {
print_help();
continue;
}
}
}
static int ast(void* slot_void)
{
/**************************************
*
* a s t
*
**************************************
*
* Functional description
* Dummy blocking ast.
*
**************************************/
ISC_STATUS_ARRAY status_vector;
int sw_release_use = sw_release;
const int slot = (int)(IPTR) slot_void; // static cast
printf("*** blocking AST for lock# %d ", slot);
if (sw_release < 0) {
printf("In the AST routine.\n");
printf("Enter ar value [1=nothing, 2=release, 3=downgrade]:");
scanf("%d", &sw_release_use);
}
if (sw_release_use == 1) {
printf("-- ignored ***\n");
return 0;
}
if (sw_release_use > 2 && levels[slot] == LCK_EX) {
LOCK_convert(locks[slot], LCK_SR, wait, NULL, 0, status_vector);
levels[slot] = LCK_SR;
printf("-- down graded to SR ***\n");
return 0;
}
LOCK_deq(locks[slot]);
printf("-- released ***\n");
return 0;
}
static lookup_agg( UCHAR * string)
{
/**************************************
*
* l o o k u p _ a g g
*
**************************************
*
* Functional description
*
**************************************/
for (tagg* ptr = aggs; ptr->tagg_string; ptr++)
if (strcmp(ptr->tagg_string, string) == 0)
return ptr->tagg_code;
return NULL;
}
static lookup_lock( UCHAR * string)
{
/**************************************
*
* l o o k u p _ l o c k
*
**************************************
*
* Functional description
*
**************************************/
for (tbl* ptr = types; ptr->tbl_string; ptr++)
if (strcmp(ptr->tbl_string, string) == 0)
return ptr->tbl_code;
return LCK_none;
}
static void print_help(void)
{
/**************************************
*
* p r i n t _ h e l p
*
**************************************
*
* Functional description
* Prints the command syntax.
*
***************************************/
printf("Command syntax is:\n");
printf
("\tnull <key>\tAcquire an 'null' lock on <key> (returns <lock#>)\n");
printf
("\tsr <key>\tAcquire an 'sr' lock on <key> (returns <lock#>)\n");
printf
("\tpr <key>\tAcquire an 'pr' lock on <key> (returns <lock#>)\n");
printf
("\tsw <key>\tAcquire an 'sw' lock on <key> (returns <lock#>)\n");
printf
("\tpw <key>\tAcquire an 'pw' lock on <key> (returns <lock#>)\n");
printf
("\tex <key>\tAcquire an 'ex' lock on <key> (returns <lock#>)\n");
printf("\tw <value>\tSet wait parameter to LOCK_enq:\n");
printf("\t\t\t\tvalue>0 willing to wait forever [default]\n");
printf("\t\t\t\tvalue=0 not willing to wait\n");
printf("\t\t\t\tvalue<0 willing to wait for that many seconds\n");
printf("\tar <value>\tControls the AST\n");
printf
("\t\t\t\tvalue=1 AST will not release nor downgrade [default]\n");
printf("\t\t\t\tvalue=2 AST will release lock\n");
printf("\t\t\t\tvalue=3 AST will attempt to downgrade first\n");
printf("\t\t\t\tvalue<0 AST will prompt\n");
printf("\t\t\t\tvalue=0 AST is not supplied\n");
printf("\trel <lock#>\tRelease lock <lock#>\n");
printf
("\tcvt <lock#> <lock-type>\n\t\t\tConvert lock <lock#> to type <lock-type>\n");
printf("\trd <lock#>\tRead data <lock#>\n");
printf("\twd <lock#> <data>\tWrite <data> to <lock#>\n");
printf
("\tqd <agg>\tQuery data for <agg := min,max,cnt,sum,avg,any>\n");
printf("\tq <don't-care>\tQuit\n");
printf("\nRemember the isc_config modifier:\n");
printf("\tV4_LOCK_GRANT_ORDER {0 | 1}\n");
printf("\t\t\t0 = disable lock-grant-order (no lock-fairness)\n");
printf("\t\t\t1 = enable lock-grant-order [default]\n");
}
SCH_ast(void)
{
/**************************************
*
* S C H _ a s t
*
**************************************
*
* Functional description
* Stub to prevent link error
*
**************************************/
}