⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 关于Berkelay数据库的共享源码
💻 C
字号:
#include <sys/types.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <atmi.h>#include <fml1632.h>#include <fml32.h>#include <tx.h>#include <xa.h>#include <db.h>#include "datafml.h"#include "hdbrec.h"#include "hcommonxa.h"#include "htimestampxa.h"/* * The two servers are largely identical, #ifdef the source code. */#ifdef SERVER1#define	TXN_FUNC		TestTxn1#define	TXN_STRING		"TestTxn1"#endif#ifdef SERVER2#define	TXN_FUNC		TestTxn2#define	TXN_STRING		"TestTxn2"#endifvoid TXN_FUNC(TPSVCINFO *);#define	HOME	"../data"#define	TABLE1	"table1.db"#define	TABLE2	"table2.db"#ifdef VERBOSEstatic int verbose = 1;				/* Debugging output. */#elsestatic int verbose = 0;#endifDB *db1, *db2;					/* Table handles. */int cnt_forward;				/* Forwarded requests. */int cnt_request;				/* Total requests. */char *progname;					/* Server run-time name. */char *db_buf(DBT *);inttpsvrinit(int argc, char* argv[]){	DB_ENV *dbenv;	int ret;	progname = argv[0];	if (verbose)		printf("%s: called\n", progname);	/*	 * This is all Berkeley DB specific.	 *	 * Open the environment and clear tables #1 and #2.  We do this with	 * our own DB_ENV handle -- Berkeley DB doesn't require servers know	 * where the database environment is, but it's pretty much necessary	 * if you want to do anything tricky.	 */	if ((ret = db_env_create(&dbenv, 0)) != 0) {		fprintf(stderr, "db_env_create: %s\n", db_strerror(ret));		return (-1);	}	if ((ret = dbenv->open(dbenv, HOME, DB_JOINENV, 0)) != 0) {		fprintf(stderr,		    "DB_ENV->open: %s: %s\n", HOME, db_strerror(ret));		return (-1);	}	if ((ret = db_create(&db1, dbenv, 0)) != 0) {		fprintf(stderr, "db_create: %s\n", db_strerror(ret));		return (-1);	}	db1->set_errfile(db1, stderr);	if ((ret = db1->open(db1, NULL,	    TABLE1, NULL, DB_BTREE, DB_AUTO_COMMIT | DB_CREATE, 0660)) != 0 ||	    (ret = db1->truncate(db1, NULL, NULL, 0)) != 0) {		fprintf(stderr,		    "DB open/truncate: %s: %s\n", TABLE1, db_strerror(ret));		return (-1);	}	if ((ret = db_create(&db2, dbenv, 0)) != 0) {		fprintf(stderr, "db_create: %s\n", db_strerror(ret));		return (-1);	}	db2->set_errfile(db2, stderr);	if ((ret = db2->open(db2, NULL,	    TABLE2, NULL, DB_BTREE, DB_AUTO_COMMIT | DB_CREATE, 0660)) != 0 ||	    (ret = db2->truncate(db2, NULL, NULL, 0)) != 0) {		fprintf(stderr,		    "DB open/truncate: %s: %s\n", TABLE2, db_strerror(ret));		return (-1);	}	/* We're done -- discard our handles. */	if ((ret = db1->close(db1, 0)) != 0) {		fprintf(stderr,		    "DB->close: %s: %s\n", TABLE1, db_strerror(ret));		return (-1);	}	if ((ret = db2->close(db2, 0)) != 0) {		fprintf(stderr,		    "DB->close: %s: %s\n", TABLE2, db_strerror(ret));		return (-1);	}	if ((ret = dbenv->close(dbenv, 0)) != 0) {		fprintf(stderr,		    "DB_ENV->close: %s: %s\n", HOME, db_strerror(ret));		return (-1);	}	/* End Berkeley DB specific setup. */	/* Open resource managers. */	if (tx_open() == TX_ERROR) {		fprintf(stderr, "tx_open: TX_ERROR\n");		return (-1);	}	/* Seed random number generator. */	srand((u_int)(time(NULL) | getpid()));	/* Open permanent XA handles. */	if ((ret = db_create(&db1, NULL, DB_XA_CREATE)) != 0) {		fprintf(stderr, "db_create: %s\n", db_strerror(ret));		return (-1);	}	db1->set_errfile(db1, stderr);	if ((ret = db1->open(db1, NULL,	    TABLE1, NULL, DB_BTREE, DB_AUTO_COMMIT | DB_CREATE, 0660)) != 0) {		fprintf(stderr, "DB open: %s: %s\n", TABLE1, db_strerror(ret));		return (-1);	}	if ((ret = db_create(&db2, NULL, DB_XA_CREATE)) != 0) {		fprintf(stderr, "db_create: %s\n", db_strerror(ret));		return (-1);	}	db2->set_errfile(db2, stderr);	if ((ret = db2->open(db2, NULL,	    TABLE2, NULL, DB_BTREE, DB_AUTO_COMMIT | DB_CREATE, 0660)) != 0) {		fprintf(stderr, "DB open: %s: %s\n", TABLE2, db_strerror(ret));		return (-1);	}	if (verbose)		printf("%s: tpsvrinit: initialization done\n", progname);	return (0);}voidtpsvrdone(){	if (db1 != NULL)		(void)db1->close(db1, 0);	if (db2 != NULL)		(void)db2->close(db2, 0);	tx_close();	if (verbose)		printf("%s: tpsvrdone: shutdown done\n", progname);	printf("%s: %d requests, %d requests forwarded to the other server\n",	    progname, cnt_request, cnt_forward);}voidTXN_FUNC(TPSVCINFO *msg){	DBT data;	DBT key;	FBFR *replyBuf;	HDbRec rcrd;	long replyLen, seqNo;	int ret;	++cnt_request;#ifdef SERVER1	/*	 * Test that servers can forward to other servers.  Randomly forward	 * half of server #1's requests to server #2.	 */	if (rand() % 2 > 0) {		++cnt_forward;		replyLen = 1024;		if ((replyBuf =		    (FBFR*)tpalloc("FML32", NULL, replyLen)) == NULL ||		    tpcall("TestTxn2", msg->data,		    0, (char**)&replyBuf, &replyLen, TPSIGRSTRT) == -1) {			fprintf(stderr, "%s: TUXEDO ERROR: %s (code %d)\n",			    progname, tpstrerror(tperrno), tperrno);			tpfree((char*)replyBuf);			tpreturn(TPFAIL, 0L, 0, 0L, 0);		} else {			tpfree((char*)replyBuf);			tpreturn(TPSUCCESS, tpurcode, 0, 0L, 0);		}		return;	}#endif						/* Read the record. */	if (Fget((FBFR*)msg->data, SEQ_NO, 0, (char *)&rcrd.SeqNo, 0) == -1)		goto fml_err;	if (Fget((FBFR*)msg->data, TS_SEC, 0, (char *)&rcrd.Ts.Sec, 0) == -1)		goto fml_err;	if (Fget(	    (FBFR*)msg->data, TS_USEC, 0, (char *)&rcrd.Ts.Usec, 0) == -1) {fml_err:	fprintf(stderr, "%s: FML ERROR: %s (code %d)\n",		    progname, Fstrerror(Ferror), Ferror);		goto err;	}	seqNo = rcrd.SeqNo;			/* Update the record. */	memset(&key, 0, sizeof(key));	key.data = &seqNo;	key.size = sizeof(seqNo);	memset(&data, 0, sizeof(data));	data.data = &rcrd;	data.size = sizeof(rcrd);	strcpy(rcrd.Msg, "Table1");		/* Table 1. */	if (verbose) {		printf("put1: key: %s\n", db_buf(&key));		printf("put1: data: %s\n", db_buf(&data));	}	if ((ret = db1->put(db1, NULL, &key, &data, 0)) != 0) {		fprintf(stderr, "%s: %s: Table1->put: %s\n",		    progname, TXN_STRING, db_strerror(ret));		goto err;	}	strcpy(rcrd.Msg, "Table2");		/* Table 2. */	if ((ret = db2->put(db2, NULL, &key, &data, 0)) != 0) {		fprintf(stderr, "%s: %s: Table2->put: %s\n",		    progname, TXN_STRING, db_strerror(ret));		goto err;	}	/*	 * Decide if the client is going to commit the global transaction or	 * not, testing the return-value path back to the client; this is the	 * path we'd use to resolve deadlock, for example.  Commit 80% of the	 * time.  Returning 0 causes the client to commit, 1 to abort.	 */	if (rand() % 10 > 7) {		if (verbose)		 	printf("%s: %s: commit\n", progname, TXN_STRING);		tpreturn(TPSUCCESS, 0L, 0, 0L, 0);	} else {		if (verbose)			printf("%s: %s: abort\n", progname, TXN_STRING);		tpreturn(TPSUCCESS, 1L, 0, 0L, 0);	}	return;err:	tpreturn(TPFAIL, 1L, 0, 0L, 0);}char *db_buf(dbt)	DBT *dbt;{	static u_char buf[1024];	size_t len;	u_char *p, *b;	for (p = dbt->data, len = dbt->size, b = buf; len > 0; ++p, --len)		if (isprint(*p))			b += sprintf((char *)b, "%c", *p);		else			b += sprintf((char *)b, "%#o", *p);	return ((char *)buf);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -