Changeset: babb06e8fe55 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=babb06e8fe55
Modified Files:
        monetdb5/mal/mal.c
        monetdb5/mal/mal_client.c
        monetdb5/mal/mal_client.h
        monetdb5/mal/mal_session.c
        monetdb5/modules/mal/clients.c
        monetdb5/modules/mal/clients.h
        monetdb5/modules/mal/clients.mal
        sql/backends/monet5/sql.mx
        sql/scripts/22_clients.sql
Branch: default
Log Message:

Constrolled shutdown
Stopping a server should be performed by the monetdb administrator.
For this he can log onto the database using mclient and issue the
following operations.

select * from sys.sessions;
to see how many users are still active

call sys.shutdown(10);
to initiate stopping all other clients within 10 seconds
at sage MAL boundaries.
The outcome can be inspected with
select * from sys.sessions;

During shutdown no clients can establish a connection anywmore.
Upon a quiet system the last console can be closed and the server
can safely stopped with 'monetdb stop <db>'
Alternatively, the command

call sys.shutdown(10,true)
will terminate the server forcefully after 10 seconds.


diffs (truncated from 329 to 300 lines):

diff --git a/monetdb5/mal/mal.c b/monetdb5/mal/mal.c
--- a/monetdb5/mal/mal.c
+++ b/monetdb5/mal/mal.c
@@ -305,38 +305,6 @@ int mal_init(void){
  *
  * Beware, mal_exit is also called during a SIGTERM from the monetdb tool
  */
-static void stopClients(void)
-{
-       Client cntxt = mal_clients;
-
-       MT_lock_set(&mal_contextLock,"stopClients");
-       for(cntxt= mal_clients +1;  cntxt < mal_clients+MAL_MAXCLIENTS; cntxt++)
-       if ( cntxt->mode == RUNCLIENT)
-               cntxt->mode = FINISHCLIENT; 
-       else if (cntxt->mode == FREECLIENT)
-               cntxt->mode = BLOCKCLIENT;
-       MT_lock_unset(&mal_contextLock,"stopClients");
-}
-
-int
-moreClients(int reruns)
-{
-       int freeclient=0, finishing=0, running=0, blocked = 0;
-       Client cntxt = mal_clients;
-
-       for(cntxt= mal_clients+1;  cntxt<mal_clients+MAL_MAXCLIENTS; cntxt++){
-               freeclient += (cntxt->mode == FREECLIENT);
-               finishing += (cntxt->mode == FINISHCLIENT);
-               running += (cntxt->mode == RUNCLIENT);
-               blocked += (cntxt->mode == BLOCKCLIENT);
-       }
-       if( reruns > 3){
-               printf("MALexit: server forced exit %d free %d finishing %d 
running %d blocked\n",
-                               freeclient, finishing,running, blocked);
-               return 0;
-       }
-       return finishing+running;
-}
 
 void mal_exit(void){
        str err;
@@ -345,16 +313,15 @@ void mal_exit(void){
         * Before continuing we should make sure that all clients
         * (except the console) have left the scene.
         */
-       stopClients();
+       MCstopClients(0);
 #if 0
 {
        int reruns=0, go_on;
        do{
-               if ( (go_on = moreClients(reruns)) )
+               if ( (go_on = MCactiveClients()) )
                        MT_sleep_ms(1000);
-               if(reruns)
-                       mnstr_printf(mal_clients->fdout,"#MALexit: clients 
still active\n");
-       } while (++reruns < SERVERSHUTDOWNDELAY && go_on);
+               mnstr_printf(mal_clients->fdout,"#MALexit: %d clients still 
active\n", go_on);
+       } while (++reruns < SERVERSHUTDOWNDELAY && go_on > 1);
 }
 #endif
        stopHeartbeat();
diff --git a/monetdb5/mal/mal_client.c b/monetdb5/mal/mal_client.c
--- a/monetdb5/mal/mal_client.c
+++ b/monetdb5/mal/mal_client.c
@@ -373,7 +373,7 @@ freeClient(Client c)
        c->stimeout = 0;
        c->user = oid_nil;
        c->mythread = 0;
-       c->mode = FREECLIENT;
+       c->mode = MCshutdowninprogress()? BLOCKCLIENT: FREECLIENT;
        GDKfree(c->glb);
        c->glb = NULL;
        if (t)
@@ -392,7 +392,49 @@ freeClient(Client c)
  *
  * Furthermore, once we enter closeClient, the process in which it is
  * raised has already lost its file descriptors.
+ *
+ * When the server is about to shutdown, we should softly terminate
+ * all outstanding session.
  */
+static int shutdowninprogress = 0;
+
+int
+MCshutdowninprogress(void){
+       return shutdowninprogress;
+}
+
+void
+MCstopClients(Client cntxt)
+{
+       Client c = mal_clients;
+
+       MT_lock_set(&mal_contextLock,"stopClients");
+       for(c= mal_clients +1;  c < mal_clients+MAL_MAXCLIENTS; c++)
+       if( cntxt != c){
+               if ( c->mode == RUNCLIENT)
+                       c->mode = FINISHCLIENT; 
+               else if (c->mode == FREECLIENT)
+                       c->mode = BLOCKCLIENT;
+       }
+       shutdowninprogress =1;
+       MT_lock_unset(&mal_contextLock,"stopClients");
+}
+
+int
+MCactiveClients(void)
+{
+       int freeclient=0, finishing=0, running=0, blocked = 0;
+       Client cntxt = mal_clients;
+
+       for(cntxt= mal_clients+1;  cntxt<mal_clients+MAL_MAXCLIENTS; cntxt++){
+               freeclient += (cntxt->mode == FREECLIENT);
+               finishing += (cntxt->mode == FINISHCLIENT);
+               running += (cntxt->mode == RUNCLIENT);
+               blocked += (cntxt->mode == BLOCKCLIENT);
+       }
+       return finishing+running;
+}
+
 void
 MCcloseClient(Client c)
 {
diff --git a/monetdb5/mal/mal_client.h b/monetdb5/mal/mal_client.h
--- a/monetdb5/mal/mal_client.h
+++ b/monetdb5/mal/mal_client.h
@@ -192,6 +192,9 @@ mal_export Client  MCgetClient(int id);
 mal_export Client  MCinitClient(oid user, bstream *fin, stream *fout);
 mal_export Client  MCinitClientRecord(Client c, oid user, bstream *fin, stream 
*fout);
 mal_export int     MCinitClientThread(Client c);
+mal_export void           MCstopClients(Client c);
+mal_export int     MCshutdowninprogress(void);
+mal_export int    MCactiveClients(void);
 mal_export void    MCcloseClient(Client c);
 mal_export str     MCsuspendClient(int id);
 mal_export str     MCawakeClient(int id);
diff --git a/monetdb5/mal/mal_session.c b/monetdb5/mal/mal_session.c
--- a/monetdb5/mal/mal_session.c
+++ b/monetdb5/mal/mal_session.c
@@ -283,8 +283,11 @@ MSscheduleClient(str command, str challe
 
                c = MCinitClient(uid, fin, fout);
                if (c == NULL) {
-                       mnstr_printf(fout, "!maximum concurrent client limit 
reached "
-                                                          "(%d), please try 
again later\n", MAL_MAXCLIENTS);
+                       if ( MCshutdowninprogress())
+                               mnstr_printf(fout, "!system shutdown in 
progress, please try again later\n");
+                       else
+                               mnstr_printf(fout, "!maximum concurrent client 
limit reached "
+                                                                  "(%d), 
please try again later\n", MAL_MAXCLIENTS);
                        exit_streams(fin, fout);
                        GDKfree(command);
                        return;
diff --git a/monetdb5/modules/mal/clients.c b/monetdb5/modules/mal/clients.c
--- a/monetdb5/modules/mal/clients.c
+++ b/monetdb5/modules/mal/clients.c
@@ -35,6 +35,7 @@
 #include "mal_instruction.h"
 #include "mal_client.h"
 #include "mal_authorize.h"
+#include "mal_private.h"
 #include "mtime.h"
 
 #ifdef HAVE_LIBREADLINE
@@ -545,10 +546,41 @@ str CLTgetUsers(Client cntxt, MalBlkPtr 
        return(MAL_SUCCEED);
 }
 
-str CLTshutdown(int *ret, bit *forced) {
-       (void) ret;
-       (void) forced;
-       throw(MAL,"clients.shutdown", PROGRAM_NYI);
+str
+CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
+       str *ret  = (str*) getArgReference(stk,pci,0);
+       int delay = *(int*) getArgReference(stk,pci,1);
+       bit force = FALSE;
+       int leftover;
+       char buf[1024]={"safe to stop last connection"};
+
+       if ( pci->argc == 3) 
+               force = *(bit*) getArgReference(stk,pci,2);
+
+       (void) mb;
+       switch( getArgType(mb,pci,1)){
+       case TYPE_bte:
+       case TYPE_sht:
+               delay = *(sht*) getArgReference(stk,pci,1);
+               break;
+       default:
+               delay = *(int*) getArgReference(stk,pci,1);
+       }
+
+       if ( cntxt->user != mal_clients[0].user)
+               throw(MAL,"mal.shutdown", "Administrator rights required");
+       MCstopClients(cntxt);
+       do{
+               if ( (leftover = MCactiveClients()) )
+                       MT_sleep_ms(1000);
+               delay --;
+       } while (delay > 0 && leftover > 1);
+       if( delay == 0 && leftover > 1)
+               snprintf(buf, 1024,"%d client sessions still running",leftover);
+       *ret = GDKstrdup(buf);
+       if ( force)
+               mal_exit();
+       return MAL_SUCCEED;
 }
 
 str
@@ -592,7 +624,7 @@ CLTsessions(Client cntxt, MalBlkPtr mb, 
        
     MT_lock_set(&mal_contextLock, "clients.sessions");
        
-    for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) 
+    for (c = mal_clients + (GDKgetenv_isyes("monet_daemon")?1:0); c < 
mal_clients + MAL_MAXCLIENTS; c++) 
        if (c->mode == RUNCLIENT) {
                BUNappend(user, &usrname, FALSE);
                (void) MTIMEunix_epoch(&ts);
diff --git a/monetdb5/modules/mal/clients.h b/monetdb5/modules/mal/clients.h
--- a/monetdb5/modules/mal/clients.h
+++ b/monetdb5/modules/mal/clients.h
@@ -56,7 +56,7 @@ clients_export str CLTsetSessionTimeout(
 clients_export str CLTgetTimeout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 clients_export str CLTwakeup(int *ret, int *id);
 
-clients_export str CLTshutdown(int *ret, bit *forced);
+clients_export str CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 clients_export str CLTmd5sum(str *ret, str *pw);
 clients_export str CLTsha1sum(str *ret, str *pw);
 clients_export str CLTripemd160sum(str *ret, str *pw);
diff --git a/monetdb5/modules/mal/clients.mal b/monetdb5/modules/mal/clients.mal
--- a/monetdb5/modules/mal/clients.mal
+++ b/monetdb5/modules/mal/clients.mal
@@ -91,16 +91,17 @@ comment "A query is aborted after q mill
 The session timeout aborts the connection after spending too
 many seconds on query processing.";
 
-command shutdown(forced:bit):void
-address CLTshutdown
-comment "Close all client connections. If forced=false the
-clients are moved into finishing mode, which means that
-the process stops at the next cycle of the scenario.
-If forced=true all client processes are immediately killed";
-
 # @+ User administration
 # These commands (except changePassword, changeUsername and
 # checkPermission) can only be executed by the administrator.
+
+pattern shutdown(delay:int):str
+address CLTshutdown;
+pattern shutdown(delay:int, forced:bit):str
+address CLTshutdown
+comment "Close all other client connections. Return if it succeeds.
+If forced is set then always stop the system the hard way";
+
 command md5sum(pw:str):str
 address CLTmd5sum
 comment "Return hex string representation of the MD5 hash of the given string";
diff --git a/sql/backends/monet5/sql.mx b/sql/backends/monet5/sql.mx
--- a/sql/backends/monet5/sql.mx
+++ b/sql/backends/monet5/sql.mx
@@ -45,6 +45,20 @@ pattern init():void
 address SQLinitEnvironment
 comment "Initialize the environment for MAL";
 
+pattern shutdown(delay:bte, force:bit):str
+address SQLshutdown_wrap;
+pattern shutdown(delay:sht, force:bit):str
+address SQLshutdown_wrap;
+pattern shutdown(delay:int, force:bit):str
+address SQLshutdown_wrap;
+
+pattern shutdown(delay:bte):str
+address SQLshutdown_wrap;
+pattern shutdown(delay:sht):str
+address SQLshutdown_wrap;
+pattern shutdown(delay:int):str
+address SQLshutdown_wrap;
+
 pattern mvc():int
 address SQLmvc
 comment "get the multiversion catalog context, needed for correct statement 
dependencies (ie sql.update, should be after sql.bind in concurrent execution)";
@@ -1366,6 +1380,7 @@ sql5_export str SQLmvc(Client cntxt, Mal
 sql5_export str SQLtransaction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 sql5_export str SQLcommit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
 sql5_export str SQLabort(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
+sql5_export str SQLshutdown_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 sql5_export str SQLtransaction2(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 sql5_export str SQLcatalog(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
 
@@ -1973,6 +1988,18 @@ SQLabort(Client cntxt, MalBlkPtr mb, Mal
 }
 
 str
+SQLshutdown_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+       str answ = *(str*) getArgReference(stk,pci,0);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to