/* ** Writes or erases a transaction log and displays a completion thermometer. ** ** 'context' must not be NULL, and defaults for element 0 & 1 of context ** must have been set. */ i4 write_transaction_log(bool create, PM_CONTEXT *context, char *log_dir[], char *log_file[], void (*message)(char *), void (*init_graph)(bool, i4), i4 graph_size, void (*update_graph)()) { # define LG_PAGE_SIZE 2048L # define LG_NUMBER_OF_PAGES 32L /* Number of pages to write at a time */ DI_IO dio[LG_MAX_FILE]; char buf[LG_PAGE_SIZE * LG_NUMBER_OF_PAGES]; char nodename[GL_MAXNAME]; i4 i, j, marker, count, num_logs; i4 num_pages, page, part_size, remainder, loop; CL_ERR_DESC err; char *string; LOCATION loc[LG_MAX_FILE]; char locbuf[MAX_LOC + 1]; char *path[LG_MAX_FILE]; i4 LOinfo_flag; LOINFORMATION loc_info; i8 size; CS_SCB scb; bool size_in_kbytes = FALSE; MEfill( sizeof( scb ), 0, ( PTR ) &scb ); ++graph_size; /* Prepare transaction for log LOCATION(s) */ for (num_logs = 0; num_logs < LG_MAX_FILE; num_logs++) { if (log_dir[num_logs] == 0) break; STcopy( log_dir[num_logs], locbuf ); LOfroms( PATH, locbuf, &loc[num_logs] ); LOfstfile( log_file[num_logs], &loc[num_logs] ); LOtos( &loc[num_logs], &path[num_logs] ); } /* get size (in bytes) of log file to be created or erased */ if( create ) { STATUS status; char *value; bool havevalue = FALSE; status = PMmGet( context, ERx( "$.$.rcp.file.kbytes" ), &value ); if ( status == OK ) { havevalue = TRUE; size_in_kbytes = TRUE; } if ( havevalue == FALSE ) { status = PMmGet( context, ERx( "$.$.rcp.file.size" ), &value ); if ( status == OK ) havevalue = TRUE; } if ( havevalue == FALSE ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, ERx( "%s %s" ), PMmExpandRequest( context, ERx( "$.$.rcp.file.kbytes" ) ), "not found." ); message( msg ); } return( 0 ); } CVal8( value, &size ); } else { LOinfo_flag = LO_I_SIZE; size = 0; for (i = 0; i < num_logs; i++) { if ( LOinfo( &loc[i], &LOinfo_flag, &loc_info ) != OK ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, "Unable to get size of transaction log:\n\n\t%s", path[i] ); (*message)( msg ); } return( 0 ); } else size += loc_info.li_size; if ((LOinfo_flag & LO_I_SIZE) == 0) break; } if ( (LOinfo_flag & LO_I_SIZE) == 0 || size == 0L) { STATUS status; char *value; bool havevalue = FALSE; status = PMmGet( context, ERx( "$.$.rcp.file.kbytes" ), &value ); if ( status == OK ) { havevalue = TRUE; size_in_kbytes = TRUE; } if ( havevalue == FALSE ) { status = PMmGet( context, ERx( "$.$.rcp.file.size" ), &value ); if ( status == OK ) havevalue = TRUE; } if ( havevalue == FALSE ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, ERx( "%s %s." ), PMmExpandRequest( context, ERx( "$.$.rcp.file.kbytes" ) ), "not found." ); message( msg ); } return( 0 ); } CVal8( value, &size ); } } for (i = 0; i < num_logs; i++) { if ( create && LOexist( &loc[i] ) == OK ) { char msg[ BIG_ENOUGH ]; if ( message != NULL ) { STprintf( msg, "%s already exists.", path[i] ); (*message)( msg ); STprintf( msg, "To create a new transaction log, you must first delete all partitions of the old one." ); (*message)( msg ); } return( 0 ); } } if ( CSinitiate( (i4 *) NULL, (char ***) NULL, (CS_CB *) NULL ) != OK ) { if ( message != NULL ) message( "Unable to connect to shared memory" ); return( 0 ); } CSset_sid( &scb ); /* create DI file */ for (i = 0; i < num_logs; i++) { if ( create && DIcreate( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), (i4)LG_PAGE_SIZE, &err) != OK ) { char msg[ BIG_ENOUGH ]; if ( message != NULL ) { STprintf( msg, "Unable to create transaction log:\n\n\t%s", path[i] ); (*message)( msg ); } return( 0 ); } /* open DI file */ if ( DIopen( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), (i4)LG_PAGE_SIZE, DI_IO_WRITE, 0, &err) != OK ) { if ( message != NULL ) { char msg[ BIG_ENOUGH ]; STprintf( msg, "Unable to open transaction log:\n\n\t%s", path[i] ); (*message)( msg ); } return( 0 ); } } if ( size_in_kbytes == FALSE ) size = (size + 1023) / 1024; (*init_graph)( create, (i4) size ); num_pages = size / (LG_PAGE_SIZE/1024); part_size = num_pages / num_logs; /* Readjust num_pages to be a multiple of num_logs */ num_pages = part_size * num_logs; loop = part_size / LG_NUMBER_OF_PAGES; remainder = part_size % LG_NUMBER_OF_PAGES; marker = loop / graph_size; /* Fill buffer with zeroes */ MEfill( sizeof( buf ), 0 , buf); for (i = 0; i < num_logs; i++) { if ( create && DIalloc( &dio[i], part_size, &page, &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength( log_dir[i] ), log_file[i], (u_i4)STlength( log_file[i] ), &err ); if ( message != NULL ) (*message)( "Unable to allocate space in transaction log file." ); return( 0 ); } } count = 0; for( j = 0; j < loop; j++ ) { i4 n = LG_NUMBER_OF_PAGES; i4 page_no = j * n; for (i = 0; i < num_logs; i++) { if ( DIwrite( &dio[i], &n, page_no, buf, &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to continue writing transaction log." ); return( 0 ); } } if ( j >= marker && j % marker == 0 && (f4) ((f4) j / (f4) loop) >= ((f4) count + 1) / graph_size ) { ++count; (*update_graph)(); SIflush( stdout ); } } if (remainder) { i4 page_no = loop * LG_NUMBER_OF_PAGES; for (i = 0; i < num_logs; i++) { if ( DIwrite( &dio[i], &remainder, page_no, buf, &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to continue writing transaction log." ); return( 0 ); } } } for (i = 0; i < num_logs; i++) { if ( DIforce( &dio[i], &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to force changes to transaction log." ); return( 0 ); } if ( create && DIflush( &dio[i], &err ) != OK ) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to flush transaction log to disk." ); return( 0 ); } if( DIclose( &dio[i], &err ) != OK) { DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]), log_file[i], (u_i4)STlength(log_file[i]), &err ); if ( message != NULL ) (*message)( "Unable to finish writing transaction log." ); return( 0 ); } } return( (i4) size ); }
/* PROGRAM = iijobdef ** NEEDLIBS = UTILLIB MALLOCLIB COMPATLIB GLLIB ** UNDEFS = II_copyright ** DEST = utility */ # endif /* VMS */ main( i4 argc, char **argv) { # ifdef VMS char *host; i4 i; PM_SCAN_REC state; STATUS status; char *lnm_table_name; struct dsc$descriptor lnm_table; char *regexp; char *name, *value; PM_CONTEXT *config; struct dsc$descriptor lnm_name; ILE3 item_list[ 2 ]; long access_mode = PSL$C_SUPER; bool failed_once = FALSE; /* lib$set_logical works? */ const match_1 = LIB$_NOCLI; /* Process has no CLI. */ const match_2 = LIB$_UNECLIERR; /* Unexpected CLI error * (non-standard CLI?). */ const match_3 = SS$_NORMAL; /* Normal return. */ const match_4 = SS$_SUPERSEDE; /* Replaced old value. */ const match_5 = SS$_NOLOGNAM; /* Not currently defined. */ bool delete_logs = FALSE; /* What are we doing? */ char *act_str; /* String for action. */ char *err_str; /* String for error exit. */ char *log_str; /* String to log action. */ char tmp_buf[BIG_ENOUGH]; MEadvise( ME_INGRES_ALLOC ); if( argc != 1 ) delete_logs = TRUE; (void) PMmInit( &config ); if( PMmLoad( config, NULL, PMerror ) != OK ) PCexit( FAIL ); host = PMmHost( config ); PMmSetDefault( config, HOST_PM_IDX, host ); /* get logical table name */ STprintf (tmp_buf , ERx( "%s.$.lnm.table.id" ), SystemCfgPrefix); if( PMmGet( config, tmp_buf , &lnm_table_name ) != OK ) { F_ERROR( "%s not found.", PMmExpandRequest( config, tmp_buf ) ); } /* set logical name table */ lnm_table_name = ERx( "LNM$JOB" ); /* compose string descriptor for logical table name */ lnm_table.dsc$w_length = STlength( lnm_table_name ); lnm_table.dsc$a_pointer = lnm_table_name; lnm_table.dsc$b_class = DSC$K_CLASS_S; lnm_table.dsc$b_dtype = DSC$K_DTYPE_T; if ( delete_logs ) { act_str = ERx( "\nDeleting %s logicals...\n\n(%s)\n\n" ); err_str = ERx( "Unable to deassign %s.\n\n" ); log_str = ERx( "" ); } else { act_str = ERx( "\nDeleting %s logicals...\n\n(%s)\n\n" ); err_str = ERx( "Unable to set %s to \"%s\".\n\n" ); log_str = ERx( "\"%s\" = \"%s\"\n" ); } F_PRINT2( act_str, SystemDBMSName, lnm_table_name ); /* scan and set node-specific logicals */ regexp = PMmExpToRegExp( config, ERx( "ii.$.lnm.%") ); for( status = PMmScan( config, regexp, &state, NULL, &name, &value ); status == OK; status = PMmScan( config, NULL, &state, NULL, &name, &value ) ) { name = PMmGetElem( config, 3, name ); lnm_name.dsc$w_length = STlength( name ); lnm_name.dsc$a_pointer = name; lnm_name.dsc$b_class = DSC$K_CLASS_S; lnm_name.dsc$b_dtype = DSC$K_DTYPE_T; item_list[ 0 ].ile3$w_length = STlength( value ); item_list[ 0 ].ile3$w_code = LNM$_STRING; item_list[ 0 ].ile3$ps_bufaddr = value; item_list[ 0 ].ile3$ps_retlen_addr = NULL; item_list[ 1 ].ile3$w_length = 0; item_list[ 1 ].ile3$w_code = 0; if ( !failed_once ) { if ( delete_logs ) status = lib$delete_logical( &lnm_name, &lnm_table ); else status = lib$set_logical( &lnm_name, NULL, &lnm_table, NULL, item_list ); if ( lib$match_cond( &status, &match_1, &match_2 )) failed_once = TRUE; } if ( failed_once ) { if ( delete_logs ) status = sys$dellnm( &lnm_table, &lnm_name, &access_mode ); else status = sys$crelnm( NULL, &lnm_table, &lnm_name, &access_mode, item_list ); } if ( !lib$match_cond( &status, &match_3, &match_4, &match_5 )) { SIfprintf( stderr, err_str, name, value ); PCexit( FAIL ); } SIprintf( log_str, name, value ); } PCexit( OK ); # else /* VMS */ SIprintf( "\nThis doesn't do much.\n\n" ); # endif /* VMS */ }