tdb/common/io.c

ソースコードを見る。

関数

static int tdb_oob (struct tdb_context *tdb, tdb_off_t len, int probe)
static int tdb_write (struct tdb_context *tdb, tdb_off_t off, const void *buf, tdb_len_t len)
void * tdb_convert (void *buf, u32 size)
static int tdb_read (struct tdb_context *tdb, tdb_off_t off, void *buf, tdb_len_t len, int cv)
static void tdb_next_hash_chain (struct tdb_context *tdb, u32 *chain)
int tdb_munmap (struct tdb_context *tdb)
void tdb_mmap (struct tdb_context *tdb)
static int tdb_expand_file (struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition)
int tdb_expand (struct tdb_context *tdb, tdb_off_t size)
int tdb_ofs_read (struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
int tdb_ofs_write (struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d)
char * tdb_alloc_read (struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len)
int tdb_parse_data (struct tdb_context *tdb, TDB_DATA key, tdb_off_t offset, tdb_len_t len, int(*parser)(TDB_DATA key, TDB_DATA data, void *private_data), void *private_data)
int tdb_rec_read (struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
int tdb_rec_write (struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
void tdb_io_init (struct tdb_context *tdb)

変数

static struct tdb_methods io_methods


関数

static int tdb_oob ( struct tdb_context tdb,
tdb_off_t  len,
int  probe 
) [static]

io.c37 行で定義されています。

参照先 tdb_context::ecodetdb_context::fdtdb_context::flagstdb_context::map_sizetdbTDB_DEBUG_FATALTDB_ERR_IOtdb_mmap()tdb_munmap().

00038 {
00039         struct stat st;
00040         if (len <= tdb->map_size)
00041                 return 0;
00042         if (tdb->flags & TDB_INTERNAL) {
00043                 if (!probe) {
00044                         /* Ensure ecode is set for log fn. */
00045                         tdb->ecode = TDB_ERR_IO;
00046                         TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n",
00047                                  (int)len, (int)tdb->map_size));
00048                 }
00049                 return TDB_ERRCODE(TDB_ERR_IO, -1);
00050         }
00051 
00052         if (fstat(tdb->fd, &st) == -1) {
00053                 return TDB_ERRCODE(TDB_ERR_IO, -1);
00054         }
00055 
00056         if (st.st_size < (size_t)len) {
00057                 if (!probe) {
00058                         /* Ensure ecode is set for log fn. */
00059                         tdb->ecode = TDB_ERR_IO;
00060                         TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n",
00061                                  (int)len, (int)st.st_size));
00062                 }
00063                 return TDB_ERRCODE(TDB_ERR_IO, -1);
00064         }
00065 
00066         /* Unmap, update size, remap */
00067         if (tdb_munmap(tdb) == -1)
00068                 return TDB_ERRCODE(TDB_ERR_IO, -1);
00069         tdb->map_size = st.st_size;
00070         tdb_mmap(tdb);
00071         return 0;
00072 }

static int tdb_write ( struct tdb_context tdb,
tdb_off_t  off,
const void *  buf,
tdb_len_t  len 
) [static]

io.c75 行で定義されています。

参照先 tdb_context::ecodeerrnotdb_context::fdtdb_context::map_ptrtdb_context::methodstdb_context::read_onlystrerror()tdbTDB_DEBUG_FATALTDB_ERR_IOTDB_ERR_RDONLYtdb_methods::tdb_oobtdb_context::traverse_read.

00077 {
00078         if (len == 0) {
00079                 return 0;
00080         }
00081 
00082         if (tdb->read_only || tdb->traverse_read) {
00083                 tdb->ecode = TDB_ERR_RDONLY;
00084                 return -1;
00085         }
00086 
00087         if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0)
00088                 return -1;
00089 
00090         if (tdb->map_ptr) {
00091                 memcpy(off + (char *)tdb->map_ptr, buf, len);
00092         } else {
00093                 ssize_t written = pwrite(tdb->fd, buf, len, off);
00094                 if ((written != (ssize_t)len) && (written != -1)) {
00095                         /* try once more */
00096                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: wrote only "
00097                                  "%d of %d bytes at %d, trying once more\n",
00098                                  (uint32_t)written, len, off));
00099                         errno = ENOSPC;
00100                         written = pwrite(tdb->fd, (void *)((char *)buf+written),
00101                                          len-written,
00102                                          off+written);
00103                 }
00104                 if (written == -1) {
00105                         /* Ensure ecode is set for log fn. */
00106                         tdb->ecode = TDB_ERR_IO;
00107                         TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d "
00108                                  "len=%d (%s)\n", off, len, strerror(errno)));
00109                         return TDB_ERRCODE(TDB_ERR_IO, -1);
00110                 } else if (written != (ssize_t)len) {
00111                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_write: failed to "
00112                                  "write %d bytes at %d in two attempts\n",
00113                                  len, off));
00114                         errno = ENOSPC;
00115                         return TDB_ERRCODE(TDB_ERR_IO, -1);
00116                 }
00117         }
00118         return 0;
00119 }

void* tdb_convert ( void *  buf,
u32  size 
)

io.c122 行で定義されています。

参照元 tdb_open_ex()tdb_read()tdb_transaction_recover()transaction_read()transaction_setup_recovery().

00123 {
00124         u32 i, *p = (u32 *)buf;
00125         for (i = 0; i < size / 4; i++)
00126                 p[i] = TDB_BYTEREV(p[i]);
00127         return buf;
00128 }

static int tdb_read ( struct tdb_context tdb,
tdb_off_t  off,
void *  buf,
tdb_len_t  len,
int  cv 
) [static]

io.c132 行で定義されています。

参照先 tdb_context::ecodeerrnotdb_context::fdtdb_context::map_ptrtdb_context::map_sizetdb_context::methodsstrerror()tdbtdb_convert()TDB_DEBUG_FATALTDB_ERR_IOtdb_methods::tdb_oob.

00134 {
00135         if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) {
00136                 return -1;
00137         }
00138 
00139         if (tdb->map_ptr) {
00140                 memcpy(buf, off + (char *)tdb->map_ptr, len);
00141         } else {
00142                 ssize_t ret = pread(tdb->fd, buf, len, off);
00143                 if (ret != (ssize_t)len) {
00144                         /* Ensure ecode is set for log fn. */
00145                         tdb->ecode = TDB_ERR_IO;
00146                         TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d "
00147                                  "len=%d ret=%d (%s) map_size=%d\n",
00148                                  (int)off, (int)len, (int)ret, strerror(errno),
00149                                  (int)tdb->map_size));
00150                         return TDB_ERRCODE(TDB_ERR_IO, -1);
00151                 }
00152         }
00153         if (cv) {
00154                 tdb_convert(buf, len);
00155         }
00156         return 0;
00157 }

static void tdb_next_hash_chain ( struct tdb_context tdb,
u32 *  chain 
) [static]

io.c165 行で定義されています。

参照先 tdb_header::hash_sizetdb_context::headertdb_context::map_ptrtdb.

00166 {
00167         u32 h = *chain;
00168         if (tdb->map_ptr) {
00169                 for (;h < tdb->header.hash_size;h++) {
00170                         if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) {
00171                                 break;
00172                         }
00173                 }
00174         } else {
00175                 u32 off=0;
00176                 for (;h < tdb->header.hash_size;h++) {
00177                         if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) {
00178                                 break;
00179                         }
00180                 }
00181         }
00182         (*chain) = h;
00183 }

int tdb_munmap ( struct tdb_context tdb  ) 

io.c186 行で定義されています。

参照先 tdb_context::flagstdb_context::map_ptrtdb_context::map_sizetdb.

参照元 tdb_close()tdb_expand()tdb_oob()tdb_open_ex()tdb_reopen()tdb_transaction_recover().

00187 {
00188         if (tdb->flags & TDB_INTERNAL)
00189                 return 0;
00190 
00191 #ifdef HAVE_MMAP
00192         if (tdb->map_ptr) {
00193                 int ret = munmap(tdb->map_ptr, tdb->map_size);
00194                 if (ret != 0)
00195                         return ret;
00196         }
00197 #endif
00198         tdb->map_ptr = NULL;
00199         return 0;
00200 }

void tdb_mmap ( struct tdb_context tdb  ) 

io.c202 行で定義されています。

参照先 errnotdb_context::fdtdb_context::flagstdb_context::map_ptrtdb_context::map_sizetdb_context::read_onlystrerror()tdbTDB_DEBUG_WARNING.

参照元 tdb_expand()tdb_oob()tdb_open_ex()tdb_reopen()tdb_transaction_recover().

00203 {
00204         if (tdb->flags & TDB_INTERNAL)
00205                 return;
00206 
00207 #ifdef HAVE_MMAP
00208         if (!(tdb->flags & TDB_NOMMAP)) {
00209                 tdb->map_ptr = mmap(NULL, tdb->map_size, 
00210                                     PROT_READ|(tdb->read_only? 0:PROT_WRITE), 
00211                                     MAP_SHARED|MAP_FILE, tdb->fd, 0);
00212 
00213                 /*
00214                  * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!!
00215                  */
00216 
00217                 if (tdb->map_ptr == MAP_FAILED) {
00218                         tdb->map_ptr = NULL;
00219                         TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", 
00220                                  tdb->map_size, strerror(errno)));
00221                 }
00222         } else {
00223                 tdb->map_ptr = NULL;
00224         }
00225 #else
00226         tdb->map_ptr = NULL;
00227 #endif
00228 }

static int tdb_expand_file ( struct tdb_context tdb,
tdb_off_t  size,
tdb_off_t  addition 
) [static]

io.c232 行で定義されています。

参照先 buftdb_context::ecodeerrnotdb_context::fdtdb_context::read_onlystrerror()tdbTDB_DEBUG_FATALTDB_DEBUG_WARNINGTDB_ERR_RDONLYtdb_context::traverse_read.

00233 {
00234         char buf[1024];
00235 
00236         if (tdb->read_only || tdb->traverse_read) {
00237                 tdb->ecode = TDB_ERR_RDONLY;
00238                 return -1;
00239         }
00240 
00241         if (ftruncate(tdb->fd, size+addition) == -1) {
00242                 char b = 0;
00243                 ssize_t written = pwrite(tdb->fd,  &b, 1, (size+addition) - 1);
00244                 if (written == 0) {
00245                         /* try once more, potentially revealing errno */
00246                         written = pwrite(tdb->fd,  &b, 1, (size+addition) - 1);
00247                 }
00248                 if (written == 0) {
00249                         /* again - give up, guessing errno */
00250                         errno = ENOSPC;
00251                 }
00252                 if (written != 1) {
00253                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", 
00254                                  size+addition, strerror(errno)));
00255                         return -1;
00256                 }
00257         }
00258 
00259         /* now fill the file with something. This ensures that the
00260            file isn't sparse, which would be very bad if we ran out of
00261            disk. This must be done with write, not via mmap */
00262         memset(buf, TDB_PAD_BYTE, sizeof(buf));
00263         while (addition) {
00264                 size_t n = addition>sizeof(buf)?sizeof(buf):addition;
00265                 ssize_t written = pwrite(tdb->fd, buf, n, size);
00266                 if (written == 0) {
00267                         /* prevent infinite loops: try _once_ more */
00268                         written = pwrite(tdb->fd, buf, n, size);
00269                 }
00270                 if (written == 0) {
00271                         /* give up, trying to provide a useful errno */
00272                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write "
00273                                 "returned 0 twice: giving up!\n"));
00274                         errno = ENOSPC;
00275                         return -1;
00276                 } else if (written == -1) {
00277                         TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of "
00278                                 "%d bytes failed (%s)\n", (uint32_t)n, strerror(errno)));
00279                         return -1;
00280                 } else if (written != n) {
00281                         TDB_LOG((tdb, TDB_DEBUG_WARNING, "expand_file: wrote "
00282                                 "only %d of %d bytes - retrying\n",
00283                                 (uint32_t)written, (uint32_t)n));
00284                 }
00285                 addition -= written;
00286                 size += written;
00287         }
00288         return 0;
00289 }

int tdb_expand ( struct tdb_context tdb,
tdb_off_t  size 
)

io.c294 行で定義されています。

参照先 tdb_context::flagstdb_context::map_sizetdb_context::methodstdb_context::page_sizetdbTDB_DEBUG_ERRORtdb_free()tdb_lock()tdb_mmap()tdb_munmap()tdb_methods::tdb_oobtdb_unlock().

参照元 tdb_allocate().

00295 {
00296         struct list_struct rec;
00297         tdb_off_t offset;
00298 
00299         if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
00300                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n"));
00301                 return -1;
00302         }
00303 
00304         /* must know about any previous expansions by another process */
00305         tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1);
00306 
00307         /* always make room for at least 10 more records, and round
00308            the database up to a multiple of the page size */
00309         size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size;
00310 
00311         if (!(tdb->flags & TDB_INTERNAL))
00312                 tdb_munmap(tdb);
00313 
00314         /*
00315          * We must ensure the file is unmapped before doing this
00316          * to ensure consistency with systems like OpenBSD where
00317          * writes and mmaps are not consistent.
00318          */
00319 
00320         /* expand the file itself */
00321         if (!(tdb->flags & TDB_INTERNAL)) {
00322                 if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0)
00323                         goto fail;
00324         }
00325 
00326         tdb->map_size += size;
00327 
00328         if (tdb->flags & TDB_INTERNAL) {
00329                 char *new_map_ptr = (char *)realloc(tdb->map_ptr,
00330                                                     tdb->map_size);
00331                 if (!new_map_ptr) {
00332                         tdb->map_size -= size;
00333                         goto fail;
00334                 }
00335                 tdb->map_ptr = new_map_ptr;
00336         } else {
00337                 /*
00338                  * We must ensure the file is remapped before adding the space
00339                  * to ensure consistency with systems like OpenBSD where
00340                  * writes and mmaps are not consistent.
00341                  */
00342 
00343                 /* We're ok if the mmap fails as we'll fallback to read/write */
00344                 tdb_mmap(tdb);
00345         }
00346 
00347         /* form a new freelist record */
00348         memset(&rec,'\0',sizeof(rec));
00349         rec.rec_len = size - sizeof(rec);
00350 
00351         /* link it into the free list */
00352         offset = tdb->map_size - size;
00353         if (tdb_free(tdb, offset, &rec) == -1)
00354                 goto fail;
00355 
00356         tdb_unlock(tdb, -1, F_WRLCK);
00357         return 0;
00358  fail:
00359         tdb_unlock(tdb, -1, F_WRLCK);
00360         return -1;
00361 }

int tdb_ofs_read ( struct tdb_context tdb,
tdb_off_t  offset,
tdb_off_t d 
)

io.c364 行で定義されています。

参照先 tdb_context::methodstdbtdb_methods::tdb_read.

参照元 remove_from_freelist()tdb_allocate()tdb_count_dead()tdb_do_delete()tdb_dump_chain()tdb_dump_record()tdb_find()tdb_find_dead()tdb_free()tdb_get_seqnum()tdb_increment_seqnum()tdb_next_lock()tdb_printfreelist()tdb_purge_dead()tdb_recovery_allocate()tdb_store()tdb_transaction_recover()tdb_validate_freelist().

00365 {
00366         return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV());
00367 }

int tdb_ofs_write ( struct tdb_context tdb,
tdb_off_t  offset,
tdb_off_t d 
)

io.c369 行で定義されています。

参照先 tdb_context::methodstdbtdb_methods::tdb_write.

参照元 remove_from_freelist()tdb_allocate_ofs()tdb_do_delete()tdb_free()tdb_increment_seqnum()tdb_store()tdb_transaction_recover()update_tailer().

00370 {
00371         tdb_off_t off = *d;
00372         return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d));
00373 }

char* tdb_alloc_read ( struct tdb_context tdb,
tdb_off_t  offset,
tdb_len_t  len 
)

io.c377 行で定義されています。

参照先 buftdb_context::ecodeerrnotdb_context::methodsstrerror()tdbTDB_DEBUG_ERRORTDB_ERR_OOMtdb_methods::tdb_read.

参照元 tdb_fetch()tdb_firstkey()tdb_nextkey()tdb_parse_data()tdb_traverse_internal().

00378 {
00379         char *buf;
00380 
00381         /* some systems don't like zero length malloc */
00382         if (len == 0) {
00383                 len = 1;
00384         }
00385 
00386         if (!(buf = (char *)malloc(len))) {
00387                 /* Ensure ecode is set for log fn. */
00388                 tdb->ecode = TDB_ERR_OOM;
00389                 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n",
00390                            len, strerror(errno)));
00391                 return TDB_ERRCODE(TDB_ERR_OOM, buf);
00392         }
00393         if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) {
00394                 SAFE_FREE(buf);
00395                 return NULL;
00396         }
00397         return buf;
00398 }

int tdb_parse_data ( struct tdb_context tdb,
TDB_DATA  key,
tdb_off_t  offset,
tdb_len_t  len,
int(*)(TDB_DATA key, TDB_DATA data, void *private_data)  parser,
void *  private_data 
)

io.c402 行で定義されています。

参照先 TDB_DATA::dptrTDB_DATA::dsizetdb_context::map_ptrtdb_context::methodsresulttdbtdb_alloc_read()tdb_methods::tdb_oobtdb_context::transaction.

参照元 tdb_find()tdb_parse_record().

00407 {
00408         TDB_DATA data;
00409         int result;
00410 
00411         data.dsize = len;
00412 
00413         if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) {
00414                 /*
00415                  * Optimize by avoiding the malloc/memcpy/free, point the
00416                  * parser directly at the mmap area.
00417                  */
00418                 if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) {
00419                         return -1;
00420                 }
00421                 data.dptr = offset + (char *)tdb->map_ptr;
00422                 return parser(key, data, private_data);
00423         }
00424 
00425         if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) {
00426                 return -1;
00427         }
00428 
00429         result = parser(key, data, private_data);
00430         free(data.dptr);
00431         return result;
00432 }

int tdb_rec_read ( struct tdb_context tdb,
tdb_off_t  offset,
struct list_struct rec 
)

io.c435 行で定義されています。

参照先 tdb_context::ecodetdb_context::methodstdb_context::nexttdbTDB_DEBUG_FATALTDB_ERR_CORRUPTtdb_methods::tdb_oobtdb_methods::tdb_read.

参照元 tdb_count_dead()tdb_do_delete()tdb_find()tdb_find_dead()tdb_next_lock()tdb_nextkey()tdb_purge_dead().

00436 {
00437         if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1)
00438                 return -1;
00439         if (TDB_BAD_MAGIC(rec)) {
00440                 /* Ensure ecode is set for log fn. */
00441                 tdb->ecode = TDB_ERR_CORRUPT;
00442                 TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset));
00443                 return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
00444         }
00445         return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0);
00446 }

int tdb_rec_write ( struct tdb_context tdb,
tdb_off_t  offset,
struct list_struct rec 
)

io.c448 行で定義されています。

参照先 tdb_context::methodstdbtdb_methods::tdb_write.

参照元 tdb_allocate_ofs()tdb_delete_hash()tdb_do_delete()tdb_free()tdb_store()tdb_update_hash().

00449 {
00450         struct list_struct r = *rec;
00451         return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r));
00452 }

void tdb_io_init ( struct tdb_context tdb  ) 

io.c466 行で定義されています。

参照先 io_methodstdb_context::methodstdb.

参照元 tdb_open_ex().

00467 {
00468         tdb->methods = &io_methods;
00469 }


変数

struct tdb_methods io_methods [static]

初期値:

io.c454 行で定義されています。

参照元 tdb_io_init().


Sambaに対してSat Aug 29 21:24:30 2009に生成されました。  doxygen 1.4.7