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

📄 mal_client.mx

📁 一个内存数据库的源代码这是服务器端还有客户端
💻 MX
📖 第 1 页 / 共 2 页
字号:
@' The contents of this file are subject to the MonetDB Public License@' Version 1.1 (the "License"); you may not use this file except in@' compliance with the License. You may obtain a copy of the License at@' http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.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 is the MonetDB Database System.@'@' The Initial Developer of the Original Code is CWI.@' Portions created by CWI are Copyright (C) 1997-2007 CWI.@' All Rights Reserved.@a M. L. Kersten@v 5.0@-Clients gain access to the Monet server through a internet connectionor through its server console.Access through the internet requires a client program at thesource, which addresses the default port of a running server.The functionality of the server console is limited.It is a bare bone textual interface for expert use.@ifset M5manualAt the server side, each client is represented by a session record with thecurrent status, such as name, file descriptors, namespace, and local stack.Each client session has a dedicated thread of control, which limitsthe number of concurrent users to the thread management facilities of theunderlying operating system. A large client base should be supported usinga single server-side client thread, geared at providinga particular service.The number of clients permitted concurrent access is a compile time option. The console is the first and is always present.It reads from standard input and writes to standard output.@end ifsetClient sessions remain in existence until the correspondingcommunication channels break or its retention timer expiresThe administrator and owner of a sesssioncan manipulate the timeout with a system call.@ifset sqlmanualThere are many user-friendly tools to interact with a SQL database server.A few based on the JDBC library of MonetDB are included for reference only.@end ifset@{Client records are linked into a hierarchy, where the top recorddenotes the context of the Monet administrator. The next layeris formed by a database administrator and the third layer containsuser sessions.This hierachy is used to share and constrain resources, suchas global variables or references to catalogue information.During parallel execution additional layers may be constructed.[This feature needs more implementation support]@}@{The routines defined below provide management of the clientadministration. Routines dealing with serviceing requestsare located in mal\_startup.@h#ifndef _MAL_CLIENT_H_#define _MAL_CLIENT_H_#define bitset int/* #define MAL_CLIENT_DEBUG */#include "mal_resolve.h"#include "mal_profiler.h"#include "mal.h"#define MAL_MAXCLIENTS  64#define CONSOLE     0#define isAdministrator(X) (X==mal_clients)#define FREECLIENT  0#define FINISHING   1   #define CLAIMED     2#define AWAITING    4#define TIMEOUT     (5*60)  /* seconds */#define PROCESSTIMEOUT  2   /* seconds */#ifdef HAVE_SYS_RESOURCE_H# include <sys/resource.h>#endif@-The prompt structure is designed to simplify recognitionof the language framework for interaction. For direct consoleaccess it is a short printable ascii string. For access throughan API we assume the prompt is an ascii string surrounded by a \001character. This simplifies recognition.The information between the prompt brackets can be used topass the mode to the front-end. Moreover, the prompt can bedropped if a single stream of information is expected from theserver(See mal_profiler.mx).@-The user can request server-side compilation as part of the initialization string. See the documentation on Scenarios.@htypedef struct CLIENT_INPUT {	bstream             *fdin;	int                 yycur;			int                 listing;	char                *prompt;	struct CLIENT_INPUT *next;    } ClientInput;typedef struct CLIENT {	int idx;        /* entry in mal_clients */	oid user;       /* user id in the auth administration */	int sessionkey; /* NOTUSED ANYMORE */	int permission; /* access mode */@-The actions for a client is separated into several stages: parsing,strategic optimization, tactial optimization, and execution. The routines to handle them are obtained once the scenario is choosen.Each stage carries a state descriptor, but they share the IO statedescription. A backup structure is providedto temporarily switch to another scenario. Propagation of the stateinformation should be dealt with separately.[TODO]@h	str     scenario;  /* scenario management references */	str     oldscenario;	str     srcFile;	/* NULL for stdin, or file name */	void    *state[7], *oldstate[7];	MALfcn  phase[7], oldphase[7];	char    itrace;     /* trace execution using interactive mdb */	short   debugOptimizer,debugScheduler;@-For program debugging we need information on the timer and memoryusage patterns.@h	sht		flags;	/* resource tracing flags */	lng     timer;  /* trace time in usec */#define timerFlag	1#define memoryFlag	2#define ioFlag	4#define flowFlag	8@-@}@-@{Session structures are currently not saved over network failures.Future releases may support a re-connect facility.  [TODO]@h	time_t      login;  	time_t      logout;	time_t      delay;@-Communication channels for the interconnect are stored here.It is perfectly legal to have a client without input stream.It will simple terminate after consuming the input buffer.The monitor file descriptor can be set to trace the input receivedfrom a particular client. This facility is used by Mapi to tracethe interaction on the system console (sysmon). @h	bstream  *fdin;	bstream	 *console;	/* always available for reading */	int      yycur;		/* the scanners current position */	ClientInput *bak;   /* used for recursive script and string execution */	stream   *fdout;    /* streams from and to user. */	str output; 	/* output buffer */	str prompt;         /* acknowledge prompt */	int promptlength;@-In interactive mode, reading one line at a time, we should beaware of parsing compound structures, such as functions andbarrier blocks. The level of nesting is maintained in blkmode,which is reset to zero upon encountering an end instruction,or the closing bracket has been detected. Once the completestructure has been parsed the program can be checked and executed.Nesting is indicated using a '+' before the prompt.@h	int blkmode;        /* control block parsing */@-Keeping track of instructions executed is a valueable tool forscript processing and debugging. Its default value is defined in the MonetDB configuration file.It can be changed at runtime for individual clients usingthe operation @sc{clients.listing}(@emph{mask}).A listing bit controls the level of detail to be generated duringprogram execution tracing. The lowest level (1) simply dumps the input,(2) also demonstrates the MAL internal structur (4) adds the type information@h	bitset  listing;        @-The MAL debugger uses the client record to keep track ofany pervasive debugger command. For detailed informationon the debugger features.@{@h	bitset debug;	stream  *sysmon;        /* trace interaction */	stream  *journal;	str  history;			/* where to keep console history */	short mode;           /* FREECLIENT..BLOCKED */	str cwd;            /* working directory of client */@-Client records are organized into a two-level dependencytree, where children may be created to deal with parallel processingactivities. Each client runs in its own process thread. Its identityis retained here for access by others (=father).@h	Thread      mythread;	size_t		mypid;	str     	errbuf;     /* location of GDK exceptions */	struct CLIENT   *father;    @-Each client has a private entry point into the namespace andobject space (the global variables).Moreover, the parser needs some administration variablesto keep track of critical elements.@h	Module      nspace;     /* private scope resolution list */	Symbol      curprg;     /* focus of parser */	Symbol      backup;     /* save parsing context */	MalStkPtr   glb;        /* global variable stack */} *Client, ClientRec;mal_export ClientRec mal_clients[MAL_MAXCLIENTS+1];mal_export Client   MCgetClient   (void);mal_export Client   MCinitClient(oid user, bstream *fin, stream *fout);mal_export void     MCinitClientThread(Client c);mal_export void     MCcloseClient    (Client c);mal_export Client   MCforkClient     (Client c);mal_export void     MCkillClient     (Client c, int timeout);mal_export int		MCcountClients(void);mal_export int      MCreadClient  (Client c);mal_export str      MCstopClient(Client c, oid which);mal_export str      MCstopClientIndex(Client c, int id);mal_export void 	MCshutdown(Client c, int timeout);mal_export void     MCcleanupClients(void);mal_export void     MCtraceAllClients(int flag);mal_export void     MCtraceClient(oid which, int flag);mal_export bstream *MCgetConsole(Client c);mal_export void     MCpushClientInput(Client c, bstream *new_input, int listing, char *prompt);mal_export void     MCpopClientInput(Client c);#endif /* _MAL_CLIENT_H_ */@-@}A client record is initialized upon acceptance of a connection.The client runs in his own thread of control until it finds asoft-termination request mode (FINISHING) or its IO filedescriptors are closed. The latter generates an IO error, whichleads to a safe termination.The system administrator client runs in the primary thread ofcontrol to simplify debugging with external debuggers.A new Client structure can only be requested if the 'adm'user is available, because it guarantees a way to deliverany error message.Searching a free client record is encapsulated ina critical section to hand them out one-at-a-time.Marking them as being claimed avoids any interference from parallelactions to obtain client records.@{@c#include "mal_config.h"#include "mal_client.h"#include "mal_readline.h"#include "mal_import.h"#include "mal_parser.h"#include "mal_namespace.h"/* This should be in src/mal/mal.h, as the function is implemented in  * src/mal/mal.c; however, it cannot, as "Client" isn't known there ... |-(  * For now, we move the prototype here, as it it only used here. * Maybe, we should concider also moving the implementation here...int streamClient(Client c, str prompt);int bstreamClient(Client c, str prompt); */static void     freeClient  (Client c);ClientRec   mal_clients[MAL_MAXCLIENTS+1];void THRsuspend(Thread h){	(void) h;	/* printf("suspend Thread %d %d\n", h->tid, (int) h->pid);*/}void THRawake(Thread h){	(void) h;	/* printf("awake Thread %d %d\n", h->tid, (int) h->pid);*/}bstream *MCgetConsole(Client c){	ClientInput *x;	if( c->bak == 0) return c->fdin;	x= c->bak;	while(x->next) x= x->next;	return x->fdin;	/* return c->console;*/}void MCpushClientInput(Client c, bstream *new_input, int listing, char *prompt){	ClientInput *x = (ClientInput*)GDKmalloc(sizeof(ClientInput));	x->fdin = c->fdin;	x->yycur = c->yycur;	x->listing = c->listing;	x->prompt = c->prompt;	x->next = c->bak;	c->bak = x;	c->fdin = new_input;	c->listing = listing;	c->prompt = GDKstrdup(prompt);	c->promptlength = strlen(c->prompt);	c->yycur = 0;}void MCpopClientInput(Client c){	ClientInput *x = c->bak;	if (c->fdin) {		/* missing protection against closing stdin stream */		(void) stream_close(c->fdin->s);		(void) stream_destroy(c->fdin->s);		(void) bstream_destroy(c->fdin);	}	GDKfree(c->prompt);	c->fdin = x->fdin;	c->yycur = x->yycur;	c->listing = x->listing;	c->prompt = x->prompt;	c->promptlength = strlen(c->prompt);	c->bak = x->next;	GDKfree(x);}Client MCnewClient(){	Client  c;	if( mal_clients[CONSOLE].user)		GDKprotect();	mal_set_lock(mal_contextLock, "newClient");	if( mal_clients[CONSOLE].user &&			mal_clients[CONSOLE].mode == FINISHING){		showException(MAL,"newClient", "system shutdown in progress");		mal_unset_lock(mal_contextLock, "newClient");		return NULL;	}	for(c = mal_clients; c < mal_clients+MAL_MAXCLIENTS; c++) {		if (c->mode == FREECLIENT) {			c->mode= CLAIMED;			break;		}	}	mal_unset_lock(mal_contextLock, "newClient");	if (c == mal_clients+MAL_MAXCLIENTS) 		return NULL;	c->idx= c - mal_clients;#ifdef MAL_CLIENT_DEBUG	printf("New client created %d\n",c-mal_clients);#endif	return c;}@-You can always retrieve a client record using the thread identifier,because we maintain a 1-1 mapping between client and thread of control.Therefore, we don't need locks either.If the number of clients becomes too large, we have to change the allocation and lookup scheme.@cClient MCgetClient(){	Client c;	size_t pid= MT_getpid();	Thread tid;	for(c = mal_clients+1; c < mal_clients+MAL_MAXCLIENTS; c++) 		if( c->mypid == pid) return c;	if( mal_clients->mypid== pid) return mal_clients;	tid= THRget(THRgettid());	for(c = mal_clients; c < mal_clients+MAL_MAXCLIENTS; c++) 		if( c->mythread == tid) return c;	for(c = mal_clients; c < mal_clients+MAL_MAXCLIENTS; c++) 		if( c->mythread) stream_printf(c->fdout,"client %d\n",c->mythread);	showException(MAL, "getClient", "unexpected call to getClient %d", tid);	return NULL;}Client MCinitClient(oid user, bstream *fin, stream *fout) {	Client c;	str prompt;	if ((c = MCnewClient()) == NULL)		return NULL;	c->user = user; 	c->scenario = NULL;	c->oldscenario = NULL;	c->srcFile = NULL;	c->sessionkey = 0;	c->blkmode = 0;	c->fdin = fin ? fin : bstream_create(GDKin,0);	c->console = c->fdin;	c->yycur = 0;	c->bak = NULL;	c->listing = 0;	c->fdout = fout ? fout : GDKstdout;	c->sysmon = mal_clients[0].sysmon ? mal_clients[0].fdout : 0;	c->journal = NULL;	c->history = 0;@-The output buffer is currently not used. Beware to garbagecollect the buffer when in use.@c	c->output = 0;	if(c->nspace==0)		c->nspace = newModule(NULL, putName("guest",5));	c->curprg = c->backup = 0;	c->glb = 0;	c->father = NULL;	c->login = time(0); c->delay= TIMEOUT;	c->logout= c->login+c->delay;	c->mode = AWAITING;	c->itrace = 0;	c->debugOptimizer = c->debugScheduler= 0;	c->timer = 0;	c->errbuf = 0;	c->cwd= GDKstrdup(monet_cwd);	prompt = !fin? GDKgetenv("monet_prompt"): PROMPT1;	c->prompt= GDKstrdup(prompt);	c->promptlength= strlen(prompt);	if( isAdministrator(c)) MCinitClientThread(c);	return c;}@-The administrator should be initialized to enableinterpretation of the command line arguments, beforeit starts serviceing statements@cvoid MCinitClientThread(Client c){	Thread t;	char cname[11 + 1];/*	still unsafe, race conditions, garbage left over??	if( c->mythread){		t= c->mythread;	} else*/		snprintf(cname, 11, SZFMT, (size_t)(c->user));

⌨️ 快捷键说明

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