The information about compaction is organized in the following manner:
Declaration
The function is declared this way:
static void objectstore::compact ( char **dbs_to_be_compacted, os_pathname_and_segment_number **segments_to_be_compacted = 0, char **dbs_referring_to_compacted_ones = 0, os_pathname_and_segment_number **segs_referring_to_compacted_ones = 0 );
char *compact_dbs[NUM_COMPACT_DBS]; . . . objectstore::compact (compact_dbs);The argument segments_to_be_compacted, like dbs_to_be_compacted, specifies what data you want compacted, but it does so at segment granularity rather than database granularity. This argument is a null-terminated array of pointers to instances of the class os_pathname_and_segment_number. Each such instance identifies a particular segment by encapsulating the pathname of the database containing the segment together with the segment number of that segment within the database. The constructor for this class is declared this way:
os_pathname_and_segment_number:: os_pathname_and_segment_number( const char *db, os_unsigned_int32 seg_number );You can obtain the segment number of a segment with an os_segment::get_number whose value type is a const char*. So here is how you might create an os_pathname_and_segment_number to identify a particular segment:
os_database *db1 = os_database::lookup("/user/parts/db1"); . . . /* retrieve obj1 from db1*/ . . . os_segment *seg1 = os_segment::of(obj1); os_pathname_and_segment_number *seg1_identifier = os_pathname_and_segment_number( db1, seg1->get_number() );
If you know that the pointers and references to compacted objects are restricted to certain segments in certain databases, you can specify just these segments rather than the entire databases. This can speed up the compaction operation. You do this with the argument segs_referring_to_compacted_ones, which is a null-terminated array of pointers to instances of pathname_and_segment_number.
char *compact_dbs[NUM_COMPACT_DBS]; char *reference_dbs[NUM_REFERENCE_DBS]; os_pathname_and_segment_number * compact_segs[NUM_COMPACT_SEGS]; os_pathname_and_segment_number * reference_segs[NUM_REFERENCE_SEGS]; . . . objectstore::compact( compact_dbs, compact_segs, reference_dbs, reference_segs );
The function will signal the exception err_os_compaction if any invalid arguments are supplied.
You can control the amount of time that other applications are locked out of data access by compacting a few segments at a time. For example, to compact a single segment in a particular database, you can use the following code:
char* referencing_dbs[2]; os_pathname_and_segment_number* compact_segs[2]; os_pathname_and_segment_number seg( "database_foo", segment_to_be_compacted->get_number() ); referencing_dbs[0] = "database_foo" ; referencing_dbs[1] = 0 ; compact_segs[0] = &seg ; compact_segs[1] = 0 ; objectstore::compact (0, compact_segs, referencing_dbs); . . .If you want to run compaction in a separate process, the application can use the UNIX exec facility to start up another process that calls the function.
os_unsigned_int32 os_segment::unused_space() const;This function returns the amount of space (in bytes) in the segment not currently occupied by any object. It accounts for space resulting from objects that have been deleted as well as space that cannot be used as a result of internal ObjectStore alignment considerations. Here is an example of its use:
if ((float) (seg1->unused_space()) / (float) (seg1->get_size()) > .10) compact_segs[i++] = seg1 ;See also os_segment::unused_space() in Chapter 2, Class Library, of the ObjectStore C++ API Reference.
Header File for Compaction
Programs using compaction must include the header file <ostore/compact.hh>, and link with the compaction library. Compaction Example
Here is a complete program that uses the compact() function:
#include <iostream.h> #include <ostore/ostore.hh> #include <ostore/compact.hh> extern "C" { char* getenv(const char*); int strcmp( const char*, const char* ); int atoi( const char* ); } static void printUsage() { cout << "Usage: apicompact [-s] [-bs] (-d <dbname>)+ \ (-r <dbname>)+ \n" << " (-ds <dbname> <seg>)+ (-rs <dbname> <seg>)+ \n" << " -s is for silent operation.\n" << " -bs is for batch schema installation.\n" << " -d database to compact.\n" << " -r database with ref's to compacted data.\n" << " -ds database segment to compact.\n" << " -rs database segment with ref's to compacted data.\n"; cout.flush(); } int apicompact_main(int argc , char* argv[]) { char* compact_dbs[16]; int compact_dbs_no = 0; char* reference_dbs[16]; int reference_dbs_no = 0; os_pathname_and_segment_number* compact_segs[16]; int compact_segs_no = 0; os_pathname_and_segment_number* reference_segs[16]; int reference_segs_no = 0; int silent = 0; int inc_schema = 1; for( int i = 1; i < argc; i++ ) { if ( strcmp(argv[i], "-d") == 0 && i < argc - 1 ) { i++; compact_dbs[compact_dbs_no++] = argv[i]; } /* end if */ else if ( strcmp(argv[i], "-r") == 0 && i < argc - 1 ) { i++; reference_dbs[reference_dbs_no++] = argv[i]; } /* end else *if / else if ( strcmp(argv[i], "-ds") == 0 && i < argc - 2 ) { compact_segs[compact_segs_no++] = new os_pathname_and_segment_number( argv[i+1], atoi( argv[i+2])); i += 2; } /* end else if */ else if ( strcmp(argv[i], "-rs") == 0 && i < argc - 2 ) { reference_segs[reference_segs_no++] = new os_pathname_and_segment_number( argv[i+1], atoi( argv[i+2])); i += 2; } /* end else if */ else if ( strcmp( argv[i], "-s" ) == 0 ) { silent = 1; } /* end else if */ else if ( strcmp( argv[i], "-bs" ) == 0 ) { inc_schema = 0; } /* end else if */ else { printUsage(); cout << "No option \"" << argv[i] << "\"\n"; } /* end else */ } /* end for loop */ compact_dbs[compact_dbs_no] = 0; reference_dbs[reference_dbs_no] = 0; compact_segs[compact_segs_no] = 0; reference_segs[reference_segs_no] = 0; if( !silent ) cout << "Starting " << argv[0] << endl << flush; objectstore::initialize(); objectstore::set_incremental_schema_installation( inc_schema ); objectstore::compact ( compact_dbs, compact_segs, reference_dbs, reference_segs); if( !silent ) cout << "Finished " << argv[0] << endl << flush; return 0; } /* end apicompact_main */
The compactor compacts all C and C++ persistent data, including ObjectStore collections, indexes, and bound queries, and correctly relocates pointers and all forms of ObjectStore references to compacted data.
ObjectStore os_reference_local references are relocated assuming that they are relative to the database containing them.
The compactor respects ObjectStore clusters, in that compaction ensures that objects allocated in a particular cluster remain in the cluster, although the cluster itself can move as a result of compaction.
Updated: 03/31/98 15:29:33