prometheus-client-mmap 0.21.0-x86_64-linux-musl → 1.2.1-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -0
  3. data/README.md +32 -17
  4. data/ext/fast_mmaped_file_rs/Cargo.toml +14 -9
  5. data/ext/fast_mmaped_file_rs/build.rs +5 -0
  6. data/ext/fast_mmaped_file_rs/extconf.rb +1 -3
  7. data/ext/fast_mmaped_file_rs/src/error.rs +2 -2
  8. data/ext/fast_mmaped_file_rs/src/file_entry.rs +222 -17
  9. data/ext/fast_mmaped_file_rs/src/file_info.rs +56 -6
  10. data/ext/fast_mmaped_file_rs/src/lib.rs +0 -1
  11. data/ext/fast_mmaped_file_rs/src/map.rs +12 -12
  12. data/ext/fast_mmaped_file_rs/src/mmap/inner.rs +704 -0
  13. data/ext/fast_mmaped_file_rs/src/mmap.rs +765 -25
  14. data/ext/fast_mmaped_file_rs/src/raw_entry.rs +1 -1
  15. data/ext/fast_mmaped_file_rs/src/testhelper.rs +1 -1
  16. data/lib/3.1/fast_mmaped_file_rs.so +0 -0
  17. data/lib/3.2/fast_mmaped_file_rs.so +0 -0
  18. data/lib/3.3/fast_mmaped_file_rs.so +0 -0
  19. data/lib/3.4/fast_mmaped_file_rs.so +0 -0
  20. data/lib/prometheus/client/formats/text.rb +1 -34
  21. data/lib/prometheus/client/helper/mmaped_file.rb +3 -3
  22. data/lib/prometheus/client/label_set_validator.rb +1 -2
  23. data/lib/prometheus/client/support/puma.rb +44 -0
  24. data/lib/prometheus/client/version.rb +1 -1
  25. metadata +67 -61
  26. data/ext/fast_mmaped_file/extconf.rb +0 -30
  27. data/ext/fast_mmaped_file/fast_mmaped_file.c +0 -122
  28. data/ext/fast_mmaped_file/file_format.c +0 -5
  29. data/ext/fast_mmaped_file/file_format.h +0 -11
  30. data/ext/fast_mmaped_file/file_parsing.c +0 -195
  31. data/ext/fast_mmaped_file/file_parsing.h +0 -27
  32. data/ext/fast_mmaped_file/file_reading.c +0 -102
  33. data/ext/fast_mmaped_file/file_reading.h +0 -30
  34. data/ext/fast_mmaped_file/globals.h +0 -14
  35. data/ext/fast_mmaped_file/mmap.c +0 -427
  36. data/ext/fast_mmaped_file/mmap.h +0 -61
  37. data/ext/fast_mmaped_file/rendering.c +0 -199
  38. data/ext/fast_mmaped_file/rendering.h +0 -8
  39. data/ext/fast_mmaped_file/utils.c +0 -56
  40. data/ext/fast_mmaped_file/utils.h +0 -22
  41. data/ext/fast_mmaped_file/value_access.c +0 -242
  42. data/ext/fast_mmaped_file/value_access.h +0 -15
  43. data/ext/fast_mmaped_file_rs/.cargo/config.toml +0 -23
  44. data/ext/fast_mmaped_file_rs/Cargo.lock +0 -790
  45. data/ext/fast_mmaped_file_rs/src/parser.rs +0 -346
  46. data/lib/2.7/fast_mmaped_file.so +0 -0
  47. data/lib/2.7/fast_mmaped_file_rs.so +0 -0
  48. data/lib/3.0/fast_mmaped_file.so +0 -0
  49. data/lib/3.0/fast_mmaped_file_rs.so +0 -0
  50. data/lib/3.1/fast_mmaped_file.so +0 -0
  51. data/lib/3.2/fast_mmaped_file.so +0 -0
  52. data/vendor/c/hashmap/.gitignore +0 -52
  53. data/vendor/c/hashmap/LICENSE +0 -21
  54. data/vendor/c/hashmap/README.md +0 -90
  55. data/vendor/c/hashmap/_config.yml +0 -1
  56. data/vendor/c/hashmap/src/hashmap.c +0 -692
  57. data/vendor/c/hashmap/src/hashmap.h +0 -267
  58. data/vendor/c/hashmap/test/Makefile +0 -22
  59. data/vendor/c/hashmap/test/hashmap_test.c +0 -608
  60. data/vendor/c/jsmn/.travis.yml +0 -4
  61. data/vendor/c/jsmn/LICENSE +0 -20
  62. data/vendor/c/jsmn/Makefile +0 -41
  63. data/vendor/c/jsmn/README.md +0 -168
  64. data/vendor/c/jsmn/example/jsondump.c +0 -126
  65. data/vendor/c/jsmn/example/simple.c +0 -76
  66. data/vendor/c/jsmn/jsmn.c +0 -314
  67. data/vendor/c/jsmn/jsmn.h +0 -76
  68. data/vendor/c/jsmn/library.json +0 -16
  69. data/vendor/c/jsmn/test/test.h +0 -27
  70. data/vendor/c/jsmn/test/tests.c +0 -407
  71. data/vendor/c/jsmn/test/testutil.h +0 -94
@@ -1,427 +0,0 @@
1
- #include "mmap.h"
2
-
3
- #include <errno.h>
4
- #include <fcntl.h>
5
- #include <ruby/util.h>
6
- #include <sys/mman.h>
7
-
8
- #include "file_format.h"
9
- #include "utils.h"
10
-
11
- #if 0
12
- #include <stdio.h>
13
- #define DEBUGF(format, ...) printf("%d: " format "\n", __LINE__, __VA_ARGS__)
14
- #else
15
- #define DEBUGF(format, ...)
16
- #endif
17
-
18
- /* This is the ID of the WeakMap used to track strings allocated that
19
- * are backed by a memory-mapped file.
20
- */
21
- #define WEAK_OBJ_TRACKER "@weak_obj_tracker"
22
-
23
- /**
24
- * Maps a given VALUE to some key for the WeakMap. For now, we just use
25
- * the integer value as the key since that suffices, though this does
26
- * require Ruby 2.7 due to https://bugs.ruby-lang.org/issues/16035.
27
- */
28
- static VALUE weak_obj_tracker_get_key(VALUE val) { return val; }
29
-
30
- /**
31
- * Adds a T_STRING type to the WeakMap. The WeakMap should be stored
32
- * as an instance variable.
33
- */
34
- static void weak_obj_tracker_add(VALUE obj, VALUE val) {
35
- Check_Type(val, T_STRING);
36
-
37
- VALUE tracker = rb_iv_get(obj, WEAK_OBJ_TRACKER);
38
- VALUE key = weak_obj_tracker_get_key(val);
39
-
40
- rb_funcall(tracker, rb_intern("[]="), 2, key, val);
41
- }
42
-
43
- /**
44
- * Iterator function for updating a single element from the WeakMap.
45
- */
46
- VALUE mm_update_obj_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, self)) {
47
- Check_Type(self, T_DATA);
48
- Check_Type(i, T_STRING);
49
- rb_check_arity(argc, 1, 1);
50
-
51
- mm_ipc *i_mm;
52
- GET_MMAP(self, i_mm, MM_MODIFY);
53
-
54
- RSTRING(i)->as.heap.ptr = i_mm->t->addr;
55
- RSTRING(i)->as.heap.len = i_mm->t->real;
56
-
57
- return Qtrue;
58
- }
59
-
60
- /**
61
- * This iterates through the WeakMap defined on the class and updates
62
- * the RStrings to use the newly-allocated memory region.
63
- */
64
- void mm_update(VALUE obj) {
65
- VALUE tracker = rb_iv_get(obj, WEAK_OBJ_TRACKER);
66
-
67
- rb_block_call(tracker, rb_intern("each_value"), 0, NULL, mm_update_obj_i, obj);
68
- }
69
-
70
- typedef struct {
71
- VALUE obj, *argv;
72
- ID id;
73
- int flag, argc;
74
- } mm_bang;
75
-
76
- static VALUE mm_protect_bang(VALUE *t) { return rb_funcall2(t[0], (ID)t[1], (int)t[2], (VALUE *)t[3]); }
77
-
78
- static VALUE mm_recycle(VALUE str) {
79
- rb_gc_force_recycle(str);
80
- return str;
81
- }
82
-
83
- static VALUE mm_vunlock(VALUE obj) {
84
- mm_ipc *i_mm;
85
-
86
- GET_MMAP(obj, i_mm, 0);
87
- return Qnil;
88
- }
89
-
90
- static VALUE mm_str(VALUE obj, int modify) {
91
- mm_ipc *i_mm;
92
- VALUE ret = Qnil;
93
-
94
- GET_MMAP(obj, i_mm, modify & ~MM_ORIGIN);
95
- if (modify & MM_MODIFY) {
96
- if (i_mm->t->flag & MM_FROZEN) rb_error_frozen("mmap");
97
- }
98
- ret = rb_obj_alloc(rb_cString);
99
- RSTRING(ret)->as.heap.ptr = i_mm->t->addr;
100
- RSTRING(ret)->as.heap.aux.capa = i_mm->t->len;
101
- RSTRING(ret)->as.heap.len = i_mm->t->real;
102
-
103
- weak_obj_tracker_add(obj, ret);
104
-
105
- DEBUGF("RString capa: %d, len: %d", RSTRING(ret)->as.heap.aux.capa, RSTRING(ret)->as.heap.len);
106
-
107
- if (modify & MM_ORIGIN) {
108
- #if HAVE_RB_DEFINE_ALLOC_FUNC
109
- RSTRING(ret)->as.heap.aux.shared = obj;
110
- FL_SET(ret, RSTRING_NOEMBED);
111
- FL_SET(ret, FL_USER18);
112
- #else
113
- RSTRING(ret)->orig = ret;
114
- #endif
115
- }
116
- if (i_mm->t->flag & MM_FROZEN) {
117
- ret = rb_obj_freeze(ret);
118
- }
119
- return ret;
120
- }
121
-
122
- static VALUE mm_i_bang(bang_st) mm_bang *bang_st;
123
- {
124
- VALUE str, res;
125
- mm_ipc *i_mm;
126
-
127
- str = mm_str(bang_st->obj, bang_st->flag);
128
- if (bang_st->flag & MM_PROTECT) {
129
- VALUE tmp[4];
130
- tmp[0] = str;
131
- tmp[1] = (VALUE)bang_st->id;
132
- tmp[2] = (VALUE)bang_st->argc;
133
- tmp[3] = (VALUE)bang_st->argv;
134
- res = rb_ensure(mm_protect_bang, (VALUE)tmp, mm_recycle, str);
135
- } else {
136
- res = rb_funcall2(str, bang_st->id, bang_st->argc, bang_st->argv);
137
- RB_GC_GUARD(res);
138
- }
139
- if (res != Qnil) {
140
- GET_MMAP(bang_st->obj, i_mm, 0);
141
- i_mm->t->real = RSTRING_LEN(str);
142
- }
143
- return res;
144
- }
145
-
146
- static VALUE mm_bang_i(VALUE obj, int flag, ID id, int argc, VALUE *argv) {
147
- VALUE res;
148
- mm_ipc *i_mm;
149
- mm_bang bang_st;
150
-
151
- GET_MMAP(obj, i_mm, 0);
152
- if ((flag & MM_CHANGE) && (i_mm->t->flag & MM_FIXED)) {
153
- rb_raise(rb_eTypeError, "try to change the size of a fixed map");
154
- }
155
- bang_st.obj = obj;
156
- bang_st.flag = flag;
157
- bang_st.id = id;
158
- bang_st.argc = argc;
159
- bang_st.argv = argv;
160
- if (i_mm->t->flag & MM_IPC) {
161
- res = rb_ensure(mm_i_bang, (VALUE)&bang_st, mm_vunlock, obj);
162
- } else {
163
- res = mm_i_bang(&bang_st);
164
- }
165
- if (res == Qnil) return res;
166
- return (flag & MM_ORIGIN) ? res : obj;
167
- }
168
-
169
- static void mm_free(mm_ipc *i_mm) {
170
- if (i_mm->t->path) {
171
- if (munmap(i_mm->t->addr, i_mm->t->len) != 0) {
172
- if (i_mm->t->path != (char *)-1 && i_mm->t->path != NULL) {
173
- free(i_mm->t->path);
174
- }
175
- free(i_mm);
176
-
177
- rb_raise(rb_eRuntimeError, "munmap failed at %s:%d with errno: %d", __FILE__, __LINE__, errno);
178
- }
179
-
180
- if (i_mm->t->path != (char *)-1) {
181
- if (i_mm->t->real < i_mm->t->len && i_mm->t->vscope != MAP_PRIVATE &&
182
- truncate(i_mm->t->path, i_mm->t->real) == -1) {
183
- free(i_mm->t->path);
184
- free(i_mm);
185
- rb_raise(rb_eTypeError, "truncate");
186
- }
187
- free(i_mm->t->path);
188
- }
189
- }
190
- free(i_mm);
191
- }
192
-
193
- /*
194
- * call-seq:
195
- * new(file)
196
- *
197
- * create a new Mmap object
198
- *
199
- * * <em>file</em>
200
- *
201
- *
202
- * Creates a mapping that's shared with all other processes
203
- * mapping the same areas of the file.
204
- *
205
- */
206
- VALUE mm_s_new(int argc, VALUE *argv, VALUE obj) {
207
- VALUE res = rb_funcall2(obj, rb_intern("allocate"), 0, 0);
208
- rb_obj_call_init(res, argc, argv);
209
- return res;
210
- }
211
-
212
- VALUE mm_s_alloc(VALUE obj) {
213
- VALUE res;
214
- mm_ipc *i_mm;
215
-
216
- res = Data_Make_Struct(obj, mm_ipc, 0, mm_free, i_mm);
217
- i_mm->t = ALLOC_N(mm_mmap, 1);
218
- MEMZERO(i_mm->t, mm_mmap, 1);
219
- i_mm->t->fd = -1;
220
- return res;
221
- }
222
-
223
- size_t next_page_boundary(size_t value) {
224
- size_t page_size = sysconf(_SC_PAGESIZE);
225
-
226
- while (page_size < value) {
227
- page_size *= 2;
228
- }
229
-
230
- return page_size;
231
- }
232
-
233
- /* Reference implementations:
234
- * mozilla: https://hg.mozilla.org/mozilla-central/file/3d846420a907/xpcom/glue/FileUtils.cpp#l71
235
- * glibc: https://github.com/lattera/glibc/blob/master/sysdeps/posix/posix_fallocate.c
236
- */
237
- int reserve_mmap_file_bytes(int fd, size_t size) {
238
- #if __linux__
239
- /* From https://stackoverflow.com/a/22820221: The difference with
240
- * ftruncate(2) is that (on file systems supporting it, e.g. Ext4)
241
- * disk space is indeed reserved by posix_fallocate but ftruncate
242
- * extends the file by adding holes (and without reserving disk
243
- * space). */
244
- return posix_fallocate(fd, 0, size);
245
- #else
246
- /* We simplify the reference implemnetations since we generally
247
- * don't need to reserve more than a page size. */
248
- return ftruncate(fd, size);
249
- #endif
250
- }
251
-
252
- VALUE mm_init(VALUE obj, VALUE fname) {
253
- struct stat st;
254
- int fd, smode = 0, pmode = 0, vscope, perm, init;
255
- MMAP_RETTYPE addr;
256
- mm_ipc *i_mm;
257
- char *path;
258
- size_t size = 0;
259
- off_t offset;
260
-
261
- vscope = 0;
262
- path = 0;
263
- fd = -1;
264
-
265
- VALUE klass = rb_eval_string("ObjectSpace::WeakMap");
266
- VALUE weak_obj_tracker = rb_class_new_instance(0, NULL, klass);
267
- rb_iv_set(obj, WEAK_OBJ_TRACKER, weak_obj_tracker);
268
-
269
- fname = rb_str_to_str(fname);
270
- SafeStringValue(fname);
271
- path = StringValuePtr(fname);
272
-
273
- vscope = MAP_SHARED;
274
- size = 0;
275
- perm = 0666;
276
-
277
- smode = O_RDWR;
278
- pmode = PROT_READ | PROT_WRITE;
279
-
280
- if ((fd = open(path, smode, perm)) == -1) {
281
- rb_raise(rb_eArgError, "Can't open %s", path);
282
- }
283
-
284
- if (fstat(fd, &st) == -1) {
285
- close(fd);
286
- rb_raise(rb_eArgError, "Can't stat %s", path);
287
- }
288
- size = st.st_size;
289
-
290
- Data_Get_Struct(obj, mm_ipc, i_mm);
291
-
292
- offset = 0;
293
- init = 0;
294
-
295
- if (size == 0) {
296
- init = 1;
297
- size = INITIAL_SIZE;
298
- }
299
-
300
- /* We need to ensure the underlying file descriptor is at least a page size.
301
- * Otherwise, we could get a SIGBUS error if mmap() attempts to read or write
302
- * past the file. */
303
- size_t reserve_size = next_page_boundary(size);
304
-
305
- if (reserve_mmap_file_bytes(fd, reserve_size) != 0) {
306
- close(fd);
307
- rb_raise(rb_eIOError, "Can't reserve %zu bytes for memory-mapped file in %s", reserve_size, path);
308
- }
309
-
310
- addr = mmap(0, size, pmode, vscope, fd, offset);
311
-
312
- if (addr == MAP_FAILED || !addr) {
313
- close(fd);
314
- rb_raise(rb_eArgError, "mmap failed (%d)", errno);
315
- }
316
- i_mm->t->fd = fd;
317
- i_mm->t->addr = addr;
318
- i_mm->t->len = size;
319
- if (!init) {
320
- i_mm->t->real = size;
321
- }
322
- i_mm->t->pmode = pmode;
323
- i_mm->t->vscope = vscope;
324
- i_mm->t->smode = smode & ~O_TRUNC;
325
- i_mm->t->path = (path) ? ruby_strdup(path) : (char *)-1;
326
-
327
- if (smode == O_WRONLY) {
328
- i_mm->t->flag |= MM_FIXED;
329
- }
330
- return obj;
331
- }
332
-
333
- /*
334
- * Document-method: []
335
- * Document-method: slice
336
- *
337
- * call-seq: [](args)
338
- *
339
- * Element reference - with the following syntax:
340
- *
341
- * self[nth]
342
- *
343
- * retrieve the <em>nth</em> character
344
- *
345
- * self[start..last]
346
- *
347
- * return a substring from <em>start</em> to <em>last</em>
348
- *
349
- * self[start, length]
350
- *
351
- * return a substring of <em>lenght</em> characters from <em>start</em>
352
- */
353
- VALUE mm_aref_m(int argc, VALUE *argv, VALUE obj) { return mm_bang_i(obj, MM_ORIGIN, rb_intern("[]"), argc, argv); }
354
-
355
- /*
356
- * Document-method: msync
357
- * Document-method: sync
358
- * Document-method: flush
359
- *
360
- * call-seq: msync
361
- *
362
- * flush the file
363
- */
364
- VALUE mm_msync(int argc, VALUE *argv, VALUE obj) {
365
- mm_ipc *i_mm;
366
- GET_MMAP(obj, i_mm, MM_MODIFY);
367
-
368
- VALUE oflag;
369
- int ret;
370
- int flag = MS_SYNC;
371
-
372
- if (argc) {
373
- rb_scan_args(argc, argv, "01", &oflag);
374
- flag = NUM2INT(oflag);
375
- }
376
- if ((ret = msync(i_mm->t->addr, i_mm->t->len, flag)) != 0) {
377
- rb_raise(rb_eArgError, "msync(%d)", ret);
378
- }
379
-
380
- return obj;
381
- }
382
-
383
- /*
384
- * Document-method: munmap
385
- * Document-method: unmap
386
- *
387
- * call-seq: munmap
388
- *
389
- * terminate the association
390
- */
391
- VALUE mm_unmap(VALUE obj) {
392
- mm_ipc *i_mm;
393
-
394
- GET_MMAP(obj, i_mm, 0);
395
- if (i_mm->t->path) {
396
- if (munmap(i_mm->t->addr, i_mm->t->len) != 0) {
397
- if (i_mm->t->path != (char *)-1 && i_mm->t->path != NULL) {
398
- free(i_mm->t->path);
399
- i_mm->t->path = NULL;
400
- }
401
-
402
- rb_raise(rb_eRuntimeError, "munmap failed at %s:%d with errno: %d", __FILE__, __LINE__, errno);
403
- }
404
-
405
- if (i_mm->t->path != (char *)-1) {
406
- if (i_mm->t->real < i_mm->t->len && i_mm->t->vscope != MAP_PRIVATE &&
407
- truncate(i_mm->t->path, i_mm->t->real) == -1) {
408
- rb_raise(rb_eTypeError, "truncate");
409
- }
410
- free(i_mm->t->path);
411
- }
412
-
413
- // Ensure any lingering RString values get a length of zero. We
414
- // can't zero out the address since GET_MMAP() inside
415
- // mm_update_obj_i() expects a non-null address and path.
416
- i_mm->t->len = 0;
417
- i_mm->t->real = 0;
418
- mm_update(obj);
419
-
420
- i_mm->t->addr = NULL;
421
- i_mm->t->path = NULL;
422
- }
423
-
424
- close(i_mm->t->fd);
425
-
426
- return Qnil;
427
- }
@@ -1,61 +0,0 @@
1
- #ifndef MMAP_H
2
- #define MMAP_H
3
-
4
- #include <ruby.h>
5
- #include <unistd.h>
6
-
7
- #define MM_MODIFY 1
8
- #define MM_ORIGIN 2
9
- #define MM_CHANGE (MM_MODIFY | 4)
10
- #define MM_PROTECT 8
11
-
12
- #define MM_FROZEN (1 << 0)
13
- #define MM_FIXED (1 << 1)
14
- #define MM_ANON (1 << 2)
15
- #define MM_LOCK (1 << 3)
16
- #define MM_IPC (1 << 4)
17
- #define MM_TMP (1 << 5)
18
-
19
- #ifndef MMAP_RETTYPE
20
- #define MMAP_RETTYPE void *
21
- #endif
22
-
23
- typedef struct {
24
- MMAP_RETTYPE addr;
25
- int smode, pmode, vscope;
26
- int advice, flag;
27
- VALUE key;
28
- size_t len, real;
29
- off_t offset;
30
- int fd;
31
- char *path;
32
- } mm_mmap;
33
-
34
- typedef struct {
35
- int count;
36
- mm_mmap *t;
37
- } mm_ipc;
38
-
39
- #define GET_MMAP(obj, i_mm, t_modify) \
40
- Data_Get_Struct(obj, mm_ipc, i_mm); \
41
- if (!i_mm->t->path || i_mm->t->fd < 0 || i_mm->t->addr == NULL || i_mm->t->addr == MAP_FAILED) { \
42
- rb_raise(rb_eIOError, "unmapped file"); \
43
- } \
44
- if ((t_modify & MM_MODIFY) && (i_mm->t->flag & MM_FROZEN)) { \
45
- rb_error_frozen("mmap"); \
46
- }
47
-
48
- VALUE mm_s_alloc(VALUE obj);
49
- VALUE mm_s_new(int argc, VALUE *argv, VALUE obj);
50
- VALUE mm_init(VALUE obj, VALUE fname);
51
- VALUE mm_aref_m(int argc, VALUE *argv, VALUE obj);
52
- VALUE mm_msync(int argc, VALUE *argv, VALUE obj);
53
- VALUE mm_unmap(VALUE obj);
54
-
55
- /* If memory is ever reallocated, any allocated Ruby strings that have not been
56
- * garbage collected need to be updated with the new region. If this isn't done,
57
- * iterating over the Ruby object space and accessing the string data will seg fault.
58
- */
59
- void mm_update(VALUE obj);
60
-
61
- #endif
@@ -1,199 +0,0 @@
1
- #include "rendering.h"
2
-
3
- #include <float.h>
4
- #include <jsmn.h>
5
-
6
- #include "file_parsing.h"
7
- #include "globals.h"
8
- #include "utils.h"
9
-
10
- #ifndef DBL_DECIMAL_DIG
11
- #define DBL_DECIMAL_DIG 17
12
- #endif
13
-
14
- #define LABELS_START_OFFSET 4
15
-
16
- static inline int is_valid(const jsmntok_t *token) { return token->start < token->end && token->start >= 0; }
17
- static inline int valid_not_null(const entry_t *entry, const jsmntok_t *token) {
18
- static const char null_s[] = "null";
19
-
20
- if (!is_valid(token)) {
21
- return 0;
22
- }
23
-
24
- if (token->type != JSMN_PRIMITIVE) {
25
- return 1;
26
- }
27
-
28
- size_t token_len = token->end - token->start;
29
-
30
- if (token_len < sizeof(null_s) - 1) {
31
- return 1;
32
- }
33
-
34
- return strncmp(null_s, entry->json + token->start, sizeof(null_s) - 1) != 0;
35
- }
36
-
37
- static inline int append_token(VALUE string, const entry_t *entry, const jsmntok_t *token) {
38
- if (!is_valid(token)) {
39
- save_exception(prom_eParsingError, "parsing failed: %s", entry->json);
40
- return 0;
41
- }
42
-
43
- rb_str_cat(string, entry->json + token->start, token->end - token->start);
44
- return 1;
45
- }
46
-
47
- static int append_labels(VALUE string, const entry_t *entry, const int label_count, const jsmntok_t *tokens) {
48
- if (label_count <= 0) {
49
- if (is_pid_significant(entry)) {
50
- rb_str_cat(string, "{pid=\"", 6);
51
- rb_str_append(string, entry->pid);
52
- rb_str_cat(string, "\"}", 2);
53
- }
54
- return 1;
55
- }
56
-
57
- rb_str_cat(string, "{", 1);
58
-
59
- for (int i = 0; i < label_count; i++) {
60
- int key = LABELS_START_OFFSET + i;
61
- int val = LABELS_START_OFFSET + label_count + 1 + i;
62
-
63
- if (!append_token(string, entry, &tokens[key])) {
64
- return 0;
65
- }
66
- rb_str_cat(string, "=", 1);
67
-
68
- rb_str_cat(string, "\"", 1);
69
- if (valid_not_null(entry, &tokens[val])) {
70
- append_token(string, entry, &tokens[val]);
71
- }
72
- rb_str_cat(string, "\"", 1);
73
-
74
- if (i < label_count - 1) {
75
- rb_str_cat(string, ",", 1);
76
- }
77
- }
78
-
79
- if (is_pid_significant(entry)) {
80
- rb_str_cat(string, ",pid=\"", 6);
81
- rb_str_append(string, entry->pid);
82
- rb_str_cat(string, "\"", 1);
83
- }
84
-
85
- rb_str_cat(string, "}", 1);
86
- return 1;
87
- }
88
-
89
- static int validate_token_count(const int token_count, const entry_t *entry) {
90
- if (token_count < 0) {
91
- save_exception(prom_eParsingError, "too many labels or malformed json: %s", entry->json);
92
- return 0;
93
- }
94
-
95
- if (token_count < LABELS_START_OFFSET) {
96
- save_exception(prom_eParsingError, "malformed json: %s", entry->json);
97
- return 0;
98
- }
99
-
100
- if ((token_count - (LABELS_START_OFFSET + 1)) % 2 != 0) {
101
- save_exception(prom_eParsingError, "mismatched number of labels: %s", entry->json);
102
- return 0;
103
- }
104
-
105
- return 1;
106
- }
107
-
108
- static int append_entry(VALUE string, const entry_t *entry) {
109
- jsmn_parser parser;
110
- jsmn_init(&parser);
111
-
112
- jsmntok_t tokens[200];
113
- jsmntok_t *name_token = &tokens[2];
114
-
115
- int token_count = jsmn_parse(&parser, entry->json, entry->json_size, tokens, sizeof(tokens) / sizeof(tokens[0]));
116
- int label_count = (token_count - (LABELS_START_OFFSET + 1)) / 2;
117
-
118
- //
119
- // Example JSON "['metric', 'name',['label_a','label_b'],['value_a', 'value_b']]"
120
- // will be parsed into following token list:
121
- //
122
- // [ "'metric', 'name',['label_a','label_b'],['value_a', 'value_b']",
123
- // "metric", "name",
124
- // "['label_a','label_b']", "label_a", "label_b",
125
- // "['value_a', 'value_b']", "value_a", "value_b" ]
126
- //
127
- // where 'metric' is the name of the metric, while 'name'
128
- // is in summaries and histograms to store names of "submetrics" like:
129
- // histogram_name_bucket or histogram_name_sum
130
-
131
- if (!validate_token_count(token_count, entry)) {
132
- return 0;
133
- }
134
-
135
- if (!append_token(string, entry, name_token)) {
136
- return 0;
137
- }
138
-
139
- if (!append_labels(string, entry, label_count, tokens)) {
140
- return 0;
141
- }
142
-
143
- char value[255];
144
-
145
- // print value with highest possible precision so that we do not lose any data
146
- int written = snprintf(value, sizeof(value), " %.*g\n", DBL_DECIMAL_DIG, entry->value);
147
- rb_str_cat(string, value, written);
148
-
149
- return 1;
150
- }
151
-
152
- static void append_entry_head(VALUE string, const entry_t *entry) {
153
- static const char help_beg[] = "# HELP ";
154
- static const char help_fin[] = " Multiprocess metric\n";
155
-
156
- rb_str_cat(string, help_beg, sizeof(help_beg) - 1);
157
- rb_str_cat(string, entry->name, entry->name_len);
158
- rb_str_cat(string, help_fin, sizeof(help_fin) - 1);
159
-
160
- static const char type_beg[] = "# TYPE ";
161
-
162
- rb_str_cat(string, type_beg, sizeof(type_beg) - 1);
163
- rb_str_cat(string, entry->name, entry->name_len);
164
- rb_str_cat(string, " ", 1);
165
- rb_str_cat2(string, rb_id2name(entry->type));
166
- rb_str_cat(string, "\n", 1);
167
- }
168
-
169
- static inline int entry_name_equal(const entry_t *a, const entry_t *b) {
170
- if (a == NULL || b == NULL) {
171
- return a == b;
172
- }
173
-
174
- if (a->name_len != b->name_len) {
175
- return 0;
176
- }
177
-
178
- return strncmp(a->name, b->name, a->name_len) == 0;
179
- }
180
-
181
- int entries_to_string(VALUE string, entry_t **sorted_entries, size_t entries_count) {
182
- entry_t *previous = NULL;
183
-
184
- for (size_t i = 0; i < entries_count; i++) {
185
- entry_t *entry = sorted_entries[i];
186
-
187
- // when entry->name changes write metric header
188
- if (!entry_name_equal(previous, entry)) {
189
- previous = entry;
190
- append_entry_head(string, entry);
191
- }
192
-
193
- if (!append_entry(string, entry)) {
194
- return 0;
195
- }
196
- }
197
-
198
- return 1;
199
- }
@@ -1,8 +0,0 @@
1
- #ifndef RENDERING_H
2
- #define RENDERING_H
3
- #include <file_parsing.h>
4
- #include <ruby.h>
5
-
6
- int entries_to_string(VALUE string, entry_t **sorted_entries, size_t entries_count);
7
-
8
- #endif