s3: piddir creation fix part 2.
[ira/wip.git] / lib / tdb / common / freelist.c
index 2f2a4c379b0690399a9f4065b15960e667300bf0..6358f64a04ab8db19693b05e6f84f282c44c348e 100644 (file)
@@ -6,11 +6,11 @@
    Copyright (C) Andrew Tridgell              1999-2005
    Copyright (C) Paul `Rusty' Russell             2000
    Copyright (C) Jeremy Allison                           2000-2003
    Copyright (C) Andrew Tridgell              1999-2005
    Copyright (C) Paul `Rusty' Russell             2000
    Copyright (C) Jeremy Allison                           2000-2003
-   
+
      ** NOTE! The following LGPL license applies to the tdb
      ** library. This does NOT imply that all of Samba is released
      ** under the LGPL
      ** NOTE! The following LGPL license applies to the tdb
      ** library. This does NOT imply that all of Samba is released
      ** under the LGPL
-   
+
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
@@ -34,7 +34,7 @@
 #define USE_RIGHT_MERGES 0
 
 /* read a freelist record and check for simple errors */
 #define USE_RIGHT_MERGES 0
 
 /* read a freelist record and check for simple errors */
-int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec)
+int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct tdb_record *rec)
 {
        if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
                return -1;
 {
        if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1)
                return -1;
@@ -54,9 +54,9 @@ int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct
                tdb->ecode = TDB_ERR_CORRUPT;
                TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", 
                           rec->magic, off));
                tdb->ecode = TDB_ERR_CORRUPT;
                TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", 
                           rec->magic, off));
-               return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+               return -1;
        }
        }
-       if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
+       if (tdb->methods->tdb_oob(tdb, rec->nextsizeof(*rec), 0) != 0)
                return -1;
        return 0;
 }
                return -1;
        return 0;
 }
@@ -78,15 +78,16 @@ static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_
                /* Follow chain (next offset is at start of record) */
                last_ptr = i;
        }
                /* Follow chain (next offset is at start of record) */
                last_ptr = i;
        }
+       tdb->ecode = TDB_ERR_CORRUPT;
        TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off));
        TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off));
-       return TDB_ERRCODE(TDB_ERR_CORRUPT, -1);
+       return -1;
 }
 #endif
 
 
 /* update a record tailer (must hold allocation lock) */
 static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
 }
 #endif
 
 
 /* update a record tailer (must hold allocation lock) */
 static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
-                        const struct list_struct *rec)
+                        const struct tdb_record *rec)
 {
        tdb_off_t totalsize;
 
 {
        tdb_off_t totalsize;
 
@@ -97,8 +98,8 @@ static int update_tailer(struct tdb_context *tdb, tdb_off_t offset,
 }
 
 /* Add an element into the freelist. Merge adjacent records if
 }
 
 /* Add an element into the freelist. Merge adjacent records if
-   neccessary. */
-int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
+   necessary. */
+int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec)
 {
        /* Allocation and tailer lock */
        if (tdb_lock(tdb, -1, F_WRLCK) != 0)
 {
        /* Allocation and tailer lock */
        if (tdb_lock(tdb, -1, F_WRLCK) != 0)
@@ -114,7 +115,7 @@ int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec)
        /* Look right first (I'm an Australian, dammit) */
        if (offset + sizeof(*rec) + rec->rec_len + sizeof(*rec) <= tdb->map_size) {
                tdb_off_t right = offset + sizeof(*rec) + rec->rec_len;
        /* Look right first (I'm an Australian, dammit) */
        if (offset + sizeof(*rec) + rec->rec_len + sizeof(*rec) <= tdb->map_size) {
                tdb_off_t right = offset + sizeof(*rec) + rec->rec_len;
-               struct list_struct r;
+               struct tdb_record r;
 
                if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right));
 
                if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right));
@@ -140,9 +141,9 @@ left:
        /* Look left */
        if (offset - sizeof(tdb_off_t) > TDB_DATA_START(tdb->header.hash_size)) {
                tdb_off_t left = offset - sizeof(tdb_off_t);
        /* Look left */
        if (offset - sizeof(tdb_off_t) > TDB_DATA_START(tdb->header.hash_size)) {
                tdb_off_t left = offset - sizeof(tdb_off_t);
-               struct list_struct l;
+               struct tdb_record l;
                tdb_off_t leftsize;
                tdb_off_t leftsize;
-               
+
                /* Read in tailer and jump back to header */
                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
                /* Read in tailer and jump back to header */
                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left));
@@ -219,9 +220,9 @@ update:
  */
 static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, 
                                  tdb_len_t length, tdb_off_t rec_ptr,
  */
 static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, 
                                  tdb_len_t length, tdb_off_t rec_ptr,
-                                 struct list_struct *rec, tdb_off_t last_ptr)
+                                 struct tdb_record *rec, tdb_off_t last_ptr)
 {
 {
-#define MIN_REC_SIZE (sizeof(struct list_struct) + sizeof(tdb_off_t) + 8)
+#define MIN_REC_SIZE (sizeof(struct tdb_record) + sizeof(tdb_off_t) + 8)
 
        if (rec->rec_len < length + MIN_REC_SIZE) {
                /* we have to grab the whole record */
 
        if (rec->rec_len < length + MIN_REC_SIZE) {
                /* we have to grab the whole record */
@@ -267,12 +268,12 @@ static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb,
 }
 
 /* allocate some space from the free list. The offset returned points
 }
 
 /* allocate some space from the free list. The offset returned points
-   to a unconnected list_struct within the database with room for at
+   to a unconnected tdb_record within the database with room for at
    least length bytes of total data
 
    0 is returned if the space could not be allocated
  */
    least length bytes of total data
 
    0 is returned if the space could not be allocated
  */
-tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec)
+tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec)
 {
        tdb_off_t rec_ptr, last_ptr, newrec_ptr;
        struct {
 {
        tdb_off_t rec_ptr, last_ptr, newrec_ptr;
        struct {
@@ -284,6 +285,9 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
        if (tdb_lock(tdb, -1, F_WRLCK) == -1)
                return 0;
 
        if (tdb_lock(tdb, -1, F_WRLCK) == -1)
                return 0;
 
+       /* over-allocate to reduce fragmentation */
+       length *= 1.25;
+
        /* Extra bytes required for tailer */
        length += sizeof(tdb_off_t);
        length = TDB_ALIGN(length, TDB_ALIGNMENT);
        /* Extra bytes required for tailer */
        length += sizeof(tdb_off_t);
        length = TDB_ALIGN(length, TDB_ALIGNMENT);
@@ -330,7 +334,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
                    bestfit.rec_len < length * multiplier) {
                        break;
                }
                    bestfit.rec_len < length * multiplier) {
                        break;
                }
-               
+
                /* this multiplier means we only extremely rarely
                   search more than 50 or so records. At 50 records we
                   accept records up to 11 times larger than what we
                /* this multiplier means we only extremely rarely
                   search more than 50 or so records. At 50 records we
                   accept records up to 11 times larger than what we
@@ -363,7 +367,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st
 /* 
    return the size of the freelist - used to decide if we should repack 
 */
 /* 
    return the size of the freelist - used to decide if we should repack 
 */
-int tdb_freelist_size(struct tdb_context *tdb)
+_PUBLIC_ int tdb_freelist_size(struct tdb_context *tdb)
 {
        tdb_off_t ptr;
        int count=0;
 {
        tdb_off_t ptr;
        int count=0;