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.
16 #include <stringring.h>
18 #define STRINGRING_DATA_CHECK() \
27 struct stringring * stringring_open(const char *filename) {
28 struct stringring *sr;
32 sr = malloc(sizeof(struct stringring));
34 perror("stringring_handle malloc");
38 sr->fd = open(filename, O_RDWR | O_CREAT, 0600);
39 flock(sr->fd, LOCK_EX);
41 perror("stringring open");
42 goto stringring_open__open_failed;
46 if (st.st_size < sizeof(struct stringring_block)) {
47 ftruncate(sr->fd, sizeof(struct stringring_block));
50 sr->sb = mmap(NULL, sizeof(struct stringring_block), PROT_READ | PROT_WRITE, MAP_SHARED, sr->fd, 0);
51 if (sr->sb == MAP_FAILED) {
52 perror("stringring mmap");
53 goto stringring_open__map_failed;
59 flock(sr->fd, LOCK_UN);
63 stringring_open__map_failed:
64 flock(sr->fd, LOCK_UN);
66 stringring_open__open_failed:
71 void stringring_close(struct stringring *sr) {
76 munmap(sr->sb, sizeof(struct stringring_block));
84 int stringring_add(struct stringring *sr, const char *data) {
85 STRINGRING_DATA_CHECK();
87 flock(sr->fd, LOCK_EX);
88 if (sr->sb->counter == 0) {
89 sr->sb->counter = STRINGRING_N_ENTRIES - 1;
94 int data_len = strlen(data);
95 sr->sb->entries[sr->sb->counter].timestamp = time(NULL);
96 strncpy((char *)sr->sb->entries[sr->sb->counter].data, data, STRINGRING_DATA_SIZE);
97 if (data_len < STRINGRING_DATA_SIZE) {
98 /* zero out the rest of the data */
99 memset(sr->sb->entries[sr->sb->counter].data + data_len, 0, STRINGRING_DATA_SIZE - data_len);
101 flock(sr->fd, LOCK_UN);
106 int stringring_find_unlocked(struct stringring *sr, const char *data, uint64_t cutoff) {
110 for (n = 0; n < STRINGRING_N_ENTRIES; n++) {
111 if (sr->sb->entries[i].timestamp > 0 &&
112 sr->sb->entries[i].timestamp > cutoff &&
113 strncmp((char *)sr->sb->entries[i].data, data, STRINGRING_DATA_SIZE) == 0) {
116 i = (i + 1) % STRINGRING_N_ENTRIES;
122 int stringring_find(struct stringring *sr, const char *data, unsigned int max_age) {
124 uint64_t cutoff = (max_age > 0 ? time(NULL) - max_age : 0);
126 flock(sr->fd, LOCK_SH);
127 ret = stringring_find_unlocked(sr, data, cutoff);
128 flock(sr->fd, LOCK_UN);
133 int stringring_remove_index_unlocked(struct stringring *sr, int idx) {
136 if (idx < 0 || idx >= STRINGRING_N_ENTRIES)
139 sr->sb->entries[idx].timestamp = 0;
140 memset(sr->sb->entries[idx].data, 0, STRINGRING_DATA_SIZE);
145 int stringring_remove_index(struct stringring *sr, int idx) {
148 flock(sr->fd, LOCK_EX);
149 ret = stringring_remove_index_unlocked(sr, idx);
150 flock(sr->fd, LOCK_UN);
155 int stringring_touch(struct stringring *sr, const char *data) {
156 STRINGRING_DATA_CHECK();
159 flock(sr->fd, LOCK_EX);
160 idx = stringring_find_unlocked(sr, data, 0);
163 sr->sb->entries[idx].timestamp = time(NULL);
165 flock(sr->fd, LOCK_UN);
170 int stringring_remove(struct stringring *sr, const char *data) {
171 STRINGRING_DATA_CHECK();
174 flock(sr->fd, LOCK_EX);
175 ret = stringring_remove_index_unlocked(sr,
176 stringring_find_unlocked(sr, data, 0));
177 flock(sr->fd, LOCK_UN);
182 int stringring_clear(struct stringring *sr) {
186 flock(sr->fd, LOCK_EX);
187 memset(sr->sb, 0, sizeof(struct stringring_block));
188 flock(sr->fd, LOCK_UN);