statsrb 0.1.3 → 0.1.4

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.
Files changed (3) hide show
  1. data/ext/statsrb/statsrb.c +64 -11
  2. data/test/test_statsrb.rb +89 -0
  3. metadata +10 -6
@@ -3,6 +3,52 @@
3
3
  #include <string.h>
4
4
  #include <stdlib.h>
5
5
 
6
+ /**
7
+ * Retrieves internal data based on specified filters.
8
+ * @param namespace [String]
9
+ * @param limit [Number]
10
+ * @param start_time [Number]
11
+ * @param end_time [Number]
12
+ * @return [Array] An array of data hashes.
13
+ */
14
+ static VALUE statsrb_get(VALUE self, VALUE query_ns, VALUE query_limit, VALUE query_start, VALUE query_end) {
15
+ VALUE statsrb_data = rb_iv_get(self, "@data");
16
+ VALUE statsrb_event = rb_hash_new();
17
+ int data_length = RARRAY_LEN(statsrb_data);
18
+ int i = 0;
19
+ int count = 0;
20
+ int tmp_ts;
21
+
22
+ VALUE filtered_data = rb_ary_new();
23
+ VALUE tmp_ns;
24
+
25
+ // @data hash key symbols.
26
+ VALUE statsrb_key_ts = rb_iv_get(self, "@key_ts");
27
+ VALUE statsrb_key_ns = rb_iv_get(self, "@key_ns");
28
+ VALUE statsrb_key_v = rb_iv_get(self, "@key_v");
29
+
30
+ // Convert into an int that ruby understands.
31
+ int limit = NUM2INT(query_limit);
32
+ int qstart = NUM2INT(query_start);
33
+ int qend = NUM2INT(query_end);
34
+
35
+ for (i = 0; i < data_length; i++) {
36
+ tmp_ts = NUM2INT(rb_hash_aref(rb_ary_entry(statsrb_data, i), statsrb_key_ts));
37
+ tmp_ns = rb_hash_aref(rb_ary_entry(statsrb_data, i), statsrb_key_ns);
38
+ if (rb_str_equal(query_ns, tmp_ns)
39
+ && (qstart == 0 || tmp_ts >= qstart)
40
+ && (qend == 0 || tmp_ts <= qend)) {
41
+ rb_hash_aset(statsrb_event, statsrb_key_ts, rb_hash_aref(rb_ary_entry(statsrb_data, i), statsrb_key_ts));
42
+ rb_hash_aset(statsrb_event, statsrb_key_ns, rb_hash_aref(rb_ary_entry(statsrb_data, i), statsrb_key_ns));
43
+ rb_hash_aset(statsrb_event, statsrb_key_v, rb_hash_aref(rb_ary_entry(statsrb_data, i), statsrb_key_v));
44
+ rb_ary_push(filtered_data, statsrb_event);
45
+ count++;
46
+ }
47
+ }
48
+
49
+ return filtered_data;
50
+ }
51
+
6
52
  /**
7
53
  * Locates data from a specified file and loads into @data.
8
54
  * @param filepath [String]
@@ -12,7 +58,7 @@
12
58
  * @param end_time [Number]
13
59
  * @return [Statsrb] A reference to the object.
14
60
  */
15
- static VALUE statsrb_query(VALUE self, VALUE logfile, VALUE query_ns, VALUE query_limit, VALUE query_start, VALUE query_end) {
61
+ static VALUE statsrb_read(VALUE self, VALUE logfile, VALUE query_ns, VALUE query_limit, VALUE query_start, VALUE query_end) {
16
62
  FILE * file;
17
63
  int line_size = 256;
18
64
  char *line = (char *) malloc(line_size);
@@ -39,13 +85,13 @@ static VALUE statsrb_query(VALUE self, VALUE logfile, VALUE query_ns, VALUE quer
39
85
  file = fopen(filepath, "r");
40
86
  if (file == NULL) {
41
87
  fprintf(stderr, "File error: could not open file %s for reading.", filepath);
42
- return;
88
+ return self;
43
89
  }
44
90
 
45
91
  int count = 0;
46
92
 
47
93
  while (NULL != fgets(line, line_size, file) && count < limit) {
48
- // strstr doesn't work with newline chars.
94
+ // strstr doesn't work with newline chars.
49
95
  size_t len = strlen(line) - 1;
50
96
  if (line[len] == '\n');
51
97
  line[len] = '\0';
@@ -66,7 +112,7 @@ static VALUE statsrb_query(VALUE self, VALUE logfile, VALUE query_ns, VALUE quer
66
112
  VALUE statsrb_str_ns = rb_str_new2(strtok(NULL, "\t"));
67
113
  //strtok(NULL, "\t");
68
114
  int statsrb_v = atoi(strtok(NULL, "\0"));
69
-
115
+
70
116
  // @TODO this should really query the namespace exactly instead of just relying on strstr.
71
117
  //if (rb_str_cmp(query_ns, statsrb_str_empty) == 0 || rb_str_cmp(query_ns, statsrb_str_ns) == 0) {
72
118
  if (statsrb_ts && (statsrb_v || statsrb_v == 0)) {
@@ -155,7 +201,7 @@ static VALUE statsrb_write(VALUE self, VALUE logfile, VALUE mode) {
155
201
  int line_size = 256;
156
202
  int tmp_ts, tmp_v;
157
203
  const char *tmp_ns = (char *) malloc(line_size);
158
-
204
+
159
205
  // @data hash key symbols.
160
206
  VALUE statsrb_key_ts = rb_iv_get(self, "@key_ts");
161
207
  VALUE statsrb_key_ns = rb_iv_get(self, "@key_ns");
@@ -164,7 +210,7 @@ static VALUE statsrb_write(VALUE self, VALUE logfile, VALUE mode) {
164
210
  file = fopen(filepath, filemode);
165
211
  if (file==NULL) {
166
212
  fprintf(stderr, "File error: could not open file %s mode %s.", filepath, filemode);
167
- return;
213
+ return self;
168
214
  }
169
215
 
170
216
  // Iterate through the data array, writing the data as we go.
@@ -222,7 +268,12 @@ static VALUE statsrb_split_write(VALUE self, VALUE logdir, VALUE mode) {
222
268
  //fputs (RSTRING_PTR(rb_obj_as_string(INT2NUM(RARRAY_LEN(tmp_data)))),stderr);
223
269
  rb_iv_set(tmp, "@data", tmp_data);
224
270
 
225
- // @todo, throw an exception if no trailing slash... or add one
271
+ // If there is no trailing slash on the log dir, add one.
272
+ const char *filepath = RSTRING_PTR(logdir);
273
+ size_t len = strlen(filepath);
274
+ if (filepath[len - 1] != '/') {
275
+ logdir = rb_str_plus(logdir, rb_str_new2("/"));
276
+ }
226
277
  statsrb_write(tmp, rb_str_plus(logdir, rb_ary_entry(ns_list, i)), mode);
227
278
  }
228
279
 
@@ -393,7 +444,7 @@ static VALUE statsrb_rack_call(VALUE self, VALUE env) {
393
444
  VALUE tmp = rb_obj_dup(self);
394
445
  VALUE tmp_data = rb_ary_new();
395
446
  rb_iv_set(tmp, "@data", tmp_data);
396
- statsrb_query(tmp, rb_str_plus(rb_iv_get(self, "@split_file_dir"), statsrb_ns), statsrb_ns, INT2NUM(query_limit), INT2NUM(query_start), INT2NUM(query_end));
447
+ statsrb_read(tmp, rb_str_plus(rb_iv_get(self, "@split_file_dir"), statsrb_ns), statsrb_ns, INT2NUM(query_limit), INT2NUM(query_start), INT2NUM(query_end));
397
448
  statsrb_sort(tmp);
398
449
 
399
450
  int i, data_length = RARRAY_LEN(tmp_data);
@@ -408,7 +459,7 @@ static VALUE statsrb_rack_call(VALUE self, VALUE env) {
408
459
  rb_ary_push(body, rb_str_new(",", 1));
409
460
  }
410
461
  rb_ary_push(body, rb_str_new("\n", 1));
411
- }
462
+ }
412
463
  rb_ary_resize(tmp_data, 0);
413
464
  }
414
465
  rb_ary_push(body, rb_str_new("]}", 2));
@@ -454,7 +505,7 @@ static VALUE statsrb_push(VALUE self, VALUE timestamp, VALUE namespace, VALUE va
454
505
 
455
506
  return self;
456
507
  }
457
-
508
+
458
509
  /**
459
510
  * Class constructor, sets up an instance variable.
460
511
  */
@@ -485,7 +536,9 @@ void Init_statsrb(void) {
485
536
 
486
537
  // Instance methods and properties.
487
538
  rb_define_method(klass, "initialize", statsrb_constructor, 0);
488
- rb_define_method(klass, "query", statsrb_query, 5);
539
+ rb_define_method(klass, "query", statsrb_read, 5);
540
+ rb_define_method(klass, "read", statsrb_read, 5);
541
+ rb_define_method(klass, "get", statsrb_get, 4);
489
542
  rb_define_method(klass, "sort", statsrb_sort, 0);
490
543
  rb_define_method(klass, "write", statsrb_write, 2);
491
544
  rb_define_method(klass, "split_write", statsrb_split_write, 2);
@@ -0,0 +1,89 @@
1
+ require 'minitest/autorun'
2
+ require 'statsrb'
3
+
4
+ class TestStatsrb < MiniTest::Test
5
+
6
+ attr_accessor :tmpfile
7
+
8
+ def setup
9
+ @s = Statsrb.new
10
+ @tmpfile = "/tmp/test.statsrb"
11
+ end
12
+
13
+ def teardown
14
+ File.delete @tmpfile unless !File.exists? @tmpfile
15
+ end
16
+
17
+ # Provides test data.
18
+ def get_data
19
+ [[123, "test1", 33],
20
+ [321, "test1", 34],
21
+ [222, "test1", 35],
22
+ [111, "test2", 36],
23
+ [432, "test2", 37]]
24
+ end
25
+
26
+ # Stores the data in the current object.
27
+ def push_data
28
+ get_data.each do |value|
29
+ @s.push value[0], value[1], value[2]
30
+ end
31
+ end
32
+
33
+ # Writes the data to a temp file.
34
+ def write_data
35
+ @s.write @tmpfile, "w+"
36
+ end
37
+
38
+ # Tests that the data was indeed pushed.
39
+ def test_push_data
40
+ push_data
41
+ assert_equal @s.data.length, get_data.length
42
+ end
43
+
44
+ # Tests that we can filter the in-memory data.
45
+ def test_get_data
46
+ push_data
47
+ t = @s.get "test2", 100, 0, 0
48
+ assert_equal(t.length, 2);
49
+ end
50
+
51
+ # Tests that we can sort the data.
52
+ def test_sort_data
53
+ current = 0
54
+ push_data
55
+ @s.sort
56
+ @s.data.each do |value|
57
+ assert value[:ts] > current
58
+ current = value[:ts]
59
+ end
60
+ end
61
+
62
+ # Tests that we can write the data to a file.
63
+ def test_write_data
64
+ push_data
65
+ write_data
66
+ data = get_data
67
+ file_data = File.read(@tmpfile).split "\n"
68
+
69
+ assert_equal file_data.length, data.length
70
+ count = 0
71
+ file_data.each do |value|
72
+ parts = value.split "\t"
73
+ assert_equal parts[0], data[count][0].to_s
74
+ assert_equal parts[1], data[count][1].to_s
75
+ assert_equal parts[2], data[count][2].to_s
76
+ count = count + 1
77
+ end
78
+ end
79
+
80
+ # Tests that we can read data from a file.
81
+ def test_read_data
82
+ push_data
83
+ write_data
84
+ @s.read @tmpfile, "test1", 100, 0, 0
85
+ assert_equal @s.data.length, 3
86
+ @s.read @tmpfile, "test2", 100, 0, 0
87
+ assert_equal @s.data.length, 2
88
+ end
89
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statsrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,8 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2013-06-08 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: A ruby stats repository.
14
+ description: A Ruby time series stats repository using flat file storage, providing
15
+ a Ruby API as well as a Rack compatible REST API.
15
16
  email: email@kevinhankens.com
16
17
  executables: []
17
18
  extensions:
@@ -21,9 +22,11 @@ files:
21
22
  - lib/statsrb.rb
22
23
  - ext/statsrb/statsrb.c
23
24
  - ext/statsrb/extconf.rb
25
+ - test/test_statsrb.rb
24
26
  homepage: https://github.com/kevinhankens/statsrb
25
- licenses: []
26
- post_install_message:
27
+ licenses:
28
+ - ! "MIT\t"
29
+ post_install_message: ! 'Please view documentation at: https://github.com/kevinhankens/statsrb'
27
30
  rdoc_options: []
28
31
  require_paths:
29
32
  - lib
@@ -44,6 +47,7 @@ rubyforge_project:
44
47
  rubygems_version: 1.8.25
45
48
  signing_key:
46
49
  specification_version: 3
47
- summary: Statsrb
48
- test_files: []
50
+ summary: A Ruby time series stats repository.
51
+ test_files:
52
+ - test/test_statsrb.rb
49
53
  has_rdoc: