prometheus-client-mmap 0.20.3-x86_64-darwin
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 +7 -0
 - data/README.md +253 -0
 - data/ext/fast_mmaped_file/extconf.rb +30 -0
 - data/ext/fast_mmaped_file/fast_mmaped_file.c +122 -0
 - data/ext/fast_mmaped_file/file_format.c +5 -0
 - data/ext/fast_mmaped_file/file_format.h +11 -0
 - data/ext/fast_mmaped_file/file_parsing.c +195 -0
 - data/ext/fast_mmaped_file/file_parsing.h +27 -0
 - data/ext/fast_mmaped_file/file_reading.c +102 -0
 - data/ext/fast_mmaped_file/file_reading.h +30 -0
 - data/ext/fast_mmaped_file/globals.h +14 -0
 - data/ext/fast_mmaped_file/mmap.c +427 -0
 - data/ext/fast_mmaped_file/mmap.h +61 -0
 - data/ext/fast_mmaped_file/rendering.c +199 -0
 - data/ext/fast_mmaped_file/rendering.h +8 -0
 - data/ext/fast_mmaped_file/utils.c +56 -0
 - data/ext/fast_mmaped_file/utils.h +22 -0
 - data/ext/fast_mmaped_file/value_access.c +242 -0
 - data/ext/fast_mmaped_file/value_access.h +15 -0
 - data/ext/fast_mmaped_file_rs/.cargo/config.toml +23 -0
 - data/ext/fast_mmaped_file_rs/Cargo.lock +790 -0
 - data/ext/fast_mmaped_file_rs/Cargo.toml +30 -0
 - data/ext/fast_mmaped_file_rs/README.md +52 -0
 - data/ext/fast_mmaped_file_rs/extconf.rb +30 -0
 - data/ext/fast_mmaped_file_rs/src/error.rs +174 -0
 - data/ext/fast_mmaped_file_rs/src/file_entry.rs +579 -0
 - data/ext/fast_mmaped_file_rs/src/file_info.rs +190 -0
 - data/ext/fast_mmaped_file_rs/src/lib.rs +79 -0
 - data/ext/fast_mmaped_file_rs/src/macros.rs +14 -0
 - data/ext/fast_mmaped_file_rs/src/map.rs +492 -0
 - data/ext/fast_mmaped_file_rs/src/mmap.rs +151 -0
 - data/ext/fast_mmaped_file_rs/src/parser.rs +346 -0
 - data/ext/fast_mmaped_file_rs/src/raw_entry.rs +473 -0
 - data/ext/fast_mmaped_file_rs/src/testhelper.rs +222 -0
 - data/ext/fast_mmaped_file_rs/src/util.rs +121 -0
 - data/lib/2.7/fast_mmaped_file.bundle +0 -0
 - data/lib/2.7/fast_mmaped_file_rs.bundle +0 -0
 - data/lib/3.0/fast_mmaped_file.bundle +0 -0
 - data/lib/3.0/fast_mmaped_file_rs.bundle +0 -0
 - data/lib/3.1/fast_mmaped_file.bundle +0 -0
 - data/lib/3.1/fast_mmaped_file_rs.bundle +0 -0
 - data/lib/3.2/fast_mmaped_file.bundle +0 -0
 - data/lib/3.2/fast_mmaped_file_rs.bundle +0 -0
 - data/lib/prometheus/client/configuration.rb +23 -0
 - data/lib/prometheus/client/counter.rb +27 -0
 - data/lib/prometheus/client/formats/text.rb +118 -0
 - data/lib/prometheus/client/gauge.rb +40 -0
 - data/lib/prometheus/client/helper/entry_parser.rb +132 -0
 - data/lib/prometheus/client/helper/file_locker.rb +50 -0
 - data/lib/prometheus/client/helper/json_parser.rb +23 -0
 - data/lib/prometheus/client/helper/metrics_processing.rb +45 -0
 - data/lib/prometheus/client/helper/metrics_representation.rb +51 -0
 - data/lib/prometheus/client/helper/mmaped_file.rb +64 -0
 - data/lib/prometheus/client/helper/plain_file.rb +29 -0
 - data/lib/prometheus/client/histogram.rb +80 -0
 - data/lib/prometheus/client/label_set_validator.rb +86 -0
 - data/lib/prometheus/client/metric.rb +80 -0
 - data/lib/prometheus/client/mmaped_dict.rb +79 -0
 - data/lib/prometheus/client/mmaped_value.rb +154 -0
 - data/lib/prometheus/client/page_size.rb +17 -0
 - data/lib/prometheus/client/push.rb +203 -0
 - data/lib/prometheus/client/rack/collector.rb +88 -0
 - data/lib/prometheus/client/rack/exporter.rb +96 -0
 - data/lib/prometheus/client/registry.rb +65 -0
 - data/lib/prometheus/client/simple_value.rb +31 -0
 - data/lib/prometheus/client/summary.rb +69 -0
 - data/lib/prometheus/client/support/unicorn.rb +35 -0
 - data/lib/prometheus/client/uses_value_type.rb +20 -0
 - data/lib/prometheus/client/version.rb +5 -0
 - data/lib/prometheus/client.rb +58 -0
 - data/lib/prometheus.rb +3 -0
 - data/vendor/c/hashmap/.gitignore +52 -0
 - data/vendor/c/hashmap/LICENSE +21 -0
 - data/vendor/c/hashmap/README.md +90 -0
 - data/vendor/c/hashmap/_config.yml +1 -0
 - data/vendor/c/hashmap/src/hashmap.c +692 -0
 - data/vendor/c/hashmap/src/hashmap.h +267 -0
 - data/vendor/c/hashmap/test/Makefile +22 -0
 - data/vendor/c/hashmap/test/hashmap_test.c +608 -0
 - data/vendor/c/jsmn/.travis.yml +4 -0
 - data/vendor/c/jsmn/LICENSE +20 -0
 - data/vendor/c/jsmn/Makefile +41 -0
 - data/vendor/c/jsmn/README.md +168 -0
 - data/vendor/c/jsmn/example/jsondump.c +126 -0
 - data/vendor/c/jsmn/example/simple.c +76 -0
 - data/vendor/c/jsmn/jsmn.c +314 -0
 - data/vendor/c/jsmn/jsmn.h +76 -0
 - data/vendor/c/jsmn/library.json +16 -0
 - data/vendor/c/jsmn/test/test.h +27 -0
 - data/vendor/c/jsmn/test/tests.c +407 -0
 - data/vendor/c/jsmn/test/testutil.h +94 -0
 - metadata +243 -0
 
| 
         @@ -0,0 +1,102 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #include "file_reading.h"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            #include <errno.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #include <fcntl.h>
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            #include "utils.h"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            static int file_open(file_t *source, const char *filepath) {
         
     | 
| 
      
 9 
     | 
    
         
            +
                source->file = fopen(filepath, "r");
         
     | 
| 
      
 10 
     | 
    
         
            +
                size_t filepath_len = strlen(filepath) + sizeof(char);
         
     | 
| 
      
 11 
     | 
    
         
            +
                source->path = malloc(filepath_len);
         
     | 
| 
      
 12 
     | 
    
         
            +
                memcpy(source->path, filepath, filepath_len);
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                if (source->file == NULL) {
         
     | 
| 
      
 15 
     | 
    
         
            +
                    save_exception(rb_eArgError, "Can't open %s, errno: %d", filepath, errno);
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                struct stat sb;
         
     | 
| 
      
 21 
     | 
    
         
            +
                if (fstat(fileno(source->file), &sb) != 0) {
         
     | 
| 
      
 22 
     | 
    
         
            +
                    fclose(source->file);
         
     | 
| 
      
 23 
     | 
    
         
            +
                    save_exception(rb_eIOError, "Can't stat file, errno: %d", errno);
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 26 
     | 
    
         
            +
                }
         
     | 
| 
      
 27 
     | 
    
         
            +
                source->length = sb.st_size;
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                // go to start
         
     | 
| 
      
 30 
     | 
    
         
            +
                if (fseek(source->file, 0L, SEEK_SET) != 0) {
         
     | 
| 
      
 31 
     | 
    
         
            +
                    fclose(source->file);
         
     | 
| 
      
 32 
     | 
    
         
            +
                    save_exception(rb_eIOError, "Can't fseek %zu, errno: %d", 0, errno);
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 35 
     | 
    
         
            +
                }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                return 1;
         
     | 
| 
      
 38 
     | 
    
         
            +
            }
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            int file_close(file_t *source) {
         
     | 
| 
      
 41 
     | 
    
         
            +
                free(source->path);
         
     | 
| 
      
 42 
     | 
    
         
            +
                if (fclose(source->file) != 0) {
         
     | 
| 
      
 43 
     | 
    
         
            +
                    save_exception(rb_eIOError, "Can't fclose file, errno: %d", 0, errno);
         
     | 
| 
      
 44 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 45 
     | 
    
         
            +
                }
         
     | 
| 
      
 46 
     | 
    
         
            +
                source->file = 0;
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                return 1;
         
     | 
| 
      
 49 
     | 
    
         
            +
            }
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            int file_open_from_params(file_t *source, VALUE params) {
         
     | 
| 
      
 52 
     | 
    
         
            +
                if (RARRAY_LEN(params) != 4) {
         
     | 
| 
      
 53 
     | 
    
         
            +
                    save_exception(rb_eArgError, "wrong number of arguments %lu instead of 4", RARRAY_LEN(params));
         
     | 
| 
      
 54 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 55 
     | 
    
         
            +
                }
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                VALUE filepath = rb_ary_entry(params, 0);
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                source->multiprocess_mode = rb_sym2id(rb_ary_entry(params, 1));
         
     | 
| 
      
 60 
     | 
    
         
            +
                source->type = rb_sym2id(rb_ary_entry(params, 2));
         
     | 
| 
      
 61 
     | 
    
         
            +
                source->pid = rb_ary_entry(params, 3);
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                return file_open(source, StringValueCStr(filepath));
         
     | 
| 
      
 64 
     | 
    
         
            +
            }
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            int read_from_file(const file_t *source, buffer_t *data) {
         
     | 
| 
      
 67 
     | 
    
         
            +
                data->size = 0;
         
     | 
| 
      
 68 
     | 
    
         
            +
                if (data->buffer == NULL) {
         
     | 
| 
      
 69 
     | 
    
         
            +
                    data->buffer = malloc(source->length);
         
     | 
| 
      
 70 
     | 
    
         
            +
                    if (data->buffer == NULL) {
         
     | 
| 
      
 71 
     | 
    
         
            +
                        save_exception(rb_eIOError, "Can't malloc %zu, errno: %d", source->length, errno);
         
     | 
| 
      
 72 
     | 
    
         
            +
                        return 0;
         
     | 
| 
      
 73 
     | 
    
         
            +
                    }
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    data->capacity = source->length;
         
     | 
| 
      
 76 
     | 
    
         
            +
                } else if (data->capacity < source->length) {
         
     | 
| 
      
 77 
     | 
    
         
            +
                    data->buffer = realloc(data->buffer, source->length);
         
     | 
| 
      
 78 
     | 
    
         
            +
                    if (data->buffer == NULL) {
         
     | 
| 
      
 79 
     | 
    
         
            +
                        save_exception(rb_eIOError, "Can't realloc %zu, errno: %d", source->length, errno);
         
     | 
| 
      
 80 
     | 
    
         
            +
                        return 0;
         
     | 
| 
      
 81 
     | 
    
         
            +
                    }
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                    data->capacity = source->length;
         
     | 
| 
      
 84 
     | 
    
         
            +
                }
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                data->size = fread(data->buffer, sizeof(char), source->length, source->file);
         
     | 
| 
      
 87 
     | 
    
         
            +
                if (data->size != source->length) {
         
     | 
| 
      
 88 
     | 
    
         
            +
                    save_exception(rb_eIOError, "Couldn't read whole file, read %zu, instead of %zu", data->size, source->length);
         
     | 
| 
      
 89 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 90 
     | 
    
         
            +
                }
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                return 1;
         
     | 
| 
      
 93 
     | 
    
         
            +
            }
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            void buffer_dispose(buffer_t *buffer) {
         
     | 
| 
      
 96 
     | 
    
         
            +
                if (buffer->buffer) {
         
     | 
| 
      
 97 
     | 
    
         
            +
                    free(buffer->buffer);
         
     | 
| 
      
 98 
     | 
    
         
            +
                }
         
     | 
| 
      
 99 
     | 
    
         
            +
                buffer->buffer = NULL;
         
     | 
| 
      
 100 
     | 
    
         
            +
                buffer->size = 0;
         
     | 
| 
      
 101 
     | 
    
         
            +
                buffer->capacity = 0;
         
     | 
| 
      
 102 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #ifndef FILE_READING_H
         
     | 
| 
      
 2 
     | 
    
         
            +
            #define FILE_READING_H
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <ruby.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            typedef struct {
         
     | 
| 
      
 6 
     | 
    
         
            +
                FILE *file;
         
     | 
| 
      
 7 
     | 
    
         
            +
                size_t length;
         
     | 
| 
      
 8 
     | 
    
         
            +
                char *path;
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                // Information processed from file path
         
     | 
| 
      
 11 
     | 
    
         
            +
                ID multiprocess_mode;
         
     | 
| 
      
 12 
     | 
    
         
            +
                ID type;
         
     | 
| 
      
 13 
     | 
    
         
            +
                VALUE pid;
         
     | 
| 
      
 14 
     | 
    
         
            +
            } file_t;
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            typedef struct {
         
     | 
| 
      
 17 
     | 
    
         
            +
                char *buffer;
         
     | 
| 
      
 18 
     | 
    
         
            +
                size_t size;
         
     | 
| 
      
 19 
     | 
    
         
            +
                size_t capacity;
         
     | 
| 
      
 20 
     | 
    
         
            +
            } buffer_t;
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            int file_close(file_t *file);
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            int file_open_from_params(file_t *file, VALUE params);
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            int read_from_file(const file_t *source, buffer_t *data);
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            void buffer_dispose(buffer_t *buffer);
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            #endif
         
     | 
| 
         @@ -0,0 +1,427 @@ 
     | 
|
| 
      
 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 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 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
         
     |