root/jlog_io.c

Revision adf2ee8486352700056029fde45a13fc81b71218, 6.0 kB (checked in by Wez Furlong <wez.furlong@messagesystems.com>, 6 years ago)

Sync with the ecelerity jlog sources

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