LCOV - code coverage report
Current view: top level - tools/mserver - shutdowntest.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 114 190 60.0 %
Date: 2024-12-20 20:06:10 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include <string.h> /* strerror */
      15             : #include <locale.h>
      16             : #include "monet_options.h"
      17             : #include "mal.h"
      18             : #include "mal_session.h"
      19             : #include "mal_import.h"
      20             : #include "mal_client.h"
      21             : #include "mal_function.h"
      22             : #include "mal_authorize.h"
      23             : #include "msabaoth.h"
      24             : #include "mutils.h"
      25             : #include "mal_linker.h"
      26             : #include "sql_execute.h"
      27             : #include "sql_scenario.h"
      28             : 
      29             : static char* dbdir = NULL;
      30             : 
      31             : static int monetdb_initialized = 0;
      32             : 
      33          22 : static void* monetdb_connect(void) {
      34          22 :         Client conn = NULL;
      35          22 :         if (!monetdb_initialized) {
      36             :                 return NULL;
      37             :         }
      38          22 :         conn = MCinitClient(MAL_ADMIN, bstream_create(GDKstdin, 0), GDKstdout);
      39          22 :         if (!MCvalid(conn)) {
      40             :                 return NULL;
      41             :         }
      42          22 :         conn->curmodule = conn->usermodule = userModule();
      43          22 :         str msg;
      44          22 :         if ((msg = SQLinitClient(conn, NULL, NULL, NULL)) != MAL_SUCCEED) {
      45           0 :                 freeException(msg);
      46           0 :                 return NULL;
      47             :         }
      48          22 :         ((backend *) conn->sqlcontext)->mvc->session->auto_commit = 1;
      49          22 :         return conn;
      50             : }
      51             : 
      52          53 : static str monetdb_query(Client c, str query) {
      53          53 :         str retval;
      54          53 :         mvc* m = ((backend *) c->sqlcontext)->mvc;
      55          53 :         res_table* res = NULL;
      56             : 
      57          53 :         retval = SQLstatementIntern(c, query, "name", 1, 0, &res);
      58          53 :         if (retval == MAL_SUCCEED)
      59          53 :                 retval = SQLautocommit(m);
      60          53 :         if (retval != MAL_SUCCEED) {
      61           0 :                 printf("Failed to execute SQL query: %s\n", query);
      62           0 :                 freeException(retval);
      63           0 :                 exit(1);
      64             :                 return MAL_SUCCEED;
      65             :         }
      66          53 :         if (res) {
      67             :                 // print result columns
      68             : //              printf("%s (", res->cols->tn);
      69             : //              for(int i = 0; i < res->nr_cols; i++) {
      70             : //                      printf("%s", res->cols[i].name);
      71             : //                      printf(i + 1 == res->nr_cols ? ")\n" : ",");
      72             : //              }
      73          21 :                 SQLdestroyResult(res);
      74             :         }
      75          53 :         return MAL_SUCCEED;
      76             : }
      77             : 
      78          22 : static void monetdb_disconnect(void* conn) {
      79          22 :         if (!MCvalid((Client) conn)) {
      80             :                 return;
      81             :         }
      82          22 :         str msg = SQLexitClient((Client) conn);
      83          22 :         freeException(msg);
      84          22 :         MCcloseClient((Client) conn);
      85             : }
      86             : 
      87          11 : static str monetdb_initialize(void) {
      88          11 :         opt *set = NULL;
      89          11 :         volatile int setlen = 0; /* use volatile for setjmp */
      90          11 :         str retval = MAL_SUCCEED;
      91          11 :         char *err;
      92          11 :         char prmodpath[FILENAME_MAX];
      93          11 :         const char *modpath = NULL;
      94          11 :         char *binpath = NULL;
      95             : 
      96          11 :         if (monetdb_initialized) return MAL_SUCCEED;
      97          11 :         monetdb_initialized = 1;
      98             : 
      99          11 :         if (setlocale(LC_CTYPE, "") == NULL) {
     100           0 :                 retval = GDKstrdup("setlocale() failed");
     101           0 :                 goto cleanup;
     102             :         }
     103             : 
     104          11 :         GDKfataljumpenable = 1;
     105          11 :         if(setjmp(GDKfataljump) != 0) {
     106           0 :                 retval = GDKfatalmsg;
     107             :                 // we will get here if GDKfatal was called.
     108           0 :                 if (retval == NULL) {
     109           0 :                         retval = GDKstrdup("GDKfatal() with unspecified error?");
     110             :                 }
     111           0 :                 goto cleanup;
     112             :         }
     113             : 
     114          11 :         binpath = get_bin_path();
     115             : 
     116          11 :         setlen = mo_builtin_settings(&set);
     117          11 :         setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbpath", dbdir);
     118             : 
     119          11 :         if (BBPaddfarm(dbdir, (1U << PERSISTENT) | (1U << TRANSIENT), false) != GDK_SUCCEED) {
     120           0 :                 retval = GDKstrdup("BBPaddfarm failed");
     121           0 :                 goto cleanup;
     122             :         }
     123          11 :         if (GDKinit(set, setlen, true, NULL) != GDK_SUCCEED) {
     124           0 :                 retval = GDKstrdup("GDKinit() failed");
     125           0 :                 goto cleanup;
     126             :         }
     127          11 :         ATOMIC_OR(&GDKdebug, NOSYNCMASK);
     128             : 
     129          11 :         if (GDKsetenv("mapi_disable", "true") != GDK_SUCCEED) {
     130           0 :                 retval = GDKstrdup("GDKsetenv failed");
     131           0 :                 goto cleanup;
     132             :         }
     133             : 
     134          11 :         if ((modpath = GDKgetenv("monet_mod_path")) == NULL) {
     135             :                 /* start probing based on some heuristics given the binary
     136             :                  * location:
     137             :                  * bin/mserver5 -> ../
     138             :                  * libX/monetdb5/lib/
     139             :                  * probe libX = lib, lib32, lib64, lib/64 */
     140          11 :                 const char *libdirs[] = { "lib", "lib64", "lib/64", "lib32", NULL };
     141          11 :                 size_t i;
     142          11 :                 struct stat sb;
     143          11 :                 if (binpath != NULL) {
     144          11 :                         char *p = strrchr(binpath, DIR_SEP);
     145          11 :                         if (p != NULL)
     146          11 :                                 *p = '\0';
     147          11 :                         p = strrchr(binpath, DIR_SEP);
     148          11 :                         if (p != NULL) {
     149          11 :                                 *p = '\0';
     150          55 :                                 for (i = 0; libdirs[i] != NULL; i++) {
     151          44 :                                         int len = snprintf(prmodpath, sizeof(prmodpath), "%s%c%s%cmonetdb5",
     152             :                                                         binpath, DIR_SEP, libdirs[i], DIR_SEP);
     153          44 :                                         if (len == -1 || len >= FILENAME_MAX)
     154           0 :                                                 continue;
     155          44 :                                         if (MT_stat(prmodpath, &sb) == 0) {
     156             :                                                 modpath = prmodpath;
     157             :                                                 break;
     158             :                                         }
     159             :                                 }
     160             :                         } else {
     161           0 :                                 printf("#warning: unusable binary location, "
     162             :                                            "please use --set monet_mod_path=/path/to/... to "
     163             :                                            "allow finding modules\n");
     164           0 :                                 fflush(NULL);
     165             :                         }
     166             :                 } else {
     167           0 :                         printf("#warning: unable to determine binary location, "
     168             :                                    "please use --set monet_mod_path=/path/to/... to "
     169             :                                    "allow finding modules\n");
     170           0 :                         fflush(NULL);
     171             :                 }
     172          11 :                 if (modpath != NULL &&
     173           0 :                     GDKsetenv("monet_mod_path", modpath) != GDK_SUCCEED) {
     174           0 :                         retval = GDKstrdup("GDKsetenv failed");
     175           0 :                         goto cleanup;
     176             :                 }
     177             :         }
     178             : 
     179             :         /* configure sabaoth to use the right dbpath and active database */
     180          11 :         msab_dbpathinit(GDKgetenv("gdk_dbpath"));
     181             :         /* wipe out all cruft, if left over */
     182          11 :         if ((retval = msab_wildRetreat()) != NULL) {
     183             :                 /* just swallow the error */
     184           0 :                 free(retval);
     185             :         }
     186             :         /* From this point, the server should exit cleanly.  Discussion:
     187             :          * even earlier?  Sabaoth here registers the server is starting up. */
     188          11 :         if ((retval = msab_registerStarting()) != NULL) {
     189             :                 /* throw the error at the user, but don't die */
     190           0 :                 fprintf(stderr, "!%s\n", retval);
     191           0 :                 free(retval);
     192             :         }
     193             : 
     194             :         {
     195          11 :                 str lang = "mal";
     196             :                 /* we inited mal before, so publish its existence */
     197          11 :                 if ((retval = msab_marchScenario(lang)) != NULL) {
     198             :                         /* throw the error at the user, but don't die */
     199           0 :                         fprintf(stderr, "!%s\n", retval);
     200           0 :                         free(retval);
     201             :                 }
     202             :         }
     203             : 
     204             :         {
     205             :                 /* unlock the vault, first see if we can find the file which
     206             :                  * holds the secret */
     207          11 :                 char secret[1024];
     208          11 :                 FILE *secretf;
     209          11 :                 size_t len;
     210             : 
     211          11 :                 if (GDKgetenv("monet_vault_key") == NULL) {
     212             :                         /* use a default (hard coded, non safe) key */
     213          11 :                         snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8");
     214             :                 } else {
     215           0 :                         if ((secretf = fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) {
     216           0 :                                 fprintf(stderr,
     217             :                                         "unable to open vault_key_file %s: %s\n",
     218           0 :                                         GDKgetenv("monet_vault_key"), strerror(errno));
     219             :                                 /* don't show this as a crash */
     220           0 :                                 err = msab_registerStop();
     221           0 :                                 if (err)
     222           0 :                                         free(err);
     223           0 :                                 exit(1);
     224             :                         }
     225           0 :                         len = fread(secret, 1, sizeof(secret), secretf);
     226           0 :                         secret[len] = '\0';
     227           0 :                         len = strlen(secret); /* secret can contain null-bytes */
     228           0 :                         if (len == 0) {
     229           0 :                                 fprintf(stderr, "vault key has zero-length!\n");
     230             :                                 /* don't show this as a crash */
     231           0 :                                 err = msab_registerStop();
     232           0 :                                 if (err)
     233           0 :                                         free(err);
     234           0 :                                 exit(1);
     235           0 :                         } else if (len < 5) {
     236           0 :                                 fprintf(stderr, "#warning: your vault key is too short "
     237             :                                                                 "(%zu), enlarge your vault key!\n", len);
     238             :                         }
     239           0 :                         fclose(secretf);
     240             :                 }
     241          11 :                 if ((retval = AUTHunlockVault(secret)) != MAL_SUCCEED) {
     242             :                         /* don't show this as a crash */
     243           0 :                         err = msab_registerStop();
     244           0 :                         if (err)
     245           0 :                                 free(err);
     246           0 :                         fprintf(stderr, "%s\n", retval);
     247           0 :                         exit(1);
     248             :                 }
     249             :         }
     250             : 
     251          11 :         char *modules[2];
     252          11 :         modules[0] = "sql";
     253          11 :         modules[1] = 0;
     254          11 :         if (mal_init(modules, true, NULL, NULL) != 0) { // mal_init() does not return meaningful codes on failure
     255           0 :                 retval = GDKstrdup("mal_init() failed");
     256           0 :                 goto cleanup;
     257             :         }
     258          11 :         GDKfataljumpenable = 0;
     259             : 
     260          11 :         if (retval != MAL_SUCCEED) {
     261             :                 printf("Failed to load SQL function: %s\n", retval);
     262             :                 retval = GDKstrdup(retval);
     263             :                 goto cleanup;
     264             :         }
     265             : 
     266             :         {
     267          11 :                 Client c = (Client) monetdb_connect();
     268          11 :                 if (!c) {
     269           0 :                         printf("Failed to initialize client\n");
     270           0 :                         retval = GDKstrdup("Failed to initialize client\n");
     271           0 :                         goto cleanup;
     272             :                 }
     273          11 :                 char* query = "SELECT * FROM tables;";
     274          11 :                 retval = monetdb_query(c, query);
     275          11 :                 monetdb_disconnect(c);
     276             :         }
     277             : 
     278          11 :         mo_free_options(set, setlen);
     279             : 
     280             :         return MAL_SUCCEED;
     281           0 : cleanup:
     282           0 :         if (set)
     283           0 :                 mo_free_options(set, setlen);
     284           0 :         monetdb_initialized = 0;
     285           0 :         return retval;
     286             : }
     287             : 
     288          10 : static void monetdb_shutdown(void) {
     289          10 :         if (monetdb_initialized) {
     290          10 :                 mal_reset();
     291          10 :                 monetdb_initialized = 0;
     292             :         }
     293          10 : }
     294             : 
     295           1 : int main(int argc, char **argv) {
     296           1 :         str retval;
     297           1 :         Client c;
     298           1 :         int i = 0;
     299           1 :         if (argc <= 1) {
     300           0 :                 printf("Usage: shutdowntest [testdir]\n");
     301           0 :                 return -1;
     302             :         }
     303           1 :         dbdir = argv[1];
     304             : 
     305           1 :         retval = monetdb_initialize();
     306           1 :         if (retval != MAL_SUCCEED) {
     307           0 :                 printf("Failed first initialization: %s\n", retval);
     308           0 :                 return -1;
     309             :         }
     310           1 :         c = (Client) monetdb_connect();
     311           1 :         if (!c) {
     312           0 :                 printf("Failed to initialize client\n");
     313           0 :                 monetdb_shutdown();
     314           0 :                 return -1;
     315             :         }
     316           1 :         monetdb_query(c, "CREATE TABLE temporary_table(i INTEGER);");
     317           1 :         monetdb_query(c, "INSERT INTO temporary_table VALUES (3), (4);");
     318           1 :         monetdb_disconnect(c);
     319             : //      printf("Successfully initialized MonetDB.\n");
     320          12 :         for(i = 0; i < 10; i++) {
     321          10 :                 monetdb_shutdown();
     322             : //              printf("Successfully shutdown MonetDB.\n");
     323          10 :                 retval = monetdb_initialize();
     324          10 :                 if (retval != MAL_SUCCEED) {
     325           0 :                         printf("Failed MonetDB restart: %s\n", retval);
     326           0 :                         return -1;
     327             :                 }
     328             : //              printf("Successfully restarted MonetDB.\n");
     329          10 :                 c = (Client) monetdb_connect();
     330          10 :                 if (!c) {
     331           0 :                         printf("Failed to initialize client\n");
     332           0 :                         monetdb_shutdown();
     333           0 :                         return -1;
     334             :                 }
     335          10 :                 monetdb_query(c, "SELECT * FROM temporary_table;");
     336          10 :                 monetdb_query(c, "DROP TABLE temporary_table;");
     337          10 :                 monetdb_query(c, "CREATE TABLE temporary_table(i INTEGER);");
     338          10 :                 monetdb_query(c, "INSERT INTO temporary_table VALUES (3), (4);");
     339          10 :                 monetdb_disconnect(c);
     340             :         }
     341             :         return 0;
     342             : }

Generated by: LCOV version 1.14