rroonga 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -127,14 +127,18 @@ def extract_groonga_win32_binary(major, minor, micro)
127
127
  message(" done\n")
128
128
 
129
129
  if File.exist?(install_dir)
130
- message("remove old install... #{install_dir}")
130
+ message("removing old install... #{install_dir}")
131
131
  FileUtils.rm_rf(install_dir)
132
132
  message(" done\n")
133
133
  end
134
134
 
135
- message("install...")
135
+ message("installing...")
136
136
  FileUtils.mv(File.basename(zip, ".zip"), install_dir)
137
137
  message(" done\n")
138
+
139
+ message("removing binary archive...")
140
+ FileUtils.rm_rf(zip)
141
+ message(" done\n")
138
142
  end
139
143
 
140
144
  def configure_command_line(prefix)
@@ -143,6 +147,8 @@ def configure_command_line(prefix)
143
147
  debug_flags = ["CFLAGS=-ggdb3 -O0", "CXXFLAGS=-ggdb3 -O0"]
144
148
  command_line.concat(debug_flags) if debug_build_p
145
149
  command_line << "--prefix=#{prefix}"
150
+ command_line << "--disable-static"
151
+ command_line << "--disable-document"
146
152
  escaped_command_line = command_line.collect do |command|
147
153
  Shellwords.escape(command)
148
154
  end
@@ -190,6 +196,14 @@ def build_groonga(major, minor, micro)
190
196
  exit(false)
191
197
  end
192
198
  end
199
+
200
+ message("removing source...")
201
+ FileUtils.rm_rf(groonga_source_dir)
202
+ message(" done\n")
203
+
204
+ message("removing source archive...")
205
+ FileUtils.rm_rf(tar_gz)
206
+ message(" done\n")
193
207
  end
194
208
 
195
209
  unless PKGConfig.have_package(package_name, major, minor, micro)
@@ -1,6 +1,6 @@
1
1
  /* -*- coding: utf-8; c-file-style: "ruby" -*- */
2
2
  /*
3
- Copyright (C) 2009-2011 Kouhei Sutou <kou@clear-code.com>
3
+ Copyright (C) 2009-2013 Kouhei Sutou <kou@clear-code.com>
4
4
 
5
5
  This library is free software; you can redistribute it and/or
6
6
  modify it under the terms of the GNU Lesser General Public
@@ -18,12 +18,6 @@
18
18
 
19
19
  #include "rb-grn.h"
20
20
 
21
- /* FIXME */
22
- void grn_log_reopen(grn_ctx *ctx);
23
- extern const char *grn_log_path;
24
- extern const char *grn_qlog_path;
25
-
26
-
27
21
  /*
28
22
  * Document-class: Groonga::Logger
29
23
  *
@@ -31,63 +25,20 @@ extern const char *grn_qlog_path;
31
25
  *
32
26
  */
33
27
 
34
- #define RVAL2GRNWRAPPER(object) (rb_grn_logger_info_wrapper_from_ruby_object(object))
35
- #define RVAL2GRNLOGLEVEL(object) (rb_grn_log_level_from_ruby_object(object))
36
- #define GRNLOGLEVEL2RVAL(level) (rb_grn_log_level_to_ruby_object(level))
28
+ #define GRNLOGLEVEL2RVAL(level) (rb_grn_log_level_to_ruby_object(level))
29
+ #define RVAL2GRNLOGLEVEL(rb_level) (rb_grn_log_level_from_ruby_object(rb_level))
37
30
 
38
31
  VALUE cGrnLogger;
32
+ VALUE mGrnLoggerFlags;
33
+ VALUE cGrnCallbackLogger;
39
34
 
40
- typedef struct _rb_grn_logger_info_wrapper
41
- {
42
- grn_logger_info *logger;
43
- VALUE handler;
44
- } rb_grn_logger_info_wrapper;
45
-
46
- static rb_grn_logger_info_wrapper *
47
- rb_grn_logger_info_wrapper_from_ruby_object (VALUE object)
48
- {
49
- rb_grn_logger_info_wrapper *wrapper;
50
-
51
- if (NIL_P(object))
52
- return NULL;
53
-
54
- if (!RVAL2CBOOL(rb_obj_is_kind_of(object, cGrnLogger))) {
55
- rb_raise(rb_eTypeError, "not a groonga logger");
56
- }
35
+ static ID id_new;
36
+ static ID id_parse;
37
+ static ID id_log;
38
+ static ID id_reopen;
39
+ static ID id_fin;
57
40
 
58
- Data_Get_Struct(object, rb_grn_logger_info_wrapper, wrapper);
59
- if (!wrapper)
60
- rb_raise(rb_eTypeError, "groonga logger is NULL");
61
-
62
- return wrapper;
63
- }
64
-
65
- grn_logger_info *
66
- rb_grn_logger_from_ruby_object (VALUE object)
67
- {
68
- rb_grn_logger_info_wrapper *wrapper;
69
-
70
- wrapper = RVAL2GRNWRAPPER(object);
71
- if (!wrapper)
72
- return NULL;
73
-
74
- return wrapper->logger;
75
- }
76
-
77
- static void
78
- rb_grn_logger_free (void *object)
79
- {
80
- rb_grn_logger_info_wrapper *wrapper = object;
81
-
82
- xfree(wrapper->logger);
83
- xfree(wrapper);
84
- }
85
-
86
- static VALUE
87
- rb_grn_logger_alloc (VALUE klass)
88
- {
89
- return Data_Wrap_Struct(klass, NULL, rb_grn_logger_free, NULL);
90
- }
41
+ static grn_logger rb_grn_logger;
91
42
 
92
43
  static grn_log_level
93
44
  rb_grn_log_level_from_ruby_object (VALUE rb_level)
@@ -172,80 +123,70 @@ rb_grn_log_level_to_ruby_object (grn_log_level level)
172
123
  }
173
124
 
174
125
  static void
175
- rb_grn_log (int level, const char *time, const char *title,
176
- const char *message, const char *location, void *func_arg)
126
+ rb_grn_logger_reset_with_error_check (VALUE klass, grn_ctx *context)
177
127
  {
178
- rb_grn_logger_info_wrapper *wrapper = func_arg;
128
+ VALUE current_logger;
179
129
 
180
- rb_funcall(wrapper->handler, rb_intern("call"), 5,
181
- GRNLOGLEVEL2RVAL(level),
182
- rb_str_new2(time),
183
- rb_str_new2(title),
184
- rb_str_new2(message),
185
- rb_str_new2(location));
130
+ current_logger = rb_cv_get(klass, "@@current_logger");
131
+ if (NIL_P(current_logger))
132
+ return;
133
+ rb_cv_set(klass, "@@current_logger", Qnil);
134
+
135
+ if (context) {
136
+ grn_logger_set(context, NULL);
137
+ rb_grn_context_check(context, current_logger);
138
+ } else {
139
+ grn_logger_set(NULL, NULL);
140
+ }
186
141
  }
187
142
 
188
143
  static void
189
- rb_grn_logger_set_handler (VALUE self, VALUE rb_handler)
144
+ rb_grn_logger_reset (VALUE klass)
190
145
  {
191
- rb_grn_logger_info_wrapper *wrapper;
192
- grn_logger_info *logger;
193
-
194
- wrapper = RVAL2GRNWRAPPER(self);
195
- wrapper->handler = rb_handler;
196
- rb_iv_set(self, "@handler", rb_handler);
197
-
198
- logger = wrapper->logger;
199
- if (NIL_P(rb_handler)) {
200
- logger->func = NULL;
201
- logger->func_arg = NULL;
202
- } else {
203
- logger->func = rb_grn_log;
204
- logger->func_arg = wrapper;
205
- }
146
+ rb_grn_logger_reset_with_error_check(klass, NULL);
206
147
  }
207
148
 
208
- static VALUE
209
- rb_grn_logger_initialize (int argc, VALUE *argv, VALUE self)
149
+ static void
150
+ rb_grn_logger_log (grn_ctx *ctx, grn_log_level level,
151
+ const char *timestamp, const char *title, const char *message,
152
+ const char *location, void *user_data)
210
153
  {
211
- rb_grn_logger_info_wrapper *wrapper;
212
- grn_logger_info *logger;
213
- grn_log_level level;
214
- int flags = 0;
215
- VALUE options, rb_level, rb_time, rb_title, rb_message, rb_location;
216
- VALUE rb_handler;
154
+ VALUE handler = (VALUE)user_data;
217
155
 
218
- rb_scan_args(argc, argv, "01&", &options, &rb_handler);
156
+ if (NIL_P(handler))
157
+ return;
219
158
 
220
- rb_grn_scan_options(options,
221
- "level", &rb_level,
222
- "time", &rb_time,
223
- "title", &rb_title,
224
- "message", &rb_message,
225
- "location", &rb_location,
226
- NULL);
159
+ /* TODO: use rb_protect(). */
160
+ rb_funcall(handler, id_log, 5,
161
+ GRNLOGLEVEL2RVAL(level),
162
+ rb_str_new2(timestamp),
163
+ rb_str_new2(title),
164
+ rb_str_new2(message),
165
+ rb_str_new2(location));
166
+ }
227
167
 
228
- level = RVAL2GRNLOGLEVEL(rb_level);
168
+ static void
169
+ rb_grn_logger_reopen (grn_ctx *ctx, void *user_data)
170
+ {
171
+ VALUE handler = (VALUE)user_data;
229
172
 
230
- if (NIL_P(rb_time) || RVAL2CBOOL(rb_time))
231
- flags |= GRN_LOG_TIME;
232
- if (NIL_P(rb_title) || RVAL2CBOOL(rb_title))
233
- flags |= GRN_LOG_TITLE;
234
- if (NIL_P(rb_message) || RVAL2CBOOL(rb_message))
235
- flags |= GRN_LOG_MESSAGE;
236
- if (NIL_P(rb_location) || RVAL2CBOOL(rb_location))
237
- flags |= GRN_LOG_LOCATION;
173
+ if (NIL_P(handler))
174
+ return;
238
175
 
239
- wrapper = ALLOC(rb_grn_logger_info_wrapper);
240
- logger = ALLOC(grn_logger_info);
241
- wrapper->logger = logger;
242
- DATA_PTR(self) = wrapper;
176
+ /* TODO: use rb_protect(). */
177
+ rb_funcall(handler, id_reopen, 0);
178
+ }
243
179
 
244
- logger->max_level = level;
245
- logger->flags = flags;
246
- rb_grn_logger_set_handler(self, rb_handler);
180
+ static void
181
+ rb_grn_logger_fin (grn_ctx *ctx, void *user_data)
182
+ {
183
+ VALUE handler = (VALUE)user_data;
247
184
 
248
- return Qnil;
185
+ if (NIL_P(handler))
186
+ return;
187
+
188
+ /* TODO: use rb_protect(). */
189
+ rb_funcall(handler, id_fin, 0);
249
190
  }
250
191
 
251
192
  /*
@@ -281,102 +222,122 @@ rb_grn_logger_initialize (int argc, VALUE *argv, VALUE self)
281
222
  static VALUE
282
223
  rb_grn_logger_s_register (int argc, VALUE *argv, VALUE klass)
283
224
  {
284
- VALUE logger, rb_context = Qnil;
225
+ VALUE rb_context = Qnil;
285
226
  grn_ctx *context;
227
+ VALUE rb_logger, rb_callback;
228
+ VALUE rb_options, rb_max_level;
229
+ VALUE rb_time, rb_title, rb_message, rb_location;
230
+ VALUE rb_flags;
231
+ grn_log_level max_level = GRN_LOG_DEFAULT_LEVEL;
232
+ int flags = 0;
233
+
234
+ rb_scan_args(argc, argv, "02&", &rb_logger, &rb_options, &rb_callback);
235
+
236
+ if (rb_block_given_p()) {
237
+ rb_logger = rb_funcall(cGrnCallbackLogger, id_new, 1, rb_callback);
238
+ }
239
+
240
+ rb_grn_scan_options(rb_options,
241
+ "max_level", &rb_max_level,
242
+ "time", &rb_time,
243
+ "title", &rb_title,
244
+ "message", &rb_message,
245
+ "location", &rb_location,
246
+ "flags", &rb_flags,
247
+ NULL);
248
+ if (!NIL_P(rb_max_level)) {
249
+ max_level = RVAL2GRNLOGLEVEL(rb_max_level);
250
+ }
251
+
252
+ if (NIL_P(rb_time) || CBOOL2RVAL(rb_time)) {
253
+ flags |= GRN_LOG_TIME;
254
+ }
255
+ if (NIL_P(rb_title) || CBOOL2RVAL(rb_title)) {
256
+ flags |= GRN_LOG_TITLE;
257
+ }
258
+ if (NIL_P(rb_message) || CBOOL2RVAL(rb_message)) {
259
+ flags |= GRN_LOG_MESSAGE;
260
+ }
261
+ if (NIL_P(rb_location) || CBOOL2RVAL(rb_location)) {
262
+ flags |= GRN_LOG_LOCATION;
263
+ }
264
+ if (!NIL_P(rb_flags)) {
265
+ flags = rb_funcall(mGrnLoggerFlags, id_parse, 2,
266
+ INT2NUM(flags), rb_flags);
267
+ }
268
+
269
+ rb_grn_logger.max_level = max_level;
270
+ rb_grn_logger.flags = flags;
271
+ rb_grn_logger.user_data = (void *)rb_logger;
286
272
 
287
- logger = rb_funcall2(klass, rb_intern("new"), argc, argv);
288
- rb_grn_logger_set_handler(logger, rb_block_proc());
289
273
  context = rb_grn_context_ensure(&rb_context);
290
- grn_logger_info_set(context, RVAL2GRNLOGGER(logger));
291
- rb_grn_context_check(context, logger);
292
- rb_cv_set(klass, "@@current_logger", logger);
274
+ grn_logger_set(context, &rb_grn_logger);
275
+ rb_grn_context_check(context, rb_logger);
276
+ rb_cv_set(klass, "@@current_logger", rb_logger);
293
277
 
294
278
  return Qnil;
295
279
  }
296
280
 
297
- static void
298
- rb_grn_logger_reset_with_error_check (VALUE klass, grn_ctx *context)
281
+ /*
282
+ * Unregister the registered logger. The default logger is used after
283
+ * unregistering.
284
+ *
285
+ * @overload unregister
286
+ * @return void
287
+ */
288
+ static VALUE
289
+ rb_grn_logger_s_unregister (VALUE klass)
299
290
  {
300
291
  VALUE current_logger;
292
+ VALUE rb_context = Qnil;
293
+ grn_ctx *context;
301
294
 
302
295
  current_logger = rb_cv_get(klass, "@@current_logger");
303
296
  if (NIL_P(current_logger))
304
- return;
297
+ return Qnil;
305
298
 
306
299
  rb_cv_set(klass, "@@current_logger", Qnil);
307
- if (context) {
308
- grn_logger_info_set(context, NULL);
309
- rb_grn_context_check(context, current_logger);
310
- } else {
311
- grn_logger_info_set(NULL, NULL);
312
- }
313
- }
314
300
 
315
- static void
316
- rb_grn_logger_reset (VALUE klass)
317
- {
318
- rb_grn_logger_reset_with_error_check(klass, NULL);
301
+ context = rb_grn_context_ensure(&rb_context);
302
+ grn_logger_set(context, NULL);
303
+ rb_grn_context_check(context, klass);
304
+
305
+ return Qnil;
319
306
  }
320
307
 
321
308
  static VALUE
322
309
  rb_grn_logger_s_reopen_with_related_object (VALUE klass, VALUE related_object)
323
310
  {
324
- #ifdef WIN32
325
- rb_raise(rb_eNotImpError, "grn_log_reopen() isn't available on Windows.");
326
- #else
327
311
  VALUE rb_context = Qnil;
328
312
  grn_ctx *context;
329
313
 
330
314
  context = rb_grn_context_ensure(&rb_context);
331
315
  rb_grn_logger_reset_with_error_check(klass, context);
332
- grn_log_reopen(context);
316
+ grn_logger_reopen(context);
333
317
  rb_grn_context_check(context, related_object);
334
- #endif
335
318
 
336
319
  return Qnil;
337
320
  }
338
321
 
339
322
  /*
340
- * groongaのデフォルトロガーがログを出力するファイルを再オー
341
- * プンする。ログファイルのバックアップ時などに使用する。
342
- *
343
- * {Groonga::Logger.register} で独自のロガーを設定している場合
344
- * は例外が発生する。
323
+ * Sends reopen request to the current logger. It is useful for
324
+ * rotating log file.
345
325
  *
346
326
  * @overload reopen
327
+ * @return void
347
328
  */
348
329
  static VALUE
349
330
  rb_grn_logger_s_reopen (VALUE klass)
350
331
  {
351
- return rb_grn_logger_s_reopen_with_related_object(klass, klass);
352
- }
353
-
354
- #ifndef WIN32
355
- static VALUE
356
- rb_grn_logger_s_set_path (VALUE klass, VALUE rb_path,
357
- const char **path, const char *class_variable_name)
358
- {
359
- grn_bool need_reopen = GRN_FALSE;
360
-
361
- if (NIL_P(rb_path)) {
362
- need_reopen = *path != NULL;
363
- *path = NULL;
364
- } else {
365
- const char *current_path = *path;
366
- *path = RSTRING_PTR(rb_path);
367
- if (!current_path || strcmp(*path, current_path) != 0) {
368
- need_reopen = GRN_TRUE;
369
- }
370
- }
371
- rb_cv_set(klass, class_variable_name, rb_path);
332
+ VALUE rb_context = Qnil;
333
+ grn_ctx *context;
372
334
 
373
- if (need_reopen) {
374
- rb_grn_logger_s_reopen_with_related_object(klass, rb_path);
375
- }
335
+ context = rb_grn_context_ensure(&rb_context);
336
+ grn_logger_reopen(context);
337
+ rb_grn_context_check(context, klass);
376
338
 
377
339
  return Qnil;
378
340
  }
379
- #endif
380
341
 
381
342
  /*
382
343
  * groongaのデフォルトロガーがログを出力するファイルのパスを返す。
@@ -387,16 +348,14 @@ rb_grn_logger_s_set_path (VALUE klass, VALUE rb_path,
387
348
  static VALUE
388
349
  rb_grn_logger_s_get_log_path (VALUE klass)
389
350
  {
390
- #ifdef WIN32
391
- rb_raise(rb_eNotImpError, "grn_log_path isn't available on Windows.");
392
- return Qnil;
393
- #else
394
- if (grn_log_path) {
395
- return rb_str_new2(grn_log_path);
351
+ const char *path;
352
+
353
+ path = grn_default_logger_get_path();
354
+ if (path) {
355
+ return rb_str_new2(path);
396
356
  } else {
397
357
  return Qnil;
398
358
  }
399
- #endif
400
359
  }
401
360
 
402
361
  /*
@@ -409,14 +368,30 @@ rb_grn_logger_s_get_log_path (VALUE klass)
409
368
  * @overload log_path=(path)
410
369
  */
411
370
  static VALUE
412
- rb_grn_logger_s_set_log_path (VALUE klass, VALUE path)
371
+ rb_grn_logger_s_set_log_path (VALUE klass, VALUE rb_path)
413
372
  {
414
- #ifdef WIN32
415
- rb_raise(rb_eNotImpError, "grn_qlog_path isn't available on Windows.");
373
+ grn_bool need_reopen = GRN_FALSE;
374
+ const char *current_path;
375
+
376
+ current_path = grn_default_logger_get_path();
377
+ if (NIL_P(rb_path)) {
378
+ need_reopen = current_path != NULL;
379
+ grn_default_logger_set_path(NULL);
380
+ } else {
381
+ const char *new_path;
382
+ new_path = RSTRING_PTR(rb_path);
383
+ if (!current_path || strcmp(new_path, current_path) != 0) {
384
+ need_reopen = GRN_TRUE;
385
+ }
386
+ grn_default_logger_set_path(new_path);
387
+ }
388
+ rb_cv_set(klass, "@@log_path", rb_path);
389
+
390
+ if (need_reopen) {
391
+ rb_grn_logger_s_reopen_with_related_object(klass, rb_path);
392
+ }
393
+
416
394
  return Qnil;
417
- #else
418
- return rb_grn_logger_s_set_path(klass, path, &grn_log_path, "@@log_path");
419
- #endif
420
395
  }
421
396
 
422
397
  /*
@@ -428,16 +403,14 @@ rb_grn_logger_s_set_log_path (VALUE klass, VALUE path)
428
403
  static VALUE
429
404
  rb_grn_logger_s_get_query_log_path (VALUE klass)
430
405
  {
431
- #ifdef WIN32
432
- rb_raise(rb_eNotImpError, "grn_qlog_path isn't available on Windows.");
433
- return Qnil;
434
- #else
435
- if (grn_qlog_path) {
436
- return rb_str_new2(grn_qlog_path);
406
+ const char *path;
407
+
408
+ path = grn_default_query_logger_get_path();
409
+ if (path) {
410
+ return rb_str_new2(path);
437
411
  } else {
438
412
  return Qnil;
439
413
  }
440
- #endif
441
414
  }
442
415
 
443
416
  /*
@@ -450,28 +423,56 @@ rb_grn_logger_s_get_query_log_path (VALUE klass)
450
423
  * @overload query_log_path=(path)
451
424
  */
452
425
  static VALUE
453
- rb_grn_logger_s_set_query_log_path (VALUE klass, VALUE path)
426
+ rb_grn_logger_s_set_query_log_path (VALUE klass, VALUE rb_path)
454
427
  {
455
- #ifdef WIN32
456
- rb_raise(rb_eNotImpError, "grn_qlog_path isn't available on Windows.");
428
+ grn_bool need_reopen = GRN_FALSE;
429
+ const char *current_path;
430
+
431
+ current_path = grn_default_query_logger_get_path();
432
+ if (NIL_P(rb_path)) {
433
+ need_reopen = current_path != NULL;
434
+ grn_default_query_logger_set_path(NULL);
435
+ } else {
436
+ const char *new_path;
437
+ new_path = RSTRING_PTR(rb_path);
438
+ if (!current_path || strcmp(new_path, current_path) != 0) {
439
+ need_reopen = GRN_TRUE;
440
+ }
441
+ grn_default_query_logger_set_path(new_path);
442
+ }
443
+ rb_cv_set(klass, "@@query_log_path", rb_path);
444
+
445
+ if (need_reopen) {
446
+ rb_grn_logger_s_reopen_with_related_object(klass, rb_path);
447
+ }
448
+
457
449
  return Qnil;
458
- #else
459
- return rb_grn_logger_s_set_path(klass, path, &grn_qlog_path,
460
- "@@query_log_path");
461
- #endif
462
450
  }
463
451
 
464
452
  void
465
453
  rb_grn_init_logger (VALUE mGrn)
466
454
  {
455
+ id_new = rb_intern("new");
456
+ id_parse = rb_intern("parse");
457
+ id_log = rb_intern("log");
458
+ id_reopen = rb_intern("reopen");
459
+ id_fin = rb_intern("fin");
460
+
461
+ rb_grn_logger.log = rb_grn_logger_log;
462
+ rb_grn_logger.reopen = rb_grn_logger_reopen;
463
+ rb_grn_logger.fin = rb_grn_logger_fin;
464
+
465
+ rb_grn_logger.user_data = (void *)Qnil;
466
+
467
467
  cGrnLogger = rb_define_class_under(mGrn, "Logger", rb_cObject);
468
- rb_define_alloc_func(cGrnLogger, rb_grn_logger_alloc);
469
468
 
470
469
  rb_cv_set(cGrnLogger, "@@current_logger", Qnil);
471
470
  rb_cv_set(cGrnLogger, "@@log_path", Qnil);
472
471
  rb_cv_set(cGrnLogger, "@@query_log_path", Qnil);
473
472
  rb_define_singleton_method(cGrnLogger, "register",
474
473
  rb_grn_logger_s_register, -1);
474
+ rb_define_singleton_method(cGrnLogger, "unregister",
475
+ rb_grn_logger_s_unregister, 0);
475
476
  rb_define_singleton_method(cGrnLogger, "reopen",
476
477
  rb_grn_logger_s_reopen, 0);
477
478
  rb_define_singleton_method(cGrnLogger, "log_path",
@@ -484,5 +485,16 @@ rb_grn_init_logger (VALUE mGrn)
484
485
  rb_grn_logger_s_set_query_log_path, 1);
485
486
  rb_set_end_proc(rb_grn_logger_reset, cGrnLogger);
486
487
 
487
- rb_define_method(cGrnLogger, "initialize", rb_grn_logger_initialize, -1);
488
+ mGrnLoggerFlags = rb_define_module_under(cGrnLogger, "Flags");
489
+ #define DEFINE_FLAG(NAME) \
490
+ rb_define_const(mGrnLoggerFlags, \
491
+ #NAME, INT2NUM(GRN_LOG_ ## NAME))
492
+ DEFINE_FLAG(TIME);
493
+ DEFINE_FLAG(TITLE);
494
+ DEFINE_FLAG(MESSAGE);
495
+ DEFINE_FLAG(LOCATION);
496
+ #undef DEFINE_FLAG
497
+
498
+ cGrnCallbackLogger =
499
+ rb_define_class_under(mGrn, "CallbackLogger", cGrnLogger);
488
500
  }