prometheus-client-mmap 0.7.0.beta41 → 0.7.0.beta42
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.
- checksums.yaml +4 -4
- data/ext/fast_mmaped_file/extconf.rb +15 -0
- data/ext/fast_mmaped_file/fast_mmaped_file.c +49 -24
- data/ext/fast_mmaped_file/file_parsing.c +84 -109
- data/ext/fast_mmaped_file/file_parsing.h +7 -6
- data/ext/fast_mmaped_file/file_reading.c +41 -32
- data/ext/fast_mmaped_file/file_reading.h +1 -1
- data/ext/fast_mmaped_file/globals.h +3 -0
- data/ext/fast_mmaped_file/hashmap.c +409 -466
- data/ext/fast_mmaped_file/jsmn.c +259 -243
- data/ext/fast_mmaped_file/mmap.c +332 -0
- data/ext/fast_mmaped_file/mmap.h +9 -0
- data/ext/fast_mmaped_file/rendering.c +110 -37
- data/ext/fast_mmaped_file/rendering.h +2 -2
- data/ext/fast_mmaped_file/utils.c +3 -2
- data/ext/fast_mmaped_file/utils.h +1 -1
- data/ext/fast_mmaped_file/value_access.c +88 -48
- data/ext/fast_mmaped_file/value_access.h +4 -2
- data/lib/fast_mmaped_file.bundle +0 -0
- data/lib/prometheus/client/helper/entry_parser.rb +1 -1
- data/lib/prometheus/client/helper/mmaped_file.rb +4 -6
- data/lib/prometheus/client/helper/plain_file.rb +3 -3
- data/lib/prometheus/client/mmaped_dict.rb +2 -7
- data/lib/prometheus/client/simple_value.rb +0 -1
- data/lib/prometheus/client/support/unicorn.rb +9 -0
- data/lib/prometheus/client/version.rb +1 -1
- metadata +3 -25
- data/ext/fast_mmaped_file/hashmap.h +0 -266
- data/ext/fast_mmaped_file/jsmn.h +0 -76
- data/lib/prometheus/client/version.rb.orig +0 -9
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e546160d5f4baf942cd59595ba9f4738f5bb112a
         | 
| 4 | 
            +
              data.tar.gz: d2369f52a14a938fec91c09d372396c031992234
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c02fd8414f65779692b0aac43e89f53a87492843bae04891924838320533f495de9977ba2c99c72d34553d937268fa0ee6b5859861f1f13a86a5969c74b4320f
         | 
| 7 | 
            +
              data.tar.gz: e9bf20cc0e44dd7307b429dd088d82702a25073bbd72ff0cc9315d4e2580e7438042b98032c21f7ddb0f668afd6bf42c0018e3f4bd81dfb40c30b79d0ecab9b4
         | 
| @@ -1,7 +1,22 @@ | |
| 1 1 | 
             
            require 'mkmf'
         | 
| 2 | 
            +
            require 'fileutils'
         | 
| 3 | 
            +
             | 
| 2 4 | 
             
            $CFLAGS << ' -std=c99 -D_POSIX_C_SOURCE=200809L -Wall -Wextra -Werror'
         | 
| 3 5 |  | 
| 6 | 
            +
            if enable_config('address-sanitizer')
         | 
| 7 | 
            +
              $CFLAGS << ' -O -fsanitize=address -fno-omit-frame-pointer -g'
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 4 10 | 
             
            CONFIG['warnflags'].slice!(/ -Wdeclaration-after-statement/)
         | 
| 5 11 |  | 
| 12 | 
            +
            cwd = File.expand_path(File.dirname(__FILE__))
         | 
| 13 | 
            +
            vendor_dir = File.join(cwd, '../../vendor/c')
         | 
| 14 | 
            +
            src_dir = File.join(cwd, '../../ext/fast_mmaped_file')
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            src_files = %W[#{vendor_dir}/jsmn/jsmn.c #{vendor_dir}/hashmap/src/hashmap.c]
         | 
| 17 | 
            +
            FileUtils.cp(src_files, src_dir)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            $INCFLAGS << " -I#{vendor_dir}/jsmn -I#{vendor_dir}/hashmap/src"
         | 
| 20 | 
            +
             | 
| 6 21 | 
             
            dir_config('fast_mmaped_file')
         | 
| 7 22 | 
             
            create_makefile('fast_mmaped_file')
         | 
| @@ -1,16 +1,20 @@ | |
| 1 | 
            +
            #include <errno.h>
         | 
| 1 2 | 
             
            #include <ruby.h>
         | 
| 2 3 | 
             
            #include <ruby/intern.h>
         | 
| 3 | 
            -
            #include <errno.h>
         | 
| 4 4 |  | 
| 5 | 
            -
            #include < | 
| 6 | 
            -
            #include <value_access.h>
         | 
| 7 | 
            -
            #include <globals.h>
         | 
| 5 | 
            +
            #include <sys/mman.h>
         | 
| 8 6 |  | 
| 9 | 
            -
            #include <jsmn.h>
         | 
| 10 7 | 
             
            #include <hashmap.h>
         | 
| 11 | 
            -
            #include < | 
| 12 | 
            -
             | 
| 13 | 
            -
            #include  | 
| 8 | 
            +
            #include <jsmn.h>
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            #include "globals.h"
         | 
| 11 | 
            +
            #include "utils.h"
         | 
| 12 | 
            +
            #include "value_access.h"
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            #include "file_parsing.h"
         | 
| 15 | 
            +
            #include "file_reading.h"
         | 
| 16 | 
            +
            #include "mmap.h"
         | 
| 17 | 
            +
            #include "rendering.h"
         | 
| 14 18 |  | 
| 15 19 | 
             
            VALUE MMAPED_FILE = Qnil;
         | 
| 16 20 |  | 
| @@ -21,9 +25,13 @@ ID sym_gauge; | |
| 21 25 | 
             
            ID sym_pid;
         | 
| 22 26 | 
             
            ID sym_samples;
         | 
| 23 27 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 28 | 
            +
            VALUE prom_eParsingError;
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            int aggregate_files(struct hashmap *map, VALUE list_of_files) {
         | 
| 31 | 
            +
                buffer_t reading_buffer;
         | 
| 32 | 
            +
                memset(&reading_buffer, 0, sizeof(buffer_t));
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                for (int i = 0; i < RARRAY_LEN(list_of_files); i++) {
         | 
| 27 35 | 
             
                    VALUE params = RARRAY_PTR(list_of_files)[i];
         | 
| 28 36 | 
             
                    file_t file;
         | 
| 29 37 |  | 
| @@ -32,19 +40,19 @@ int aggregate_files(struct hashmap *map, VALUE list_of_files){ | |
| 32 40 | 
             
                        return 0;
         | 
| 33 41 | 
             
                    }
         | 
| 34 42 |  | 
| 35 | 
            -
                    if (!read_from_file(&file, &reading_buffer)){
         | 
| 43 | 
            +
                    if (!read_from_file(&file, &reading_buffer)) {
         | 
| 36 44 | 
             
                        buffer_dispose(&reading_buffer);
         | 
| 37 45 | 
             
                        file_close(&file);
         | 
| 38 46 | 
             
                        return 0;
         | 
| 39 47 | 
             
                    }
         | 
| 40 48 |  | 
| 41 | 
            -
                    if (!process_buffer(&file, &reading_buffer, map)){
         | 
| 49 | 
            +
                    if (!process_buffer(&file, &reading_buffer, map)) {
         | 
| 42 50 | 
             
                        buffer_dispose(&reading_buffer);
         | 
| 43 51 | 
             
                        file_close(&file);
         | 
| 44 52 | 
             
                        return 0;
         | 
| 45 53 | 
             
                    }
         | 
| 46 54 |  | 
| 47 | 
            -
                    if (!file_close(&file)){
         | 
| 55 | 
            +
                    if (!file_close(&file)) {
         | 
| 48 56 | 
             
                        buffer_dispose(&reading_buffer);
         | 
| 49 57 | 
             
                        return 0;
         | 
| 50 58 | 
             
                    }
         | 
| @@ -54,30 +62,36 @@ int aggregate_files(struct hashmap *map, VALUE list_of_files){ | |
| 54 62 | 
             
                return 1;
         | 
| 55 63 | 
             
            }
         | 
| 56 64 |  | 
| 57 | 
            -
            VALUE method_to_metrics(VALUE UNUSED(self), VALUE file_list){
         | 
| 65 | 
            +
            VALUE method_to_metrics(VALUE UNUSED(self), VALUE file_list) {
         | 
| 58 66 | 
             
                struct hashmap map;
         | 
| 59 67 | 
             
                hashmap_setup(&map);
         | 
| 60 68 |  | 
| 61 | 
            -
                if (!aggregate_files(&map, file_list)){ | 
| 69 | 
            +
                if (!aggregate_files(&map, file_list)) {  // all entries in map are now copies that need to be disposed
         | 
| 62 70 | 
             
                    hashmap_destroy(&map);
         | 
| 63 71 | 
             
                    raise_last_exception();
         | 
| 64 72 | 
             
                    return Qnil;
         | 
| 65 73 | 
             
                }
         | 
| 66 74 |  | 
| 67 | 
            -
                 | 
| 75 | 
            +
                entry_t **sorted_entries;
         | 
| 68 76 |  | 
| 69 | 
            -
                if (!sort_map_entries(&map, &sorted_entries)){
         | 
| 70 | 
            -
                    entries_destroy(&map);
         | 
| 77 | 
            +
                if (!sort_map_entries(&map, &sorted_entries)) {
         | 
| 71 78 | 
             
                    hashmap_destroy(&map);
         | 
| 72 79 |  | 
| 73 80 | 
             
                    raise_last_exception();
         | 
| 74 81 | 
             
                    return Qnil;
         | 
| 75 82 | 
             
                }
         | 
| 76 83 |  | 
| 77 | 
            -
                VALUE rv =  | 
| 84 | 
            +
                VALUE rv = rb_str_new("", 0);
         | 
| 85 | 
            +
                if (!entries_to_string(rv, sorted_entries, hashmap_size(&map))) {
         | 
| 86 | 
            +
                    free(sorted_entries);
         | 
| 87 | 
            +
                    hashmap_destroy(&map);
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    raise_last_exception();
         | 
| 90 | 
            +
                    return Qnil;
         | 
| 91 | 
            +
                }
         | 
| 78 92 |  | 
| 93 | 
            +
                RB_GC_GUARD(file_list);  // ensure file list is not GCed before this point
         | 
| 79 94 | 
             
                free(sorted_entries);
         | 
| 80 | 
            -
                entries_destroy(&map);
         | 
| 81 95 | 
             
                hashmap_destroy(&map);
         | 
| 82 96 | 
             
                return rv;
         | 
| 83 97 | 
             
            }
         | 
| @@ -90,11 +104,22 @@ void Init_fast_mmaped_file() { | |
| 90 104 | 
             
                sym_pid = rb_intern("pid");
         | 
| 91 105 | 
             
                sym_samples = rb_intern("samples");
         | 
| 92 106 |  | 
| 93 | 
            -
                 | 
| 107 | 
            +
                prom_eParsingError = rb_define_class("PrometheusParsingError", rb_eRuntimeError);
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                MMAPED_FILE = rb_define_class("FastMmapedFile", rb_cObject);
         | 
| 110 | 
            +
                rb_define_const(MMAPED_FILE, "MAP_SHARED", INT2FIX(MAP_SHARED));
         | 
| 111 | 
            +
             | 
| 94 112 | 
             
                rb_define_singleton_method(MMAPED_FILE, "to_metrics", method_to_metrics, 1);
         | 
| 95 113 |  | 
| 96 | 
            -
                 | 
| 114 | 
            +
                rb_define_alloc_func(MMAPED_FILE, mm_s_alloc);
         | 
| 115 | 
            +
                rb_define_singleton_method(MMAPED_FILE, "new", mm_s_new, -1);
         | 
| 116 | 
            +
                rb_define_method(MMAPED_FILE, "initialize", mm_init, 1);
         | 
| 117 | 
            +
                rb_define_method(MMAPED_FILE, "slice", mm_aref_m, -1);
         | 
| 118 | 
            +
                rb_define_method(MMAPED_FILE, "sync", mm_msync, -1);
         | 
| 119 | 
            +
                rb_define_method(MMAPED_FILE, "munmap", mm_unmap, 0);
         | 
| 120 | 
            +
             | 
| 97 121 | 
             
                rb_define_method(MMAPED_FILE, "used", method_load_used, 0);
         | 
| 98 122 | 
             
                rb_define_method(MMAPED_FILE, "used=", method_save_used, 1);
         | 
| 99 | 
            -
                rb_define_method(MMAPED_FILE, " | 
| 123 | 
            +
                rb_define_method(MMAPED_FILE, "fetch_entry", method_fetch_entry, 3);
         | 
| 124 | 
            +
                rb_define_method(MMAPED_FILE, "upsert_entry", method_upsert_entry, 3);
         | 
| 100 125 | 
             
            }
         | 
| @@ -1,67 +1,38 @@ | |
| 1 1 | 
             
            #include <hashmap.h>
         | 
| 2 | 
            -
            #include <file_format.h>
         | 
| 3 | 
            -
            #include <globals.h>
         | 
| 4 | 
            -
            #include <utils.h>
         | 
| 5 2 | 
             
            #include <jsmn.h>
         | 
| 6 | 
            -
            #include  | 
| 3 | 
            +
            #include <ruby.h>
         | 
| 7 4 |  | 
| 8 | 
            -
             | 
| 5 | 
            +
            #include "file_format.h"
         | 
| 6 | 
            +
            #include "file_parsing.h"
         | 
| 7 | 
            +
            #include "globals.h"
         | 
| 8 | 
            +
            #include "utils.h"
         | 
| 9 9 |  | 
| 10 | 
            -
             | 
| 10 | 
            +
            HASHMAP_FUNCS_CREATE(entry, const entry_t, entry_t)
         | 
| 11 11 |  | 
| 12 | 
            -
             | 
| 13 | 
            -
            	size_t hash = 0;
         | 
| 12 | 
            +
            typedef int (*compare_fn)(const void *a, const void *b);
         | 
| 14 13 |  | 
| 15 | 
            -
             | 
| 16 | 
            -
            		hash += *(const char *)(entry->json + i);
         | 
| 17 | 
            -
            		hash += (hash << 10);
         | 
| 18 | 
            -
            		hash ^= (hash >> 6);
         | 
| 19 | 
            -
            	}
         | 
| 20 | 
            -
            	hash += (hash << 3);
         | 
| 21 | 
            -
            	hash ^= (hash >> 11);
         | 
| 22 | 
            -
            	hash += (hash << 15);
         | 
| 23 | 
            -
            	return hash;
         | 
| 24 | 
            -
            }
         | 
| 14 | 
            +
            static size_t hashmap_hash_entry(const entry_t *entry) { return hashmap_hash_string(entry->json); }
         | 
| 25 15 |  | 
| 26 | 
            -
            int hashmap_compare_entry(const  | 
| 27 | 
            -
            {
         | 
| 28 | 
            -
                if (a->json_size != b->json_size){
         | 
| 16 | 
            +
            static int hashmap_compare_entry(const entry_t *a, const entry_t *b) {
         | 
| 17 | 
            +
                if (a->json_size != b->json_size) {
         | 
| 29 18 | 
             
                    return -1;
         | 
| 30 19 | 
             
                }
         | 
| 31 20 |  | 
| 32 | 
            -
                if (is_pid_significant(a) && (rb_str_equal(a->pid, b->pid) == Qfalse)){ | 
| 21 | 
            +
                if (is_pid_significant(a) && (rb_str_equal(a->pid, b->pid) == Qfalse)) {
         | 
| 33 22 | 
             
                    return -1;
         | 
| 34 23 | 
             
                }
         | 
| 35 24 |  | 
| 36 | 
            -
             | 
| 25 | 
            +
                return strncmp(a->json, b->json, a->json_size);
         | 
| 37 26 | 
             
            }
         | 
| 38 27 |  | 
| 39 | 
            -
             | 
| 40 | 
            -
                entry_struct *copied = (entry_struct *)malloc(sizeof(entry_struct));
         | 
| 41 | 
            -
                if (copied == NULL) {
         | 
| 42 | 
            -
                    return NULL;
         | 
| 43 | 
            -
                }
         | 
| 44 | 
            -
                memcpy(copied, entry, sizeof(entry_struct));
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                copied->json = malloc(entry->json_size);
         | 
| 47 | 
            -
                if (copied->json == NULL){
         | 
| 48 | 
            -
                    free(copied);
         | 
| 49 | 
            -
                    return NULL;
         | 
| 50 | 
            -
                }
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                memcpy(copied->json, entry->json, entry->json_size);
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                return copied;
         | 
| 55 | 
            -
            }
         | 
| 56 | 
            -
             | 
| 57 | 
            -
            void entry_free(entry_struct *entry){
         | 
| 28 | 
            +
            static void entry_free(entry_t *entry) {
         | 
| 58 29 | 
             
                free(entry->json);
         | 
| 59 30 | 
             
                free(entry);
         | 
| 60 31 | 
             
            }
         | 
| 61 32 |  | 
| 62 | 
            -
            void merge_entry( | 
| 63 | 
            -
                if (entry->type == sym_gauge){
         | 
| 64 | 
            -
                    if (entry->multiprocess_mode == sym_min){
         | 
| 33 | 
            +
            static void merge_entry(entry_t *found, const entry_t *entry) {
         | 
| 34 | 
            +
                if (entry->type == sym_gauge) {
         | 
| 35 | 
            +
                    if (entry->multiprocess_mode == sym_min) {
         | 
| 65 36 | 
             
                        found->value = min(found->value, entry->value);
         | 
| 66 37 | 
             
                    } else if (entry->multiprocess_mode == sym_max) {
         | 
| 67 38 | 
             
                        found->value = max(found->value, entry->value);
         | 
| @@ -75,60 +46,72 @@ void merge_entry(entry_struct *found, const entry_struct *entry){ | |
| 75 46 | 
             
                }
         | 
| 76 47 | 
             
            }
         | 
| 77 48 |  | 
| 78 | 
            -
             | 
| 79 | 
            -
                 | 
| 80 | 
            -
                if (found){
         | 
| 49 | 
            +
            void merge_or_store(struct hashmap *map, entry_t *entry) {
         | 
| 50 | 
            +
                entry_t *found = entry_hashmap_get(map, entry);
         | 
| 51 | 
            +
                if (found) {
         | 
| 81 52 | 
             
                    merge_entry(found, entry);
         | 
| 53 | 
            +
                    entry_free(entry);
         | 
| 82 54 | 
             
                } else {
         | 
| 83 | 
            -
                     | 
| 84 | 
            -
                    if (copy == NULL) {
         | 
| 85 | 
            -
                        save_exception(rb_eNoMemError, "Failed copying metrics entry");
         | 
| 86 | 
            -
                        return 0;
         | 
| 87 | 
            -
                    }
         | 
| 88 | 
            -
                    entry_hashmap_put(map, copy, copy); // use the hashmap like hashset actually
         | 
| 55 | 
            +
                    entry_hashmap_put(map, entry, entry);  // use the hashmap like hashset actually
         | 
| 89 56 | 
             
                }
         | 
| 90 | 
            -
                return 1;
         | 
| 91 57 | 
             
            }
         | 
| 92 58 |  | 
| 93 | 
            -
            inline  | 
| 94 | 
            -
                 | 
| 59 | 
            +
            inline entry_t *entry_new(buffer_t *source, uint32_t pos, uint32_t encoded_len, file_t *file_info) {
         | 
| 60 | 
            +
                entry_t *entry = calloc(1, sizeof(entry_t));
         | 
| 61 | 
            +
                if (entry == NULL) {
         | 
| 62 | 
            +
                    return NULL;
         | 
| 63 | 
            +
                }
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                entry->json = malloc(encoded_len + 1);
         | 
| 66 | 
            +
                if (entry->json == NULL) {
         | 
| 67 | 
            +
                    free(entry);
         | 
| 68 | 
            +
                    return NULL;
         | 
| 69 | 
            +
                }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                memcpy(entry->json, source->buffer + pos, encoded_len);
         | 
| 72 | 
            +
                entry->json[encoded_len] = '\0';
         | 
| 73 | 
            +
                entry->json_size = encoded_len;
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                entry->pid = file_info->pid;
         | 
| 76 | 
            +
                entry->multiprocess_mode = file_info->multiprocess_mode;
         | 
| 77 | 
            +
                entry->type = file_info->type;
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                char *value_ptr = source->buffer + pos + encoded_len + padding_length(encoded_len);
         | 
| 80 | 
            +
                memcpy(&(entry->value), value_ptr, sizeof(double));
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                return entry;
         | 
| 95 83 | 
             
            }
         | 
| 96 84 |  | 
| 97 | 
            -
             | 
| 85 | 
            +
            static int add_parsed_name(entry_t *entry) {
         | 
| 98 86 | 
             
                jsmn_parser parser;
         | 
| 99 87 | 
             
                jsmn_init(&parser);
         | 
| 100 88 |  | 
| 101 | 
            -
                jsmntok_t  | 
| 102 | 
            -
                 | 
| 89 | 
            +
                jsmntok_t tokens[2];
         | 
| 90 | 
            +
                memset(&tokens, 0, sizeof(tokens));
         | 
| 103 91 |  | 
| 104 | 
            -
                 | 
| 105 | 
            -
             | 
| 106 | 
            -
                }
         | 
| 92 | 
            +
                jsmn_parse(&parser, entry->json, entry->json_size, tokens, 2);
         | 
| 93 | 
            +
                jsmntok_t *name_token = &tokens[1];
         | 
| 107 94 |  | 
| 108 | 
            -
                 | 
| 109 | 
            -
             | 
| 95 | 
            +
                if (name_token->start < name_token->end && name_token->start > 0) {
         | 
| 96 | 
            +
                    entry->name = entry->json + name_token->start;
         | 
| 97 | 
            +
                    entry->name_len = name_token->end - name_token->start;
         | 
| 98 | 
            +
                    return 1;
         | 
| 99 | 
            +
                }
         | 
| 100 | 
            +
                return 0;
         | 
| 110 101 | 
             
            }
         | 
| 111 102 |  | 
| 112 | 
            -
            int entry_lexical_comparator(const  | 
| 103 | 
            +
            static int entry_lexical_comparator(const entry_t **a, const entry_t **b) {
         | 
| 113 104 | 
             
                size_t min_length = min((*a)->json_size, (*b)->json_size);
         | 
| 114 105 | 
             
                return strncmp((*a)->json, (*b)->json, min_length);
         | 
| 115 106 | 
             
            }
         | 
| 116 107 |  | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
            }
         | 
| 122 | 
            -
             | 
| 123 | 
            -
            void entries_destroy(struct hashmap *map){
         | 
| 124 | 
            -
                struct hashmap_iter *iter;
         | 
| 125 | 
            -
                for (iter = hashmap_iter(map); iter; iter = hashmap_iter_next(map, iter)) {
         | 
| 126 | 
            -
                    entry_struct *entry = (entry_struct *)entry_hashmap_iter_get_key(iter);
         | 
| 127 | 
            -
                    entry_free(entry);
         | 
| 128 | 
            -
                }
         | 
| 108 | 
            +
            void hashmap_setup(struct hashmap *map) {
         | 
| 109 | 
            +
                hashmap_init(map, (size_t(*)(const void *))hashmap_hash_entry,
         | 
| 110 | 
            +
                             (int (*)(const void *, const void *))hashmap_compare_entry, 1000);
         | 
| 111 | 
            +
                hashmap_set_key_alloc_funcs(map, NULL, (void (*)(void *))entry_free);
         | 
| 129 112 | 
             
            }
         | 
| 130 113 |  | 
| 131 | 
            -
            int process_buffer(file_t *file_info, buffer_t *source, struct hashmap *map){
         | 
| 114 | 
            +
            int process_buffer(file_t *file_info, buffer_t *source, struct hashmap *map) {
         | 
| 132 115 | 
             
                if (source->size < START_POSITION) {
         | 
| 133 116 | 
             
                    // nothing to read
         | 
| 134 117 | 
             
                    return 1;
         | 
| @@ -136,10 +119,9 @@ int process_buffer(file_t *file_info, buffer_t *source, struct hashmap *map){ | |
| 136 119 | 
             
                uint32_t used;
         | 
| 137 120 | 
             
                memcpy(&used, source->buffer, sizeof(uint32_t));
         | 
| 138 121 |  | 
| 139 | 
            -
                if (used > source->size){
         | 
| 140 | 
            -
                     | 
| 141 | 
            -
             | 
| 142 | 
            -
                        file_info->path, used, source->size);
         | 
| 122 | 
            +
                if (used > source->size) {
         | 
| 123 | 
            +
                    save_exception(prom_eParsingError, "source file %s corrupted, used %u > file size %u", file_info->path, used,
         | 
| 124 | 
            +
                                   source->size);
         | 
| 143 125 | 
             
                    return 0;
         | 
| 144 126 | 
             
                }
         | 
| 145 127 |  | 
| @@ -152,62 +134,55 @@ int process_buffer(file_t *file_info, buffer_t *source, struct hashmap *map){ | |
| 152 134 | 
             
                    uint32_t value_offset = encoded_len + padding_length(encoded_len);
         | 
| 153 135 |  | 
| 154 136 | 
             
                    if (pos + value_offset + sizeof(double) > used) {
         | 
| 155 | 
            -
                         | 
| 156 | 
            -
             | 
| 157 | 
            -
                                    file_info->path, used, pos + value_offset + sizeof(double));
         | 
| 137 | 
            +
                        save_exception(prom_eParsingError, "source file %s corrupted, used %u < stored data length %u",
         | 
| 138 | 
            +
                                       file_info->path, used, pos + value_offset + sizeof(double));
         | 
| 158 139 | 
             
                        return 0;
         | 
| 159 140 | 
             
                    }
         | 
| 160 141 |  | 
| 161 | 
            -
                     | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
                    entry.pid = file_info->pid;
         | 
| 165 | 
            -
                    entry.type = file_info->type;
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                    memcpy(&entry.value, entry.json + value_offset, sizeof(double));
         | 
| 168 | 
            -
             | 
| 169 | 
            -
                    if (!process_entry(map, &entry)) {
         | 
| 170 | 
            -
                        entries_destroy(map);
         | 
| 142 | 
            +
                    entry_t *entry = entry_new(source, pos, encoded_len, file_info);
         | 
| 143 | 
            +
                    if (entry == NULL) {
         | 
| 144 | 
            +
                        save_exception(rb_eNoMemError, "Failed creating metrics entry");
         | 
| 171 145 | 
             
                        return 0;
         | 
| 172 146 | 
             
                    }
         | 
| 173 147 |  | 
| 148 | 
            +
                    merge_or_store(map, entry);
         | 
| 149 | 
            +
             | 
| 174 150 | 
             
                    pos += value_offset + sizeof(double);
         | 
| 175 151 | 
             
                }
         | 
| 176 152 | 
             
                return 1;
         | 
| 177 153 | 
             
            }
         | 
| 178 154 |  | 
| 179 | 
            -
            int sort_map_entries(const struct hashmap *map,  | 
| 155 | 
            +
            int sort_map_entries(const struct hashmap *map, entry_t ***sorted_entries) {
         | 
| 180 156 | 
             
                size_t num = hashmap_size(map);
         | 
| 181 157 |  | 
| 182 | 
            -
                 | 
| 183 | 
            -
                entry_struct **list = malloc(list_size);
         | 
| 158 | 
            +
                entry_t **list = calloc(num, sizeof(entry_t *));
         | 
| 184 159 |  | 
| 185 | 
            -
                if (list == NULL){
         | 
| 186 | 
            -
                    save_exception(rb_eNoMemError, "Couldn't allocate %zu memory",  | 
| 160 | 
            +
                if (list == NULL) {
         | 
| 161 | 
            +
                    save_exception(rb_eNoMemError, "Couldn't allocate for %zu memory", num * sizeof(entry_t *));
         | 
| 187 162 | 
             
                    return 0;
         | 
| 188 163 | 
             
                }
         | 
| 189 164 |  | 
| 190 165 | 
             
                size_t cnt = 0;
         | 
| 191 166 | 
             
                struct hashmap_iter *iter;
         | 
| 192 167 | 
             
                for (iter = hashmap_iter(map); iter; iter = hashmap_iter_next(map, iter)) {
         | 
| 193 | 
            -
                     | 
| 194 | 
            -
                    add_parsed_name(entry) | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
                     | 
| 168 | 
            +
                    entry_t *entry = (entry_t *)entry_hashmap_iter_get_key(iter);
         | 
| 169 | 
            +
                    if (add_parsed_name(entry)) {
         | 
| 170 | 
            +
                        list[cnt] = entry;
         | 
| 171 | 
            +
                        cnt++;
         | 
| 172 | 
            +
                    }
         | 
| 198 173 | 
             
                }
         | 
| 199 | 
            -
                if (cnt != num){
         | 
| 174 | 
            +
                if (cnt != num) {
         | 
| 200 175 | 
             
                    save_exception(rb_eRuntimeError, "Processed entries %zu != map entries %zu", cnt, num);
         | 
| 201 176 | 
             
                    free(list);
         | 
| 202 177 | 
             
                    return 0;
         | 
| 203 178 | 
             
                }
         | 
| 204 179 |  | 
| 205 | 
            -
                qsort(list, cnt, sizeof( | 
| 180 | 
            +
                qsort(list, cnt, sizeof(entry_t *), (compare_fn)&entry_lexical_comparator);
         | 
| 206 181 | 
             
                *sorted_entries = list;
         | 
| 207 182 | 
             
                return 1;
         | 
| 208 183 | 
             
            }
         | 
| 209 184 |  | 
| 210 | 
            -
            int is_pid_significant(const  | 
| 185 | 
            +
            int is_pid_significant(const entry_t *e) {
         | 
| 211 186 | 
             
                ID mp = e->multiprocess_mode;
         | 
| 212 187 | 
             
                return e->type == sym_gauge && !(mp == sym_min || mp == sym_max || mp == sym_livesum);
         | 
| 213 188 | 
             
            }
         |