db

mp_cmpr.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1999, 2000
00005  * Loic Dachary. All rights reserved.
00006  * 
00007  * TODO:
00008  * Keith Bostic says:
00009  * The only change I'd probably think about is if
00010  * we should merge the call to CDB___memp_pg and CDB___memp_cmpr -- kind
00011  * of a stack of page modification routines, that sits on top of
00012  * CDB___os_io. That's a bigger change, but it's probably cleaner
00013  * in the long-run.
00014  * 
00015  * Pending questions:
00016  *
00017  * The CMPR structure contains binary data. Should we store them in network order ?
00018  * How is this related to DB_AM_SWAP ?
00019  *
00020  * In CDB___memp_cmpr, niop is always multiplied by compression factor for page 0. 
00021  * I see no problems with this but it's a bit awkward.
00022  *
00023  * In __memp_cmpr_page, the page built fills some fields of the PAGE structure
00024  * others are set to 0. I'm not 100% sure this is enough. It should only impact
00025  * utilities that read pages by incrementing pgno. Only stat does this an it's
00026  * enough for it. I've not found any other context where these fake pages are 
00027  * used.
00028  * 
00029  */
00030 
00031 #include "config.h"
00032 
00033 #ifndef lint
00034 static const char sccsid[] = "@(#)mp_cmpr.c 1.1 (Senga) 01/08/99";
00035 #endif /* not lint */
00036 
00037 #ifndef NO_SYSTEM_INCLUDES
00038 #include <sys/types.h>
00039 #include <string.h>
00040 #include <errno.h>
00041 #endif
00042 
00043 #include "db_int.h"
00044 #include "db_page.h"
00045 #include "shqueue.h"
00046 #include "db_shash.h"
00047 #include "mp.h"
00048 #include "db_page.h"
00049 #include "common_ext.h"
00050 
00051 #ifdef DEBUG
00052 #include "WordMonitor.h"
00053 #endif /* DEBUG */
00054 
00055 #if 0
00056 #define DEBUG_CMPR 1
00057 #endif
00058 #if 0
00059 #define DEBUG_CMPR_ALLOC 1
00060 #endif
00061 
00062 /*
00063  * Helpers declarations.
00064  */
00065 static int __memp_cmpr_page __P((DB_MPOOLFILE *, CMPR *, DB_IO *, ssize_t *));
00066 
00067 /*
00068  * Maximum chain length
00069  */
00070 #define CMPR_MAX (dbenv->mp_cmpr_info->max_npages)
00071 
00072 #define CMPR_MULTIPLY(n) ((n) << (dbenv->mp_cmpr_info->coefficient))
00073 #define CMPR_DIVIDE(n) ((n) >> (dbenv->mp_cmpr_info->coefficient))
00074 
00075 #ifdef HAVE_LIBZ
00076 static DB_CMPR_INFO default_cmpr_info = {
00077 CDB___memp_cmpr_deflate, 
00078 CDB___memp_cmpr_inflate, 
00079 1,
00080 3,
00081 NULL
00082 };
00083 #else /* HAVE_LIBZ */
00084 static DB_CMPR_INFO default_cmpr_info = {
00085 0,
00086 0,
00087 0,
00088 0,
00089 NULL
00090 };
00091 #endif /* HAVE_LIBZ */
00092 
00093 /*
00094  * Entry point. Functionaly equivalent to CDB___os_io.
00095  * Compress/uncompress pages before returning them or writing them to disk.
00096  */
00097 
00098 /*
00099  * CDB___memp_cmpr --
00100  * Transparent compression read/write
00101  *
00102  * PUBLIC: int CDB___memp_cmpr __P((DB_MPOOLFILE *, BH *, DB_IO *, int, ssize_t *));
00103  */
00104 int
00105 CDB___memp_cmpr(dbmfp, bhp, db_io, flag, niop)
00106 DB_MPOOLFILE *dbmfp;
00107 BH *bhp;
00108 DB_IO *db_io;
00109 int flag;
00110 ssize_t *niop;
00111 {
00112 size_t orig_pagesize = db_io->pagesize;
00113 db_pgno_t orig_pgno = db_io->pgno;
00114 size_t orig_bytes = db_io->bytes;
00115 DB_ENV *dbenv = dbmfp->dbmp->dbenv;
00116 int ret = 0;
00117 
00118 db_io->pagesize = CMPR_DIVIDE(db_io->pagesize);
00119 db_io->bytes = CMPR_DIVIDE(db_io->bytes);
00120 
00121 /*
00122  * Page 0 is a special case. It contains the metadata information
00123  * (at most 256 bytes) and must not be compressed because it is read
00124  * with CDB___os_read and not CDB___os_io. This read is done before
00125  * any memory pool structure is initialized, we therefore have no
00126  * chance to trap it anywhere but here. 
00127  */
00128 switch (flag) {
00129 case DB_IO_READ:
00130 if(db_io->pgno == PGNO_BASE_MD) {
00131 ret = CDB___os_io(dbenv, db_io, DB_IO_READ, niop);
00132 *niop = CMPR_MULTIPLY(*niop);
00133 } else 
00134 ret = CDB___memp_cmpr_read(dbmfp, bhp, db_io, niop);
00135 break;
00136 case DB_IO_WRITE:
00137 if(db_io->pgno == PGNO_BASE_MD) {
00138 /*
00139  * Write a copy of the DBMETA information at 
00140  * 256, 512, 1024, 2048, 4096, ... up to the actually required page size.
00141  * This ensure that the DBMETA information will be found without knowing
00142  * the actual page size used in the file. 
00143  * !! Assume that PGNO_BASE_MD == 1
00144  */
00145 size_t required = db_io->pagesize;
00146 size_t orig_bytes = db_io->bytes;
00147 db_io->bytes = DBMETASIZE;
00148 for(db_io->pagesize = DBMETASIZE; db_io->pagesize < required; db_io->pagesize <<= 1) {
00149 ret = CDB___os_io(dbenv, db_io, DB_IO_WRITE, niop);
00150 if(ret != 0 || *niop != DBMETASIZE)
00151 break;
00152 }
00153 db_io->bytes = orig_bytes;
00154 db_io->pagesize = required;
00155 if(ret == 0)
00156 ret = CDB___os_io(dbenv, db_io, DB_IO_WRITE, niop);
00157 *niop = CMPR_MULTIPLY(*niop);
00158 } else
00159 ret = CDB___memp_cmpr_write(dbmfp, bhp, db_io, niop);
00160 break;
00161 }
00162 
00163 db_io->pgno = orig_pgno;
00164 db_io->pagesize = orig_pagesize;
00165 db_io->bytes = orig_bytes;
00166 
00167 return ret;
00168 }
00169 
00170 /*
00171  * CDB___memp_cmpr_read_meta --
00172  * Transparent compression read page containing meta header
00173  */
00174 int
00175 CDB___memp_cmpr_read_meta(dbenv, fhp, buff, buff_length, nrp)
00176 DB_ENV *dbenv;
00177 DB_FH *fhp;
00178 void *buff;
00179 size_t buff_length;
00180 ssize_t *nrp;
00181 {
00182 CMPR cmpr;
00183 int ret;
00184 int i;
00185 
00186 if((ret = CDB___os_read(dbenv, fhp, buff, buff_length, nrp)) != 0)
00187 goto err;
00188 
00189 if(*nrp != buff_length)
00190 goto err;
00191 
00192 /*
00193  * Read the cmpr header from page.
00194  */
00195 memcpy(&cmpr, buff, sizeof(CMPR));
00196 
00197 /*
00198  * If not at the beginning of compressed page chain, build
00199  * a fake page.
00200  */
00201 if(F_ISSET(&cmpr, DB_CMPR_FREE) || F_ISSET(&cmpr, DB_CMPR_INTERNAL)) {
00202 ret = CDB___db_panic(dbenv, EINVAL);
00203 goto err;
00204 }
00205 
00206 for(i = 0; i < buff_length - (DB_CMPR_OVERHEAD + 1); i++)
00207 ((char*)buff)[i] = ((char*)buff)[i + (DB_CMPR_OVERHEAD + 1)];
00208 
00209 err:
00210 return ret;
00211 }
00212 
00213 /*
00214  * CDB___memp_cmpr_read --
00215  * Transparent compression read
00216  *
00217  * PUBLIC: int CDB___memp_cmpr_read __P((DB_MPOOLFILE *, BH *, DB_IO *, ssize_t *));
00218  */
00219 int
00220 CDB___memp_cmpr_read(dbmfp, bhp, db_io, niop)
00221 DB_MPOOLFILE *dbmfp;
00222 BH *bhp;
00223 DB_IO *db_io;
00224 ssize_t *niop;
00225 {
00226 CMPR cmpr;
00227 int ret;
00228 int chain = 0;
00229 u_int8_t *buffcmpr = 0;
00230 int buffcmpr_length = 0;
00231 int chain_length = 0;
00232 db_pgno_t first_pgno = db_io->pgno;
00233 DB_ENV *dbenv = dbmfp->dbmp->dbenv;
00234 DB_CMPR_INFO *cmpr_info = dbenv->mp_cmpr_info;
00235 /*
00236  * By default the compression does not use too much space,
00237  * hence the chain is empty.
00238  */
00239 F_CLR(bhp, BH_CMPR);
00240 
00241 /*
00242  * Read first page (if no overflow, this is the only one)
00243  */
00244 ret = CDB___os_io(dbenv, db_io, DB_IO_READ, niop);
00245 
00246 /*
00247  * An error or partial read on the first page means that we're not
00248  * going anywhere.
00249  */
00250 if(ret || *niop < db_io->pagesize)
00251 goto err;
00252 
00253 /*
00254  * Read the cmpr header from page.
00255  */
00256 memcpy(&cmpr, db_io->buf, sizeof(CMPR));
00257 
00258 /*
00259  * If not at the beginning of compressed page chain, build
00260  * a fake page.
00261  */
00262 if(F_ISSET(&cmpr, DB_CMPR_FREE) || F_ISSET(&cmpr, DB_CMPR_INTERNAL)) {
00263 ret = __memp_cmpr_page(dbmfp, &cmpr, db_io, niop);
00264 goto err;
00265 }
00266 
00267 /*
00268  * Sanity check. Happens if file corrupted.
00269  */
00270 if(!F_ISSET(&cmpr, DB_CMPR_FIRST)) {
00271 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_read: expected DB_CMPR_FIRST flag set at pgno = %ld", db_io->pgno);
00272 ret = CDB___db_panic(dbmfp->dbmp->dbenv, EINVAL);
00273 goto err;
00274 }
00275 
00276 if((ret = CDB___os_malloc(dbenv, db_io->pagesize * CMPR_MAX, NULL, &buffcmpr)) != 0)
00277 goto err;
00278 
00279 do {
00280 /*
00281  * Read the first part of the compressed data from page.
00282  */
00283 memcpy(buffcmpr + buffcmpr_length, DB_CMPR_DATA(db_io), DB_CMPR_PAGESIZE(db_io));
00284 buffcmpr_length += DB_CMPR_PAGESIZE(db_io);
00285 
00286 /*
00287  * Flag must only contain FIRST|INTERNAL and/or CHAIN. If other bits are
00288  * set, the data is corrupted. Removing the FIRST|INTERNAL bits and checking
00289  * the CHAIN bit with == instead of F_ISSET verify this.
00290  */
00291 F_CLR(&cmpr, DB_CMPR_FIRST | DB_CMPR_INTERNAL);
00292 chain = cmpr.flags;
00293 
00294 if(chain == DB_CMPR_CHAIN) {
00295 /*
00296  * Overflow Case. Continue reading data from extra pages.
00297  */
00298 
00299 chain_length++;
00300 if(chain_length >= CMPR_MAX) {
00301 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_read: compression chain too long at pgno = %ld", db_io->pgno);
00302 ret = CDB___db_panic(dbmfp->dbmp->dbenv, EINVAL);
00303 goto err;
00304 }
00305 
00306 if(cmpr.next == 0) {
00307 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_read: cmpr.next is null at pgno = %ld", chain, db_io->pgno);
00308 ret = CDB___db_panic(dbmfp->dbmp->dbenv, EINVAL);
00309 goto err;
00310 }
00311 /*
00312  * Keep the chain in buffer header.
00313  */
00314 CDB___memp_cmpr_alloc_chain(dbmfp->dbmp, bhp, BH_CMPR_POOL);
00315 
00316 bhp->chain[chain_length - 1] = cmpr.next;
00317 db_io->pgno = cmpr.next;
00318 /*
00319  * Read data from extra page.
00320  */
00321 if((ret = CDB___os_io(dbenv, db_io, DB_IO_READ, niop)) != 0 ||
00322 *niop != db_io->pagesize) {
00323 ret = EIO;
00324 goto err;
00325 }
00326 /*
00327  * Read the cmpr header from this extra page
00328  */
00329 memcpy(&cmpr, db_io->buf, sizeof(CMPR));
00330 } else if(chain != 0) {
00331 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_read: unexpected compression flag value 0x%x at pgno = %ld", chain, db_io->pgno);
00332 ret = CDB___db_panic(dbmfp->dbmp->dbenv, ret);
00333 goto err;
00334 } else if(cmpr.next != 0) {
00335 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_read: cmpr.next is not null at pgno = %ld", chain, db_io->pgno);
00336 ret = CDB___db_panic(dbmfp->dbmp->dbenv, ret);
00337 goto err;
00338 }
00339 } while(chain);
00340 
00341 /*
00342  * We gathered all the compressed data in buffcmpr, inflate it.
00343  */
00344 {
00345 switch((*buffcmpr) & TYPE_MASK) {
00346 case P_HASHMETA:
00347 case P_BTREEMETA:
00348 case P_QAMMETA:
00349 case P_INVALID:
00350 memcpy(db_io->buf, buffcmpr + sizeof(char), 255);
00351 break;
00352 default:
00353 if((ret = (*cmpr_info->uncompress)(dbenv, buffcmpr, buffcmpr_length, db_io->buf, CMPR_MULTIPLY(db_io->pagesize), cmpr_info->user_data)) != 0) {
00354 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_read: unable to uncompress page at pgno = %ld", first_pgno);
00355 ret = CDB___db_panic(dbmfp->dbmp->dbenv, ret);
00356 goto err;
00357 }
00358 break;
00359 }
00360 }
00361 #ifdef DEBUG
00362 {
00363 int ratio = buffcmpr_length > 0 ? (CMPR_MULTIPLY(db_io->pagesize) / buffcmpr_length) : 0;
00364 if(ratio > 10) ratio = 10;
00365 word_monitor_add(DB_MONITOR(dbenv), WORD_MONITOR_COMPRESS_01 + ratio, 1);
00366 }
00367 #endif /* DEBUG */
00368 
00369 *niop = CMPR_MULTIPLY(db_io->pagesize);
00370 
00371 err:
00372 #ifdef DEBUG_CMPR
00373 if(chain_length > 0) {
00374 int i;
00375 fprintf(stderr,"CDB___memp_cmpr_read:: chain_length (number of overflow pages):%2d\n",chain_length);
00376 fprintf(stderr,"CDB___memp_cmpr_read:: chain ");
00377 for(i = 0; i < chain_length; i++)
00378 fprintf(stderr, "%d, ", bhp->chain[i]);
00379 fprintf(stderr, "\n");
00380 }
00381 #endif
00382 if(buffcmpr) CDB___os_free(buffcmpr, 0);
00383 return ret;
00384 }
00385 
00386 /*
00387  * CDB___memp_cmpr_write --
00388  * Transparent compression write
00389  *
00390  * PUBLIC: int CDB___memp_cmpr_write __P((DB_MPOOLFILE *, BH *, DB_IO *, ssize_t *));
00391  */
00392 int
00393 CDB___memp_cmpr_write(dbmfp, bhp, db_io, niop)
00394 DB_MPOOLFILE *dbmfp;
00395 BH *bhp;
00396 DB_IO *db_io;
00397 ssize_t *niop;
00398 {
00399 CMPR cmpr;
00400 int chain_length = 0;
00401 int first_nonreused_chain_pos = 0;
00402 int ret;
00403 u_int8_t *buffcmpr = 0;
00404 u_int8_t *buffp;
00405 int buffcmpr_length;
00406 u_int8_t *orig_buff = db_io->buf;
00407 DB_ENV *dbenv = dbmfp->dbmp->dbenv;
00408 DB_CMPR_INFO *cmpr_info = dbenv->mp_cmpr_info;
00409 
00410 if((ret = CDB___os_malloc(dbenv, CMPR_MULTIPLY(db_io->bytes), NULL, &db_io->buf)) != 0)
00411 goto err;
00412 
00413 /*
00414  * Call the compression function, except for META pages (at most 256 bytes)
00415  */
00416 {
00417 PAGE* pp = (PAGE*)orig_buff;
00418 switch(TYPE(pp)) {
00419 case P_HASHMETA:
00420 case P_BTREEMETA:
00421 case P_QAMMETA:
00422 case P_INVALID:
00423 /*
00424  * Compressed meta is type byte + 255 bytes (the largest META info
00425  * is smaller than 255 bytes).
00426  */
00427 buffcmpr_length = 256;
00428 if ((ret = CDB___os_malloc(dbenv, buffcmpr_length, NULL, &buffcmpr)) != 0)
00429 goto err;
00430 buffcmpr[0] = TYPE_TAGS(pp);
00431 memcpy(buffcmpr + 1, orig_buff, 255);
00432 break;
00433 default:
00434 if((ret = (*cmpr_info->compress)(dbenv, orig_buff, CMPR_MULTIPLY(db_io->pagesize), &buffcmpr, &buffcmpr_length, cmpr_info->user_data)) != 0) {
00435 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_write: unable to compress page at pgno = %ld", db_io->pgno);
00436 ret = CDB___db_panic(dbmfp->dbmp->dbenv, ret);
00437 goto err;
00438 }
00439 }
00440 }
00441 #ifdef DEBUG
00442 {
00443 int ratio = buffcmpr_length > 0 ? (CMPR_MULTIPLY(db_io->pagesize) / buffcmpr_length) : 0;
00444 if(ratio > 10) ratio = 10;
00445 word_monitor_add(DB_MONITOR(dbenv), WORD_MONITOR_COMPRESS_01 + ratio, 1);
00446 }
00447 #endif /* DEBUG */
00448 
00449 /*
00450  * This can never happen.
00451  */
00452 if(buffcmpr_length > DB_CMPR_PAGESIZE(db_io) * CMPR_MAX) {
00453 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_write: compressed data is too big at pgno = %ld", db_io->pgno);
00454 ret = CDB___db_panic(dbmfp->dbmp->dbenv, EINVAL);
00455 goto err;
00456 }
00457 
00458 buffp = buffcmpr;
00459 cmpr.flags = DB_CMPR_FIRST;
00460 cmpr.next = 0;
00461 
00462 /* write pages until the whole compressed data is written */ 
00463 do {
00464 int length = buffcmpr_length - (buffp - buffcmpr);
00465 int copy_length = length > DB_CMPR_PAGESIZE(db_io) ? DB_CMPR_PAGESIZE(db_io) : length;
00466 /*
00467  * We handle serious compression stuff only if we need to.
00468  * overflow! the compressed buffer is too big -> get extra page
00469  */
00470 if(length > copy_length) {
00471 chain_length++;
00472 if(chain_length >= CMPR_MAX) {
00473 CDB___db_err(dbmfp->dbmp->dbenv, "CDB___memp_cmpr_write: chain_length overflow");
00474 ret = CDB___db_panic(dbmfp->dbmp->dbenv, EINVAL);
00475 goto err;
00476 }
00477 F_SET(&cmpr, DB_CMPR_CHAIN);
00478 if((ret = CDB___memp_cmpr_alloc(dbmfp, &cmpr.next, db_io->pagesize, bhp, &first_nonreused_chain_pos)) != 0)
00479 goto err;
00480 CDB___memp_cmpr_alloc_chain(dbmfp->dbmp, bhp, BH_CMPR_OS);
00481 bhp->chain[chain_length - 1] = cmpr.next;
00482 }
00483 /* write in the cmpr header */
00484 memcpy(db_io->buf, &cmpr, DB_CMPR_OVERHEAD);
00485 /* write in what's left of the compressed buffer (and that also fits in) */
00486 memcpy(db_io->buf + DB_CMPR_OVERHEAD, buffp, copy_length);
00487 buffp += copy_length;
00488 /* actual output */
00489 if((ret = CDB___os_io(dbenv, db_io, DB_IO_WRITE, niop)) != 0 ||
00490 *niop != db_io->pagesize) {
00491 ret = EIO;
00492 goto err;
00493 }
00494 db_io->pgno = cmpr.next;
00495 cmpr.flags = DB_CMPR_INTERNAL;
00496 cmpr.next = 0;
00497 } while(buffp - buffcmpr < buffcmpr_length);
00498 
00499 #ifdef DEBUG_CMPR
00500 fprintf(stderr,"CDB___memp_cmpr_write:: chain_length (number of overflow pages):%2d\n",chain_length);
00501 if(chain_length > 0) {
00502 int i;
00503 fprintf(stderr,"CDB___memp_cmpr_write:: chain ");
00504 for(i = 0; i < chain_length; i++)
00505 fprintf(stderr, "%d, ", bhp->chain[i]);
00506 fprintf(stderr, "\n");
00507 }
00508 #endif
00509 /*
00510  * If the chain was not completely reused, free the remaining pages (the page compression
00511  * rate is better).
00512  */
00513 if(F_ISSET(bhp, BH_CMPR) && first_nonreused_chain_pos >= 0) {
00514 int i;
00515 for(i = first_nonreused_chain_pos; i < (CMPR_MAX - 1) && bhp->chain[i]; i++) {
00516 if((ret = CDB___memp_cmpr_free(dbmfp, bhp->chain[i], db_io->pagesize)) != 0)
00517 goto err;
00518 bhp->chain[i] = 0;
00519 }
00520 }
00521 
00522 CDB___memp_cmpr_free_chain(dbmfp->dbmp, bhp);
00523 
00524 /*
00525  * In case of success, always pretend that we exactly wrote the
00526  * all bytes of the original pagesize.
00527  */
00528 *niop = CMPR_MULTIPLY(db_io->pagesize);
00529 
00530 err:
00531 CDB___os_free(db_io->buf, 0);
00532 db_io->buf = orig_buff;
00533 if(buffcmpr) CDB___os_free(buffcmpr, 0);
00534 
00535 return ret;
00536 }
00537 
00538 /*
00539  * Helpers
00540  */
00541 
00542 /*
00543  * __memp_cmpr_page --
00544  * Build a fake page. This function is a CDB___memp_cmpr_read helper.
00545  *
00546  */
00547 static int
00548 __memp_cmpr_page(dbmfp, cmpr, db_io, niop)
00549 DB_MPOOLFILE *dbmfp; 
00550 CMPR *cmpr;
00551 DB_IO *db_io;
00552 ssize_t *niop;
00553 {
00554 DB_ENV *dbenv = dbmfp->dbmp->dbenv;
00555 int ret = 0;
00556 PAGE page;
00557 
00558 memset((char*)&page, '0円', sizeof(PAGE));
00559 
00560 page.pgno = db_io->pgno;
00561 page.type = F_ISSET(cmpr, DB_CMPR_FREE) ? P_CMPR_FREE : P_CMPR_INTERNAL;
00562 
00563 /*
00564  * Sanity check
00565  */
00566 if(db_io->pagesize < sizeof(PAGE)) {
00567 ret = ENOMEM;
00568 goto err;
00569 }
00570 
00571 memcpy(db_io->buf, (char*)&page, sizeof(PAGE));
00572 
00573 *niop = CMPR_MULTIPLY(db_io->pagesize);
00574 
00575 err:
00576 
00577 return ret;
00578 }
00579 
00580 #ifdef HAVE_LIBZ
00581 #include "zlib.h"
00582 #endif /* HAVE_LIBZ */
00583 
00584 /*
00585  * CDB___memp_cmpr_inflate --
00586  * Decompress buffer
00587  *
00588  * PUBLIC: int CDB___memp_cmpr_inflate __P((const u_int8_t *, int, u_int8_t *, int, void *));
00589  */
00590 int
00591 CDB___memp_cmpr_inflate(dbenv, inbuff, inbuff_length, outbuff, outbuff_length, user_data)
00592 DB_ENV *dbenv;
00593 const u_int8_t* inbuff;
00594 int inbuff_length;
00595 u_int8_t* outbuff;
00596 int outbuff_length;
00597 void *user_data;
00598 {
00599 #ifdef HAVE_LIBZ
00600 int ret = 0;
00601 z_stream c_stream;
00602 
00603 c_stream.zalloc=(alloc_func)0;
00604 c_stream.zfree=(free_func)0;
00605 c_stream.opaque=(voidpf)0;
00606 c_stream.next_in = (Bytef*)inbuff;
00607 c_stream.avail_in = inbuff_length;
00608 c_stream.next_out = outbuff;
00609 c_stream.avail_out = outbuff_length;
00610 
00611 if(inflateInit(&c_stream) != Z_OK ||
00612 inflate(&c_stream, Z_FINISH) != Z_STREAM_END ||
00613 inflateEnd(&c_stream) != Z_OK)
00614 ret = EIO;
00615 
00616 /*
00617  * The uncompressed data must *exactly* fill outbuff_length.
00618  */
00619 if(c_stream.avail_out != 0)
00620 ret = EIO;
00621 
00622 return ret;
00623 #else /* HAVE_LIBZ */
00624 return EINVAL;
00625 #endif /* HAVE_LIBZ */
00626 }
00627 
00628 
00629 
00630 /*
00631  * CDB___memp_cmpr_deflate --
00632  * Compress buffer
00633  *
00634  * PUBLIC: int CDB___memp_cmpr_deflate __P((const u_int8_t *, int, u_int8_t **, int*, void *));
00635  */
00636 int
00637 CDB___memp_cmpr_deflate(dbenv, inbuff, inbuff_length, outbuffp, outbuff_lengthp, user_data)
00638 DB_ENV* dbenv;
00639 const u_int8_t* inbuff;
00640 int inbuff_length;
00641 u_int8_t** outbuffp;
00642 int* outbuff_lengthp;
00643 void *user_data;
00644 {
00645 #ifdef HAVE_LIBZ
00646 int ret = 0;
00647 int r;
00648 z_stream c_stream;
00649 u_int8_t* outbuff;
00650 
00651 /*
00652  * Z_FINISH can be used immediately after deflateInit if all the compression
00653  * is to be done in a single step. In this case, avail_out must be at least
00654  * 0.1% larger than avail_in plus 12 bytes. If deflate does not return
00655  * Z_STREAM_END, then it must be called again as described above.
00656  *
00657  * !!!
00658  * In order to avoid division by 1000, divide by 512 (2^9) using shift.
00659  * That is, make the buffer 0.2% larger. 
00660  */
00661 int outbuff_length = inbuff_length + (inbuff_length >> 9) + 12;
00662 
00663 *outbuffp = 0;
00664 *outbuff_lengthp = 0;
00665 
00666 if(CDB___os_malloc(dbenv, outbuff_length, NULL, &outbuff) != 0) {
00667 ret = ENOMEM;
00668 goto err;
00669 }
00670 
00671 /*
00672  * Clear possible garbage in the page
00673  */
00674 {
00675 PAGE* pg = (PAGE*)inbuff;
00676 switch(TYPE(pg)) {
00677 case P_IBTREE:
00678 case P_LBTREE:
00679 memset((char*)(inbuff + LOFFSET(pg)), '0円', P_FREESPACE(pg));
00680 break;
00681 }
00682 }
00683 
00684 c_stream.zalloc=(alloc_func)0;
00685 c_stream.zfree=(free_func)0;
00686 c_stream.opaque=(voidpf)0;
00687 
00688 if(deflateInit(&c_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
00689 ret = EIO;
00690 goto err;
00691 }
00692 
00693 c_stream.next_in = (Bytef*)inbuff;
00694 c_stream.avail_in = inbuff_length;
00695 c_stream.next_out = outbuff;
00696 c_stream.avail_out = outbuff_length;
00697 
00698 while((r = deflate(&c_stream, Z_FINISH)) != Z_STREAM_END && r == Z_OK)
00699 ;
00700 
00701 if(r != Z_STREAM_END)
00702 ret = EIO;
00703 
00704 if(deflateEnd(&c_stream) != Z_OK)
00705 ret = EIO;
00706 
00707 if(ret == 0) {
00708 *outbuffp = outbuff;
00709 *outbuff_lengthp = outbuff_length - c_stream.avail_out;
00710 } else {
00711 CDB___os_free(outbuff, outbuff_length);
00712 }
00713 #ifdef DEBUG_CMPR
00714 fprintf(stderr,"CDB___memp_cmpr_deflate:: compress %d bytes to %d \n", inbuff_length, *outbuff_lengthp);
00715 #endif
00716 
00717 err:
00718 return ret;
00719 #else /* HAVE_LIBZ */
00720 return EINVAL;
00721 #endif /* HAVE_LIBZ */
00722 }
00723 
00724 
00725 
00726 /*
00727  * __memp_cmpr_info_valid --
00728  * Compute compressed page size
00729  */
00730 static int
00731 __memp_cmpr_info_valid(dbenv,cmpr_info)
00732 DB_ENV *dbenv;
00733 DB_CMPR_INFO *cmpr_info;
00734 {
00735 int ret = 0;
00736 if(!cmpr_info ) {
00737 CDB___db_err(dbenv, "__memp_cmpr_info_valid: cmpr_info == NULL");
00738 ret = CDB___db_panic(dbenv, EINVAL);
00739 goto err;
00740 }
00741 
00742 if(!cmpr_info->compress ) {
00743 CDB___db_err(dbenv, "__memp_cmpr_info_valid: compress == NULL!");
00744 ret = CDB___db_panic(dbenv, EINVAL);
00745 goto err;
00746 }
00747 
00748 if(!cmpr_info->uncompress ) {
00749 CDB___db_err(dbenv, "__memp_cmpr_info_valid: uncompress == NULL!");
00750 ret = CDB___db_panic(dbenv, EINVAL);
00751 goto err;
00752 }
00753 
00754 if(cmpr_info->coefficient == 0 || cmpr_info->coefficient > 5 ) {
00755 CDB___db_err(dbenv, "__memp_cmpr_info_valid: coefficient should be > 0 and < 5 coefficient=%d ", cmpr_info->coefficient);
00756 ret = CDB___db_panic(dbenv, EINVAL);
00757 goto err;
00758 }
00759 
00760 if(cmpr_info->max_npages == 0 || cmpr_info->max_npages > 128 ) {
00761 CDB___db_err(dbenv, "__memp_cmpr_info_valid: max_npages should be > 0 and < 128 max_npages=%d ", cmpr_info->max_npages);
00762 ret = CDB___db_panic(dbenv, EINVAL);
00763 goto err;
00764 }
00765 err:
00766 return ret;
00767 }
00768 
00769 /*
00770  * __memp_cmpr_coefficient --
00771  *
00772  * PUBLIC: u_int8_t CDB___memp_cmpr_coefficient __P((DB_ENV *dbenv));
00773  */
00774 u_int8_t
00775 CDB___memp_cmpr_coefficient(dbenv)
00776 DB_ENV *dbenv;
00777 {
00778 u_int8_t ret = 0;
00779 
00780 if(!dbenv || !dbenv->mp_cmpr_info) {
00781 ret = default_cmpr_info.coefficient;
00782 } else {
00783 __memp_cmpr_info_valid(dbenv, dbenv->mp_cmpr_info);
00784 ret = dbenv->mp_cmpr_info->coefficient;
00785 }
00786 
00787 return (ret);
00788 }
00789 
00790 /*
00791  * Initialisation of page compression
00792  */
00793 
00794 #define CMPR_META_NORMAL 0x01
00795 #define CMPR_META_COMPRESSED 0x02
00796 
00797 typedef struct _cmprmeta {
00798 u_int32_t magic; /* 00-03: Magic number. */
00799 db_pgno_t free; /* 04-07: First free page. */
00800 } CMPRMETA;
00801 
00802 int
00803 CDB___memp_cmpr_create(dbenv, fhp, pgsize, flags)
00804 DB_ENV *dbenv;
00805 DB_FH *fhp;
00806 size_t pgsize;
00807 int flags;
00808 {
00809 int ret;
00810 int count = 0;
00811 CMPRMETA meta;
00812 char* buffer;
00813 
00814 if((ret = CDB___os_malloc(dbenv, pgsize, NULL, &buffer)) != 0) {
00815 CDB___db_err(dbenv, "CDB___memp_cmpr_create: os_malloc %d bytes failed:%d", pgsize, ret);
00816 ret = CDB___db_panic(dbenv, EINVAL);
00817 return ret;
00818 }
00819 
00820 meta.magic = flags == MP_CMPR ? CMPR_META_COMPRESSED : CMPR_META_NORMAL;
00821 meta.free = PGNO_INVALID;
00822 
00823 if((ret = CDB___os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0) {
00824 CDB___db_err(dbenv, "CDB___memp_cmpr_create: seek to 0 error");
00825 return CDB___db_panic(dbenv, ret);
00826 }
00827 memcpy(buffer, (char*)&meta, sizeof(CMPRMETA));
00828 if((ret = CDB___os_write(dbenv, fhp, buffer, pgsize, &count)) < 0) {
00829 CDB___db_err(dbenv, "CDB___memp_cmpr_create: write error at 0");
00830 return CDB___db_panic(dbenv, ret);
00831 }
00832 if(count != pgsize) {
00833 CDB___db_err(dbenv, "CDB___memp_cmpr_create: write error %d bytes instead of %d bytes", count, pgsize);
00834 return CDB___db_panic(dbenv, EINVAL);
00835 }
00836 CDB___os_free(buffer, pgsize);
00837 
00838 return ret;
00839 }
00840 
00841 /*
00842  * CDB___memp_cmpr_open --
00843  * Cache the meta information about compression, initialize dbenv info.
00844  *
00845  * PUBLIC: int CDB___memp_cmpr_open __P((DB_ENV *, MPOOLFILE *, const char *));
00846  */
00847 int
00848 CDB___memp_cmpr_open(dbenv, mfp, path)
00849 DB_ENV *dbenv;
00850 MPOOLFILE *mfp;
00851 const char *path;
00852 {
00853 int ret;
00854 /*
00855  * Read compression meta information
00856  */
00857 DB_FH fh;
00858 ssize_t count;
00859 CMPRMETA meta;
00860 
00861 if((ret = CDB___os_open(dbenv, path, DB_OSO_RDONLY, 0, &fh)) != 0) {
00862 CDB___db_err(dbenv, "CDB___memp_cmpr_open: cannot open %s readonly", path);
00863 return CDB___db_panic(dbenv, ret);
00864 }
00865 
00866 if((ret = CDB___os_read(dbenv, &fh, (void*)&meta, sizeof(CMPRMETA), &count)) != 0) {
00867 CDB___db_err(dbenv, "CDB___memp_cmpr_open: cannot read page 0");
00868 ret = CDB___db_panic(dbenv, ret);
00869 goto err;
00870 }
00871 
00872 if(count != sizeof(CMPRMETA)) {
00873 CDB___db_err(dbenv, "CDB___memp_cmpr_open: read error %d bytes instead of %d bytes", count, sizeof(CMPRMETA));
00874 ret = CDB___db_panic(dbenv, EINVAL);
00875 goto err;
00876 }
00877 
00878 if(meta.magic == CMPR_META_COMPRESSED) {
00879 mfp->flags |= MP_CMPR;
00880 mfp->cmpr_free = meta.free;
00881 
00882 /*
00883  * Initialisation of cmpr_context
00884  */
00885 if(!dbenv->mp_cmpr_info) {
00886 if(default_cmpr_info.compress == 0) {
00887 CDB___db_err(dbenv, "CDB___memp_cmpr_open: zlib compression not available, re-compile --with-zlib=DIR");
00888 ret = CDB___db_panic(dbenv, EINVAL);
00889 goto err;
00890 }
00891 dbenv->mp_cmpr_info = &default_cmpr_info;
00892 }
00893 /*
00894  * Check if cmpr_info is sane
00895  */
00896 if((ret = __memp_cmpr_info_valid(dbenv, dbenv->mp_cmpr_info)))
00897 goto err;
00898 }
00899 
00900 err:
00901 CDB___os_closehandle(&fh);
00902 
00903 return ret;
00904 }
00905 
00906 /*
00907  * CDB___memp_cmpr_close --
00908  * This is not really a close but a sync. It is called more than
00909  * once per file, specifically when opening subdatabases. The
00910  * file handle will be used afterwards, most of the time.
00911  *
00912  * PUBLIC: int CDB___memp_cmpr_close __P((DB_ENV *, DB_MPOOLFILE *));
00913  */
00914 int
00915 CDB___memp_cmpr_close(dbenv, dbmfp)
00916 DB_ENV *dbenv;
00917 DB_MPOOLFILE *dbmfp;
00918 {
00919 /*
00920  * If handle is READ/WRITE
00921  */
00922 if(dbmfp->flags & MP_UPGRADE) {
00923 MPOOLFILE *mfp = dbmfp->mfp;
00924 DB_FH *fhp = &dbmfp->fh;
00925 size_t count = 0;
00926 int ret;
00927 
00928 CMPRMETA meta;
00929 memset((char*)&meta, '0円', sizeof(CMPRMETA));
00930 
00931 meta.magic = mfp->flags & MP_CMPR ? CMPR_META_COMPRESSED : CMPR_META_NORMAL;
00932 if(mfp->flags & MP_CMPR)
00933 meta.free = mfp->cmpr_free;
00934 
00935 if((ret = CDB___os_seek(dbenv, fhp, 0, 0, 0, 0, DB_OS_SEEK_SET)) != 0) {
00936 CDB___db_err(dbenv, "CDB___memp_cmpr_close: seek to 0 error");
00937 return CDB___db_panic(dbenv, ret);
00938 }
00939 
00940 if((ret = CDB___os_write(dbenv, fhp, (void*)&meta, sizeof(CMPRMETA), &count)) < 0) {
00941 CDB___db_err(dbenv, "CDB___memp_cmpr_close: write error at 0");
00942 return CDB___db_panic(dbenv, ret);
00943 }
00944 
00945 if(count != sizeof(CMPRMETA)) {
00946 CDB___db_err(dbenv, "CDB___memp_cmpr_close: write error %d bytes instead of %d bytes", count, sizeof(CMPRMETA));
00947 return CDB___db_panic(dbenv, EINVAL);
00948 }
00949 }
00950 
00951 return 0;
00952 }
00953 
00954 /*
00955  * CDB___memp_cmpr_alloc --
00956  * Get a new free page to store weak compression data.
00957  *
00958  * PUBLIC: int CDB___memp_cmpr_alloc __P((DB_MPOOLFILE *, db_pgno_t *, size_t, BH *, int *));
00959  */
00960 int
00961 CDB___memp_cmpr_alloc(dbmfp, pgnop, pagesize, bhp, first_nonreused_chain_posp)
00962 DB_MPOOLFILE *dbmfp;
00963 db_pgno_t *pgnop;
00964 size_t pagesize;
00965 BH *bhp;
00966 int *first_nonreused_chain_posp;
00967 {
00968 DB_ENV *dbenv = dbmfp->dbmp->dbenv;
00969 int ret = 0;
00970 
00971 #ifdef DEBUG_CMPR
00972 fprintf(stderr,"CDB___memp_cmpr_alloc:: bhp:%8x bhp->chain:%8x first_nonreused_chain_posp:%2d\n", bhp, bhp->chain, *first_nonreused_chain_posp);
00973 #endif
00974 if(F_ISSET(bhp, BH_CMPR) && bhp->chain == NULL) {
00975 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: BH_CMPR set and bhp->chain == NULL");
00976 ret = CDB___db_panic(dbenv, EINVAL);
00977 goto err;
00978 }
00979 
00980 if((*first_nonreused_chain_posp) >= (CMPR_MAX - 1)) {
00981 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: first_nonreused_chain_pos >= (CMPR_MAX - 1)");
00982 ret = CDB___db_panic(dbenv, EINVAL);
00983 goto err;
00984 }
00985 
00986 /*
00987  * If possible reuse an existing chain.
00988  */
00989 if((*first_nonreused_chain_posp) >= 0 && F_ISSET(bhp, BH_CMPR) && bhp->chain[*first_nonreused_chain_posp]) {
00990 *pgnop = bhp->chain[*first_nonreused_chain_posp];
00991 (*first_nonreused_chain_posp)++;
00992 #ifdef DEBUG_CMPR
00993 fprintf(stderr,"CDB___memp_cmpr_alloc:: reusing page in chain \n");
00994 #endif
00995 } else {
00996 MPOOLFILE *mfp = dbmfp->mfp;
00997 DB_MPOOL *dbmp = dbmfp->dbmp;
00998 
00999 /* all pages in bhp->chain are now reused */
01000 (*first_nonreused_chain_posp) = -1;
01001 #ifdef DEBUG_CMPR
01002 fprintf(stderr,"CDB___memp_cmpr_alloc:: no more reusable pages in chain\n");
01003 #endif
01004 R_LOCK(dbenv, dbmp->reginfo);
01005 if(mfp->cmpr_free == PGNO_INVALID) {
01006 #ifdef DEBUG_CMPR
01007 fprintf(stderr,"CDB___memp_cmpr_alloc:: free page pool empty, allocating\n");
01008 #endif
01009 ret = 0;
01010 ++dbmfp->mfp->last_pgno;
01011 #ifdef DEBUG
01012 word_monitor_set(DB_MONITOR(dbenv), WORD_MONITOR_PGNO, dbmfp->mfp->last_pgno);
01013 #endif /* DEBUG */
01014 *pgnop = dbmfp->mfp->last_pgno;
01015 } else {
01016 /*
01017  * Read the free page, save the next free page number.
01018  */
01019 CMPR cmpr;
01020 size_t count;
01021 DB_FH *fhp = &dbmfp->fh;
01022 
01023 *pgnop = mfp->cmpr_free;
01024 
01025 if((ret = CDB___os_seek(dbenv, fhp, pagesize, *pgnop, 0, 0, DB_OS_SEEK_SET)) != 0) {
01026 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: seek error at %d", *pgnop);
01027 ret = CDB___db_panic(dbenv, ret);
01028 goto oops;
01029 }
01030 if((ret = CDB___os_read(dbenv, fhp, (void*)&cmpr, sizeof(CMPR), &count)) != 0) {
01031 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: read error at %d", *pgnop);
01032 ret = CDB___db_panic(dbenv, ret);
01033 goto oops;
01034 }
01035 if(count != sizeof(CMPR)) {
01036 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: read error %d bytes instead of %d bytes", count, sizeof(CMPR));
01037 ret = CDB___db_panic(dbenv, ret);
01038 goto oops;
01039 }
01040 if(cmpr.flags != DB_CMPR_FREE) {
01041 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: got %d flags instead of DB_CMPR_FREE", cmpr.flags);
01042 ret = CDB___db_panic(dbenv, ret);
01043 goto oops;
01044 }
01045 mfp->cmpr_free = cmpr.next;
01046 
01047 if(*pgnop == 0) {
01048 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc: unexpected pgno == 0");
01049 ret = CDB___db_panic(dbenv, ret);
01050 goto oops;
01051 }
01052 
01053 #ifdef DEBUG_CMPR
01054 fprintf(stderr,"CDB___memp_cmpr_alloc:: reuse free page %d\n", *pgnop);
01055 #endif
01056 }
01057 oops:
01058 R_UNLOCK(dbenv, dbmp->reginfo);
01059 }
01060 err:
01061 return ret;
01062 }
01063 
01064 /*
01065  * CDB___memp_cmpr_free --
01066  * Release a page used to store weak compression data.
01067  *
01068  * PUBLIC: int CDB___memp_cmpr_free __P((DB_MPOOLFILE *, db_pgno_t));
01069  */
01070 int
01071 CDB___memp_cmpr_free(dbmfp, pgno, pagesize)
01072 DB_MPOOLFILE *dbmfp;
01073 db_pgno_t pgno;
01074 size_t pagesize;
01075 {
01076 int ret = 0;
01077 
01078 DB_ENV *dbenv = dbmfp->dbmp->dbenv;
01079 MPOOLFILE *mfp = dbmfp->mfp;
01080 DB_MPOOL *dbmp = dbmfp->dbmp;
01081 DB_FH *fhp = &dbmfp->fh;
01082 CMPR cmpr;
01083 size_t count;
01084 
01085 R_LOCK(dbenv, dbmp->reginfo);
01086 
01087 cmpr.flags = DB_CMPR_FREE;
01088 cmpr.next = mfp->cmpr_free;
01089 mfp->cmpr_free = pgno;
01090 
01091 #ifdef DEBUG_CMPR
01092 fprintf(stderr,"CDB___memp_cmpr_free:: freeing page:%3d \n",pgno);
01093 #endif
01094 
01095 if((ret = CDB___os_seek(dbenv, fhp, pagesize, pgno, 0, 0, DB_OS_SEEK_SET)) != 0) {
01096 CDB___db_err(dbenv, "CDB___memp_cmpr_free: seek error at %d", pgno);
01097 ret = CDB___db_panic(dbenv, ret);
01098 goto err;
01099 }
01100 if((ret = CDB___os_write(dbenv, fhp, (void*)&cmpr, sizeof(CMPR), &count)) < 0) {
01101 CDB___db_err(dbenv, "CDB___memp_cmpr_free: write error at %d", pgno);
01102 ret = CDB___db_panic(dbenv, ret);
01103 goto err;
01104 }
01105 if(count != sizeof(CMPR)) {
01106 CDB___db_err(dbenv, "CDB___memp_cmpr_free: write error %d bytes instead of %d bytes", count, sizeof(CMPR));
01107 ret = CDB___db_panic(dbenv, ret);
01108 goto err;
01109 }
01110 
01111 err:
01112 R_UNLOCK(dbenv, dbmp->reginfo);
01113 return ret;
01114 }
01115 
01116 
01117 /*
01118  * CDB___memp_cmpr_alloc_chain --
01119  * Allocate chain entry in BH
01120  *
01121  * PUBLIC: int CDB___memp_cmpr_alloc_chain __P((DB_MPOOL *, BH *));
01122  */
01123 
01124 int
01125 CDB___memp_cmpr_alloc_chain(dbmp, bhp, alloc_type)
01126 DB_MPOOL *dbmp;
01127 BH *bhp;
01128 int alloc_type;
01129 {
01130 DB_ENV *dbenv = dbmp->dbenv;
01131 int ret = 0;
01132 if(!bhp->chain) {
01133 int alloc_ret;
01134 int alloc_length = sizeof(db_pgno_t)*(CMPR_MAX-1);
01135 switch(alloc_type) {
01136 case BH_CMPR_POOL:
01137 {
01138 MPOOL *mp = dbmp->reginfo[0].primary;
01139 int n_cache = NCACHE(mp, bhp->pgno);
01140 alloc_ret = CDB___memp_alloc(dbmp, &dbmp->reginfo[n_cache], NULL, alloc_length, NULL, (void *)(&bhp->chain));
01141 F_SET(bhp, BH_CMPR_POOL);
01142 }
01143 break;
01144 case BH_CMPR_OS:
01145 alloc_ret = CDB___os_malloc(dbenv, alloc_length, NULL, &bhp->chain);
01146 F_SET(bhp, BH_CMPR_OS);
01147 break;
01148 default:
01149 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc_chain: unknown alloc type :%d", alloc_type);
01150 ret = CDB___db_panic(dbenv, EINVAL);
01151 goto err;
01152 break;
01153 }
01154 
01155 if(alloc_ret) {
01156 CDB___db_err(dbenv, "CDB___memp_cmpr_alloc_chain: memp_alloc %d bytes failed:%d", alloc_length, alloc_ret);
01157 ret = CDB___db_panic(dbenv, EINVAL);
01158 goto err;
01159 }
01160 memset((void *)bhp->chain, 0, alloc_length);
01161 #if defined(DEBUG_CMPR) || defined(DEBUG_CMPR_ALLOC)
01162 fprintf(stderr, "CDB___memp_cmpr_alloc_chain:: allocate chain in %s :%8x\n", (alloc_type == BH_CMPR_OS ? "malloc" : "shalloc"), bhp->chain);
01163 #endif
01164 } else {
01165 #ifdef DEBUG_CMPR
01166 fprintf(stderr, "CDB___memp_cmpr_alloc_chain:: existing chain:%8x\n", bhp->chain);
01167 #endif
01168 }
01169 F_SET(bhp, BH_CMPR);
01170 err:
01171 return ret;
01172 }
01173 
01174 /*
01175  * CDB___memp_cmpr_free_chain --
01176  * Free chain entry in BH
01177  *
01178  * PUBLIC: int CDB___memp_cmpr_free_chain __P((DB_MPOOL *, BH *));
01179  */
01180 
01181 int
01182 CDB___memp_cmpr_free_chain(dbmp, bhp)
01183 DB_MPOOL *dbmp;
01184 BH *bhp;
01185 {
01186 DB_ENV *dbenv = dbmp->dbenv;
01187 
01188 if(F_ISSET(bhp, BH_CMPR)) {
01189 if(bhp->chain) {
01190 int alloc_length = sizeof(db_pgno_t)*(CMPR_MAX-1);
01191 int alloc_type = bhp->flags & (BH_CMPR_POOL|BH_CMPR_OS);
01192 switch(alloc_type) {
01193 case BH_CMPR_POOL:
01194 {
01195 MPOOL *mp = dbmp->reginfo[0].primary;
01196 int n_cache = NCACHE(mp, bhp->pgno);
01197 CDB___db_shalloc_free(dbmp->reginfo[n_cache].addr, bhp->chain);
01198 }
01199 break;
01200 case BH_CMPR_OS:
01201 CDB___os_free(bhp->chain, alloc_length);
01202 break;
01203 default:
01204 CDB___db_err(dbenv, "CDB___memp_cmpr_free_chain: unknown alloc type :%d", alloc_type);
01205 return CDB___db_panic(dbenv, EINVAL);
01206 break;
01207 }
01208 #if defined(DEBUG_CMPR) || defined(DEBUG_CMPR_ALLOC)
01209 fprintf(stderr, "CDB___memp_cmpr_free_chain:: free chain in %s :%8x\n", (alloc_type == BH_CMPR_OS ? "malloc" : "shalloc"), bhp->chain);
01210 #endif
01211 bhp->chain = NULL;
01212 } else {
01213 CDB___db_err(dbenv, "CDB___memp_cmpr_free_chain: BH_CMPR set but null bhp->chain");
01214 return CDB___db_panic(dbenv, EINVAL);
01215 }
01216 } else if(bhp->chain) {
01217 CDB___db_err(dbenv, "CDB___memp_cmpr_free_chain: BH_CMPR not set but bhp->chain not null");
01218 return CDB___db_panic(dbenv, EINVAL);
01219 }
01220 
01221 F_CLR(bhp, BH_CMPR | BH_CMPR_OS | BH_CMPR_POOL);
01222 
01223 return 0;
01224 }

Generated on Sun Jun 8 10:56:38 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /