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 : /*
14 : * (author) M.L. Kersten
15 : * These routines assume that the signatures for all MAL files are defined as text in mal_embedded.h
16 : * They are parsed upon system restart without access to their source files.
17 : * This way the definitions are part of the library upon compilation.
18 : * It assumes that all necessary libraries are already loaded.
19 : * A failure to bind the address in the context of an embedded version is not considered an error.
20 : */
21 :
22 : #include "monetdb_config.h"
23 :
24 : #include "mal_embedded.h"
25 : #include "mal_builder.h"
26 : #include "mal_stack.h"
27 : #include "mal_linker.h"
28 : #include "mal_session.h"
29 : #include "mal_scenario.h"
30 : #include "mal_parser.h"
31 : #include "mal_interpreter.h"
32 : #include "mal_namespace.h" /* for initNamespace() */
33 : #include "mal_client.h"
34 : #include "mal_dataflow.h"
35 : #include "mal_private.h"
36 : #include "mal_internal.h"
37 : #include "mal_runtime.h"
38 : #include "mal_atom.h"
39 : #include "mal_resource.h"
40 : #include "mal_atom.h"
41 : #include "msabaoth.h"
42 : #include "mal_authorize.h"
43 : #include "mal_profiler.h"
44 : #include "mutils.h"
45 :
46 : static bool embeddedinitialized = false;
47 :
48 : str
49 1 : malEmbeddedBoot(int workerlimit, int memorylimit, int querytimeout,
50 : int sessiontimeout, bool with_mapi_server)
51 : {
52 1 : Client c;
53 1 : QryCtx *qc_old;
54 1 : str msg = MAL_SUCCEED;
55 :
56 1 : if (embeddedinitialized)
57 : return MAL_SUCCEED;
58 :
59 : {
60 : /* unlock the vault, first see if we can find the file which
61 : * holds the secret */
62 1 : char secret[1024];
63 1 : FILE *secretf;
64 1 : size_t len;
65 :
66 1 : if (GDKinmemory(0) || GDKgetenv("monet_vault_key") == NULL) {
67 : /* use a default (hard coded, non safe) key */
68 1 : snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8");
69 : } else {
70 0 : if ((secretf = MT_fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) {
71 0 : throw(MAL, "malEmbeddedBoot",
72 : "unable to open vault_key_file %s: %s\n",
73 0 : GDKgetenv("monet_vault_key"), strerror(errno));
74 : }
75 0 : len = fread(secret, 1, sizeof(secret) - 1, secretf);
76 0 : fclose(secretf);
77 0 : secret[len] = '\0';
78 0 : len = strlen(secret); /* secret can contain null-bytes */
79 0 : if (len == 0) {
80 0 : throw(MAL, "malEmbeddedBoot", "vault key has zero-length!\n");
81 0 : } else if (len < 5) {
82 0 : throw(MAL, "malEmbeddedBoot",
83 : "#warning: your vault key is too short "
84 : "(%zu), enlarge your vault key!\n", len);
85 : }
86 : }
87 1 : if ((msg = AUTHunlockVault(secret)) != MAL_SUCCEED) {
88 : /* don't show this as a crash */
89 : return msg;
90 : }
91 : }
92 :
93 1 : if (!MCinit())
94 0 : throw(MAL, "malEmbeddedBoot", "Failed to initialize clients structure");
95 : // monet_memory = MT_npages() * MT_pagesize();
96 1 : initNamespace();
97 1 : initHeartbeat();
98 : // initResource();
99 1 : qc_old = MT_thread_get_qry_ctx();
100 1 : c = MCinitClient((oid) 0, 0, 0);
101 1 : if (c == NULL)
102 0 : throw(MAL, "malEmbeddedBoot", "Failed to initialize client");
103 1 : c->workerlimit = workerlimit;
104 1 : c->memorylimit = memorylimit;
105 1 : c->qryctx.querytimeout = querytimeout * 1000000; // from sec to usec
106 1 : c->sessiontimeout = sessiontimeout * 1000000;
107 1 : c->curmodule = c->usermodule = userModule();
108 1 : if (c->usermodule == NULL) {
109 0 : MCcloseClient(c);
110 0 : MT_thread_set_qry_ctx(qc_old);
111 0 : throw(MAL, "malEmbeddedBoot", "Failed to initialize client MAL module");
112 : }
113 1 : if ((msg = defaultScenario(c))) {
114 0 : MCcloseClient(c);
115 0 : MT_thread_set_qry_ctx(qc_old);
116 0 : return msg;
117 : }
118 1 : if ((msg = MSinitClientPrg(c, "user", "main")) != MAL_SUCCEED) {
119 0 : MCcloseClient(c);
120 0 : MT_thread_set_qry_ctx(qc_old);
121 0 : return msg;
122 : }
123 1 : char *modules[6] = { "embedded", "sql", "generator", "udf", "csv" };
124 1 : if ((msg = malIncludeModules(c, modules, 0, !with_mapi_server, NULL)) != MAL_SUCCEED) {
125 0 : MCcloseClient(c);
126 0 : MT_thread_set_qry_ctx(qc_old);
127 0 : return msg;
128 : }
129 1 : pushEndInstruction(c->curprg->def);
130 : #if 0
131 : msg = chkProgram(c->usermodule, c->curprg->def);
132 : if (msg != MAL_SUCCEED || (msg = c->curprg->def->errors) != MAL_SUCCEED) {
133 : MCcloseClient(c);
134 : MT_thread_set_qry_ctx(qc_old);
135 : return msg;
136 : }
137 : msg = MALengine(c);
138 : #endif
139 1 : if (msg == MAL_SUCCEED)
140 1 : embeddedinitialized = true;
141 1 : MCcloseClient(c);
142 1 : MT_thread_set_qry_ctx(qc_old);
143 1 : initProfiler();
144 1 : return msg;
145 : }
146 :
147 : /*
148 : * Upon exit we should attempt to remove all allocated memory explicitly.
149 : * This seemingly superflous action is necessary to simplify analyis of
150 : * memory leakage problems later ons and to allow an embedded server to
151 : * restart the server properly.
152 : *
153 : * It is the responsibility of the enclosing application to finish/cease all
154 : * activity first.
155 : * This function should be called after you have issued sql_reset();
156 : */
157 :
158 : void
159 1 : malEmbeddedReset(void) //remove extra modules and set to non-initialized again
160 : {
161 1 : if (!embeddedinitialized)
162 : return;
163 :
164 1 : GDKprepareExit();
165 1 : MCstopClients(0);
166 1 : setHeartbeat(-1);
167 1 : stopProfiler(0);
168 1 : AUTHreset();
169 1 : if (!GDKinmemory(0) && !GDKembedded()) {
170 0 : str err = 0;
171 :
172 0 : if ((err = msab_wildRetreat()) !=NULL) {
173 0 : TRC_ERROR(MAL_SERVER, "%s\n", err);
174 0 : free(err);
175 : }
176 0 : if ((err = msab_registerStop()) !=NULL) {
177 0 : TRC_ERROR(MAL_SERVER, "%s\n", err);
178 0 : free(err);
179 : }
180 : }
181 1 : mal_dataflow_reset();
182 1 : mal_client_reset();
183 1 : mal_linker_reset();
184 1 : mal_resource_reset();
185 1 : mal_runtime_reset();
186 1 : mal_module_reset();
187 1 : mal_atom_reset();
188 :
189 1 : memset((char *) monet_cwd, 0, sizeof(monet_cwd));
190 1 : memset((char *) monet_characteristics, 0, sizeof(monet_characteristics));
191 1 : mal_namespace_reset();
192 : /* No need to clean up the namespace, it will simply be extended
193 : * upon restart mal_namespace_reset(); */
194 1 : GDKreset(0); // terminate all other threads
195 1 : embeddedinitialized = false;
196 : }
197 :
198 : /* stopping clients should be done with care, as they may be in the mids of
199 : * transactions. One safe place is between MAL instructions, which would
200 : * abort the transaction by raising an exception. All sessions are
201 : * terminate this way.
202 : * We should also ensure that no new client enters the scene while shutting down.
203 : * For this we mark the client records as BLOCKCLIENT.
204 : */
205 :
206 : void
207 0 : malEmbeddedStop(int status)
208 : {
209 0 : malEmbeddedReset();
210 0 : exit(status); /* properly end GDK */
211 : }
|