agoo 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

@@ -5,30 +5,38 @@
5
5
 
6
6
  #include <stdbool.h>
7
7
 
8
- #include <ruby.h>
9
-
10
- #include "types.h"
8
+ #include "method.h"
9
+ #include "seg.h"
11
10
 
12
11
  typedef enum {
13
- NO_HOOK = '\0',
14
- RACK_HOOK = 'R',
15
- BASE_HOOK = 'B',
16
- WAB_HOOK = 'W',
17
- PUSH_HOOK = 'P',
12
+ NO_HOOK = '\0',
13
+ RACK_HOOK = 'R',
14
+ BASE_HOOK = 'B',
15
+ WAB_HOOK = 'W',
16
+ PUSH_HOOK = 'P',
17
+ STDIO_HOOK = 'S', // for OpO
18
+ FAST_HOOK = 'F', // for OpO
19
+ GET_HOOK = 'G', // for OpO
20
+ TNEW_HOOK = 'c', // for OpO
21
+ TGET_HOOK = 'r', // for OpO
22
+ TUP_HOOK = 'u', // for OpO
23
+ TDEL_HOOK = 'd', // for OpO
24
+ TQL_HOOK = 'T', // for OpO
25
+ GRAPHQL_HOOK = 'Q', // for OpO
18
26
  } HookType;
19
27
 
20
28
  typedef struct _Hook {
21
29
  struct _Hook *next;
22
30
  Method method;
23
- VALUE handler;
24
31
  char *pattern;
25
32
  HookType type;
33
+ void* handler;
26
34
  } *Hook;
27
35
 
28
- extern Hook hook_create(Method method, const char *pattern, VALUE handler);
36
+ extern Hook hook_create(Method method, const char *pattern, void *handler, HookType type);
29
37
  extern void hook_destroy(Hook hook);
30
38
 
31
- extern bool hook_match(Hook hook, Method method, const char *path, const char *pend);
32
- extern Hook hook_find(Hook hook, Method method, const char *path, const char *pend);
39
+ extern bool hook_match(Hook hook, Method method, const Seg seg);
40
+ extern Hook hook_find(Hook hook, Method method, const Seg seg);
33
41
 
34
42
  #endif // __AGOO_HOOK_H__
@@ -54,8 +54,6 @@ static struct _Color colors[] = {
54
54
 
55
55
  static const char level_chars[] = { 'F', 'E', 'W', 'I', 'D', '?' };
56
56
 
57
- static VALUE log_mod = Qundef;
58
-
59
57
  struct _Log the_log = {NULL};
60
58
  struct _LogCat fatal_cat;
61
59
  struct _LogCat error_cat;
@@ -68,7 +66,7 @@ struct _LogCat resp_cat;
68
66
  struct _LogCat eval_cat;
69
67
  struct _LogCat push_cat;
70
68
 
71
- static Color
69
+ Color
72
70
  find_color(const char *name) {
73
71
  if (NULL != name) {
74
72
  for (Color c = colors; NULL != c->name; c++) {
@@ -212,7 +210,7 @@ remove_old_logs() {
212
210
  struct dirent *de;
213
211
  long seq;
214
212
  char *end;
215
- char path[1024];
213
+ char path[1500];
216
214
  DIR *dir = opendir(the_log.dir);
217
215
  char prefix[32];
218
216
  int psize;
@@ -248,8 +246,8 @@ remove_old_logs() {
248
246
 
249
247
  void
250
248
  log_rotate() {
251
- char from[1024];
252
- char to[1024];
249
+ char from[1060];
250
+ char to[1060];
253
251
 
254
252
  if (NULL != the_log.file) {
255
253
  fclose(the_log.file);
@@ -260,20 +258,20 @@ log_rotate() {
260
258
 
261
259
  sprintf(name, log_pid_name, getpid());
262
260
  for (int seq = the_log.max_files; 0 < seq; seq--) {
263
- snprintf(to, sizeof(to), log_pid_format, the_log.dir, getpid(), seq + 1);
264
- snprintf(from, sizeof(from), log_pid_format, the_log.dir, getpid(), seq);
261
+ snprintf(to, sizeof(to) - 1, log_pid_format, the_log.dir, getpid(), seq + 1);
262
+ snprintf(from, sizeof(from) - 1, log_pid_format, the_log.dir, getpid(), seq);
265
263
  rename(from, to);
266
264
  }
267
- snprintf(to, sizeof(to), log_pid_format, the_log.dir, getpid(), 1);
268
- snprintf(from, sizeof(from), "%s/%s", the_log.dir, name);
265
+ snprintf(to, sizeof(to) - 1, log_pid_format, the_log.dir, getpid(), 1);
266
+ snprintf(from, sizeof(from) - 1, "%s/%s", the_log.dir, name);
269
267
  } else {
270
268
  for (int seq = the_log.max_files; 0 < seq; seq--) {
271
- snprintf(to, sizeof(to), log_format, the_log.dir, seq + 1);
272
- snprintf(from, sizeof(from), log_format, the_log.dir, seq);
269
+ snprintf(to, sizeof(to) - 1, log_format, the_log.dir, seq + 1);
270
+ snprintf(from, sizeof(from) - 1, log_format, the_log.dir, seq);
273
271
  rename(from, to);
274
272
  }
275
- snprintf(to, sizeof(to), log_format, the_log.dir, 1);
276
- snprintf(from, sizeof(from), "%s/%s", the_log.dir, log_name);
273
+ snprintf(to, sizeof(to) - 1, log_format, the_log.dir, 1);
274
+ snprintf(from, sizeof(from) - 1, "%s/%s", the_log.dir, log_name);
277
275
  }
278
276
  rename(from, to);
279
277
 
@@ -332,9 +330,9 @@ log_flush(double timeout) {
332
330
  return true;
333
331
  }
334
332
 
335
- static void
333
+ void
336
334
  open_log_file() {
337
- char path[1024];
335
+ char path[1500];
338
336
 
339
337
  if (the_log.with_pid) {
340
338
  snprintf(path, sizeof(path), "%s/%s_%d", the_log.dir, log_name, getpid());
@@ -343,13 +341,16 @@ open_log_file() {
343
341
  }
344
342
  the_log.file = fopen(path, "a");
345
343
  if (NULL == the_log.file) {
346
- rb_raise(rb_eIOError, "Failed to create '%s'.", path);
344
+ struct _Err err;
345
+
346
+ err_no(&err, "Failed to create '%s'.", path);
347
+ the_log.on_error(&err);
347
348
  }
348
349
  the_log.size = ftell(the_log.file);
349
350
  if (the_log.max_size <= the_log.size) {
350
351
  log_rotate();
351
352
  }
352
- // TBD open rscok and wsock
353
+ // TBD open rsock and wsock
353
354
  }
354
355
 
355
356
  void
@@ -442,7 +443,6 @@ log_catv(LogCat cat, const char *fmt, va_list ap) {
442
443
  struct timezone tz;
443
444
 
444
445
  gettimeofday(&tv, &tz);
445
-
446
446
  e->when = (int64_t)tv.tv_sec * 1000000000LL + (int64_t)tv.tv_usec * 1000.0;
447
447
  #endif
448
448
  }
@@ -480,451 +480,32 @@ log_cat(LogCat cat, const char *fmt, ...) {
480
480
  va_end(ap);
481
481
  }
482
482
 
483
- /* Document-method: configure
484
- *
485
- * call-seq: configure(options)
486
- *
487
- * Configures the logger
488
- *
489
- * - *options* [_Hash_] server options
490
- *
491
- * - *:dir* [_String_] directory to place log files in. If nil or empty then no log files are written.
492
- *
493
- * - *:console* [_true_|_false_] if true log entry are display on the console.
494
- *
495
- * - *:classic* [_true_|_false_] if true log entry follow a classic format. If false log entries are JSON.
496
- *
497
- * - *:colorize* [_true_|_false_] if true log entries are colorized.
498
- *
499
- * - *:states* [_Hash_] a map of logging categories and whether they should be on or off. Categories are:
500
- * - *:ERROR* errors
501
- * - *:WARN* warnings
502
- * - *:INFO* infomational
503
- * - *:DEBUG* debugging
504
- * - *:connect* openning and closing of connections
505
- * - *:request* requests
506
- * - *:response* responses
507
- * - *:eval* handler evaluationss
508
- * - *:push* writes to WebSocket or SSE connection
509
- */
510
- static VALUE
511
- rlog_configure(VALUE self, VALUE options) {
512
- if (Qnil != options) {
513
- VALUE v;
514
-
515
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("dir"))))) {
516
- rb_check_type(v, T_STRING);
517
- strncpy(the_log.dir, StringValuePtr(v), sizeof(the_log.dir));
518
- the_log.dir[sizeof(the_log.dir) - 1] = '\0';
519
- }
520
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("max_files"))))) {
521
- int max = FIX2INT(v);
522
-
523
- if (1 <= max || max < 100) {
524
- the_log.max_files = max;
525
- } else {
526
- rb_raise(rb_eArgError, "max_files must be between 1 and 100.");
527
- }
528
- }
529
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("max_size"))))) {
530
- int max = FIX2INT(v);
531
-
532
- if (1 <= max) {
533
- the_log.max_size = max;
534
- } else {
535
- rb_raise(rb_eArgError, "max_size must be 1 or more.");
536
- }
537
- }
538
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("console"))))) {
539
- the_log.console = (Qtrue == v);
540
- }
541
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("classic"))))) {
542
- the_log.classic = (Qtrue == v);
543
- }
544
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("colorize"))))) {
545
- the_log.colorize = (Qtrue == v);
546
- }
547
- if (Qnil != (v = rb_hash_lookup(options, ID2SYM(rb_intern("states"))))) {
548
- if (T_HASH == rb_type(v)) {
549
- LogCat cat = the_log.cats;
550
- VALUE cv;
551
-
552
- for (; NULL != cat; cat = cat->next) {
553
- if (Qnil != (cv = rb_hash_lookup(v, ID2SYM(rb_intern(cat->label))))) {
554
- if (Qtrue == cv) {
555
- cat->on = true;
556
- } else if (Qfalse == cv) {
557
- cat->on = false;
558
- }
559
- }
560
- }
561
- } else {
562
- rb_raise(rb_eArgError, "states must be a Hash.");
563
- }
564
- }
565
- }
483
+ void
484
+ log_start(bool with_pid) {
566
485
  if (NULL != the_log.file) {
567
486
  fclose(the_log.file);
568
487
  the_log.file = NULL;
488
+ // TBD close rsock and wsock
569
489
  }
570
- if ('\0' != *the_log.dir) {
490
+ the_log.with_pid = with_pid;
491
+ if (with_pid && '\0' != *the_log.dir) {
571
492
  if (0 != mkdir(the_log.dir, 0770) && EEXIST != errno) {
572
- rb_raise(rb_eIOError, "Failed to create '%s'.", the_log.dir);
493
+ struct _Err err;
494
+
495
+ err_no(&err, "Failed to create '%s'", the_log.dir);
496
+ the_log.on_error(&err);
573
497
  }
574
498
  open_log_file();
575
499
  }
576
- return Qnil;
577
- }
578
-
579
- /* Document-method: shutdown
580
- *
581
- * call-seq: shutdown()
582
- *
583
- * Shutdown the logger. Writes are flushed before shutting down.
584
- */
585
- static VALUE
586
- rlog_shutdown(VALUE self) {
587
- log_close();
588
- return Qnil;
589
- }
590
-
591
- /* Document-method: error?
592
- *
593
- * call-seq: error?()
594
- *
595
- * Returns true is errors are being logged.
596
- */
597
- static VALUE
598
- rlog_errorp(VALUE self) {
599
- return error_cat.on ? Qtrue : Qfalse;
600
- }
601
-
602
- /* Document-method: warn?
603
- *
604
- * call-seq: warn?()
605
- *
606
- * Returns true is warnings are being logged.
607
- */
608
- static VALUE
609
- rlog_warnp(VALUE self) {
610
- return warn_cat.on ? Qtrue : Qfalse;
611
- }
612
-
613
- /* Document-method: info?
614
- *
615
- * call-seq: info?()
616
- *
617
- * Returns true is info entries are being logged.
618
- */
619
- static VALUE
620
- rlog_infop(VALUE self) {
621
- return info_cat.on ? Qtrue : Qfalse;
622
- }
623
-
624
- /* Document-method: debug?
625
- *
626
- * call-seq: debug?()
627
- *
628
- * Returns true is debug entries are being logged.
629
- */
630
- static VALUE
631
- rlog_debugp(VALUE self) {
632
- return debug_cat.on ? Qtrue : Qfalse;
633
- }
634
-
635
- /* Document-method: error
636
- *
637
- * call-seq: error(msg)
638
- *
639
- * Log an error message.
640
- */
641
- static VALUE
642
- rlog_error(VALUE self, VALUE msg) {
643
- log_cat(&error_cat, "%s", StringValuePtr(msg));
644
- return Qnil;
645
- }
646
-
647
- /* Document-method: warn
648
- *
649
- * call-seq: warn(msg)
650
- *
651
- * Log a warn message.
652
- */
653
- static VALUE
654
- rlog_warn(VALUE self, VALUE msg) {
655
- log_cat(&warn_cat, "%s", StringValuePtr(msg));
656
- return Qnil;
657
- }
658
-
659
- /* Document-method: info
660
- *
661
- * call-seq: info(msg)
662
- *
663
- * Log an info message.
664
- */
665
- static VALUE
666
- rlog_info(VALUE self, VALUE msg) {
667
- log_cat(&info_cat, "%s", StringValuePtr(msg));
668
- return Qnil;
669
- }
670
-
671
- /* Document-method: debug
672
- *
673
- * call-seq: debug(msg)
674
- *
675
- * Log a debug message.
676
- */
677
- static VALUE
678
- rlog_debug(VALUE self, VALUE msg) {
679
- log_cat(&debug_cat, "%s", StringValuePtr(msg));
680
- return Qnil;
681
- }
682
-
683
- /* Document-method: color
684
- *
685
- * call-seq: color(label)
686
- *
687
- * Returns the current color name as a Symbol for the specified label.
688
- */
689
- static VALUE
690
- rlog_color_get(VALUE self, VALUE label) {
691
- LogCat cat = log_cat_find(StringValuePtr(label));
692
-
693
- if (NULL == cat) {
694
- return Qnil;
695
- }
696
- return ID2SYM(rb_intern(cat->color->name));
697
- }
698
-
699
- /* Document-method: set_color
700
- *
701
- * call-seq: set_color(label, color_symbol)
702
- *
703
- * Sets color of the category associated with a label. Valid colors are
704
- * :black, :red, :green, :yellow, :blue, :magenta, :cyan, :white, :gray,
705
- * :dark_red, :dark_green, :brown, :dark_blue, :purple, and :dark_cyan.
706
- */
707
- static VALUE
708
- rlog_color_set(VALUE self, VALUE label, VALUE color) {
709
- const char *label_str = StringValuePtr(label);
710
- const char *color_name = StringValuePtr(color);
711
- LogCat cat = log_cat_find(label_str);
712
- Color c = find_color(color_name);
713
-
714
- if (NULL == cat) {
715
- rb_raise(rb_eArgError, "%s is not a valid category.", label_str);
716
- }
717
- if (NULL == c) {
718
- rb_raise(rb_eArgError, "%s is not a valid color.", color_name);
719
- }
720
- cat->color = c;
721
-
722
- return Qnil;
723
- }
724
-
725
- /* Document-method: state
726
- *
727
- * call-seq: state(label)
728
- *
729
- * Returns the current state of the category identified by the specified
730
- * label.
731
- */
732
- static VALUE
733
- rlog_on_get(VALUE self, VALUE label) {
734
- LogCat cat = log_cat_find(StringValuePtr(label));
735
-
736
- if (NULL == cat) {
737
- return Qfalse;
738
- }
739
- return cat->on ? Qtrue : Qfalse;
500
+ pthread_create(&the_log.thread, NULL, loop, NULL);
740
501
  }
741
502
 
742
- /* Document-method: set_state
743
- *
744
- * call-seq: set_state(label, state)
745
- *
746
- * Sets state of the category associated with a label.
747
- */
748
- static VALUE
749
- rlog_on_set(VALUE self, VALUE label, VALUE state) {
750
- const char *label_str = StringValuePtr(label);
751
- LogCat cat = log_cat_find(label_str);
752
-
753
- if (NULL == cat) {
754
- rb_raise(rb_eArgError, "%s is not a valid category.", label_str);
755
- }
756
- cat->on = (Qtrue == state);
757
-
758
- return cat->on ? Qtrue : Qfalse;
759
- }
760
-
761
- /* Document-method: log
762
- *
763
- * call-seq: log[label] = msg
764
- *
765
- * Log a message in the specified category.
766
- */
767
- static VALUE
768
- rlog_log(VALUE self, VALUE label, VALUE msg) {
769
- const char *label_str = StringValuePtr(label);
770
- LogCat cat = log_cat_find(label_str);
771
-
772
- if (NULL == cat) {
773
- rb_raise(rb_eArgError, "%s is not a valid category.", label_str);
774
- }
775
- log_cat(cat, "%s", StringValuePtr(msg));
776
-
777
- return Qnil;
778
- }
779
-
780
- /* Document-method: flush
781
- *
782
- * call-seq: flush
783
- *
784
- * Flush the log queue and write all entries to disk or the console. The call
785
- * waits for the flush to complete or the timeout to be exceeded.
786
- */
787
- static VALUE
788
- rlog_flush(VALUE self, VALUE to) {
789
- double timeout = NUM2DBL(to);
790
-
791
- if (!log_flush(timeout)) {
792
- rb_raise(rb_eStandardError, "timed out waiting for log flush.");
793
- }
794
- return Qnil;
795
- }
796
-
797
- /* Document-method: rotate
798
- *
799
- * call-seq: rotate()
800
- *
801
- * Rotate the log files.
802
- */
803
- static VALUE
804
- rlog_rotate(VALUE self) {
805
- log_rotate();
806
- return Qnil;
807
- }
808
-
809
- /* Document-method: console=
810
- *
811
- * call-seq: console=(on)
812
- *
813
- * If on then log output also goes to the console.
814
- */
815
- static VALUE
816
- rlog_console(VALUE self, VALUE on) {
817
- the_log.console = (Qtrue == on);
818
- return Qnil;
819
- }
820
-
821
- /* Document-method: classic
822
- *
823
- * call-seq: classic()
824
- *
825
- * Set the log format to classic format.
826
- */
827
- static VALUE
828
- rlog_classic(VALUE self) {
829
- the_log.classic = true;
830
- return Qnil;
831
- }
832
-
833
- /* Document-method: json
834
- *
835
- * call-seq: json()
836
- *
837
- * Set the log format to JSON format.
838
- */
839
- static VALUE
840
- rlog_json(VALUE self) {
841
- the_log.classic = false;
842
- return Qnil;
843
- }
844
-
845
- /* Document-method: max_size
846
- *
847
- * call-seq: max_size(size)
848
- *
849
- * Maximum log files size is reset.
850
- */
851
- static VALUE
852
- rlog_max_size(VALUE self, VALUE rmax) {
853
- int max = FIX2INT(rmax);
854
-
855
- if (1 <= max) {
856
- the_log.max_size = max;
857
- } else {
858
- rb_raise(rb_eArgError, "max_size must be 1 or more.");
859
- }
860
- return Qnil;
861
- }
862
-
863
- /* Document-method: max_files
864
- *
865
- * call-seq: max_files(max)
866
- *
867
- * Maximum log files files is reset.
868
- */
869
- static VALUE
870
- rlog_max_files(VALUE self, VALUE rmax) {
871
- int max = FIX2INT(rmax);
872
-
873
- if (1 <= max || max < 100) {
874
- the_log.max_files = max;
875
- } else {
876
- rb_raise(rb_eArgError, "max_files must be between 1 and 100.");
877
- }
878
- return Qnil;
879
- }
880
-
881
-
882
- /* Document-class: Agoo::Log
883
- *
884
- * An asynchronous and thread safe logger that includes file rollover and
885
- * multiple logging categories. It is a feature based logger with a level
886
- * overlay.
887
- */
888
503
  void
889
- log_init(VALUE mod) {
504
+ log_init() {
890
505
  time_t t = time(NULL);
891
506
  struct tm *tm = localtime(&t);
892
507
  int qsize = 1024;
893
508
 
894
- log_mod = rb_define_module_under(mod, "Log");
895
-
896
- rb_define_module_function(log_mod, "configure", rlog_configure, 1);
897
- rb_define_module_function(log_mod, "shutdown", rlog_shutdown, 0);
898
-
899
- rb_define_module_function(log_mod, "error?", rlog_errorp, 0);
900
- rb_define_module_function(log_mod, "warn?", rlog_warnp, 0);
901
- rb_define_module_function(log_mod, "info?", rlog_infop, 0);
902
- rb_define_module_function(log_mod, "debug?", rlog_debugp, 0);
903
-
904
- rb_define_module_function(log_mod, "error", rlog_error, 1);
905
- rb_define_module_function(log_mod, "warn", rlog_warn, 1);
906
- rb_define_module_function(log_mod, "info", rlog_info, 1);
907
- rb_define_module_function(log_mod, "debug", rlog_debug, 1);
908
-
909
- // TBD maybe in a future version
910
- //rb_define_module_function(log_mod, "register", rlog_register, 2);
911
-
912
- rb_define_module_function(log_mod, "color", rlog_color_get, 1);
913
- rb_define_module_function(log_mod, "set_color", rlog_color_set, 2);
914
-
915
- rb_define_module_function(log_mod, "state", rlog_on_get, 1);
916
- rb_define_module_function(log_mod, "set_state", rlog_on_set, 2);
917
-
918
- rb_define_module_function(log_mod, "log", rlog_log, 2);
919
-
920
- rb_define_module_function(log_mod, "flush", rlog_flush, 1);
921
- rb_define_module_function(log_mod, "rotate", rlog_rotate, 0);
922
- rb_define_module_function(log_mod, "console=", rlog_console, 1);
923
- rb_define_module_function(log_mod, "classic", rlog_classic, 0);
924
- rb_define_module_function(log_mod, "json", rlog_json, 0);
925
- rb_define_module_function(log_mod, "max_size=", rlog_max_size, 1);
926
- rb_define_module_function(log_mod, "max_files=", rlog_max_files, 1);
927
-
928
509
  the_log.cats = NULL;
929
510
  *the_log.dir = '\0';
930
511
  the_log.file = NULL;
@@ -968,20 +549,3 @@ log_init(VALUE mod) {
968
549
 
969
550
  log_start(false);
970
551
  }
971
-
972
- void
973
- log_start(bool with_pid) {
974
- if (NULL != the_log.file) {
975
- fclose(the_log.file);
976
- the_log.file = NULL;
977
- // TBD close rsock and wsock
978
- }
979
- the_log.with_pid = with_pid;
980
- if (with_pid && '\0' != *the_log.dir) {
981
- if (0 != mkdir(the_log.dir, 0770) && EEXIST != errno) {
982
- rb_raise(rb_eIOError, "Failed to create '%s'.", the_log.dir);
983
- }
984
- open_log_file();
985
- }
986
- pthread_create(&the_log.thread, NULL, loop, log);
987
- }