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 1 : mal_startup();
60 : {
61 : /* unlock the vault, first see if we can find the file which
62 : * holds the secret */
63 1 : char secret[1024];
64 1 : FILE *secretf;
65 1 : size_t len;
66 :
67 1 : if (GDKinmemory(0) || GDKgetenv("monet_vault_key") == NULL) {
68 : /* use a default (hard coded, non safe) key */
69 1 : snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8");
70 : } else {
71 0 : if ((secretf = MT_fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) {
72 0 : throw(MAL, "malEmbeddedBoot",
73 : "unable to open vault_key_file %s: %s\n",
74 0 : GDKgetenv("monet_vault_key"), strerror(errno));
75 : }
76 0 : len = fread(secret, 1, sizeof(secret) - 1, secretf);
77 0 : fclose(secretf);
78 0 : secret[len] = '\0';
79 0 : len = strlen(secret); /* secret can contain null-bytes */
80 0 : if (len == 0) {
81 0 : throw(MAL, "malEmbeddedBoot", "vault key has zero-length!\n");
82 0 : } else if (len < 5) {
83 0 : throw(MAL, "malEmbeddedBoot",
84 : "#warning: your vault key is too short "
85 : "(%zu), enlarge your vault key!\n", len);
86 : }
87 : }
88 1 : if ((msg = AUTHunlockVault(secret)) != MAL_SUCCEED) {
89 : /* don't show this as a crash */
90 : return msg;
91 : }
92 : }
93 :
94 1 : if (!MCinit())
95 0 : throw(MAL, "malEmbeddedBoot", "Failed to initialize clients structure");
96 : // monet_memory = MT_npages() * MT_pagesize();
97 1 : initNamespace();
98 1 : initHeartbeat();
99 : // initResource();
100 1 : qc_old = MT_thread_get_qry_ctx();
101 1 : c = MCinitClient((oid) 0, 0, 0);
102 1 : if (c == NULL)
103 0 : throw(MAL, "malEmbeddedBoot", "Failed to initialize client");
104 1 : c->workerlimit = workerlimit;
105 1 : c->memorylimit = memorylimit;
106 1 : c->querytimeout = querytimeout * 1000000; // from sec to usec
107 1 : c->qryctx.endtime = c->qryctx.starttime && c->querytimeout ? c->qryctx.starttime + c->querytimeout : 0;
108 1 : c->sessiontimeout = sessiontimeout * 1000000;
109 1 : c->curmodule = c->usermodule = userModule();
110 1 : if (c->usermodule == NULL) {
111 0 : MCcloseClient(c);
112 0 : MT_thread_set_qry_ctx(qc_old);
113 0 : throw(MAL, "malEmbeddedBoot", "Failed to initialize client MAL module");
114 : }
115 1 : if ((msg = defaultScenario(c))) {
116 0 : MCcloseClient(c);
117 0 : MT_thread_set_qry_ctx(qc_old);
118 0 : return msg;
119 : }
120 1 : if ((msg = MSinitClientPrg(c, userRef, mainRef)) != MAL_SUCCEED) {
121 0 : MCcloseClient(c);
122 0 : MT_thread_set_qry_ctx(qc_old);
123 0 : return msg;
124 : }
125 1 : char *modules[6] = { "embedded", "sql", "generator", "udf", "csv" };
126 1 : if ((msg = malIncludeModules(c, modules, 0, !with_mapi_server, NULL)) != MAL_SUCCEED) {
127 0 : MCcloseClient(c);
128 0 : MT_thread_set_qry_ctx(qc_old);
129 0 : return msg;
130 : }
131 1 : pushEndInstruction(c->curprg->def);
132 : #if 0
133 : msg = chkProgram(c->usermodule, c->curprg->def);
134 : if (msg != MAL_SUCCEED || (msg = c->curprg->def->errors) != MAL_SUCCEED) {
135 : MCcloseClient(c);
136 : MT_thread_set_qry_ctx(qc_old);
137 : return msg;
138 : }
139 : msg = MALengine(c);
140 : #endif
141 1 : if (msg == MAL_SUCCEED)
142 1 : embeddedinitialized = true;
143 1 : MCcloseClient(c);
144 1 : MT_thread_set_qry_ctx(qc_old);
145 1 : initProfiler();
146 1 : return msg;
147 : }
148 :
149 : /*
150 : * Upon exit we should attempt to remove all allocated memory explicitly.
151 : * This seemingly superfluous action is necessary to simplify analysis of
152 : * memory leakage problems later on and to allow an embedded server to
153 : * restart the server properly.
154 : *
155 : * It is the responsibility of the enclosing application to finish/cease all
156 : * activity first.
157 : * This function should be called after you have issued sql_reset();
158 : */
159 :
160 : void
161 1 : malEmbeddedReset(void) //remove extra modules and set to non-initialized again
162 : {
163 1 : if (!embeddedinitialized)
164 : return;
165 :
166 1 : GDKprepareExit();
167 1 : MCstopClients(0);
168 1 : setHeartbeat(-1);
169 1 : stopProfiler(0);
170 1 : AUTHreset();
171 1 : if (!GDKinmemory(0) && !GDKembedded()) {
172 0 : str err = 0;
173 :
174 0 : if ((err = msab_wildRetreat()) !=NULL) {
175 0 : TRC_ERROR(MAL_SERVER, "%s\n", err);
176 0 : free(err);
177 : }
178 0 : if ((err = msab_registerStop()) !=NULL) {
179 0 : TRC_ERROR(MAL_SERVER, "%s\n", err);
180 0 : free(err);
181 : }
182 : }
183 1 : mal_dataflow_reset();
184 1 : mal_client_reset();
185 1 : mal_linker_reset();
186 1 : mal_resource_reset();
187 1 : mal_runtime_reset();
188 1 : mal_module_reset();
189 1 : mal_atom_reset();
190 :
191 1 : memset((char *) monet_cwd, 0, sizeof(monet_cwd));
192 1 : memset((char *) monet_characteristics, 0, sizeof(monet_characteristics));
193 1 : 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 : }
|