00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
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
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
00064
00065 static int __memp_cmpr_page __P((DB_MPOOLFILE *, CMPR *, DB_IO *, ssize_t *));
00066
00067
00068
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
00084 static DB_CMPR_INFO default_cmpr_info = {
00085 0,
00086 0,
00087 0,
00088 0,
00089 NULL
00090 };
00091 #endif
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
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
00123
00124
00125
00126
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
00140
00141
00142
00143
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
00172
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
00194
00195 memcpy(&cmpr, buff, sizeof(CMPR));
00196
00197
00198
00199
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
00215
00216
00217
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
00237
00238
00239 F_CLR(bhp, BH_CMPR);
00240
00241
00242
00243
00244 ret = CDB___os_io(dbenv, db_io, DB_IO_READ, niop);
00245
00246
00247
00248
00249
00250 if(ret || *niop < db_io->pagesize)
00251 goto err;
00252
00253
00254
00255
00256 memcpy(&cmpr, db_io->buf, sizeof(CMPR));
00257
00258
00259
00260
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
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
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
00288
00289
00290
00291 F_CLR(&cmpr, DB_CMPR_FIRST | DB_CMPR_INTERNAL);
00292 chain = cmpr.flags;
00293
00294 if(chain == DB_CMPR_CHAIN) {
00295
00296
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
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
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
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
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
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
00388
00389
00390
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
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
00425
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
00448
00449
00450
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
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
00468
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
00484 memcpy(db_io->buf, &cmpr, DB_CMPR_OVERHEAD);
00485
00486 memcpy(db_io->buf + DB_CMPR_OVERHEAD, buffp, copy_length);
00487 buffp += copy_length;
00488
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
00511
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
00526
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
00540
00541
00542
00543
00544
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
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
00583
00584
00585
00586
00587
00588
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
00618
00619 if(c_stream.avail_out != 0)
00620 ret = EIO;
00621
00622 return ret;
00623 #else
00624 return EINVAL;
00625 #endif
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
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
00653
00654
00655
00656
00657
00658
00659
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
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
00720 return EINVAL;
00721 #endif
00722 }
00723
00724
00725
00726
00727
00728
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
00771
00772
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
00792
00793
00794 #define CMPR_META_NORMAL 0x01
00795 #define CMPR_META_COMPRESSED 0x02
00796
00797 typedef struct _cmprmeta {
00798 u_int32_t magic;
00799 db_pgno_t free;
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
00843
00844
00845
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
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
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
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
00908
00909
00910
00911
00912
00913
00914 int
00915 CDB___memp_cmpr_close(dbenv, dbmfp)
00916 DB_ENV *dbenv;
00917 DB_MPOOLFILE *dbmfp;
00918 {
00919
00920
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
00956
00957
00958
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
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
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
01014 *pgnop = dbmfp->mfp->last_pgno;
01015 } else {
01016
01017
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
01066
01067
01068
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
01119
01120
01121
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
01176
01177
01178
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 }