root/jlog_io.c

Revision 81ac86a15e3940ff0b787698853fb6a6157f800b, 4.4 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 7 years ago)

initial import with Ecelerity bits removed and some autoconf glue added in. Could certainly use some work on the build/install. Needs shared lib support for multiple platforms

  • Property mode set to 100644
Line 
1 #include "jlog_config.h"
2 #include "jlog_hash.h"
3 #include "jlog_io.h"
4 #include <assert.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <pthread.h>
8 #include <sys/mman.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11
12 static pthread_mutex_t jlog_files_lock = PTHREAD_MUTEX_INITIALIZER;
13 static jlog_hash_table jlog_files = JLOG_HASH_EMPTY;
14
15 typedef struct {
16   dev_t st_dev;
17   ino_t st_ino;
18 } jlog_file_id;
19
20 struct _jlog_file {
21   jlog_file_id id;
22   int fd;
23   int refcnt;
24   int locked;
25   pthread_mutex_t lock;
26 };
27
28 jlog_file *jlog_file_open(const char *path, int flags, int mode)
29 {
30   struct stat sb;
31   jlog_file_id id;
32   jlog_file *f = NULL;
33   union {
34     jlog_file *f;
35     void *vptr;
36   } pun;
37   int fd, realflags = O_RDWR;
38
39   if (flags & O_CREAT) realflags |= O_CREAT;
40   if (flags & O_EXCL) realflags |= O_EXCL;
41
42   if (pthread_mutex_lock(&jlog_files_lock) != 0) return NULL;
43
44   if (stat(path, &sb) == 0) {
45     if (!S_ISREG(sb.st_mode)) goto out;
46     id.st_dev = sb.st_dev;
47     id.st_ino = sb.st_ino;
48     if (jlog_hash_retrieve(&jlog_files, (void *)&id, sizeof(jlog_file_id),
49                            &pun.vptr))
50     {
51       if (!(flags & O_EXCL)) {
52         f = pun.f;
53         f->refcnt++;
54       }
55       goto out;
56     }
57   }
58
59   if ((fd = open(path, realflags, mode)) == -1) goto out;
60   if (fstat(fd, &sb) != 0) {
61     while (close(fd) == -1 && errno == EINTR) ;
62     goto out;
63   }
64   id.st_dev = sb.st_dev;
65   id.st_ino = sb.st_ino;
66   if (!(f = malloc(sizeof(jlog_file)))) {
67     while (close(fd) == -1 && errno == EINTR) ;
68     goto out;
69   }
70   memset(f, 0, sizeof(jlog_file));
71   f->id = id;
72   f->fd = fd;
73   f->refcnt = 1;
74   f->locked = 0;
75   pthread_mutex_init(&(f->lock), NULL);
76   if (!jlog_hash_store(&jlog_files, (void *)&f->id, sizeof(jlog_file_id), f)) {
77     while (close(f->fd) == -1 && errno == EINTR) ;
78     free(f);
79     f = NULL;
80   }
81 out:
82   pthread_mutex_unlock(&jlog_files_lock);
83   return f;
84 }
85
86 int jlog_file_close(jlog_file *f)
87 {
88   if (pthread_mutex_lock(&jlog_files_lock) != 0) return 0;
89   if (--f->refcnt == 0) {
90     assert(jlog_hash_delete(&jlog_files, (void *)&f->id, sizeof(jlog_file_id),
91                             NULL, NULL));
92     while (close(f->fd) == -1 && errno == EINTR) ;
93     free(f);
94   }
95   pthread_mutex_unlock(&jlog_files_lock); 
96   return 1;
97 }
98
99 int jlog_file_lock(jlog_file *f)
100 {
101   struct flock fl;
102   int frv;
103
104   memset(&fl, 0, sizeof(fl));
105   fl.l_type = F_WRLCK;
106   fl.l_whence = SEEK_SET;
107   fl.l_start = 0;
108   fl.l_len = 0;
109
110   if (pthread_mutex_lock(&(f->lock)) != 0) return 0;
111   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && errno == EINTR) ;
112   if (frv != 0) {
113     int save = errno;
114     pthread_mutex_unlock(&(f->lock));
115     errno = save;
116     return 0;
117   }
118   f->locked = 1;
119   return 1;
120 }
121
122 int jlog_file_unlock(jlog_file *f)
123 {
124   struct flock fl;
125   int frv;
126
127   if (!f->locked) return 0;
128
129   memset(&fl, 0, sizeof(fl));
130   fl.l_type = F_UNLCK;
131   fl.l_whence = SEEK_SET;
132   fl.l_start = 0;
133   fl.l_len = 0;
134
135   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && errno == EINTR) ;
136   if (frv != 0) return 0;
137   f->locked = 0;
138   pthread_mutex_unlock(&(f->lock));
139   return 1;
140 }
141
142 int jlog_file_pread(jlog_file *f, void *buf, size_t nbyte, off_t offset)
143 {
144   while (nbyte > 0) {
145     ssize_t rv = pread(f->fd, buf, nbyte, offset);
146     if (rv == -1 && errno == EINTR) continue;
147     if (rv <= 0) return 0;
148     nbyte -= rv;
149     offset += rv;
150   }
151   return 1;
152 }
153
154 int jlog_file_pwrite(jlog_file *f, const void *buf, size_t nbyte, off_t offset)
155 {
156   while (nbyte > 0) {
157     ssize_t rv = pwrite(f->fd, buf, nbyte, offset);
158     if (rv == -1 && errno == EINTR) continue;
159     if (rv <= 0) return 0;
160     nbyte -= rv;
161     offset += rv;
162   }
163   return 1;
164 }
165
166 int jlog_file_sync(jlog_file *f)
167 {
168   int rv;
169
170 #ifdef HAVE_FDATASYNC
171   while((rv = fdatasync(f->fd)) == -1 && errno == EINTR) ;
172 #else
173   while((rv = fsync(f->fd)) == -1 && errno == EINTR) ;
174 #endif
175   if (rv == 0) return 1;
176   return 0;
177 }
178
179 int jlog_file_map_read(jlog_file *f, void **base, size_t *len)
180 {
181   struct stat sb;
182   void *my_map;
183   int flags = 0;
184
185 #ifdef MAP_SHARED
186   flags = MAP_SHARED;
187 #endif
188   if (fstat(f->fd, &sb) != 0) return 0;
189   my_map = mmap(NULL, sb.st_size, PROT_READ, flags, f->fd, 0);
190   if (my_map == MAP_FAILED) return 0;
191   *base = my_map;
192   *len = sb.st_size;
193   return 1;
194 }
195
196 off_t jlog_file_size(jlog_file *f)
197 {
198   struct stat sb;
199   if (fstat(f->fd, &sb) != 0)
200     return -1;
201   return sb.st_size;
202 }
203
204 int jlog_file_truncate(jlog_file *f, off_t len)
205 {
206   int rv;
207   while ((rv = ftruncate(f->fd, len)) == -1 && errno == EINTR) ;
208   if (rv == 0) return 1;
209   return 0;
210 }
211
212 /* vim:se ts=2 sw=2 et: */
Note: See TracBrowser for help on using the browser.