int4 mu_size_arsample(mval *gn, uint4 M, boolean_t ar, int seed) { enum cdb_sc status; trans_num ret_tn; int k, h; boolean_t verify_reads; boolean_t tn_aborted; unsigned int lcl_t_tries; double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */ stat_t rstat, ustat; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; inctn_opcode = inctn_invalid_op; op_gvname(VARLSTCNT(1) gn); if (0 == gv_target->root) { /* Global does not exist (online rollback). Not an error. */ gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); return EXIT_NRM; } if (!seed) seed = (int4)(time(0) * process_id); srand48(seed); /* do random traversals until M of them are accepted at level 1 */ INIT_STATS(rstat); for (k = 1; rstat.N[1] < M; k++) { if (mu_ctrlc_occurred || mu_ctrly_occurred) return EXIT_ERR; t_begin(ERR_MUSIZEFAIL, 0); for (;;) { CLEAR_VECTOR(r); if (cdb_sc_normal != (status = rand_traverse(r))) { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } gv_target->clue.end = 0; gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */ DEBUG_ONLY(lcl_t_tries = t_tries); if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED))) { ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted); if (tn_aborted) { /* Global does not exist (online rollback). Not an error. */ gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); return EXIT_NRM; } continue; } accum_stats_ar(&rstat, r, ar); break; } } finalize_stats_ar(&rstat, ar); /* display rstat data */ /* Showing the error as 2 standard deviations which is a 95% confidence interval for the mean number of blocks at * each level*/ util_out_print("!/Number of generated samples = !UL", FLUSH, rstat.n); util_out_print("Number of accepted samples = !UL", FLUSH, rstat.N[1]); util_out_print("Level Blocks 2 sigma(+/-) % Accepted", FLUSH); for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--); for ( ; h > 0; h--) util_out_print("!5UL !15UL !15UL ~ !3UL% !15UL", FLUSH, h, (int)ROUND(rstat.blktot[h]), (int)ROUND(sqrt(rstat.blkerr[h])*2), (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100), (int)ROUND(100.0*rstat.N[h]/rstat.n) ); util_out_print("!5UL !15UL !15UL ~ !3UL% N/A", FLUSH, h, (int)ROUND(rstat.blktot[h]), (int)ROUND(sqrt(rstat.blkerr[h])*2), (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0) ); util_out_print("Total !15UL !15UL ~ !3UL% N/A", FLUSH, (int)ROUND(rstat.B), (int)ROUND(sqrt(rstat.error)*2), (int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0) ); return EXIT_NRM; }
void gvzwr_fini(zshow_out *out, int pat) { char m[SIZEOF(mident_fixed)]; mval local, data; gv_key *old; gvnh_reg_t *gvnh_reg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (!gv_currkey) gvinit(); ESTABLISH(gvzwrite_ch); zwr_output = out; assert(INVALID_GV_TARGET == reset_gv_target); reset_gv_target = gv_target; DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE); gvzwrite_block->gd_reg = gv_cur_region; gvzwrite_block->old_targ = (unsigned char *)gv_target; old = (gv_key *)malloc(SIZEOF(gv_key) + gv_currkey->end); gvzwrite_block->old_key = (unsigned char *)old; memcpy(gvzwrite_block->old_key, gv_currkey, SIZEOF(gv_key) + gv_currkey->end); gvzwrite_block->gv_last_subsc_null = TREF(gv_last_subsc_null); gvzwrite_block->gv_some_subsc_null = TREF(gv_some_subsc_null); if (!pat) { local = *gvzwrite_block->pat; if (local.str.len) /* New reference. Will get new gv_target.. */ { gv_target = NULL; gv_currkey->base[0] = '\0'; op_gvname(VARLSTCNT(1) &local); op_gvdata(&data); if (!(MV_FORCE_INTD(&data))) { if (!undef_inhibit) sgnl_gvundef(); } else { gvzwrite_block->fixed = (gvzwrite_block->fixed ? TRUE : FALSE); gvzwr_var(MV_FORCE_INTD(&data), 0); } } else /* Old (naked) reference. Keep previous gv_target reference */ { if (gv_currkey->prev == 0) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_GVNAKED); gv_currkey->end = gv_currkey->prev; gv_currkey->base[gv_currkey->end] = 0; gv_currkey->prev = 0; /* If gvnh_reg corresponds to a spanning global, then determine * gv_cur_region/gv_target/gd_targ_* variables based on updated gv_currkey. */ gvnh_reg = TREF(gd_targ_gvnh_reg); /* set by op_gvname in previous call */ GV_BIND_SUBSNAME_FROM_GVNH_REG_IF_GVSPAN(gvnh_reg, gd_header, gv_currkey); op_gvdata(&data); if (!(MV_FORCE_INTD(&data))) { if (!undef_inhibit) sgnl_gvundef(); } else { gvzwrite_block->fixed = (gvzwrite_block->fixed ? TRUE : FALSE); gvzwr_var((int4)MV_FORCE_INTD(&data), 0); } } } else { gv_target = NULL; gv_currkey->base[0] = '\0'; local.mvtype = MV_STR; local.str.addr = &m[0]; local.str.len = 1; m[0] = '%'; gvzwrite_block->fixed = FALSE; for (; ;) { op_gvname(VARLSTCNT(1) &local); if (do_pattern(&local, gvzwrite_block->pat)) { op_gvdata(&data); if ((MV_FORCE_INTD(&data))) { gvzwr_var((int4)MV_FORCE_INTD(&data), 0); } } op_gvorder(&local); if (local.str.len) { assert(local.str.len <= MAX_MIDENT_LEN + 1); local.str.addr++; local.str.len--; memcpy(&m[0], local.str.addr, local.str.len); local.str.addr = &m[0]; } else break; } } gvzwrite_clnup(); /* this routine is called by gvzwrite_ch() too */ REVERT; return; }
void gvzwr_fini(zshow_out *out, int pat) { char m[sizeof(mident_fixed)]; mval local, data; gv_key *old; error_def(ERR_GVNAKED); if (!gv_currkey) gvinit(); ESTABLISH(gvzwrite_ch); zwr_output = out; assert(INVALID_GV_TARGET == reset_gv_target); reset_gv_target = gv_target; DBG_CHECK_GVTARGET_CSADDRS_IN_SYNC; gvzwrite_block.gd_reg = gv_cur_region; gvzwrite_block.old_targ = (unsigned char *)gv_target; old = (gv_key *)malloc(sizeof(gv_key) + gv_currkey->end); gvzwrite_block.old_key = (unsigned char *)old; memcpy(gvzwrite_block.old_key, gv_currkey, sizeof(gv_key) + gv_currkey->end); gvzwrite_block.old_map = gd_map; gvzwrite_block.old_map_top = gd_map_top; if (!pat) { local = *gvzwrite_block.pat; if (local.str.len) /* New reference. Will get new gv_target.. */ { gv_target = NULL; gv_currkey->base[0] = '\0'; op_gvname(VARLSTCNT(1) &local); op_gvdata(&data); if (!(MV_FORCE_INTD(&data))) sgnl_gvundef(); else { gvzwrite_block.fixed = (gvzwrite_block.fixed ? TRUE : FALSE); gvzwr_var(MV_FORCE_INTD(&data), 0); } } else /* Old (naked) reference. Keep previous gv_target reference */ { if (gv_currkey->prev == 0) rts_error(VARLSTCNT(1) ERR_GVNAKED); gv_currkey->end = gv_currkey->prev; gv_currkey->base[ gv_currkey->end ] = 0; gv_currkey->prev = 0; op_gvdata(&data); if (!(MV_FORCE_INTD(&data))) sgnl_gvundef(); else { gvzwrite_block.fixed = (gvzwrite_block.fixed ? TRUE : FALSE); gvzwr_var((int4)MV_FORCE_INTD(&data), 0); } } } else { gv_target = NULL; gv_currkey->base[0] = '\0'; local.mvtype = MV_STR; local.str.addr = &m[0]; local.str.len = 1; m[0] = '%'; gvzwrite_block.fixed = FALSE; for (; ;) { op_gvname(VARLSTCNT(1) &local); if (do_pattern(&local, gvzwrite_block.pat)) { op_gvdata(&data); if ((MV_FORCE_INTD(&data))) { gvzwr_var((int4)MV_FORCE_INTD(&data), 0); } } op_gvorder(&local); if (local.str.len) { assert(local.str.len <= MAX_MIDENT_LEN + 1); local.str.addr++; local.str.len--; memcpy(&m[0], local.str.addr, local.str.len); local.str.addr = &m[0]; } else break; } } gvzwrite_clnup(); /* this routine is called by gvzwrite_ch() too */ REVERT; return; }
/**************************************************************** Input Parameter: gn = Global name exclude_glist_ptr = list of globals in EXCLUDE option index_fill_factor = index blocks' fill factor data_fill_factor = data blocks' fill factor Input/Output Parameter: resume = resume flag reorg_op = What operations to do (coalesce or, swap or, split) [Default is all] [Only for debugging] ****************************************************************/ boolean_t mu_reorg(mval *gn, glist *exclude_glist_ptr, boolean_t *resume, int index_fill_factor, int data_fill_factor, int reorg_op) { boolean_t end_of_tree = FALSE, complete_merge, detailed_log; int rec_size; /* * * "level" is the level of the working block. * "pre_order_successor_level" is pre_order successor level except in the case * where we are in a left-most descent of the tree * in which case pre_order_successor_level will be the maximum height of that subtree * until we reach the leaf level block . * In other words, pre_order_successor_level and level variable controls the iterative pre-order traversal. * We start reorg from the (root_level - 1) to 0. That is, level = pre_order_successor_level:-1:0. */ int pre_order_successor_level, level; static block_id dest_blk_id = 0; int tkeysize; int blks_killed, blks_processed, blks_reused, blks_coalesced, blks_split, blks_swapped, count, file_extended, lvls_reduced; int d_max_fill, i_max_fill, blk_size, cur_blk_size, max_fill, toler, d_toler, i_toler; int cnt1, cnt2; kill_set kill_set_list; sm_uc_ptr_t rPtr1; enum cdb_sc status; srch_hist *rtsib_hist; jnl_buffer_ptr_t jbp; trans_num ret_tn; error_def(ERR_MUREORGFAIL); error_def(ERR_DBRDONLY); error_def(ERR_GBLNOEXIST); error_def(ERR_MAXBTLEVEL); t_err = ERR_MUREORGFAIL; kill_set_tail = &kill_set_list; /* Initialization for current global */ op_gvname(VARLSTCNT(1) gn); /* Cannot proceed for read-only data files */ if (gv_cur_region->read_only) { gtm_putmsg(VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region)); return FALSE; } dest_blk_id = cs_addrs->reorg_last_dest; inctn_opcode = inctn_mu_reorg; /* If resume option is present, then reorg_restart_key should be not null. * Skip all globals until we are in the region for that global. * Get the reorg_restart_key and reorg_restart_block from database header and restart from there. */ if (*resume && 0 != cs_data->reorg_restart_key[0]) { /* resume from last key reorged in GVT */ GET_KEY_LEN(tkeysize, &cs_data->reorg_restart_key[0]); memcpy(gv_currkey->base, cs_data->reorg_restart_key, tkeysize); gv_currkey->end = tkeysize - 1; dest_blk_id = cs_data->reorg_restart_block; if (0 == memcmp(cs_data->reorg_restart_key, gn->str.addr, gn->str.len)) /* Going to resume from current global, so it resumed and make it false */ *resume = FALSE; } else { /* start from the left most leaf */ memcpy(&gv_currkey->base[0], gn->str.addr, gn->str.len); gv_currkey->base[gn->str.len] = gv_currkey->base[gn->str.len + 1] = 0; gv_currkey->end = gn->str.len + 1; } if (*resume) { util_out_print("REORG cannot be resumed from this point, Skipping this global...", FLUSH); memcpy(&gv_currkey->base[0], gn->str.addr, gn->str.len); gv_currkey->base[gn->str.len] = gv_currkey->base[gn->str.len + 1] = 0; gv_currkey->end = gn->str.len + 1; return TRUE; } memcpy(&gv_currkey_next_reorg->base[0], &gv_currkey->base[0], gv_currkey->end + 1); gv_currkey_next_reorg->end = gv_currkey->end; if (2 > dest_blk_id) dest_blk_id = 2; /* we know that first block is bitmap and next one is directory tree root */ file_extended = cs_data->trans_hist.total_blks; blk_size = cs_data->blk_size; d_max_fill = (double)data_fill_factor * blk_size / 100.0 - cs_data->reserved_bytes; i_max_fill = (double)index_fill_factor * blk_size / 100.0 - cs_data->reserved_bytes; d_toler = (double) DATA_FILL_TOLERANCE * blk_size / 100.0; i_toler = (double) INDEX_FILL_TOLERANCE * blk_size / 100.0; blks_killed = blks_processed = blks_reused = lvls_reduced = blks_coalesced = blks_split = blks_swapped = 0; pre_order_successor_level = level = MAX_BT_DEPTH + 1; /* Just some high value to initialize */ /* --- more detailed debugging information --- */ if (detailed_log = reorg_op & DETAIL) util_out_print("STARTING to work on global ^!AD from region !AD", TRUE, gn->str.len, gn->str.addr, REG_LEN_STR(gv_cur_region)); /* In each iteration of MAIN loop, a working block is processed for a GVT */ for (; ;) /* ================ START MAIN LOOP ================ */ { /* If right sibling is completely merged with the working block, do not swap the working block * with its final destination block. Continue trying next right sibling. Swap only at the end. */ complete_merge = TRUE; while(complete_merge) /* === START WHILE COMPLETE_MERGE === */ { if (mu_ctrlc_occurred || mu_ctrly_occurred) { cs_data->reorg_restart_block = dest_blk_id; memcpy(&cs_data->reorg_restart_key[0], &gv_currkey->base[0], gv_currkey->end + 1); return FALSE; } complete_merge = FALSE; blks_processed++; t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK); /* Folllowing for loop is to handle concurrency retry for split/coalesce */ for (; ;) /* === SPLIT-COALESCE LOOP STARTS === */ { gv_target->clue.end = 0; /* search gv_currkey and get the result in gv_target */ if ((status = gvcst_search(gv_currkey, NULL)) != cdb_sc_normal) { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } else if (gv_currkey->end + 1 != gv_target->hist.h[0].curr_rec.match) { if (SIZEOF(blk_hdr) == ((blk_hdr_ptr_t)gv_target->hist.h[0].buffaddr)->bsiz && 1 == gv_target->hist.depth) { if (cs_addrs->now_crit) { t_abort(gv_cur_region, cs_addrs); /* do crit and other cleanup */ gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused, file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped); return TRUE; /* It is not an error that global was killed */ } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } } } if (gv_target->hist.depth <= level) { /* Will come here * 1) first iteration of the for loop (since level == MAX_BT_DEPTH + 1) or, * 2) tree depth decreased for mu_reduce_level or, M-kill */ pre_order_successor_level = gv_target->hist.depth - 1; if (MAX_BT_DEPTH + 1 != level) { /* break the loop when tree depth decreased (case 2) */ level = pre_order_successor_level; break; } level = pre_order_successor_level; } max_fill = (0 == level)? d_max_fill : i_max_fill; toler = (0 == level)? d_toler:i_toler; cur_blk_size = ((blk_hdr_ptr_t)(gv_target->hist.h[level].buffaddr))->bsiz; if (cur_blk_size > max_fill + toler && 0 == (reorg_op & NOSPLIT)) /* SPLIT BLOCK */ { cnt1 = cnt2 = 0; /* history of current working block is in gv_target */ status = mu_split(level, i_max_fill, d_max_fill, &cnt1, &cnt2); if (cdb_sc_maxlvl == status) { gtm_putmsg(VARLSTCNT(4) ERR_MAXBTLEVEL, 2, gn->str.len, gn->str.addr); reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused, file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped); return FALSE; } else if (cdb_sc_normal == status) { if ((trans_num)0 == (ret_tn = t_end(&(gv_target->hist), NULL, TN_NOT_SPECIFIED))) { need_kip_incr = FALSE; continue; } if (detailed_log) log_detailed_log("SPL", &(gv_target->hist), NULL, level, NULL, ret_tn); blks_reused += cnt1; lvls_reduced -= cnt2; blks_split++; break; } else if (cdb_sc_oprnotneeded == status) { /* undo any update_array/cw_set changes and DROP THRU to mu_clsce */ cw_set_depth = 0; CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */ assert(0 == cw_map_depth); /* mu_swap_blk (that changes cw_map_depth) comes later */ } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } } /* end if SPLIT BLOCK */ /* We are here because, mu_split() was not called or, split was not done or, not required */ rtsib_hist = gv_target->alt_hist; status = gvcst_rtsib(rtsib_hist, level); if (cdb_sc_normal != status && cdb_sc_endtree != status) { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } if (cdb_sc_endtree == status) { if (0 == level) end_of_tree = TRUE; break; } else if (0 == level) pre_order_successor_level = rtsib_hist->depth - 1; /* COALESCE WITH RTSIB */ kill_set_list.used = 0; if (cur_blk_size < max_fill - toler && 0 == (reorg_op & NOCOALESCE)) { /* histories are sent in &gv_target->hist and gv_target->alt_hist */ status = mu_clsce(level, i_max_fill, d_max_fill, &kill_set_list, &complete_merge); if (cdb_sc_normal == status) { if (level) /* delete lower elements of array, t_end might confuse */ { memmove(&rtsib_hist->h[0], &rtsib_hist->h[level], SIZEOF(srch_blk_status)*(rtsib_hist->depth - level + 2)); rtsib_hist->depth = rtsib_hist->depth - level; } if (0 < kill_set_list.used) /* increase kill_in_prog */ { need_kip_incr = TRUE; if (!cs_addrs->now_crit) /* Do not sleep while holding crit */ WAIT_ON_INHIBIT_KILLS(cs_addrs->nl, MAXWAIT2KILL); } if ((trans_num)0 == (ret_tn = t_end(&(gv_target->hist), rtsib_hist, TN_NOT_SPECIFIED))) { need_kip_incr = FALSE; assert(NULL == kip_csa); if (level) { /* reinitialize level member in rtsib_hist srch_blk_status' */ for (count = 0; count < MAX_BT_DEPTH; count++) rtsib_hist->h[count].level = count; } continue; } if (level) { /* reinitialize level member in rtsib_hist srch_blk_status' */ for (count = 0; count < MAX_BT_DEPTH; count++) rtsib_hist->h[count].level = count; } if (detailed_log) log_detailed_log("CLS", &(gv_target->hist), rtsib_hist, level, NULL, ret_tn); assert(0 < kill_set_list.used || (NULL == kip_csa)); if (0 < kill_set_list.used) /* decrease kill_in_prog */ { gvcst_kill_sort(&kill_set_list); GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg, inctn_opcode, cs_addrs) DECR_KIP(cs_data, cs_addrs, kip_csa); if (detailed_log) log_detailed_log("KIL", &(gv_target->hist), NULL, level, &kill_set_list, ret_tn); blks_killed += kill_set_list.used; } blks_coalesced++; break; } else if (cdb_sc_oprnotneeded == status) { /* undo any update_array/cw_set changes and DROP THRU to t_end */ cw_set_depth = 0; CHECK_AND_RESET_UPDATE_ARRAY; /* reset update_array_ptr to update_array */ assert(0 == cw_map_depth); /* mu_swap_blk (that changes cw_map_depth) comes later */ } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } } /* end if try coalesce */ if (0 == level) { /* Note: In data block level: * if split is successful or, * if coalesce is successful without a complete merge of rtsib, * then gv_currkey_next_reorg is already set from the called function. * if split or, coalesce do a retry or, * if coalesce is successful with a complete merge then * gv_currkey will not be changed. * If split or, coalesce is not successful or, not needed then * here gv_currkey_next_reorg will be set from right sibling */ cw_set_depth = cw_map_depth = 0; GET_KEY_LEN(tkeysize, rtsib_hist->h[0].buffaddr + SIZEOF(blk_hdr) + SIZEOF(rec_hdr)); if (2 < tkeysize && MAX_KEY_SZ >= tkeysize) { memcpy(&(gv_currkey_next_reorg->base[0]), rtsib_hist->h[0].buffaddr + SIZEOF(blk_hdr) +SIZEOF(rec_hdr), tkeysize); gv_currkey_next_reorg->end = tkeysize - 1; inctn_opcode = inctn_invalid_op; /* temporary reset; satisfy an assert in t_end() */ assert(UPDTRNS_DB_UPDATED_MASK == update_trans); update_trans = 0; /* tell t_end, this is no longer an update transaction */ if ((trans_num)0 == (ret_tn = t_end(rtsib_hist, NULL, TN_NOT_SPECIFIED))) { need_kip_incr = FALSE; inctn_opcode = inctn_mu_reorg; /* reset inctn_opcode to its default */ update_trans = UPDTRNS_DB_UPDATED_MASK;/* reset update_trans to old value */ assert(NULL == kip_csa); continue; } /* There is no need to reset update_trans in case of a successful "t_end" call. * This is because before the next call to "t_end" we should have a call to * "t_begin" which will reset update_trans anyways. */ inctn_opcode = inctn_mu_reorg; /* reset inctn_opcode to its default */ if (detailed_log) log_detailed_log("NOU", rtsib_hist, NULL, level, NULL, ret_tn); } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } } /* end if (0 == level) */ break; }/* === SPLIT-COALESCE LOOP END === */ t_abort(gv_cur_region, cs_addrs); /* do crit and other cleanup */ }/* === START WHILE COMPLETE_MERGE === */ if (mu_ctrlc_occurred || mu_ctrly_occurred) { cs_data->reorg_restart_block = dest_blk_id; memcpy(&cs_data->reorg_restart_key[0], &gv_currkey->base[0], gv_currkey->end+1); return FALSE; } /* Now swap the working block */ if (0 == (reorg_op & NOSWAP)) { t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK); /* Following loop is to handle concurrency retry for swap */ for (; ;) /* === START OF SWAP LOOP === */ { kill_set_list.used = 0; gv_target->clue.end = 0; /* search gv_currkey and get the result in gv_target */ if ((status = gvcst_search(gv_currkey, NULL)) != cdb_sc_normal) { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } else if (gv_currkey->end + 1 != gv_target->hist.h[0].curr_rec.match) { if (SIZEOF(blk_hdr) == ((blk_hdr_ptr_t)gv_target->hist.h[0].buffaddr)->bsiz && 1 == gv_target->hist.depth) { if (cs_addrs->now_crit) { t_abort(gv_cur_region, cs_addrs); /* do crit and other cleanup */ gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused, file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped); return TRUE; /* It is not an error that global was killed */ } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } } } if (gv_target->hist.depth <= level) break; /* swap working block with appropriate dest_blk_id block. Historys are sent as gv_target->hist and reorg_gv_target->hist */ mu_reorg_in_swap_blk = TRUE; status = mu_swap_blk(level, &dest_blk_id, &kill_set_list, exclude_glist_ptr); mu_reorg_in_swap_blk = FALSE; if (cdb_sc_oprnotneeded == status) { if (cs_data->trans_hist.total_blks <= dest_blk_id) { util_out_print("REORG may be incomplete for this global.", TRUE); reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused, file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped); return TRUE; } } else if (cdb_sc_normal == status) { if (0 < kill_set_list.used) { need_kip_incr = TRUE; if (!cs_addrs->now_crit) /* Do not sleep while holding crit */ WAIT_ON_INHIBIT_KILLS(cs_addrs->nl, MAXWAIT2KILL); /* second history not needed, because, we are reusing a free block, which does not need history */ if ((trans_num)0 == (ret_tn = t_end(&(gv_target->hist), NULL, TN_NOT_SPECIFIED))) { need_kip_incr = FALSE; assert(NULL == kip_csa); DECR_BLK_NUM(dest_blk_id); continue; } if (detailed_log) log_detailed_log("SWA", &(gv_target->hist), NULL, level, NULL, ret_tn); gvcst_kill_sort(&kill_set_list); GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg, inctn_opcode, cs_addrs) DECR_KIP(cs_data, cs_addrs, kip_csa); if (detailed_log) log_detailed_log("KIL", &(gv_target->hist), NULL, level, &kill_set_list, ret_tn); blks_reused += kill_set_list.used; blks_killed += kill_set_list.used; } /* gv_target->hist is for working block's history, and reorg_gv_target->hist is for destinition block's history. Note: gv_target and reorg_gv_target can be part of different GVT. */ else if ((trans_num)0 == (ret_tn = t_end(&(gv_target->hist), &(reorg_gv_target->hist), TN_NOT_SPECIFIED))) { need_kip_incr = FALSE; assert(NULL == kip_csa); DECR_BLK_NUM(dest_blk_id); continue; } if ((0 >= kill_set_list.used) && detailed_log) log_detailed_log("SWA", &(gv_target->hist), &(reorg_gv_target->hist), level, NULL, ret_tn); blks_swapped++; if (reorg_op & SWAPHIST) util_out_print("Dest !SL From !SL", TRUE, dest_blk_id, gv_target->hist.h[level].blk_num); } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } break; } /* === END OF SWAP LOOP === */ t_abort(gv_cur_region, cs_addrs); /* do crit and other cleanup */ } if (mu_ctrlc_occurred || mu_ctrly_occurred) { cs_data->reorg_restart_block = dest_blk_id; memcpy(&cs_data->reorg_restart_key[0], &gv_currkey->base[0], gv_currkey->end + 1); return FALSE; } if (end_of_tree) break; if (0 < level) level--; /* Order of reorg is root towards leaf */ else { level = pre_order_successor_level; memcpy(&gv_currkey->base[0], &gv_currkey_next_reorg->base[0], gv_currkey_next_reorg->end + 1); gv_currkey->end = gv_currkey_next_reorg->end; cs_data->reorg_restart_block = dest_blk_id; memcpy(&cs_data->reorg_restart_key[0], &gv_currkey->base[0], gv_currkey->end + 1); } } /* ================ END MAIN LOOP ================ */ /* =========== START REDUCE LEVEL ============== */ memcpy(&gv_currkey->base[0], gn->str.addr, gn->str.len); gv_currkey->base[gn->str.len] = gv_currkey->base[gn->str.len + 1] = 0; gv_currkey->end = gn->str.len + 1; for (;;) /* Reduce level continues until it fails to reduce */ { t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK); cnt1 = 0; for (; ;) /* main reduce level loop starts */ { kill_set_list.used = 0; gv_target->clue.end = 0; /* search gv_currkey and get the result in gv_target */ if ((status = gvcst_search(gv_currkey, NULL)) != cdb_sc_normal) { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } else if (gv_currkey->end + 1 != gv_target->hist.h[0].curr_rec.match) { if (SIZEOF(blk_hdr) == ((blk_hdr_ptr_t)gv_target->hist.h[0].buffaddr)->bsiz && 1 == gv_target->hist.depth) { if (cs_addrs->now_crit) { t_abort(gv_cur_region, cs_addrs); /* do crit and other cleanup */ gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused, file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped); return TRUE; /* It is not an error that global was killed */ } else { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } } } if (gv_target->hist.depth <= level) break; /* History is passed in gv_target->hist */ status = mu_reduce_level(&kill_set_list); if (cdb_sc_oprnotneeded != status && cdb_sc_normal != status) { assert(CDB_STAGNATE > t_tries); t_retry(status); continue; } else if (cdb_sc_normal == status) { assert(0 < kill_set_list.used); need_kip_incr = TRUE; if (!cs_addrs->now_crit) /* Do not sleep while holding crit */ WAIT_ON_INHIBIT_KILLS(cs_addrs->nl, MAXWAIT2KILL); if ((trans_num)0 == (ret_tn = t_end(&(gv_target->hist), NULL, TN_NOT_SPECIFIED))) { need_kip_incr = FALSE; assert(NULL == kip_csa); continue; } if (detailed_log) log_detailed_log("RDL", &(gv_target->hist), NULL, level, NULL, ret_tn); gvcst_kill_sort(&kill_set_list); GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg, inctn_opcode, cs_addrs) DECR_KIP(cs_data, cs_addrs, kip_csa); if (detailed_log) log_detailed_log("KIL", &(gv_target->hist), NULL, level, &kill_set_list, ret_tn); blks_reused += kill_set_list.used; blks_killed += kill_set_list.used; cnt1 = 1; lvls_reduced++; } break; } /* main reduce level loop ends */ t_abort(gv_cur_region, cs_addrs); /* do crit and other cleanup */ if (0 == cnt1) break; } /* =========== END REDUCE LEVEL ===========*/ reorg_finish(dest_blk_id, blks_processed, blks_killed, blks_reused, file_extended, lvls_reduced, blks_coalesced, blks_split, blks_swapped); return TRUE; } /* end mu_reorg() */
void gv_select(char *cli_buff, int n_len, boolean_t freeze, char opname[], glist *gl_head, int *reg_max_rec, int *reg_max_key, int *reg_max_blk) { bool stashed = FALSE; int num_quote, len; char *ptr, *ptr1, *c; mstr gmap[256], *gmap_ptr, gmap_beg, gmap_end; mval val, curr_gbl_name; glist *gl_tail, *gl_ptr; htab_desc *ext_hash; mname ht_mname; ht_entry *h; error_def(ERR_FREEZE); error_def(ERR_DBRDONLY); error_def(ERR_SELECTSYNTAX); error_def(ERR_MUNOFINISH); error_def(ERR_MUNOACTION); memset(gmap, 0, sizeof(gmap)); for (ptr = cli_buff; *ptr; ptr = ptr1) { for (ptr1 = ptr; ; ptr1++) { if (',' == *ptr1) { len = ptr1 - ptr; ptr1++; break; } else if (!*ptr1) { len = ptr1 - ptr; break; } } gmap_beg.addr = ptr; c = gmap_beg.addr + len - 1; num_quote = 0; while ('"' == *c) { len--; c--; num_quote++; } if (0 >= len) { gtm_putmsg(VARLSTCNT(4) ERR_SELECTSYNTAX, 2, LEN_AND_STR(opname)); mupip_exit(ERR_MUNOACTION); } c = gmap_beg.addr; while (0 < num_quote) { if ('"' == *c) { c++; len--; } else { gtm_putmsg(VARLSTCNT(4) ERR_SELECTSYNTAX, 2, LEN_AND_STR(opname)); mupip_exit(ERR_MUNOACTION); } num_quote--; } gmap_beg.addr = c; if ('^' == *c) { gmap_beg.addr++; len--; } gmap_beg.len = len; c = mu_extr_ident(&gmap_beg); len -= (c - gmap_beg.addr); assert(len >= 0); if (0 == len) gmap_end = gmap_beg; else if (gmap_beg.len == 1 && '*' == *c) { gmap_beg.addr = (char*)&percent_lit; gmap_beg.len = sizeof(percent_lit); gmap_end.addr = (char*)&tilde_lit; gmap_end.len = sizeof(tilde_lit); } else if (1 == len && '*' == *c) { gmap_end = gmap_beg; gmap_beg.len--; *c = '~'; } else if (':' != *c) { gtm_putmsg(VARLSTCNT(4) ERR_SELECTSYNTAX, 2, LEN_AND_STR(opname)); mupip_exit(ERR_MUNOACTION); } else { gmap_beg.len = c - gmap_beg.addr; c++; gmap_end.addr = c; gmap_end.len = len - 1; if ('^' == *c) { gmap_end.addr++; gmap_end.len--; } c = mu_extr_ident(&gmap_end); if (c - gmap_end.addr != gmap_end.len || mstrcmp(&gmap_beg, &gmap_end) > 0) { gtm_putmsg(VARLSTCNT(4) ERR_SELECTSYNTAX, 2, LEN_AND_STR(opname)); mupip_exit(ERR_MUNOACTION); } } global_map(gmap, &gmap_beg, &gmap_end); } if (freeze) { ext_hash = (htab_desc *)malloc(sizeof(htab_desc)); ht_init(ext_hash, 0); memset(&ht_mname.txt[0], 0, sizeof(mname)); } gl_head->next = NULL; gl_tail = gl_head; *reg_max_rec = 0; *reg_max_key = 0; *reg_max_blk = 0; for (gmap_ptr = gmap; gmap_ptr->addr ; gmap_ptr++) { curr_gbl_name.mvtype = MV_STR; curr_gbl_name.str = *gmap_ptr++; op_gvname(VARLSTCNT(1) &curr_gbl_name); if (dba_cm == gv_cur_region->dyn.addr->acc_meth) { util_out_print("Can not select globals from region !AD across network",TRUE,gv_cur_region->rname_len, gv_cur_region->rname); mupip_exit(ERR_MUNOFINISH); } if (dba_bg != gv_cur_region->dyn.addr->acc_meth && dba_mm != gv_cur_region->dyn.addr->acc_meth) { assert(gv_cur_region->dyn.addr->acc_meth == dba_usr); util_out_print("Can not select globals from non-GTC region !AD",TRUE,gv_cur_region->rname_len, gv_cur_region->rname); mupip_exit(ERR_MUNOFINISH); } op_gvdata(&val); if (0 == val.m[1]) { op_gvname(VARLSTCNT(1) &curr_gbl_name); op_gvorder(&curr_gbl_name); if (!curr_gbl_name.str.len) break; assert('^' == *curr_gbl_name.str.addr); curr_gbl_name.str.addr++; curr_gbl_name.str.len--; } for (;;) { if (mstrcmp(&curr_gbl_name.str, gmap_ptr) > 0) break; if (freeze) { memcpy(&ht_mname.txt[0], &gv_cur_region, sizeof(int4)); h = ht_put(ext_hash, &ht_mname, &stashed); if (stashed) { if (cs_addrs->hdr->freeze) { gtm_putmsg(VARLSTCNT(4) ERR_FREEZE, 2, gv_cur_region->rname_len, gv_cur_region->rname); mupip_exit(ERR_MUNOFINISH); } /* Cannot proceed for read-only data files */ if (gv_cur_region->read_only) { util_out_print("Cannot freeze the database",TRUE); gtm_putmsg(VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region)); mupip_exit(ERR_MUNOFINISH); } while (FALSE == region_freeze(gv_cur_region, TRUE, FALSE)) hiber_start(1000); wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH); } } assert(curr_gbl_name.str.len > 0); gl_ptr = (glist*)malloc(sizeof(glist) - 1 + curr_gbl_name.str.len); gl_ptr->name.mvtype = MV_STR; gl_ptr->name.str.addr = (char*)gl_ptr->nbuf; gl_ptr->name.str.len = curr_gbl_name.str.len; memcpy(gl_ptr->nbuf, curr_gbl_name.str.addr, curr_gbl_name.str.len); gl_ptr->next = 0; gl_tail->next = gl_ptr; gl_tail = gl_ptr; if (*reg_max_rec < cs_data->max_rec_size) *reg_max_rec = cs_data->max_rec_size; if (*reg_max_key < cs_data->max_key_size) *reg_max_key = cs_data->max_key_size; if (*reg_max_blk < cs_data->blk_size) *reg_max_blk = cs_data->blk_size; op_gvname(VARLSTCNT(1) &gl_tail->name); op_gvorder(&curr_gbl_name); if (0 == curr_gbl_name.str.len) { (gmap_ptr + 1)->addr = 0; break; } assert('^' == *curr_gbl_name.str.addr); curr_gbl_name.str.addr++; curr_gbl_name.str.len--; } } }