1 /* Blerg is (C) 2011 The Dominion of Awesome, and is distributed under a
2 * BSD-style license. Please see the COPYING file for details.
14 #include <stringring.h>
16 #define STRINGRING_DATA_CHECK() \
25 struct stringring_handle * stringring_open(const char *filename) {
26 struct stringring_handle *sh;
30 sh = malloc(sizeof(struct stringring_handle));
32 perror("stringring_handle malloc");
36 sh->fd = open(filename, O_RDWR | O_CREAT, 0600);
37 flock(sh->fd, LOCK_EX);
39 perror("stringring open");
40 goto stringring_open__open_failed;
44 if (st.st_size < sizeof(struct stringring)) {
45 ftruncate(sh->fd, sizeof(struct stringring));
48 sh->sr = mmap(NULL, sizeof(struct stringring), PROT_READ | PROT_WRITE, MAP_SHARED, sh->fd, 0);
49 if (sh->sr == MAP_FAILED) {
50 perror("stringring mmap");
51 goto stringring_open__map_failed;
57 flock(sh->fd, LOCK_UN);
61 stringring_open__map_failed:
62 flock(sh->fd, LOCK_UN);
64 stringring_open__open_failed:
69 void stringring_close(struct stringring_handle *sh) {
74 munmap(sh->sr, sizeof(struct stringring));
82 int stringring_add(struct stringring_handle *sh, const char *data) {
83 STRINGRING_DATA_CHECK();
85 flock(sh->fd, LOCK_EX);
86 if (sh->sr->counter == 0) {
87 sh->sr->counter = STRINGRING_N_ENTRIES - 1;
92 int data_len = strlen(data);
93 sh->sr->entries[sh->sr->counter].timestamp = time(NULL);
94 strncpy(sh->sr->entries[sh->sr->counter].data, data, STRINGRING_DATA_SIZE);
95 if (data_len < STRINGRING_DATA_SIZE) {
96 /* zero out the rest of the data */
97 memset(sh->sr->entries[sh->sr->counter].data + data_len, 0, STRINGRING_DATA_SIZE - data_len);
99 flock(sh->fd, LOCK_UN);
104 int stringring_find_unlocked(struct stringring_handle *sh, const char *data, uint64_t cutoff) {
108 for (n = 0; n < STRINGRING_N_ENTRIES; n++) {
109 if (sh->sr->entries[i].timestamp > 0 &&
110 sh->sr->entries[i].timestamp > cutoff &&
111 strncmp(sh->sr->entries[i].data, data, STRINGRING_DATA_SIZE) == 0) {
114 i = (i + 1) % STRINGRING_N_ENTRIES;
120 int stringring_find(struct stringring_handle *sh, const char *data, unsigned int max_age) {
122 uint64_t cutoff = (max_age > 0 ? time(NULL) - max_age : 0);
124 flock(sh->fd, LOCK_SH);
125 ret = stringring_find_unlocked(sh, data, cutoff);
126 flock(sh->fd, LOCK_UN);
131 int stringring_remove_index_unlocked(struct stringring_handle *sh, int idx) {
134 if (idx < 0 || idx >= STRINGRING_N_ENTRIES)
137 sh->sr->entries[idx].timestamp = 0;
138 memset(sh->sr->entries[idx].data, 0, STRINGRING_DATA_SIZE);
143 int stringring_remove_index(struct stringring_handle *sh, int idx) {
146 flock(sh->fd, LOCK_EX);
147 ret = stringring_remove_index_unlocked(sh, idx);
148 flock(sh->fd, LOCK_UN);
153 int stringring_remove(struct stringring_handle *sh, const char *data) {
154 STRINGRING_DATA_CHECK();
157 flock(sh->fd, LOCK_EX);
158 ret = stringring_remove_index_unlocked(sh,
159 stringring_find_unlocked(sh, data, 0));
160 flock(sh->fd, LOCK_UN);
165 int stringring_clear(struct stringring_handle *sh) {
169 flock(sh->fd, LOCK_EX);
170 memset(sh->sr, 0, sizeof(struct stringring));
171 flock(sh->fd, LOCK_UN);