/** * Allocate a single block in the file, without extending it. * * @param db the sdbm database * @param first first block to consider * * @return the block number if found, 0 otherwise. */ static size_t big_falloc(DBM *db, size_t first) { DBMBIG *dbg = db->big; long max_bitmap = dbg->bitmaps; long i; long bmap; size_t first_bit; bmap = first / BIG_BITCOUNT; /* Bitmap handling this block */ first_bit = first & (BIG_BITCOUNT - 1); /* Index within bitmap */ g_assert(first_bit != 0); /* Bit 0 is the bitmap itself */ /* * Loop through all the currently existing bitmaps. */ for (i = bmap; i < max_bitmap; i++) { size_t bno; if (!fetch_bitbuf(db, i)) return 0; bno = bit_field_first_clear(dbg->bitbuf, first_bit, BIG_BITCOUNT - 1); if ((size_t) -1 == bno) continue; /* * Found a free block. */ bit_field_set(dbg->bitbuf, bno); dbg->bitbuf_dirty = TRUE; /* * Correct the block number corresponding to "bno", if we did * not find it in bitmap #0. */ bno = size_saturate_add(bno, size_saturate_mult(BIG_BITCOUNT, i)); /* Make sure we can represent the block number in 32 bits */ g_assert(bno <= MAX_INT_VAL(guint32)); return bno; /* Allocated block number */ } return 0; /* No free block found */ }
/** * Shrink .dat file on disk to remove needlessly allocated blocks. * * @return TRUE if we were able to successfully shrink the file. */ gboolean big_shrink(DBM *db) { DBMBIG *dbg = db->big; long i; filesize_t offset = 0; if (-1 == dbg->fd) { /* * We do not want to call big_open() unless the .dat file already * exists because that would create it and it was not needed so far. */ if (-1 == big_open_lazy(dbg, TRUE)) return 0 == errno; } g_assert(dbg->fd != -1); /* * Loop through all the currently existing bitmaps, starting from the last * one, looking for the last set bit indicating the last used page. */ for (i = dbg->bitmaps - 1; i >= 0; i--) { size_t bno; if (!fetch_bitbuf(db, i)) return FALSE; bno = bit_field_last_set(dbg->bitbuf, 0, BIG_BITCOUNT - 1); if ((size_t) -1 == bno) { g_warning("sdbm: \"%s\": corrupted bitmap #%ld, considered empty", sdbm_name(db), i); } else if (bno != 0) { bno = size_saturate_add(bno, size_saturate_mult(BIG_BITCOUNT, i)); offset = OFF_DAT(bno + 1); break; } } if (-1 == ftruncate(dbg->fd, offset)) return FALSE; dbg->bitmaps = i + 1; /* Possibly reduced the amount of bitmaps */ return TRUE; }
/** * HTTP async callback, invoked when new HTTP data is read. * The EOF condition is indicated by data being NULL. */ static void soap_data_ind(http_async_t *ha, char *data, int len) { soap_rpc_t *sr = http_async_get_opaque(ha); size_t new_length; soap_rpc_check(sr); /* * When data is NULL, we reached EOF and we're done. Time to process * the data we got back. * * The HTTP asynchronous handle is nullified since it is about to be * closed by the HTTP layer upon return. */ if (NULL == data) { sr->ha = NULL; soap_process_reply(sr); return; } /* * Ensure we don't get too much and resize the memory buffer where * we store the reply if needed. */ new_length = size_saturate_add(sr->reply_len, len); if (new_length > sr->content_len) { http_async_error(ha, HTTP_ASYNC_DATA2BIG); return; } if (new_length > sr->reply_size) { size_t new_size = size_saturate_mult(sr->reply_size, 2); sr->reply_data = hrealloc(sr->reply_data, new_size); sr->reply_size = new_size; } /* * Append new data. */ memcpy(&sr->reply_data[sr->reply_len], data, len); sr->reply_len = new_length; }
/** * Extend token buffer. */ static void extend_token(strtok_t *s) { size_t len; strtok_check(s); if (s->len > 0) { if (s->len > STRTOK_GROW) len = size_saturate_add(s->len, STRTOK_GROW); else len = size_saturate_mult(s->len, 2); } else { len = STRTOK_FIRST_LEN; } grow_token(s, len); }
/** * Allocate "n" consecutive (sequential) blocks in the file, without * attempting to extend it. * * @param db the sdbm database * @param bmap bitmap number from which we need to start looking * @param n amount of consecutive blocks we want * * @return the block number of the first "n" blocks if found, 0 if nothing * was found. */ static size_t big_falloc_seq(DBM *db, int bmap, int n) { DBMBIG *dbg = db->big; long max_bitmap = dbg->bitmaps; long i; g_assert(bmap >= 0); g_assert(n > 0); /* * Loop through all the currently existing bitmaps, starting at the * specified bitmap number. */ for (i = bmap; i < max_bitmap; i++) { size_t first; size_t j; int r; /* Remaining blocks to allocate consecutively */ if (!fetch_bitbuf(db, i)) return 0; /* * We start at bit #1 since bit #0 is the bitmap itself. * * Bit #0 should always be set but in case the file is corrupted, * we don't want to start allocating data in the bitmap itself!. */ first = bit_field_first_clear(dbg->bitbuf, 1, BIG_BITCOUNT - 1); if ((size_t) -1 == first) continue; for (j = first + 1, r = n - 1; r > 0 && j < BIG_BITCOUNT; r--, j++) { if (bit_field_get(dbg->bitbuf, j)) break; } /* * If "r" is 0, we have no remaining page to allocate: we found our * "n" consecutive free blocks. */ if (0 == r) { /* * Mark the "n" consecutive blocks as busy. */ for (j = first, r = n; r > 0; r--, j++) { bit_field_set(dbg->bitbuf, j); } dbg->bitbuf_dirty = TRUE; /* * Correct the block number corresponding to "first", if we did * not find it in bitmap #0. */ first = size_saturate_add(first, size_saturate_mult(BIG_BITCOUNT, i)); /* Make sure we can represent all block numbers in 32 bits */ g_assert(size_saturate_add(first, n - 1) <= MAX_INT_VAL(guint32)); return first; /* "n" consecutive free blocks found */ } } return 0; /* No free block found */ }