~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
 *
3
 * PrimeBase Media Stream for MySQL
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 *
19
 * Original author: Paul McCullagh (H&G2JCtL)
20
 * Continued development: Barry Leslie
21
 *
22
 * 2007-05-20
23
 *
24
 * The main exception classes
25
 *
26
 */
27
28
#include "CSConfig.h"
29
30
#include <sys/signal.h>
31
#include <limits.h>
32
#include <string.h>
33
34
#include "CSGlobal.h"
35
#include "CSException.h"
36
#include "CSStrUtil.h"
37
#include "CSLog.h"
38
39
void CSException::setStackTrace(CSThread *self, const char *stack)
40
{
41
	char buffer[CS_EXC_CONTEXT_SIZE];
42
43
	self->myException.iStackTrace.setLength(0);
44
	if (stack)
45
		self->myException.iStackTrace.append(stack);
46
	for (int i=self->callTop-1; i>=0; i--) {
47
		cs_format_context(CS_EXC_CONTEXT_SIZE, buffer,
48
			self->callStack[i].cs_func, self->callStack[i].cs_file, self->callStack[i].cs_line);
49
		self->myException.iStackTrace.append(buffer);
50
		self->myException.iStackTrace.append('\n');
51
	}
52
}
53
54
void CSException::setStackTrace(CSThread *self)
55
{
56
	setStackTrace(self, NULL);
57
}
58
59
const char *CSException::getStackTrace()
60
{
61
	return iStackTrace.getCString();
62
}
63
64
void CSException::log(CSThread *self)
65
{
66
	CSL.lock();
67
	CSL.log(self, CSLog::Error, getContext());
68
	CSL.log(self, CSLog::Error, " ");
69
	CSL.log(self, CSLog::Error, getMessage());
70
	CSL.eol(self, CSLog::Error);
71
	CSL.log(self, CSLog::Error, getStackTrace());
72
	CSL.unlock();
73
}
74
75
void CSException::log(CSThread *self, const char *message)
76
{
77
	CSL.lock();
78
	CSL.log(self, CSLog::Error, message);
79
	CSL.eol(self, CSLog::Error);
80
	CSL.log(self, CSLog::Error, getContext());
81
	CSL.log(self, CSLog::Error, " ");
82
	CSL.log(self, CSLog::Error, getMessage());
83
	CSL.eol(self, CSLog::Error);
84
	CSL.log(self, CSLog::Error, getStackTrace());
85
	CSL.unlock();
86
}
87
88
void CSException::initException(const char *func, const char *file, int line, int err, const char *message)
89
{
90
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
91
	iErrorCode = err;
92
	cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, message);
93
}
94
1548.2.11 by Barry.Leslie at PrimeBase
Removed libxml reqirement by using a home grown xml parser.
95
void CSException::initException(CSException &exception)
96
{
97
	iErrorCode = exception.iErrorCode;
98
	strcpy(iContext, exception.iContext);
99
	strcpy(iMessage, exception.iMessage);
100
	
101
	iStackTrace.setLength(0);
102
	iStackTrace.append(exception.iStackTrace.getCString());
103
104
}
105
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
106
void CSException::initAssertion(const char *func, const char *file, int line, const char *message)
107
{
108
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
109
	iErrorCode = CS_ERR_ASSERTION;
110
	cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, message);
111
}
112
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
113
void CSException::getCoreError(uint32_t size, char *buffer, int err)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
114
{
115
	const char *message = NULL;
116
117
	switch (err) {
118
		case CS_ERR_JUMP_OVERFLOW: message = "Jump stack overflow"; break;
119
		case CS_ERR_BAD_ADDRESS: message = "Incorrect network address: %"; break;
120
		case CS_ERR_UNKNOWN_SERVICE: message = "Unknown network service: %"; break;
121
		case CS_ERR_UNKNOWN_HOST:  message = "Unknown host: %"; break;
122
		case CS_ERR_UNKNOWN_METHOD: message = "Unknown HTTP method: %"; break;
123
		case CS_ERR_NO_LISTENER: message = "Listening port has been closed"; break;
124
		case CS_ERR_RELEASE_OVERFLOW: message = "Release stack overflow"; break;
125
		case CS_ERR_IMPL_MISSING: message = "Function %s not implemented"; break;
126
		case CS_ERR_BAD_HEADER_MAGIC: message = "Incorrect file type"; break;
127
		case CS_ERR_VERSION_TOO_NEW: message = "Incompatible file version"; break;
128
	}
129
	if (message)
130
		cs_strcpy(size, buffer, message);
131
	else {
132
		cs_strcpy(size, buffer, "Unknown system error ");
133
		cs_strcat(size, buffer, err);
134
	}
135
}
136
137
void CSException::initCoreError(const char *func, const char *file, int line, int err)
138
{
139
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
140
	iErrorCode = err;
141
	getCoreError(CS_EXC_MESSAGE_SIZE, iMessage, err);
142
}
143
144
void CSException::initCoreError(const char *func, const char *file, int line, int err, const char *item)
145
{
146
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
147
	iErrorCode = err;
148
	getCoreError(CS_EXC_MESSAGE_SIZE, iMessage, err);
149
	cs_replace_string(CS_EXC_MESSAGE_SIZE, iMessage, '%', item);
150
}
151
152
void CSException::initOSError(const char *func, const char *file, int line, int err)
153
{
154
	char *msg;
155
156
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
157
	iErrorCode = err;
158
159
#ifdef XT_WIN
160
	if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, iMessage, CS_EXC_MESSAGE_SIZE, NULL)) {
161
		char *ptr;
162
163
		ptr = &iMessage[strlen(iMessage)];
164
		while (ptr-1 > err_msg) {
165
			if (*(ptr-1) != '\n' && *(ptr-1) != '\r' && *(ptr-1) != '.')
166
				break;
167
			ptr--;
168
		}
169
		*ptr = 0;
170
171
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, " (");
172
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, err);
173
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ")");
174
		return;
175
	}
176
#endif
177
178
	msg = strerror(err);
179
	if (msg) {
180
		cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, msg);
181
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, " (");
182
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, err);
183
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ")");
184
	}
185
	else {
186
		cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "Unknown OS error code ");
187
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, err);
188
	}
189
}
190
191
void CSException::initFileError(const char *func, const char *file, int line, const char *path, int err)
192
{
193
	initOSError(func, file, line, err);
194
	cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ": '");
195
	cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, path);
196
	cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, "'");
197
}
198
199
void CSException::initSignal(const char *func, const char *file, int line, int sig)
200
{
201
	char *str;
202
203
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
204
	iErrorCode = sig;
205
	if (!(str = strsignal(sig))) {
206
		cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "Unknown signal ");
207
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, sig);
208
	}
209
	else {
210
		cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, str);
211
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, " (");
212
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, sig);
213
		cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ")");
214
	}
215
}
216
217
void CSException::initEOFError(const char *func, const char *file, int line, const char *path)
218
{
219
	cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
220
	iErrorCode = CS_ERR_EOF;
221
	cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "EOF encountered: '");
222
	cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, path);
223
	cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, "'");
224
}
225
226
void CSException::RecordException(const char *func, const char *file, int line, int err, const char *message)
227
{
228
	CSThread *self;
229
230
	if ((self = CSThread::getSelf())) {
231
		if (!self->myException.getErrorCode())
232
			self->myException.initException(func, file, line, err, message);
233
	}
234
}
235
236
void CSException::ClearException()
237
{
238
	CSThread *self;
239
240
	if ((self = CSThread::getSelf())) {
241
		self->myException.setErrorCode(0);
242
	}
243
}
244
245
void CSException::throwException(const char *func, const char *file, int line, int err, const char *message, const char *stack)
246
{
247
	CSThread *self;
248
249
	if ((self = CSThread::getSelf())) {
250
		self->myException.initException(func, file, line, err, message);
251
		self->myException.setStackTrace(self, stack);
252
		self->throwException();
253
	}
254
	else {
255
		CSException e;
256
		
257
		e.initException(func, file, line, err,message);
258
		e.log(NULL, "*** Uncaught error");
259
	}
260
}
261
262
void CSException::throwException(const char *func, const char *file, int line, int err, const char *message)
263
{
264
	throwException(func, file, line, err, message, NULL);
265
}
266
267
void CSException::throwAssertion(const char *func, const char *file, int line, const char *message)
268
{
269
	CSThread *self;
270
271
	if ((self = CSThread::getSelf())) {
272
		self->myException.initAssertion(func, file, line, message);
273
		self->myException.setStackTrace(self);
274
		self->logException();
275
		self->throwException();
276
	}
277
	else {
278
		CSException e;
279
		
280
		e.initAssertion(func, file, line, message);
281
		e.log(NULL, "*** Uncaught error");
282
	}
283
}
284
285
void CSException::throwCoreError(const char *func, const char *file, int line, int err)
286
{
287
	CSThread *self;
288
289
	if ((self = CSThread::getSelf())) {
290
		self->myException.initCoreError(func, file, line, err);
291
		self->myException.setStackTrace(self);
292
		self->throwException();
293
	}
294
	else {
295
		CSException e;
296
		
297
		e.initCoreError(func, file, line, err);
298
		e.log(NULL, "*** Uncaught error");
299
	}
300
}
301
302
void CSException::throwCoreError(const char *func, const char *file, int line, int err, const char *item)
303
{
304
	CSThread *self;
305
306
	if ((self = CSThread::getSelf())) {
307
		self->myException.initCoreError(func, file, line, err, item);
308
		self->myException.setStackTrace(self);
309
		self->throwException();
310
	}
311
	else {
312
		CSException e;
313
		
314
		e.initCoreError(func, file, line, err, item);
315
		e.log(NULL, "*** Uncaught error");
316
	}
317
}
318
319
void CSException::throwOSError(const char *func, const char *file, int line, int err)
320
{
321
	CSThread *self;
322
323
	if ((self = CSThread::getSelf())) {
324
		/* A pending signal has priority over a system error,
325
		 * In fact, the pending signal may be the reason for
326
		 * system error:
327
		 */
328
		self->interrupted();
329
		self->myException.initOSError(func, file, line, err);
330
		self->myException.setStackTrace(self);
331
		self->throwException();
332
	}
333
	else {
334
		CSException e;
335
		
336
		e.initOSError(func, file, line, err);
337
		e.log(NULL, "*** Uncaught error");
338
	}
339
}
340
341
void CSException::throwFileError(const char *func, const char *file, int line, const char *path, int err)
342
{
343
	CSThread *self;
344
345
	if ((self = CSThread::getSelf())) {
346
		self->interrupted();
347
		self->myException.initFileError(func, file, line, path, err);
348
		self->myException.setStackTrace(self);
349
		self->throwException();
350
	}
351
	else {
352
		CSException e;
353
		
354
		e.initFileError(func, file, line, path, err);
355
		e.log(NULL, "*** Uncaught error");
356
	}
357
}
358
359
void CSException::throwFileError(const char *func, const char *file, int line, CSString *path, int err)
360
{
361
	CSThread *self;
362
363
	if ((self = CSThread::getSelf())) {
364
		self->interrupted();
365
		self->myException.initFileError(func, file, line, path->getCString(), err);
366
		self->myException.setStackTrace(self);
367
		self->throwException();
368
	}
369
	else {
370
		CSException e;
371
		
372
		e.initFileError(func, file, line, path->getCString(), err);
373
		e.log(NULL, "*** Uncaught error");
374
	}
375
}
376
377
void CSException::throwSignal(const char *func, const char *file, int line, int sig)
378
{
379
	CSThread *self;
380
381
	if ((self = CSThread::getSelf())) {
382
		self->myException.initSignal(func, file, line, sig);
383
		self->myException.setStackTrace(self);
384
		self->throwException();
385
	}
386
	else {
387
		CSException e;
388
		
389
		e.initSignal(func, file, line, sig);
390
		e.log(NULL, "*** Uncaught error");
391
	}
392
}
393
394
void CSException::throwEOFError(const char *func, const char *file, int line, const char *path)
395
{
396
	CSThread *self;
397
398
	if ((self = CSThread::getSelf())) {
399
		self->interrupted();
400
		self->myException.initEOFError(func, file, line, path);
401
		self->myException.setStackTrace(self);
402
		self->throwException();
403
	}
404
	else {
405
		CSException e;
406
		
407
		e.initEOFError(func, file, line, path);
408
		e.log(NULL, "*** Uncaught error");
409
	}
410
}
411
412
void CSException::throwLastError(const char *func, const char *file, int line)
413
{
414
#ifdef OS_WINDOWS
415
	throwOSError(func, file, line, (int) getLastError());
416
#else
417
	throwOSError(func, file, line, (int) errno);
418
#endif
419
}
420
421
void CSException::logOSError(const char *func, const char *file, int line, int err)
422
{
423
	CSThread *self;
424
425
	if ((self = CSThread::getSelf())) {
426
		self->myException.initOSError(func, file, line, err);
427
		self->myException.setStackTrace(self);
428
		self->logException();
429
	}
430
	else {
431
		CSException e;
432
		
433
		e.initOSError(func, file, line, err);
434
		e.log(NULL);
435
	}
436
}
437
438
void CSException::logOSError(CSThread *self, const char *func, const char *file, int line, int err)
439
{
440
	self->myException.initOSError(func, file, line, err);
441
	self->myException.setStackTrace(self);
442
	self->logException();
443
}
444
445
void CSException::logException(const char *func, const char *file, int line, int err, const char *message)
446
{
447
	CSThread *self;
448
449
	if ((self = CSThread::getSelf())) {
450
		self->myException.initException(func, file, line, err, message);
451
		self->logException();
452
	}
453
	else {
454
		CSException e;
455
		
456
		e.initException(func, file, line, err,message);
457
		e.log(NULL);
458
	}
459
}
460
461