1 #include "libautomation.h"
8 #include <sys/stat.h> /* For mode constants */
9 #include <fcntl.h> /* For O_* constants */
13 #include "managed_data.h"
15 #define MAGIC_NUMBER 217
19 ATM_SHM atm_shm_stdmem
;
21 static int _atm_shm_open(const char *id
, int flags
) {
24 snprintf(name
, NAME_MAX
, "/dev/shm/libautomation_%s", id
);
25 return open(name
, flags
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
28 static ATM_SHM
_atm_shm_alloc(struct ATM_SHM_HEADER
*h
) {
29 ATM_SHM mem
= malloc(sizeof(*mem
));
32 mem
->keys
= (void *) h
+ sizeof(*h
);
33 mem
->data
= (void *) h
+ SHM_SIZE
/2;
39 ATM_SHM
atm_shm_attach(const char *id
) {
40 struct ATM_SHM_HEADER
*h
;
44 fd
= _atm_shm_open(id
, O_RDONLY
);
50 h
= mmap(NULL
, SHM_SIZE
, PROT_READ
, MAP_SHARED
, fd
, 0);
52 atm_fail(id
); /* Should never happen */
54 if (h
->magic
!= MAGIC_NUMBER
) {
55 atm_log("Shared memory with id '%s' is corrupted!", id
);
59 mem
= _atm_shm_alloc(h
);
65 ATM_SHM
atm_shm_create(const char *id
) {
66 struct ATM_SHM_HEADER
*h
;
71 fd
= _atm_shm_open(id
, O_RDWR
| O_CREAT
);
77 if (fd_info
.st_size
== 0) /* File was just created */
78 ftruncate(fd
, SHM_SIZE
);
79 else if (fd_info
.st_size
!= SHM_SIZE
) /* Not our file !!! */
82 h
= mmap(NULL
, SHM_SIZE
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
84 atm_fail(id
); /* Should never happen */
86 mem
= _atm_shm_alloc(h
);
89 if (fd_info
.st_size
== 0) { /* Need to initialize data structure */
90 /* mem->keys[] already initialized by ftruncate() */
91 h
->magic
= MAGIC_NUMBER
;
93 else if (h
->magic
!= MAGIC_NUMBER
) {
95 atm_log("Shared memory with id '%s' is corrupted!", id
);
102 atm_shm_stdmem
= mem
;
108 * Internal version of atm_shm_find() assumes that mem->keys[] is already
109 * locked by mem->header->sem ...
111 static int _atm_shm_find(ATM_SHM mem
, const char *key
) {
115 for (i
= 0; *p
; ++i
) {
119 p
+= strlen(&mem
->keys
[i
]) + 1;
125 struct ATM_VALUE
*atm_shm_find(ATM_SHM mem
, const char *key
) {
128 flock(mem
->fd
, LOCK_EX
);
129 i
= _atm_shm_find(mem
, key
);
130 flock(mem
->fd
, LOCK_UN
);
132 return i
== -1 ? NULL
: &mem
->data
[i
];
135 struct ATM_VALUE
*atm_shm_register(ATM_SHM mem
, const char *key
) {
138 flock(mem
->fd
, LOCK_EX
);
140 i
= _atm_shm_find(mem
, key
);
142 keysize
= strlen(key
) + 1;
143 if (keysize
+ mem
->header
->ks
+ sizeof(*mem
->header
) >= SHM_SIZE
/2) {
144 atm_log("running out of shared memory, crashing ...");
147 strcpy(&mem
->keys
[mem
->header
->ks
], key
);
148 mem
->header
->ks
+= keysize
;
149 i
= mem
->header
->value_count
++;
152 flock(mem
->fd
, LOCK_UN
);
154 return &mem
->data
[i
];
157 struct MD_LUT _atm_shm_lut
= {0, 0, NULL
};
159 struct ATM_VALUE
*atm_shm_get(const char *id
, const char *key
) {
160 struct MD_LUT_ENTRY
*e
= NULL
;
163 if (_atm_shm_lut
.size
== 0)
164 md_lut_init(&_atm_shm_lut
);
166 e
= md_lut_find(&_atm_shm_lut
, id
);
169 return atm_shm_find(e
->data
, key
);
171 mem
= atm_shm_attach(id
);
175 md_lut_insert(&_atm_shm_lut
, id
, mem
);
177 return atm_shm_find(mem
, key
);
180 void atm_shm_update(struct ATM_VALUE
*var
, int value
) {
182 var
->ts
= atm_timestamp();
185 struct ATM_VALUE
*atm_value(const char *key
) {
186 return (atm_shm_stdmem
&& key
) ? atm_shm_register(atm_shm_stdmem
, key
)
187 : malloc(sizeof(struct ATM_VALUE
));