root/src/jlog/jlog_io.c

Revision cc981f5c55100675865b6960135d70148d8585af, 6.2 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

pull in jlog @ 52

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2005-2008, Message Systems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *    * Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    * Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *    * Neither the name Message Systems, Inc. nor the names
16  *      of its contributors may be used to endorse or promote products
17  *      derived from this software without specific prior written
18  *      permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * We want the single unix spec, so this define is needed on
35  * the identity crisis that is Linux. pread()/pwrite()
36  */
37 #define _XOPEN_SOURCE 500
38
39 #include "jlog_config.h"
40 #include "jlog_hash.h"
41 #include "jlog_io.h"
42 #include <assert.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <pthread.h>
46 #include <sys/mman.h>
47 #include <sys/stat.h>
48 #include <unistd.h>
49
50 static pthread_mutex_t jlog_files_lock = PTHREAD_MUTEX_INITIALIZER;
51 static jlog_hash_table jlog_files = JLOG_HASH_EMPTY;
52
53 typedef struct {
54   dev_t st_dev;
55   ino_t st_ino;
56 } jlog_file_id;
57
58 struct _jlog_file {
59   jlog_file_id id;
60   int fd;
61   int refcnt;
62   int locked;
63   pthread_mutex_t lock;
64 };
65
66 jlog_file *jlog_file_open(const char *path, int flags, int mode)
67 {
68   struct stat sb;
69   jlog_file_id id;
70   jlog_file *f = NULL;
71   union {
72     jlog_file *f;
73     void *vptr;
74   } pun;
75   int fd, realflags = O_RDWR;
76
77   if (flags & O_CREAT) realflags |= O_CREAT;
78   if (flags & O_EXCL) realflags |= O_EXCL;
79
80   if (pthread_mutex_lock(&jlog_files_lock) != 0) return NULL;
81
82   if (stat(path, &sb) == 0) {
83     if (!S_ISREG(sb.st_mode)) goto out;
84     id.st_dev = sb.st_dev;
85     id.st_ino = sb.st_ino;
86     if (jlog_hash_retrieve(&jlog_files, (void *)&id, sizeof(jlog_file_id),
87                            &pun.vptr))
88     {
89       if (!(flags & O_EXCL)) {
90         f = pun.f;
91         f->refcnt++;
92       }
93       goto out;
94     }
95   }
96
97   if ((fd = open(path, realflags, mode)) == -1) goto out;
98   if (fstat(fd, &sb) != 0) {
99     while (close(fd) == -1 && errno == EINTR) ;
100     goto out;
101   }
102   id.st_dev = sb.st_dev;
103   id.st_ino = sb.st_ino;
104   if (!(f = malloc(sizeof(jlog_file)))) {
105     while (close(fd) == -1 && errno == EINTR) ;
106     goto out;
107   }
108   memset(f, 0, sizeof(jlog_file));
109   f->id = id;
110   f->fd = fd;
111   f->refcnt = 1;
112   f->locked = 0;
113   pthread_mutex_init(&(f->lock), NULL);
114   if (!jlog_hash_store(&jlog_files, (void *)&f->id, sizeof(jlog_file_id), f)) {
115     while (close(f->fd) == -1 && errno == EINTR) ;
116     free(f);
117     f = NULL;
118   }
119 out:
120   pthread_mutex_unlock(&jlog_files_lock);
121   return f;
122 }
123
124 int jlog_file_close(jlog_file *f)
125 {
126   if (pthread_mutex_lock(&jlog_files_lock) != 0) return 0;
127   if (--f->refcnt == 0) {
128     assert(jlog_hash_delete(&jlog_files, (void *)&f->id, sizeof(jlog_file_id),
129                             NULL, NULL));
130     while (close(f->fd) == -1 && errno == EINTR) ;
131     free(f);
132   }
133   pthread_mutex_unlock(&jlog_files_lock); 
134   return 1;
135 }
136
137 int jlog_file_lock(jlog_file *f)
138 {
139   struct flock fl;
140   int frv;
141
142   memset(&fl, 0, sizeof(fl));
143   fl.l_type = F_WRLCK;
144   fl.l_whence = SEEK_SET;
145   fl.l_start = 0;
146   fl.l_len = 0;
147
148   if (pthread_mutex_lock(&(f->lock)) != 0) return 0;
149   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && errno == EINTR) ;
150   if (frv != 0) {
151     int save = errno;
152     pthread_mutex_unlock(&(f->lock));
153     errno = save;
154     return 0;
155   }
156   f->locked = 1;
157   return 1;
158 }
159
160 int jlog_file_unlock(jlog_file *f)
161 {
162   struct flock fl;
163   int frv;
164
165   if (!f->locked) return 0;
166
167   memset(&fl, 0, sizeof(fl));
168   fl.l_type = F_UNLCK;
169   fl.l_whence = SEEK_SET;
170   fl.l_start = 0;
171   fl.l_len = 0;
172
173   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && errno == EINTR) ;
174   if (frv != 0) return 0;
175   f->locked = 0;
176   pthread_mutex_unlock(&(f->lock));
177   return 1;
178 }
179
180 int jlog_file_pread(jlog_file *f, void *buf, size_t nbyte, off_t offset)
181 {
182   while (nbyte > 0) {
183     ssize_t rv = pread(f->fd, buf, nbyte, offset);
184     if (rv == -1 && errno == EINTR) continue;
185     if (rv <= 0) return 0;
186     nbyte -= rv;
187     offset += rv;
188   }
189   return 1;
190 }
191
192 int jlog_file_pwrite(jlog_file *f, const void *buf, size_t nbyte, off_t offset)
193 {
194   while (nbyte > 0) {
195     ssize_t rv = pwrite(f->fd, buf, nbyte, offset);
196     if (rv == -1 && errno == EINTR) continue;
197     if (rv <= 0) return 0;
198     nbyte -= rv;
199     offset += rv;
200   }
201   return 1;
202 }
203
204 int jlog_file_sync(jlog_file *f)
205 {
206   int rv;
207
208 #ifdef HAVE_FDATASYNC
209   while((rv = fdatasync(f->fd)) == -1 && errno == EINTR) ;
210 #else
211   while((rv = fsync(f->fd)) == -1 && errno == EINTR) ;
212 #endif
213   if (rv == 0) return 1;
214   return 0;
215 }
216
217 int jlog_file_map_read(jlog_file *f, void **base, size_t *len)
218 {
219   struct stat sb;
220   void *my_map;
221   int flags = 0;
222
223 #ifdef MAP_SHARED
224   flags = MAP_SHARED;
225 #endif
226   if (fstat(f->fd, &sb) != 0) return 0;
227   my_map = mmap(NULL, sb.st_size, PROT_READ, flags, f->fd, 0);
228   if (my_map == MAP_FAILED) return 0;
229   *base = my_map;
230   *len = sb.st_size;
231   return 1;
232 }
233
234 off_t jlog_file_size(jlog_file *f)
235 {
236   struct stat sb;
237   if (fstat(f->fd, &sb) != 0)
238     return -1;
239   return sb.st_size;
240 }
241
242 int jlog_file_truncate(jlog_file *f, off_t len)
243 {
244   int rv;
245   while ((rv = ftruncate(f->fd, len)) == -1 && errno == EINTR) ;
246   if (rv == 0) return 1;
247   return 0;
248 }
249
250 /* vim:se ts=2 sw=2 et: */
Note: See TracBrowser for help on using the browser.