/* * ------------------------------------------ * Hang the process for a specified time. * * Goes to sleep for a positive value. * Any caught signal will terminate the sleep * following the execution of that signal's catching routine. * * Arguments: * num - time to sleep * * Return: * none * ------------------------------------------ */ void op_hang(mval* num) { int ms; #ifdef VMS uint4 time[2]; int4 efn_mask, status; error_def(ERR_SYSCALL); #endif ms = 0; MV_FORCE_NUM(num); if (num->mvtype & MV_INT) { if (0 < num->m[1]) { assert(MV_BIAS >= 1000); /* if formats change overflow may need attention */ ms = num->m[1] * (1000 / MV_BIAS); } } else if (0 == num->sgn) /* if sign is not 0 it means num is negative */ ms = mval2i(num) * 1000; /* too big to care about fractional amounts */ if (ms) { UNIX_ONLY(hiber_start(ms);) VMS_ONLY( time[0] = -time_low_ms(ms); time[1] = -time_high_ms(ms) - 1; efn_mask = (1 << efn_outofband | 1 << efn_timer); if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0))) rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status); if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask))) rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status); ) if (outofband)
int create_server(void) { int child_pid, done_pid, status = 0; # ifdef _BSD union wait chld_status; # define CSTAT chld_status # else # define CSTAT status # endif int save_errno; FORK(child_pid); if (0 == child_pid) { process_id = getpid(); /* Do exec using gtmsecshr_path, which was initialize in file check code - send_mesg2gtmsecshr */ if (WBTEST_ENABLED(WBTEST_BADEXEC_SECSHR_PROCESS)) STRCPY(gtmsecshr_path, ""); status = EXECL(gtmsecshr_path, gtmsecshr_path, 0); if (-1 == status) { send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_GTMSECSHRSTART, 3, RTS_ERROR_TEXT("Client"), process_id, ERR_TEXT, 2, RTS_ERROR_STRING(secshrstart_error_code[UNABLETOEXECGTMSECSHR])); UNDERSCORE_EXIT(UNABLETOEXECGTMSECSHR); } } else { if (-1 == child_pid) { status = GNDCHLDFORKFLD; gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(10) ERR_GTMSECSHRSTART, 3, RTS_ERROR_TEXT("Client"), process_id, ERR_TEXT, 2, RTS_ERROR_TEXT("Failed to fork off gtmsecshr"), errno); /* Sleep for a while and hope a subsequent fork will succeed */ hiber_start(1000); } for (; !status ;) { /* To prevent a warning message that the compiler issues */ done_pid = wait(&CSTAT); if (done_pid == child_pid) { status = WEXITSTATUS(CSTAT); break; } else if (-1 == done_pid) { if (ECHILD == errno) /* Assume normal exit status */ break; else if (EINTR != errno) { status = GNDCHLDFORKFLD; gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(10) ERR_GTMSECSHRSTART, 3, RTS_ERROR_TEXT("Client"), process_id, ERR_TEXT, 2, RTS_ERROR_TEXT("Error spawning gtmsecshr"), errno); } } } } return status; }
STATICFNDEF int extend_wait_for_fallocate(unix_db_info *udi, off_t new_size) { int to_wait, to_msg, wait_period, save_errno; /* Attempt to fallocate every second, and send message to operator every 1/20 of cs_data->wait_disk_space */ wait_period = to_wait = DIVIDE_ROUND_UP(cs_data->wait_disk_space, CDB_STAGNATE + 1); to_msg = (to_wait / 8) ? (to_wait / 8) : 1; /* send around 8 messages during 1 wait_period */ do { if ((to_wait == cs_data->wait_disk_space) || (to_wait % to_msg == 0)) ISSUE_WAITDSKSPACE(to_wait, wait_period, send_msg_csa); hiber_start(1000); to_wait--; save_errno = posix_fallocate(udi->fd, 0, new_size); } while ((to_wait > 0) && (ENOSPC == save_errno)); return save_errno; }
STATICFNDEF int extend_wait_for_write(unix_db_info *udi, int blk_size, off_t new_eof) { int to_wait, to_msg, wait_period, save_errno; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; /* Attempt to write every second, and send message to operator every 1/20 of cs_data->wait_disk_space */ wait_period = to_wait = DIVIDE_ROUND_UP(cs_data->wait_disk_space, CDB_STAGNATE + 1); to_msg = (to_wait / 8) ? (to_wait / 8) : 1; /* send around 8 messages during 1 wait_period */ do { if ((to_wait == cs_data->wait_disk_space) || (to_wait % to_msg == 0)) ISSUE_WAITDSKSPACE(to_wait, wait_period, send_msg_csa); hiber_start(1000); to_wait--; save_errno = db_write_eof_block(udi, udi->fd, blk_size, new_eof, &(TREF(dio_buff))); } while ((to_wait > 0) && (ENOSPC == save_errno)); return save_errno; }
boolean_t iosocket_bind(socket_struct *socketptr, int4 timepar, boolean_t update_bufsiz) { int temp_1 = 1; char *errptr; int4 errlen, msec_timeout, real_errno; short len; in_port_t actual_port; boolean_t no_time_left = FALSE; d_socket_struct *dsocketptr; struct addrinfo *ai_ptr; char port_buffer[NI_MAXSERV]; int errcode; ABS_TIME cur_time, end_time; GTM_SOCKLEN_TYPE addrlen; GTM_SOCKLEN_TYPE sockbuflen; dsocketptr = socketptr->dev; ai_ptr = (struct addrinfo*)(&socketptr->local.ai); assert(NULL != dsocketptr); dsocketptr->iod->dollar.key[0] = '\0'; if (FD_INVALID != socketptr->temp_sd) { socketptr->sd = socketptr->temp_sd; socketptr->temp_sd = FD_INVALID; } if (timepar != NO_M_TIMEOUT) { msec_timeout = timeout2msec(timepar); sys_get_curr_time(&cur_time); add_int_to_abs_time(&cur_time, msec_timeout, &end_time); } do { temp_1 = 1; if (-1 == tcp_routines.aa_setsockopt(socketptr->sd, SOL_SOCKET, SO_REUSEADDR, &temp_1, SIZEOF(temp_1))) { real_errno = errno; errptr = (char *)STRERROR(real_errno); errlen = STRLEN(errptr); SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, RTS_ERROR_LITERAL("SO_REUSEADDR"), real_errno, errlen, errptr); return FALSE; } #ifdef TCP_NODELAY temp_1 = socketptr->nodelay ? 1 : 0; if (-1 == tcp_routines.aa_setsockopt(socketptr->sd, IPPROTO_TCP, TCP_NODELAY, &temp_1, SIZEOF(temp_1))) { real_errno = errno; errptr = (char *)STRERROR(real_errno); errlen = STRLEN(errptr); SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, RTS_ERROR_LITERAL("TCP_NODELAY"), real_errno, errlen, errptr); return FALSE; } #endif if (update_bufsiz) { if (-1 == tcp_routines.aa_setsockopt(socketptr->sd, SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, SIZEOF(socketptr->bufsiz))) { real_errno = errno; errptr = (char *)STRERROR(real_errno); errlen = STRLEN(errptr); SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, RTS_ERROR_LITERAL("SO_RCVBUF"), real_errno, errlen, errptr); return FALSE; } } else { sockbuflen = SIZEOF(socketptr->bufsiz); if (-1 == tcp_routines.aa_getsockopt(socketptr->sd, SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, &sockbuflen)) { real_errno = errno; errptr = (char *)STRERROR(real_errno); errlen = STRLEN(errptr); SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_GETSOCKOPTERR, 5, RTS_ERROR_LITERAL("SO_RCVBUF"), real_errno, errlen, errptr); return FALSE; } } temp_1 = tcp_routines.aa_bind(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), ai_ptr->ai_addrlen); if (temp_1 < 0) { real_errno = errno; no_time_left = TRUE; switch (real_errno) { case EADDRINUSE: if (NO_M_TIMEOUT != timepar) { sys_get_curr_time(&cur_time); cur_time = sub_abs_time(&end_time, &cur_time); if (cur_time.at_sec > 0) no_time_left = FALSE; } break; case EINTR: break; default: SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_SOCKBIND, 0, real_errno, 0); break; } if (no_time_left) return FALSE; hiber_start(100); tcp_routines.aa_close(socketptr->sd); if (-1 == (socketptr->sd = tcp_routines.aa_socket(ai_ptr->ai_family,ai_ptr->ai_socktype, ai_ptr->ai_protocol))) { real_errno = errno; errptr = (char *)STRERROR(real_errno); errlen = STRLEN(errptr); SOCKET_FREE(socketptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_SOCKINIT, 3, real_errno, errlen, errptr); return FALSE; } } } while (temp_1 < 0); /* obtain actual port from the bound address if port 0 was specified */ addrlen = SOCKET_ADDRLEN(socketptr, ai_ptr, local); if (-1 == tcp_routines.aa_getsockname(socketptr->sd, SOCKET_LOCAL_ADDR(socketptr), &addrlen)) { real_errno = errno; errptr = (char *)STRERROR(real_errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_GETSOCKNAMERR, 3, real_errno, errlen, errptr); return FALSE; } assert(ai_ptr->ai_addrlen == addrlen); GETNAMEINFO(SOCKET_LOCAL_ADDR(socketptr), addrlen, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode); if (0 != errcode) { SOCKET_FREE(socketptr); RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return FALSE; } actual_port = ATOI(port_buffer); if (0 == socketptr->local.port) socketptr->local.port = actual_port; assert(socketptr->local.port == actual_port); socketptr->state = socket_bound; len = SIZEOF(BOUND) - 1; memcpy(&dsocketptr->iod->dollar.key[0], BOUND, len); dsocketptr->iod->dollar.key[len++] = '|'; memcpy(&dsocketptr->iod->dollar.key[len], socketptr->handle, socketptr->handle_len); len += socketptr->handle_len; dsocketptr->iod->dollar.key[len++] = '|'; SPRINTF(&dsocketptr->iod->dollar.key[len], "%d", socketptr->local.port); return TRUE; }
uint4 gdsfilext(uint4 blocks, uint4 filesize, boolean_t trans_in_prog) { sm_uc_ptr_t old_base[2], mmap_retaddr; boolean_t was_crit, is_mm; int result, save_errno, status; DEBUG_ONLY(int first_save_errno); uint4 new_bit_maps, bplmap, map, new_blocks, new_total, max_tot_blks, old_total; uint4 jnl_status; gtm_uint64_t avail_blocks, mmap_sz; off_t new_eof, new_size; trans_num curr_tn; unix_db_info *udi; inctn_opcode_t save_inctn_opcode; int4 prev_extend_blks_to_upgrd; jnl_private_control *jpc; jnl_buffer_ptr_t jbp; cache_rec_ptr_t cr; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; assert(!IS_DSE_IMAGE); assert((cs_addrs->nl == NULL) || (process_id != cs_addrs->nl->trunc_pid)); /* mu_truncate shouldn't extend file... */ assert(!process_exiting); DEBUG_ONLY(old_base[0] = old_base[1] = NULL); assert(!gv_cur_region->read_only); udi = FILE_INFO(gv_cur_region); is_mm = (dba_mm == cs_addrs->hdr->acc_meth); # if !defined(MM_FILE_EXT_OK) if (!udi->grabbed_access_sem && is_mm) return (uint4)(NO_FREE_SPACE); /* should this be changed to show extension not allowed ? */ # endif /* Both blocks and total blocks are unsigned ints so make sure we aren't asking for huge numbers that will overflow and end up doing silly things. */ assert((blocks <= (MAXTOTALBLKS(cs_data) - cs_data->trans_hist.total_blks)) || WBTEST_ENABLED(WBTEST_FILE_EXTEND_ERROR)); # if defined(__sun) || defined(__hpux) cs_data->defer_allocate = TRUE; # endif if (!blocks && (cs_data->defer_allocate || (TRANS_IN_PROG_TRUE == trans_in_prog))) return (uint4)(NO_FREE_SPACE); /* should this be changed to show extension not enabled ? */ bplmap = cs_data->bplmap; /* New total of non-bitmap blocks will be number of current, non-bitmap blocks, plus new blocks desired * There are (bplmap - 1) non-bitmap blocks per bitmap, so add (bplmap - 2) to number of non-bitmap blocks * and divide by (bplmap - 1) to get total number of bitmaps for expanded database. (must round up in this * manner as every non-bitmap block must have an associated bitmap) * Current number of bitmaps is (total number of current blocks + bplmap - 1) / bplmap. * Subtract current number of bitmaps from number needed for expanded database to get number of new bitmaps needed. */ new_bit_maps = DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, bplmap) + blocks, bplmap - 1) - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, bplmap); new_blocks = blocks + new_bit_maps; assert((0 < (int)new_blocks) || (!cs_data->defer_allocate && (0 == new_blocks))); if (new_blocks + cs_data->trans_hist.total_blks > MAXTOTALBLKS(cs_data)) { assert(WBTEST_ENABLED(WBTEST_FILE_EXTEND_ERROR)); send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_TOTALBLKMAX); return (uint4)(NO_FREE_SPACE); } if (0 != (save_errno = disk_block_available(udi->fd, &avail_blocks, FALSE))) { send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); } else { if (!(gtmDebugLevel & GDL_IgnoreAvailSpace)) { /* Bypass this space check if debug flag above is on. Allows us to create a large sparce DB * in space it could never fit it if wasn't sparse. Needed for some tests. */ avail_blocks = avail_blocks / (cs_data->blk_size / DISK_BLOCK_SIZE); if ((blocks * EXTEND_WARNING_FACTOR) > avail_blocks) { if (blocks > (uint4)avail_blocks) { if (!INST_FREEZE_ON_NOSPC_ENABLED(cs_addrs)) return (uint4)(NO_FREE_SPACE); else send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(6) MAKE_MSG_WARNING(ERR_NOSPACEEXT), 4, DB_LEN_STR(gv_cur_region), new_blocks, (uint4)avail_blocks); } else send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DSKSPACEFLOW, 3, DB_LEN_STR(gv_cur_region), (uint4)(avail_blocks - ((new_blocks <= avail_blocks) ? new_blocks : 0))); } } } # ifdef DEBUG if (WBTEST_ENABLED(WBTEST_MM_CONCURRENT_FILE_EXTEND) && dollar_tlevel && !MEMCMP_LIT(gv_cur_region->rname, "DEFAULT")) { SYSTEM("$gtm_dist/mumps -run $gtm_wbox_mrtn"); assert(1 == cs_addrs->nl->wbox_test_seq_num); /* should have been set by mubfilcpy */ cs_addrs->nl->wbox_test_seq_num = 2; /* signal mupip backup to stop sleeping in mubfilcpy */ } # endif /* From here on, we need to use GDSFILEXT_CLNUP before returning to the caller */ was_crit = cs_addrs->now_crit; assert(!cs_addrs->hold_onto_crit || was_crit); /* If we are coming from mupip_extend (which gets crit itself) we better have waited for any unfreezes to occur. * If we are coming from online rollback (when that feature is available), we will come in holding crit and in * the final retry. In that case too, we expect to have waited for unfreezes to occur in the caller itself. * Therefore if we are coming in holding crit from MUPIP, we expect the db to be unfrozen so no need to wait for * freeze. * If we are coming from GT.M and final retry (in which case we come in holding crit) we expect to have waited * for any unfreezes (by invoking tp_crit_all_regions) to occur (TP or non-TP) before coming into this * function. However, there is one exception. In the final retry, if tp_crit_all_regions notices that * at least one of the participating regions did ONLY READs, it will not wait for any freeze on THAT region * to complete before grabbing crit. Later, in the final retry, if THAT region did an update which caused * op_tcommit to invoke bm_getfree->gdsfilext, then we would have come here with a frozen region on which * we hold crit. */ assert(!was_crit || !FROZEN_HARD(cs_data) || (dollar_tlevel && (CDB_STAGNATE <= t_tries))); /* * If we are in the final retry and already hold crit, it is possible that csa->nl->wc_blocked is also set to TRUE * (by a concurrent process in phase2 which encountered an error in the midst of commit and secshr_db_clnup * finished the job for it). In this case we do NOT want to invoke wcs_recover as that will update the "bt" * transaction numbers without correspondingly updating the history transaction numbers (effectively causing * a cdb_sc_blkmod type of restart). Therefore do NOT call grab_crit (which unconditionally invokes wcs_recover) * if we already hold crit. */ if (!was_crit) { for ( ; ; ) { grab_crit(gv_cur_region); if (FROZEN_CHILLED(cs_data)) DO_CHILLED_AUTORELEASE(cs_addrs, cs_data); if (!FROZEN(cs_data) && !IS_REPL_INST_FROZEN) break; rel_crit(gv_cur_region); while (FROZEN(cs_data) || IS_REPL_INST_FROZEN) { hiber_start(1000); if (FROZEN_CHILLED(cs_data) && CHILLED_AUTORELEASE(cs_data)) break; } } } else if (FROZEN_HARD(cs_data) && dollar_tlevel) { /* We don't want to continue with file extension as explained above. Hence return with an error code which * op_tcommit will recognize (as a cdb_sc_needcrit/cdb_sc_instancefreeze type of restart) and restart accordingly. */ assert(CDB_STAGNATE <= t_tries); GDSFILEXT_CLNUP; return (uint4)FINAL_RETRY_FREEZE_PROG; } else WAIT_FOR_REGION_TO_UNCHILL(cs_addrs, cs_data); if (IS_REPL_INST_FROZEN && trans_in_prog) { assert(CDB_STAGNATE <= t_tries); GDSFILEXT_CLNUP; return (uint4)FINAL_RETRY_INST_FREEZE; } assert(cs_addrs->ti->total_blks == cs_data->trans_hist.total_blks); old_total = cs_data->trans_hist.total_blks; if (old_total != filesize) { /* Somebody else has already extended it, since we are in crit, this is trust-worthy. However, in case of MM, * we still need to remap the database */ assert((old_total > filesize) || !is_mm); /* For BG, someone else could have truncated or extended - we have no idea */ GDSFILEXT_CLNUP; return (SS_NORMAL); } if (trans_in_prog && SUSPICIOUS_EXTEND) { if (!was_crit) { GDSFILEXT_CLNUP; return (uint4)(EXTEND_SUSPECT); } /* If free_blocks counter is not ok, then correct it. Do the check again. If still fails, then it means we held * crit through bm_getfree into gdsfilext and still didn't get it right. */ assertpro(!is_free_blks_ctr_ok() && !SUSPICIOUS_EXTEND); } if (JNL_ENABLED(cs_data)) { if (!jgbl.dont_reset_gbl_jrec_time) SET_GBL_JREC_TIME; /* needed before jnl_ensure_open as that can write jnl records */ jpc = cs_addrs->jnl; jbp = jpc->jnl_buff; /* Before writing to jnlfile, adjust jgbl.gbl_jrec_time if needed to maintain time order * of jnl records. This needs to be done BEFORE the jnl_ensure_open as that could write * journal records (if it decides to switch to a new journal file). */ ADJUST_GBL_JREC_TIME(jgbl, jbp); jnl_status = jnl_ensure_open(gv_cur_region, cs_addrs); if (jnl_status) { GDSFILEXT_CLNUP; send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(cs_data), DB_LEN_STR(gv_cur_region)); return (uint4)(NO_FREE_SPACE); /* should have better return status */ } } if (is_mm) { cs_addrs->nl->mm_extender_pid = process_id; status = wcs_wtstart(gv_cur_region, 0, NULL, NULL); cs_addrs->nl->mm_extender_pid = 0; assertpro(SS_NORMAL == status); old_base[0] = cs_addrs->db_addrs[0]; old_base[1] = cs_addrs->db_addrs[1]; cs_addrs->db_addrs[0] = NULL; /* don't rely on it until the mmap below */ # ifdef _AIX status = shmdt(old_base[0] - BLK_ZERO_OFF(cs_data->start_vbn)); # else status = munmap((caddr_t)old_base[0], (size_t)(old_base[1] - old_base[0])); # endif if (0 != status) { save_errno = errno; GDSFILEXT_CLNUP; send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(12) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), ERR_SYSCALL, 5, LEN_AND_STR(MEM_UNMAP_SYSCALL), CALLFROM, save_errno); return (uint4)(NO_FREE_SPACE); } } else { /* Due to concurrency issues, it is possible some process had issued a disk read of the GDS block# corresponding * to "old_total" right after a truncate wrote a GDS-block of zeros on disk (to signal end of the db file). * If so, the global buffer containing this block needs to be invalidated now as part of the extend. If not, it is * possible the EOF block on disk is now going to be overwritten by a properly initialized bitmap block (as part * of the gdsfilext below) while the global buffer continues to have an incorrect copy of that bitmap block and * this in turn would cause XXXX failures due to a bad bitmap block in shared memory. (GTM-7519) */ cr = db_csh_get((block_id)old_total); if ((NULL != cr) && ((cache_rec_ptr_t)CR_NOTVALID != cr)) { assert((0 == cr->dirty) && (0 == cr->bt_index) && !cr->stopped); cr->cycle++; cr->blk = CR_BLKEMPTY; } } CHECK_TN(cs_addrs, cs_data, cs_data->trans_hist.curr_tn); /* can issue rts_error TNTOOLARGE */ new_total = old_total + new_blocks; new_eof = BLK_ZERO_OFF(cs_data->start_vbn) + ((off_t)new_total * cs_data->blk_size); # if !defined(__sun) && !defined(__hpux) if (!cs_data->defer_allocate) { new_size = new_eof + cs_data->blk_size; save_errno = posix_fallocate(udi->fd, 0, new_size); DEBUG_ONLY(first_save_errno = save_errno); if ((ENOSPC == save_errno) && IS_GTM_IMAGE) save_errno = extend_wait_for_fallocate(udi, new_size); if (0 != save_errno) { GDSFILEXT_CLNUP; assert(ENOSPC == save_errno); if (ENOSPC != save_errno) send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_PREALLOCATEFAIL, 2, DB_LEN_STR(gv_cur_region), save_errno); return (uint4)(NO_FREE_SPACE); } } # endif save_errno = db_write_eof_block(udi, udi->fd, cs_data->blk_size, new_eof, &(TREF(dio_buff))); if ((ENOSPC == save_errno) && IS_GTM_IMAGE) save_errno = extend_wait_for_write(udi, cs_data->blk_size, new_eof); if (0 != save_errno) { GDSFILEXT_CLNUP; if (ENOSPC != save_errno) send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); return (uint4)(NO_FREE_SPACE); } if (WBTEST_ENABLED(WBTEST_FILE_EXTEND_INTERRUPT_1)) { LONG_SLEEP(600); assert(FALSE); } /* Ensure the EOF and metadata get to disk BEFORE any bitmap writes. Otherwise, the file size could no longer reflect * a proper extent and subsequent invocations of gdsfilext could corrupt the database. */ if (!IS_STATSDB_CSA(cs_addrs)) { GTM_DB_FSYNC(cs_addrs, udi->fd, status); assert(0 == status); if (0 != status) { GDSFILEXT_CLNUP; send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(8) ERR_DBFILERR, 5, RTS_ERROR_LITERAL("fsync1()"), CALLFROM, status); return (uint4)(NO_FREE_SPACE); } } if (WBTEST_ENABLED(WBTEST_FILE_EXTEND_INTERRUPT_2)) { LONG_SLEEP(600); assert(FALSE); /* Should be killed before that */ } DEBUG_ONLY(prev_extend_blks_to_upgrd = cs_data->blks_to_upgrd;)
boolean_t mu_truncate(int4 truncate_percent) { sgmnt_addrs *csa; sgmnt_data_ptr_t csd; int num_local_maps; int lmap_num, lmap_blk_num; int bml_status, sigkill; int save_errno; int ftrunc_status; uint4 jnl_status; uint4 old_total, new_total; uint4 old_free, new_free; uint4 end_blocks; int4 blks_in_lmap, blk; gtm_uint64_t before_trunc_file_size; off_t trunc_file_size; off_t padding; uchar_ptr_t lmap_addr; boolean_t was_crit; uint4 found_busy_blk; srch_blk_status bmphist; srch_blk_status *blkhist; srch_hist alt_hist; trans_num curr_tn; blk_hdr_ptr_t lmap_blk_hdr; block_id *blkid_ptr; unix_db_info *udi; jnl_private_control *jpc; jnl_buffer_ptr_t jbp; char *err_msg; intrpt_state_t prev_intrpt_state; off_t offset; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; csa = cs_addrs; csd = cs_data; if (dba_mm == csd->acc_meth) { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_MUTRUNCNOTBG, 2, REG_LEN_STR(gv_cur_region)); return TRUE; } if ((GDSVCURR != csd->desired_db_format) || (csd->blks_to_upgrd != 0)) { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_MUTRUNCNOV4, 2, REG_LEN_STR(gv_cur_region)); return TRUE; } if (csa->ti->free_blocks < (truncate_percent * csa->ti->total_blks / 100)) { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_MUTRUNCNOSPACE, 3, REG_LEN_STR(gv_cur_region), truncate_percent); return TRUE; } /* already checked for parallel truncates on this region --- see mupip_reorg.c */ gv_target = NULL; assert(csa->nl->trunc_pid == process_id); assert(dba_mm != csd->acc_meth); old_total = csa->ti->total_blks; old_free = csa->ti->free_blocks; sigkill = 0; found_busy_blk = 0; memset(&alt_hist, 0, SIZEOF(alt_hist)); /* null-initialize history */ assert(csd->bplmap == BLKS_PER_LMAP); end_blocks = old_total % BLKS_PER_LMAP; /* blocks in the last lmap (first one we start scanning) */ if (0 == end_blocks) end_blocks = BLKS_PER_LMAP; num_local_maps = DIVIDE_ROUND_UP(old_total, BLKS_PER_LMAP); /* ======================================== PHASE 1 ======================================== */ for (lmap_num = num_local_maps - 1; (lmap_num > 0 && !found_busy_blk); lmap_num--) { if (mu_ctrly_occurred || mu_ctrlc_occurred) return TRUE; assert(csa->ti->total_blks >= old_total); /* otherwise, a concurrent truncate happened... */ if (csa->ti->total_blks != old_total) /* Extend (likely called by mupip extend) -- don't truncate */ { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_MUTRUNCNOSPACE, 3, REG_LEN_STR(gv_cur_region), truncate_percent); return TRUE; } lmap_blk_num = lmap_num * BLKS_PER_LMAP; if (csa->nl->highest_lbm_with_busy_blk >= lmap_blk_num) { found_busy_blk = lmap_blk_num; break; } blks_in_lmap = (lmap_num == num_local_maps - 1) ? end_blocks : BLKS_PER_LMAP; /* Loop through non-bitmap blocks of this lmap, do recycled2free */ DBGEHND((stdout, "DBG:: lmap_num = [%lu], lmap_blk_num = [%lu], blks_in_lmap = [%lu]\n", lmap_num, lmap_blk_num, blks_in_lmap)); for (blk = 1; blk < blks_in_lmap && blk != -1 && !found_busy_blk;) { t_begin(ERR_MUTRUNCFAIL, UPDTRNS_DB_UPDATED_MASK); for (;;) /* retry loop for recycled to free transactions */ { curr_tn = csd->trans_hist.curr_tn; /* Read the nth local bitmap into memory */ bmphist.blk_num = lmap_blk_num; bmphist.buffaddr = t_qread(bmphist.blk_num, &bmphist.cycle, &bmphist.cr); lmap_blk_hdr = (blk_hdr_ptr_t)bmphist.buffaddr; if (!(bmphist.buffaddr) || (BM_SIZE(BLKS_PER_LMAP) != lmap_blk_hdr->bsiz)) { /* Could not read the block successfully. Retry. */ t_retry((enum cdb_sc)rdfail_detail); continue; } lmap_addr = bmphist.buffaddr + SIZEOF(blk_hdr); /* starting from the hint (blk itself), find the first busy or recycled block */ blk = bml_find_busy_recycled(blk, lmap_addr, blks_in_lmap, &bml_status); assert(blk < BLKS_PER_LMAP); if (blk == -1 || blk >= blks_in_lmap) { /* done with this lmap, continue to next */ t_abort(gv_cur_region, csa); break; } else if (BLK_BUSY == bml_status || csa->nl->highest_lbm_with_busy_blk >= lmap_blk_num) { /* stop processing blocks... skip ahead to phase 2 */ found_busy_blk = lmap_blk_num; t_abort(gv_cur_region, csa); break; } else if (BLK_RECYCLED == bml_status) { /* Write PBLK records for recycled blocks only if before_image journaling is * enabled. t_end() takes care of checking if journaling is enabled and * writing PBLK record. We have to at least mark the recycled block as free. */ RESET_UPDATE_ARRAY; update_trans = UPDTRNS_DB_UPDATED_MASK; *((block_id *)update_array_ptr) = blk; update_array_ptr += SIZEOF(block_id); *(int *)update_array_ptr = 0; alt_hist.h[1].blk_num = 0; alt_hist.h[0].level = 0; alt_hist.h[0].cse = NULL; alt_hist.h[0].tn = curr_tn; alt_hist.h[0].blk_num = lmap_blk_num + blk; alt_hist.h[0].buffaddr = t_qread(alt_hist.h[0].blk_num, &alt_hist.h[0].cycle, &alt_hist.h[0].cr); if (!alt_hist.h[0].buffaddr) { t_retry((enum cdb_sc)rdfail_detail); continue; } if (!t_recycled2free(&alt_hist.h[0])) { t_retry(cdb_sc_lostbmlcr); continue; } t_write_map(&bmphist, (unsigned char *)update_array, curr_tn, 0); /* Set the opcode for INCTN record written by t_end() */ inctn_opcode = inctn_blkmarkfree; if ((trans_num)0 == t_end(&alt_hist, NULL, TN_NOT_SPECIFIED)) continue; /* block processed, scan from the next one */ blk++; break; } else { assert(t_tries < CDB_STAGNATE); t_retry(cdb_sc_badbitmap); continue; } } /* END recycled2free retry loop */ } /* END scanning blocks of this particular lmap */ /* Write PBLK for the bitmap block, in case it hasn't been written i.e. t_end() was never called above */ /* Do a transaction that just increments the bitmap block's tn so that t_end() can do its thing */ DBGEHND((stdout, "DBG:: bitmap block inctn -- lmap_blk_num = [%lu]\n", lmap_blk_num)); t_begin(ERR_MUTRUNCFAIL, UPDTRNS_DB_UPDATED_MASK); for (;;) { RESET_UPDATE_ARRAY; BLK_ADDR(blkid_ptr, SIZEOF(block_id), block_id); *blkid_ptr = 0; update_trans = UPDTRNS_DB_UPDATED_MASK; inctn_opcode = inctn_mu_reorg; /* inctn_mu_truncate */ curr_tn = csd->trans_hist.curr_tn; blkhist = &alt_hist.h[0]; blkhist->blk_num = lmap_blk_num; blkhist->tn = curr_tn; blkhist->cse = NULL; /* start afresh (do not use value from previous retry) */ /* Read the nth local bitmap into memory */ blkhist->buffaddr = t_qread(lmap_blk_num, (sm_int_ptr_t)&blkhist->cycle, &blkhist->cr); lmap_blk_hdr = (blk_hdr_ptr_t)blkhist->buffaddr; if (!(blkhist->buffaddr) || (BM_SIZE(BLKS_PER_LMAP) != lmap_blk_hdr->bsiz)) { /* Could not read the block successfully. Retry. */ t_retry((enum cdb_sc)rdfail_detail); continue; } t_write_map(blkhist, (unsigned char *)blkid_ptr, curr_tn, 0); blkhist->blk_num = 0; /* create empty history for bitmap block */ if ((trans_num)0 == t_end(&alt_hist, NULL, TN_NOT_SPECIFIED)) continue; break; } } /* END scanning lmaps */ /* ======================================== PHASE 2 ======================================== */ assert(!csa->now_crit); for (;;) { /* wait for FREEZE, we don't want to truncate a frozen database */ grab_crit(gv_cur_region); if (FROZEN_CHILLED(cs_data)) DO_CHILLED_AUTORELEASE(csa, cs_data); if (!FROZEN(cs_data) && !IS_REPL_INST_FROZEN) break; rel_crit(gv_cur_region); while (FROZEN(cs_data) || IS_REPL_INST_FROZEN) { hiber_start(1000); if (FROZEN_CHILLED(cs_data) && CHILLED_AUTORELEASE(cs_data)) break; } } assert(csa->nl->trunc_pid == process_id); /* Flush pending updates to disk. If this is not done, old updates can be flushed AFTER ftruncate, extending the file. */ if (!wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_MSYNC_DB)) { assert(FALSE); gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_BUFFLUFAILED, 4, LEN_AND_LIT("MUPIP REORG TRUNCATE"), DB_LEN_STR(gv_cur_region)); rel_crit(gv_cur_region); return FALSE; } csa->nl->highest_lbm_with_busy_blk = MAX(found_busy_blk, csa->nl->highest_lbm_with_busy_blk); assert(IS_BITMAP_BLK(csa->nl->highest_lbm_with_busy_blk)); new_total = MIN(old_total, csa->nl->highest_lbm_with_busy_blk + BLKS_PER_LMAP); if (mu_ctrly_occurred || mu_ctrlc_occurred) { rel_crit(gv_cur_region); return TRUE; } else if (csa->ti->total_blks != old_total || new_total == old_total) { assert(csa->ti->total_blks >= old_total); /* Better have been an extend, not a truncate... */ gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_MUTRUNCNOSPACE, 3, REG_LEN_STR(gv_cur_region), truncate_percent); rel_crit(gv_cur_region); return TRUE; } else if (GDSVCURR != csd->desired_db_format || csd->blks_to_upgrd != 0 || !csd->fully_upgraded) { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_MUTRUNCNOV4, 2, REG_LEN_STR(gv_cur_region)); rel_crit(gv_cur_region); return TRUE; } else if (SNAPSHOTS_IN_PROG(csa->nl)) { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_MUTRUNCSSINPROG, 2, REG_LEN_STR(gv_cur_region)); rel_crit(gv_cur_region); return TRUE; } else if (BACKUP_NOT_IN_PROGRESS != cs_addrs->nl->nbb) { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_MUTRUNCBACKINPROG, 2, REG_LEN_STR(gv_cur_region)); rel_crit(gv_cur_region); return TRUE; } DEFER_INTERRUPTS(INTRPT_IN_TRUNC, prev_intrpt_state); if (JNL_ENABLED(csa)) { /* Write JRT_TRUNC and INCTN records */ if (!jgbl.dont_reset_gbl_jrec_time) SET_GBL_JREC_TIME; /* needed before jnl_ensure_open as that can write jnl records */ jpc = csa->jnl; jbp = jpc->jnl_buff; /* Before writing to jnlfile, adjust jgbl.gbl_jrec_time if needed to maintain time order * of jnl records. This needs to be done BEFORE the jnl_ensure_open as that could write * journal records (if it decides to switch to a new journal file). */ ADJUST_GBL_JREC_TIME(jgbl, jbp); jnl_status = jnl_ensure_open(gv_cur_region, csa); if (SS_NORMAL != jnl_status) send_msg_csa(CSA_ARG(csa) VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(csd), DB_LEN_STR(gv_cur_region)); else { if (0 == jpc->pini_addr) jnl_put_jrt_pini(csa); jnl_write_trunc_rec(csa, old_total, csa->ti->free_blocks, new_total); inctn_opcode = inctn_mu_reorg; jnl_write_inctn_rec(csa); jnl_status = jnl_flush(gv_cur_region); if (SS_NORMAL != jnl_status) { send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_JNLFLUSH, 2, JNL_LEN_STR(csd), ERR_TEXT, 2, RTS_ERROR_TEXT("Error with journal flush during mu_truncate"), jnl_status); assert(NOJNL == jpc->channel); /* jnl file lost has been triggered */ } } } /* Good to go ahead and REALLY truncate (reduce total_blks, clear cache_array, FTRUNCATE) */ curr_tn = csa->ti->curr_tn; CHECK_TN(csa, csd, curr_tn); udi = FILE_INFO(gv_cur_region); /* Information used by recover_truncate to check if the file size and csa->ti->total_blks are INCONSISTENT */ trunc_file_size = BLK_ZERO_OFF(csd->start_vbn) + ((off_t)csd->blk_size * (new_total + 1)); csd->after_trunc_total_blks = new_total; csd->before_trunc_free_blocks = csa->ti->free_blocks; csd->before_trunc_total_blks = old_total; /* Flags interrupted truncate for recover_truncate */ /* file size and total blocks: INCONSISTENT */ csa->ti->total_blks = new_total; /* past the point of no return -- shared memory intact */ assert(csa->ti->free_blocks >= DELTA_FREE_BLOCKS(old_total, new_total)); csa->ti->free_blocks -= DELTA_FREE_BLOCKS(old_total, new_total); new_free = csa->ti->free_blocks; KILL_TRUNC_TEST(WBTEST_CRASH_TRUNCATE_1); /* 55 : Issue a kill -9 before 1st fsync */ fileheader_sync(gv_cur_region); DB_FSYNC(gv_cur_region, udi, csa, db_fsync_in_prog, save_errno); CHECK_DBSYNC(gv_cur_region, save_errno); /* past the point of no return -- shared memory deleted */ KILL_TRUNC_TEST(WBTEST_CRASH_TRUNCATE_2); /* 56 : Issue a kill -9 after 1st fsync */ clear_cache_array(csa, csd, gv_cur_region, new_total, old_total); offset = (off_t)BLK_ZERO_OFF(csd->start_vbn) + (off_t)new_total * csd->blk_size; save_errno = db_write_eof_block(udi, udi->fd, csd->blk_size, offset, &(TREF(dio_buff))); if (0 != save_errno) { err_msg = (char *)STRERROR(errno); rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_MUTRUNCERROR, 4, REG_LEN_STR(gv_cur_region), LEN_AND_STR(err_msg)); return FALSE; } KILL_TRUNC_TEST(WBTEST_CRASH_TRUNCATE_3); /* 57 : Issue a kill -9 after reducing csa->ti->total_blks, before FTRUNCATE */ /* Execute an ftruncate() and truncate the DB file * ftruncate() is a SYSTEM CALL on almost all platforms (except SunOS) * It ignores kill -9 signal till its operation is completed. * So we can safely assume that the result of ftruncate() will be complete. */ FTRUNCATE(FILE_INFO(gv_cur_region)->fd, trunc_file_size, ftrunc_status); if (0 != ftrunc_status) { err_msg = (char *)STRERROR(errno); rts_error_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_MUTRUNCERROR, 4, REG_LEN_STR(gv_cur_region), LEN_AND_STR(err_msg)); /* should go through recover_truncate now, which will again try to FTRUNCATE */ return FALSE; } /* file size and total blocks: CONSISTENT (shrunk) */ KILL_TRUNC_TEST(WBTEST_CRASH_TRUNCATE_4); /* 58 : Issue a kill -9 after FTRUNCATE, before 2nd fsync */ csa->nl->root_search_cycle++; /* Force concurrent processes to restart in t_end/tp_tend to make sure no one * tries to commit updates past the end of the file. Bitmap validations together * with highest_lbm_with_busy_blk should actually be sufficient, so this is * just to be safe. */ csd->before_trunc_total_blks = 0; /* indicate CONSISTENT */ /* Increment TN */ assert(csa->ti->early_tn == csa->ti->curr_tn); csd->trans_hist.early_tn = csd->trans_hist.curr_tn + 1; INCREMENT_CURR_TN(csd); fileheader_sync(gv_cur_region); DB_FSYNC(gv_cur_region, udi, csa, db_fsync_in_prog, save_errno); KILL_TRUNC_TEST(WBTEST_CRASH_TRUNCATE_5); /* 58 : Issue a kill -9 after after 2nd fsync */ CHECK_DBSYNC(gv_cur_region, save_errno); ENABLE_INTERRUPTS(INTRPT_IN_TRUNC, prev_intrpt_state); curr_tn = csa->ti->curr_tn; rel_crit(gv_cur_region); send_msg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_MUTRUNCSUCCESS, 5, DB_LEN_STR(gv_cur_region), old_total, new_total, &curr_tn); util_out_print("Truncated region: !AD. Reduced total blocks from [!UL] to [!UL]. Reduced free blocks from [!UL] to [!UL].", FLUSH, REG_LEN_STR(gv_cur_region), old_total, new_total, old_free, new_free); return TRUE; } /* END of mu_truncate() */
void op_zlink(mval *v, mval *quals) { struct FAB srcfab; struct NAM srcnam, objnam; struct XABDAT srcxab, objxab; boolean_t compile, expdir, libr, obj_found, src_found; short flen; unsigned short type; unsigned char srccom[MAX_FN_LEN], srcnamebuf[MAX_FN_LEN], objnamebuf[MAX_FN_LEN], objnamelen, srcnamelen,ver[6]; unsigned char objcom[MAX_FN_LEN], list_file[MAX_FN_LEN], ceprep_file[MAX_FN_LEN], *fname; zro_ent *srcdir, *objdir; mstr srcstr, objstr, version; mval qualifier; unsigned status, srcfnb; uint4 lcnt, librindx, qlf; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; MV_FORCE_STR(v); if (MAX_FN_LEN < v->str.len) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, MIN(UCHAR_MAX, v->str.len), v->str.addr, ERR_FILENAMETOOLONG); version.len = 0; srcdir = objdir = 0; version.addr = ver; libr = FALSE; obj_fab = cc$rms_fab; if (quals) { MV_FORCE_STR(quals); srcfab = cc$rms_fab; srcfab.fab$l_fna = v->str.addr; srcfab.fab$b_fns = v->str.len; srcfab.fab$l_nam = &srcnam; srcnam = cc$rms_nam; srcnam.nam$l_esa = srcnamebuf; srcnam.nam$b_ess = SIZEOF(srcnamebuf); srcnam.nam$b_nop = NAM$M_SYNCHK; status = sys$parse(&srcfab); if (!(status & 1)) rts_error(VARLSTCNT(9) ERR_ZLINKFILE, 2, v->str.len, v->str.addr, ERR_FILEPARSE, 2, v->str.len, v->str.addr, status); if (srcnam.nam$l_fnb & NAM$M_WILDCARD) rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr, ERR_WILDCARD, 2, v->str.len, v->str.addr); srcfnb = srcnam.nam$l_fnb; expdir = (srcfnb & (NAM$M_NODE | NAM$M_EXP_DEV | NAM$M_EXP_DIR)); if (srcfnb & NAM$M_EXP_VER) { memcpy(version.addr, srcnam.nam$l_ver, srcnam.nam$b_ver); version.len = srcnam.nam$b_ver; } if (expdir) { if (version.len) flen = srcnam.nam$b_esl - srcnam.nam$b_type - version.len; else flen = srcnam.nam$b_esl - srcnam.nam$b_type - 1; /* semicolon is put in by default */ fname = srcnam.nam$l_esa; } else { flen = srcnam.nam$b_name; fname = srcnam.nam$l_name; } ENSURE_STP_FREE_SPACE(flen); memcpy(stringpool.free, fname, flen); dollar_zsource.str.addr = stringpool.free; dollar_zsource.str.len = flen; stringpool.free += flen; if (srcfnb & NAM$M_EXP_TYPE) { if ((SIZEOF(DOTOBJ) - 1 == srcnam.nam$b_type) && !MEMCMP_LIT(srcnam.nam$l_type, DOTOBJ)) { type = OBJ; objstr.addr = srcnam.nam$l_esa; objstr.len = srcnam.nam$b_esl; } else { type = SRC; memcpy(srcnamebuf, dollar_zsource.str.addr, flen); memcpy(&srcnamebuf[flen], srcnam.nam$l_type, srcnam.nam$b_type); memcpy(&srcnamebuf[flen + srcnam.nam$b_type], version.addr, version.len); srcnamelen = flen + srcnam.nam$b_type + version.len; srcnamebuf[srcnamelen] = 0; srcstr.addr = srcnamebuf; srcstr.len = srcnamelen; memcpy(objnamebuf, dollar_zsource.str.addr, flen); memcpy(&objnamebuf[flen], DOTOBJ, SIZEOF(DOTOBJ)); objnamelen = flen + SIZEOF(DOTOBJ) - 1; objstr.addr = objnamebuf; objstr.len = objnamelen; } } else { type = NOTYPE; memcpy(srcnamebuf, dollar_zsource.str.addr, flen); memcpy(&srcnamebuf[flen], DOTM, SIZEOF(DOTM)); srcnamelen = flen + SIZEOF(DOTM) - 1; memcpy(objnamebuf, dollar_zsource.str.addr, flen); MEMCPY_LIT(&objnamebuf[flen], DOTOBJ); memcpy(&objnamebuf[flen + SIZEOF(DOTOBJ) - 1], version.addr, version.len); objnamelen = flen + SIZEOF(DOTOBJ) + version.len - 1; objnamebuf[objnamelen] = 0; srcstr.addr = srcnamebuf; srcstr.len = srcnamelen; objstr.addr = objnamebuf; objstr.len = objnamelen; } if (!expdir) { if (OBJ == type) { zro_search(&objstr, &objdir, 0, 0); if (!objdir) rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, ERR_FILENOTFND, 2, dollar_zsource.str.len, dollar_zsource.str.addr); } else if (SRC == type) { zro_search(&objstr, &objdir, &srcstr, &srcdir); if (!srcdir) rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_FILENOTFND, 2, srcnamelen, srcnamebuf); } else { zro_search(&objstr, &objdir, &srcstr, &srcdir); if (!objdir && !srcdir) rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, ERR_FILENOTFND, 2, dollar_zsource.str.len, dollar_zsource.str.addr); } } } else { expdir = FALSE; type = NOTYPE; flen = v->str.len; memcpy(srcnamebuf, v->str.addr, flen); MEMCPY_LIT(&srcnamebuf[flen], DOTM); srcnamelen = flen + SIZEOF(DOTM) - 1; if ('%' == srcnamebuf[0]) srcnamebuf[0] = '_'; memcpy(objnamebuf, srcnamebuf, flen); MEMCPY_LIT(&objnamebuf[flen], DOTOBJ); objnamelen = flen + SIZEOF(DOTOBJ) - 1; srcstr.addr = srcnamebuf; srcstr.len = srcnamelen; objstr.addr = objnamebuf; objstr.len = objnamelen; zro_search(&objstr, &objdir, &srcstr, &srcdir); if (!objdir && !srcdir) rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, v->str.len, v->str.addr, ERR_FILENOTFND, 2, v->str.len, v->str.addr); qualifier.mvtype = MV_STR; qualifier.str = TREF(dollar_zcompile); quals = &qualifier; } if (OBJ == type) { obj_fab.fab$b_fac = FAB$M_GET; obj_fab.fab$b_shr = FAB$M_SHRGET; if (NULL != objdir) { if (ZRO_TYPE_OBJLIB == objdir->type) libr = TRUE; else { srcfab.fab$l_dna = objdir->str.addr; srcfab.fab$b_dns = objdir->str.len; } } for (lcnt = 0; lcnt < MAX_FILE_OPEN_TRIES; lcnt++) { status = (FALSE == libr) ? sys$open(&srcfab): zl_olb(&objdir->str, &objstr, &librindx); if (RMS$_FLK != status) break; hiber_start(WAIT_FOR_FILE_TIME); } if (FALSE == (status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, status); if (FALSE == ((FALSE == libr) ? incr_link(&srcfab, libr) : incr_link(&librindx, libr))) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, ERR_VERSION); status = (FALSE == libr) ? sys$close(&srcfab) : lbr$close(&librindx); if (FALSE == (status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, dollar_zsource.str.len, dollar_zsource.str.addr, status); } else /* either NO type or SOURCE type */ { src_found = obj_found = compile = FALSE; srcfab = obj_fab = cc$rms_fab; obj_fab.fab$l_xab = &objxab; srcxab = objxab = cc$rms_xabdat; obj_fab.fab$l_nam = &objnam; srcnam = objnam = cc$rms_nam; obj_fab.fab$l_fna = objnamebuf; obj_fab.fab$b_fns = objnamelen; obj_fab.fab$b_fac = FAB$M_GET; obj_fab.fab$b_shr = FAB$M_SHRGET; objnam.nam$l_esa = objcom; objnam.nam$b_ess = SIZEOF(objcom); srcfab.fab$l_nam = &srcnam; srcfab.fab$l_xab = &srcxab; srcfab.fab$l_fna = srcnamebuf; srcfab.fab$b_fns = srcnamelen; srcfab.fab$b_fac = FAB$M_GET; srcfab.fab$b_shr = FAB$M_SHRGET; srcnam.nam$l_esa = srccom; srcnam.nam$b_ess = SIZEOF(srccom); cmd_qlf.object_file.str.addr = objcom; cmd_qlf.object_file.str.len = 255; cmd_qlf.list_file.str.addr = list_file; cmd_qlf.list_file.str.len = 255; cmd_qlf.ceprep_file.str.addr = ceprep_file; cmd_qlf.ceprep_file.str.len = 255; if (srcdir && srcdir->str.len) { srcfab.fab$l_dna = srcdir->str.addr; srcfab.fab$b_dns = srcdir->str.len; } if (objdir && objdir->str.len) { if (ZRO_TYPE_OBJLIB == objdir->type) libr = TRUE; else { obj_fab.fab$l_dna = objdir->str.addr; obj_fab.fab$b_dns = objdir->str.len; } } if (SRC != type) { if (!expdir && !objdir) obj_found = FALSE; else if (!libr) { for (lcnt = 0; lcnt < MAX_FILE_OPEN_TRIES; lcnt++) { status = sys$open(&obj_fab); if (RMS$_FLK != status) break; hiber_start(WAIT_FOR_FILE_TIME); } if (!(status & 1)) { if (RMS$_FNF == status) obj_found = FALSE; else rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, status); } else obj_found = TRUE; } else { status = zl_olb(&objdir->str, &objstr, &librindx); if (status) obj_found = TRUE; } } else compile = TRUE; if (!expdir && !srcdir) src_found = FALSE; else { for (lcnt = 0; lcnt < MAX_FILE_OPEN_TRIES; lcnt++) { status = sys$open(&srcfab); if (RMS$_FLK != status) break; hiber_start(WAIT_FOR_FILE_TIME); } if (!(status & 1)) { if ((RMS$_FNF == status) && (SRC != type)) src_found = FALSE; else rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, status); } else { src_found = TRUE; if (SRC == type) { status = sys$close(&srcfab); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, status); } } } if (SRC != type) { if (src_found) { if (obj_found) { if (QUADCMP(&srcxab.xab$q_rdt, &objxab.xab$q_rdt)) { status = sys$close(&obj_fab); obj_fab = cc$rms_fab; if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, status); compile = TRUE; } } else compile = TRUE; status = sys$close(&srcfab); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, status); } else if (!obj_found) rts_error(VARLSTCNT(8) ERR_ZLINKFILE, 2, objnamelen, objnamebuf, ERR_FILENOTFND, 2, objnamelen, objnamebuf); } if (compile) { zl_cmd_qlf(&quals->str, &cmd_qlf); if (!MV_DEFINED(&cmd_qlf.object_file)) { objnam.nam$b_nop = NAM$M_SYNCHK; status = sys$parse(&obj_fab); if (!(status & 1)) rts_error(VARLSTCNT(4) ERR_FILEPARSE, 2, obj_fab.fab$b_fns, obj_fab.fab$l_fna); cmd_qlf.object_file.mvtype = MV_STR; cmd_qlf.object_file.str.len = objnam.nam$b_esl - objnam.nam$b_ver; } qlf = cmd_qlf.qlf; if (!(cmd_qlf.qlf & CQ_OBJECT) && (SRC != type)) { cmd_qlf.qlf = glb_cmd_qlf.qlf; rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT); } zlcompile(srcnam.nam$b_esl, srcnam.nam$l_esa); if ((SRC == type) && !(qlf & CQ_OBJECT)) return; } status = libr ? incr_link(&librindx, libr) : incr_link(&obj_fab, libr); if (!status) /* due only to version mismatch, so recompile */ { if (!libr) { status = sys$close(&obj_fab); obj_fab = cc$rms_fab; } else status = lbr$close(&librindx); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objstr.len, objstr.addr, status); if (compile) GTMASSERT; if (!src_found) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_VERSION); zl_cmd_qlf(&quals->str, &cmd_qlf); if (!MV_DEFINED(&cmd_qlf.object_file)) { objnam.nam$b_nop = NAM$M_SYNCHK; status = sys$parse(&obj_fab); if (!(status & 1)) rts_error(VARLSTCNT(4) ERR_FILEPARSE, 2, obj_fab.fab$b_fns, obj_fab.fab$l_fna); cmd_qlf.object_file.mvtype = MV_STR; cmd_qlf.object_file.str.len = objnam.nam$b_esl - objnam.nam$b_ver; } if (!(cmd_qlf.qlf & CQ_OBJECT) && (SRC != type)) { cmd_qlf.qlf = glb_cmd_qlf.qlf; rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, srcnamelen, srcnamebuf, ERR_ZLNOOBJECT); } zlcompile(srcnam.nam$b_esl, srcnam.nam$l_esa); if (!incr_link(&obj_fab, libr)) GTMASSERT; } if (!libr) { status = sys$close(&obj_fab); obj_fab = cc$rms_fab; } else status = lbr$close(&librindx); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_ZLINKFILE, 2, objstr.len, objstr.addr, status); } return; }
/* * ------------------------------------------ * Hang the process for a specified time. * * Goes to sleep for a positive value. * Any caught signal will terminate the sleep * following the execution of that signal's catching routine. * * Arguments: * num - time to sleep * * Return: * none * ------------------------------------------ */ void op_hang(mval* num) { int ms; mv_stent *mv_zintcmd; ABS_TIME cur_time, end_time; # ifdef VMS uint4 time[2]; int4 efn_mask, status; # endif DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; ms = 0; MV_FORCE_NUM(num); if (num->mvtype & MV_INT) { if (0 < num->m[1]) { assert(MV_BIAS >= 1000); /* if formats change overflow may need attention */ ms = num->m[1] * (1000 / MV_BIAS); } } else if (0 == num->sgn) /* if sign is not 0 it means num is negative */ ms = mval2i(num) * 1000; /* too big to care about fractional amounts */ if (ms) { if (TREF(tpnotacidtime) * 1000 < ms) TPNOTACID_CHECK(HANGSTR); # if defined(DEBUG) && defined(UNIX) if (gtm_white_box_test_case_enabled && (WBTEST_DEFERRED_TIMERS == gtm_white_box_test_case_number) && (3 > gtm_white_box_test_case_count) && (123000 == ms)) { DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS); DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n")); LONG_SLEEP(20); DBGFPF((stderr, "OP_HANG: done sleeping\n")); ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS); return; } if (gtm_white_box_test_case_enabled && (WBTEST_BREAKMPC == gtm_white_box_test_case_number) && (0 == gtm_white_box_test_case_count) && (999 == ms)) { frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678) NON_GTM64_ONLY(0xdead1234); return; } /* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of UTIL_OUT_SYSLOG_INTERVAL * and prints a long message via util_out_ptr. */ if (gtm_white_box_test_case_enabled && (WBTEST_UTIL_OUT_BUFFER_PROTECTION == gtm_white_box_test_case_number) && (0 == gtm_white_box_test_case_count) && (999 == ms)) { start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL); return; } # endif sys_get_curr_time(&cur_time); mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE); if (!mv_zintcmd) add_int_to_abs_time(&cur_time, ms, &end_time); else { end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain; cur_time = sub_abs_time(&end_time, &cur_time); /* get remaing time to sleep */ if (0 <= cur_time.at_sec) ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000); else ms = 0; /* all done */ /* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */ TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior; TAREF1(zintcmd_active, ZINTCMD_HANG).count--; assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count); if (mv_chain == mv_zintcmd) POP_MV_STENT(); /* just pop if top of stack */ else { /* flag as not active */ mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP; mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL; } if (0 == ms) return; /* done HANGing */ } UNIX_ONLY(hiber_start(ms);) VMS_ONLY( time[0] = -time_low_ms(ms); time[1] = -time_high_ms(ms) - 1; efn_mask = (1 << efn_outofband | 1 << efn_timer); if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0))) rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status); if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask))) rts_error(VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status); ) if (outofband)
OS_PAGE_SIZE_DECLARE uint4 gdsfilext(uint4 blocks, uint4 filesize, boolean_t trans_in_prog) { sm_uc_ptr_t old_base[2], mmap_retaddr; boolean_t was_crit, is_mm; char buff[DISK_BLOCK_SIZE]; int result, save_errno, status; uint4 new_bit_maps, bplmap, map, new_blocks, new_total, max_tot_blks, old_total; uint4 jnl_status, to_wait, to_msg, wait_period; gtm_uint64_t avail_blocks, mmap_sz; off_t new_eof; trans_num curr_tn; unix_db_info *udi; inctn_opcode_t save_inctn_opcode; int4 prev_extend_blks_to_upgrd; jnl_private_control *jpc; jnl_buffer_ptr_t jbp; cache_rec_ptr_t cr; DCL_THREADGBL_ACCESS; assert(!IS_DSE_IMAGE); assert((cs_addrs->nl == NULL) || (process_id != cs_addrs->nl->trunc_pid)); /* mu_truncate shouldn't extend file... */ assert(!process_exiting); DEBUG_ONLY(old_base[0] = old_base[1] = NULL); assert(!gv_cur_region->read_only); udi = FILE_INFO(gv_cur_region); is_mm = (dba_mm == cs_addrs->hdr->acc_meth); # if !defined(MM_FILE_EXT_OK) if (!udi->grabbed_access_sem && is_mm) return (uint4)(NO_FREE_SPACE); /* should this be changed to show extension not allowed ? */ # endif /* Both blocks and total blocks are unsigned ints so make sure we aren't asking for huge numbers that will overflow and end up doing silly things. */ assert((blocks <= (MAXTOTALBLKS(cs_data) - cs_data->trans_hist.total_blks)) || WBTEST_ENABLED(WBTEST_FILE_EXTEND_ERROR)); if (!blocks) return (uint4)(NO_FREE_SPACE); /* should this be changed to show extension not enabled ? */ bplmap = cs_data->bplmap; /* New total of non-bitmap blocks will be number of current, non-bitmap blocks, plus new blocks desired * There are (bplmap - 1) non-bitmap blocks per bitmap, so add (bplmap - 2) to number of non-bitmap blocks * and divide by (bplmap - 1) to get total number of bitmaps for expanded database. (must round up in this * manner as every non-bitmap block must have an associated bitmap) * Current number of bitmaps is (total number of current blocks + bplmap - 1) / bplmap. * Subtract current number of bitmaps from number needed for expanded database to get number of new bitmaps needed. */ new_bit_maps = DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, bplmap) + blocks, bplmap - 1) - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, bplmap); new_blocks = blocks + new_bit_maps; assert(0 < (int)new_blocks); if (new_blocks + cs_data->trans_hist.total_blks > MAXTOTALBLKS(cs_data)) { assert(FALSE); send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(1) ERR_TOTALBLKMAX); return (uint4)(NO_FREE_SPACE); } if (0 != (save_errno = disk_block_available(udi->fd, &avail_blocks, FALSE))) { send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); rts_error_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); } else { if (!(gtmDebugLevel & GDL_IgnoreAvailSpace)) { /* Bypass this space check if debug flag above is on. Allows us to create a large sparce DB * in space it could never fit it if wasn't sparse. Needed for some tests. */ avail_blocks = avail_blocks / (cs_data->blk_size / DISK_BLOCK_SIZE); if ((blocks * EXTEND_WARNING_FACTOR) > avail_blocks) { if (blocks > (uint4)avail_blocks) { SETUP_THREADGBL_ACCESS; if (!INST_FREEZE_ON_NOSPC_ENABLED(cs_addrs)) return (uint4)(NO_FREE_SPACE); else send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(6) MAKE_MSG_WARNING(ERR_NOSPACEEXT), 4, DB_LEN_STR(gv_cur_region), new_blocks, (uint4)avail_blocks); } else send_msg_csa(CSA_ARG(cs_addrs) VARLSTCNT(5) ERR_DSKSPACEFLOW, 3, DB_LEN_STR(gv_cur_region), (uint4)(avail_blocks - ((new_blocks <= avail_blocks) ? new_blocks : 0))); } } } /* From here on, we need to use GDSFILEXT_CLNUP before returning to the caller */ was_crit = cs_addrs->now_crit; assert(!cs_addrs->hold_onto_crit || was_crit); /* If we are coming from mupip_extend (which gets crit itself) we better have waited for any unfreezes to occur. * If we are coming from online rollback (when that feature is available), we will come in holding crit and in * the final retry. In that case too, we expect to have waited for unfreezes to occur in the caller itself. * Therefore if we are coming in holding crit from MUPIP, we expect the db to be unfrozen so no need to wait for * freeze. * If we are coming from GT.M and final retry (in which case we come in holding crit) we expect to have waited * for any unfreezes (by invoking tp_crit_all_regions) to occur (TP or non-TP) before coming into this * function. However, there is one exception. In the final retry, if tp_crit_all_regions notices that * at least one of the participating regions did ONLY READs, it will not wait for any freeze on THAT region * to complete before grabbing crit. Later, in the final retry, if THAT region did an update which caused * op_tcommit to invoke bm_getfree->gdsfilext, then we would have come here with a frozen region on which * we hold crit. */ assert(!was_crit || !cs_data->freeze || (dollar_tlevel && (CDB_STAGNATE <= t_tries))); /* * If we are in the final retry and already hold crit, it is possible that csa->nl->wc_blocked is also set to TRUE * (by a concurrent process in phase2 which encountered an error in the midst of commit and secshr_db_clnup * finished the job for it). In this case we do NOT want to invoke wcs_recover as that will update the "bt" * transaction numbers without correspondingly updating the history transaction numbers (effectively causing * a cdb_sc_blkmod type of restart). Therefore do NOT call grab_crit (which unconditionally invokes wcs_recover) * if we already hold crit. */ if (!was_crit) { for ( ; ; ) { grab_crit(gv_cur_region); if (!cs_data->freeze && !IS_REPL_INST_FROZEN) break; rel_crit(gv_cur_region); while (cs_data->freeze || IS_REPL_INST_FROZEN) hiber_start(1000); } } else if (cs_data->freeze && dollar_tlevel) { /* We don't want to continue with file extension as explained above. Hence return with an error code which * op_tcommit will recognize (as a cdb_sc_needcrit/cdb_sc_instancefreeze type of restart) and restart accordingly. */ assert(CDB_STAGNATE <= t_tries); GDSFILEXT_CLNUP; return (uint4)FINAL_RETRY_FREEZE_PROG; } if (IS_REPL_INST_FROZEN && trans_in_prog) { assert(CDB_STAGNATE <= t_tries); GDSFILEXT_CLNUP; return (uint4)FINAL_RETRY_INST_FREEZE; } assert(cs_addrs->ti->total_blks == cs_data->trans_hist.total_blks); old_total = cs_data->trans_hist.total_blks; if (old_total != filesize) { /* Somebody else has already extended it, since we are in crit, this is trust-worthy. However, in case of MM, * we still need to remap the database */ assert((old_total > filesize) GTM_TRUNCATE_ONLY( || !is_mm)); /* For BG, someone else could have truncated or extended - we have no idea */ GDSFILEXT_CLNUP; return (SS_NORMAL); }
/* * ------------------------------------------ * Hang the process for a specified time. * * Goes to sleep for a positive value. * Any caught signal will terminate the sleep * following the execution of that signal's catching routine. * * The actual hang duration should be NO LESS than the specified * duration for specified durations greater than .001 seconds. * Certain applications depend on this assumption. * * Arguments: * num - time to sleep * * Return: * none * ------------------------------------------ */ void op_hang(mval* num) { int ms; double tmp; mv_stent *mv_zintcmd; ABS_TIME cur_time, end_time; # ifdef VMS uint4 time[2]; int4 efn_mask, status; # endif DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; ms = 0; MV_FORCE_NUM(num); if (num->mvtype & MV_INT) { if (0 < num->m[1]) { assert(MV_BIAS >= 1000); /* if formats change overflow may need attention */ ms = num->m[1] * (1000 / MV_BIAS); } } else if (0 == num->sgn) /* if sign is not 0 it means num is negative */ { tmp = mval2double(num) * (double)1000; ms = ((double)MAXPOSINT4 >= tmp) ? (int)tmp : (int)MAXPOSINT4; } if (ms) { if (TREF(tpnotacidtime) * 1000 < ms) TPNOTACID_CHECK(HANGSTR); # if defined(DEBUG) && defined(UNIX) if (WBTEST_ENABLED(WBTEST_DEFERRED_TIMERS) && (3 > gtm_white_box_test_case_count) && (123000 == ms)) { DEFER_INTERRUPTS(INTRPT_NO_TIMER_EVENTS); DBGFPF((stderr, "OP_HANG: will sleep for 20 seconds\n")); LONG_SLEEP(20); DBGFPF((stderr, "OP_HANG: done sleeping\n")); ENABLE_INTERRUPTS(INTRPT_NO_TIMER_EVENTS); return; } if (WBTEST_ENABLED(WBTEST_BREAKMPC)&& (0 == gtm_white_box_test_case_count) && (999 == ms)) { frame_pointer->old_frame_pointer->mpc = (unsigned char *)GTM64_ONLY(0xdeadbeef12345678) NON_GTM64_ONLY(0xdead1234); return; } if (WBTEST_ENABLED(WBTEST_UTIL_OUT_BUFFER_PROTECTION) && (0 == gtm_white_box_test_case_count) && (999 == ms)) { /* Upon seeing a .999s hang this white-box test launches a timer that pops with a period of * UTIL_OUT_SYSLOG_INTERVAL and prints a long message via util_out_ptr. */ start_timer((TID)&util_out_syslog_dump, UTIL_OUT_SYSLOG_INTERVAL, util_out_syslog_dump, 0, NULL); return; } # endif sys_get_curr_time(&cur_time); mv_zintcmd = find_mvstent_cmd(ZINTCMD_HANG, restart_pc, restart_ctxt, FALSE); if (!mv_zintcmd) add_int_to_abs_time(&cur_time, ms, &end_time); else { end_time = mv_zintcmd->mv_st_cont.mvs_zintcmd.end_or_remain; cur_time = sub_abs_time(&end_time, &cur_time); /* get remaing time to sleep */ if (0 <= cur_time.at_sec) ms = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000); else ms = 0; /* all done */ /* restore/pop previous zintcmd_active[ZINTCMD_HANG] hints */ TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_prior; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_ctxt_prior; TAREF1(zintcmd_active, ZINTCMD_HANG).count--; assert(0 <= TAREF1(zintcmd_active, ZINTCMD_HANG).count); if (mv_chain == mv_zintcmd) POP_MV_STENT(); /* just pop if top of stack */ else { /* flag as not active */ mv_zintcmd->mv_st_cont.mvs_zintcmd.command = ZINTCMD_NOOP; mv_zintcmd->mv_st_cont.mvs_zintcmd.restart_pc_check = NULL; } if (0 == ms) return; /* done HANGing */ } # ifdef UNIX if (ms < 10) SLEEP_USEC(ms * 1000, TRUE); /* Finish the sleep if it is less than 10ms. */ else hiber_start(ms); # elif defined(VMS) time[0] = -time_low_ms(ms); time[1] = -time_high_ms(ms) - 1; efn_mask = (1 << efn_outofband | 1 << efn_timer); if (SS$_NORMAL != (status = sys$setimr(efn_timer, &time, NULL, &time, 0))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$setimr"), CALLFROM, status); if (SS$_NORMAL != (status = sys$wflor(efn_outofband, efn_mask))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$wflor"), CALLFROM, status); if (outofband) { if (SS$_WASCLR == (status = sys$readef(efn_timer, &efn_mask))) { if (SS$_NORMAL != (status = sys$cantim(&time, 0))) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("$cantim"), CALLFROM, status); } else assertpro(SS$_WASSET == status); } # endif } else rel_quant(); if (outofband) { PUSH_MV_STENT(MVST_ZINTCMD); mv_chain->mv_st_cont.mvs_zintcmd.end_or_remain = end_time; mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_check = restart_ctxt; mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_check = restart_pc; /* save current information from zintcmd_active */ mv_chain->mv_st_cont.mvs_zintcmd.restart_ctxt_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last; mv_chain->mv_st_cont.mvs_zintcmd.restart_pc_prior = TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_pc_last = restart_pc; TAREF1(zintcmd_active, ZINTCMD_HANG).restart_ctxt_last = restart_ctxt; TAREF1(zintcmd_active, ZINTCMD_HANG).count++; mv_chain->mv_st_cont.mvs_zintcmd.command = ZINTCMD_HANG; outofband_action(FALSE); } return; }
bool io_open_try(io_log_name *naml, io_log_name *tl, mval *pp, int4 timeout, mval *mspace) { char buf1[MAX_TRANS_NAME_LEN]; /* buffer to hold translated name */ char dev_type[MAX_DEV_TYPE_LEN]; int n; mstr tn; /* translated name */ uint4 stat; /* status */ int p_offset; unsigned char ch; ABS_TIME cur_time, end_time; bool out_of_time = FALSE; if (0 == naml->iod) { if (0 == tl->iod) { tl->iod = (io_desc *)malloc(SIZEOF(io_desc)); memset((char*)tl->iod, 0, SIZEOF(io_desc)); tl->iod->pair.in = tl->iod; tl->iod->pair.out = tl->iod; tl->iod->trans_name = tl; p_offset = 0; while (iop_eol != *(pp->str.addr + p_offset)) { if ((iop_tmpmbx == (ch = *(pp->str.addr + p_offset++))) || (iop_prmmbx == ch)) tl->iod->type = mb; else if (iop_nl == ch) tl->iod->type = nl; p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } if (!tl->iod->type && mspace && mspace->str.len) { lower_to_upper(dev_type, mspace->str.addr, mspace->str.len); if (((SIZEOF("SOCKET") - 1) == mspace->str.len) && (0 == memcmp(dev_type, LIT_AND_LEN("SOCKET")))) tl->iod->type = gtmsocket; else tl->iod->type = us; } if (!tl->iod->type) { tn.len = tl->len; tn.addr = &tl->dollar_io; tl->iod->type = io_type(&tn); } } naml->iod = tl->iod; } tl->iod->disp_ptr = &io_dev_dispatch[tl->iod->type]; assert(0 != naml->iod); active_device = naml->iod; if (dev_never_opened == naml->iod->state) { naml->iod->wrap = DEFAULT_IOD_WRAP; naml->iod->width = DEFAULT_IOD_WIDTH; naml->iod->length = DEFAULT_IOD_LENGTH; naml->iod->write_filter = write_filter; } if (dev_open != naml->iod->state) { naml->iod->dollar.x = 0; naml->iod->dollar.y = 0; naml->iod->dollar.za = 0; naml->iod->dollar.zb[0] = 0; naml->iod->dollar.zeof = FALSE; } if (0 == timeout) stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout); /* ZY: add a parameter timeout */ else if (NO_M_TIMEOUT == timeout) { while (FALSE == (stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout))) /* ZY: add timeout */ { hiber_start(1000); /* 1 second */ if (outofband) outofband_action(FALSE); } } else { sys_get_curr_time(&cur_time); add_int_to_abs_time(&cur_time, timeout * 1000, &end_time); while (FALSE == (stat = (naml->iod->disp_ptr->open)(naml, pp, -1, mspace, timeout)) /* ZY: add timeout */ && (!out_of_time)) { hiber_start(1000); /* 1 second */ if (outofband) outofband_action(FALSE); sys_get_curr_time(&cur_time); if (abs_time_comp(&end_time, &cur_time) <= 0) out_of_time = TRUE; } } if (TRUE == stat) { naml->iod->state = dev_open; if (27 == naml->iod->trans_name->dollar_io[0]) { tn.addr = &naml->iod->trans_name->dollar_io[4]; n = naml->iod->trans_name->len - 4; if (n < 0) n = 0; tn.len = n; naml->iod->trans_name = get_log_name(&tn, INSERT); naml->iod->trans_name->iod = naml->iod; } } else { if (dev_open == naml->iod->state && (gtmsocket != naml->iod->type)) naml->iod->state = dev_closed; else if ((gtmsocket == naml->iod->type) && naml->iod->newly_created) { assert(naml->iod->state != dev_open); iosocket_destroy(naml->iod); } } active_device = 0; if ((NO_M_TIMEOUT != timeout) && IS_MCODE_RUNNING) return (stat); return FALSE; }
uint4 gdsfilext (uint4 blocks, uint4 filesize) { sm_uc_ptr_t old_base[2]; boolean_t was_crit, need_to_restore_mask = FALSE; char *buff; int mm_prot, result, save_errno, status; uint4 new_bit_maps, bplmap, map, new_blocks, new_total, max_tot_blks; uint4 jnl_status, to_wait, to_msg, wait_period; GTM_BAVAIL_TYPE avail_blocks; sgmnt_data_ptr_t tmp_csd; off_t new_eof; trans_num curr_tn; unix_db_info *udi; sigset_t savemask; inctn_opcode_t save_inctn_opcode; int4 prev_extend_blks_to_upgrd; jnl_private_control *jpc; jnl_buffer_ptr_t jbp; error_def(ERR_DBFILERR); error_def(ERR_DBFILEXT); error_def(ERR_DSKSPACEFLOW); error_def(ERR_JNLFLUSH); error_def(ERR_TEXT); error_def(ERR_TOTALBLKMAX); error_def(ERR_WAITDSKSPACE); #ifdef __hppa if (dba_mm == cs_addrs->hdr->acc_meth) return (uint4)(NO_FREE_SPACE); /* should this be changed to show extension not allowed ? */ #endif /* Both blocks and total blocks are unsigned ints so make sure we aren't asking for huge numbers that will overflow and end up doing silly things. */ assert(blocks <= (MAXTOTALBLKS(cs_data) - cs_data->trans_hist.total_blks)); if (!blocks) return (uint4)(NO_FREE_SPACE); /* should this be changed to show extension not enabled ? */ bplmap = cs_data->bplmap; /* new total of non-bitmap blocks will be number of current, non-bitmap blocks, plus new blocks desired There are (bplmap - 1) non-bitmap blocks per bitmap, so add (bplmap - 2) to number of non-bitmap blocks and divide by (bplmap - 1) to get total number of bitmaps for expanded database. (must round up in this manner as every non-bitmap block must have an associated bitmap) Current number of bitmaps is (total number of current blocks + bplmap - 1) / bplmap. Subtract current number of bitmaps from number needed for expanded database to get number of new bitmaps needed. */ new_bit_maps = DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, bplmap) + blocks, bplmap - 1) - DIVIDE_ROUND_UP(cs_data->trans_hist.total_blks, bplmap); new_blocks = blocks + new_bit_maps; assert(0 < (int)new_blocks); udi = FILE_INFO(gv_cur_region); if (0 != (save_errno = disk_block_available(udi->fd, &avail_blocks, FALSE))) { send_msg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); rts_error(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); } else { avail_blocks = avail_blocks / (cs_data->blk_size / DISK_BLOCK_SIZE); if ((blocks * EXTEND_WARNING_FACTOR) > avail_blocks) { send_msg(VARLSTCNT(5) ERR_DSKSPACEFLOW, 3, DB_LEN_STR(gv_cur_region), (uint4)(avail_blocks - ((new_blocks <= avail_blocks) ? new_blocks : 0))); #ifndef __MVS__ if (blocks > (uint4)avail_blocks) return (uint4)(NO_FREE_SPACE); #endif } } cs_addrs->extending = TRUE; was_crit = cs_addrs->now_crit; /* If we are coming from mupip_extend (which gets crit itself) we better have waited for any unfreezes to occur */ assert(!was_crit || CDB_STAGNATE == t_tries || FALSE == cs_data->freeze); for ( ; ; ) { /* If we are in the final retry and already hold crit, it is possible that csd->wc_blocked is also set to TRUE * (by a concurrent process in phase2 which encountered an error in the midst of commit and secshr_db_clnup * finished the job for it). In this case we do NOT want to invoke wcs_recover as that will update the "bt" * transaction numbers without correspondingly updating the history transaction numbers (effectively causing * a cdb_sc_blkmod type of restart). Therefore do NOT call grab_crit (which unconditionally invokes wcs_recover) * if we already hold crit. */ if (!was_crit) grab_crit(gv_cur_region); if (FALSE == cs_data->freeze) break; rel_crit(gv_cur_region); if (was_crit) { /* Two cases. * (i) Final retry and in TP. We might be holding crit in other regions too. * We can't do a grab_crit() on this region again unless it is deadlock-safe. * To be on the safer side, we do a restart. The tp_restart() logic will wait * for this region's freeze to be removed before grabbing crit. * (ii) Final retry and not in TP. In that case too, it is better to restart in case there is * some validation code that shortcuts the checking for the final retry assuming we were * in crit from t_begin() to t_end(). t_retry() has logic that will wait for unfreeze. * In either case, we need to restart. Returning EXTEND_UNFREEZECRIT will cause one in t_end/tp_tend. */ return (uint4)(EXTEND_UNFREEZECRIT); } while (cs_data->freeze) hiber_start(1000); } assert(cs_addrs->ti->total_blks == cs_data->trans_hist.total_blks); if (cs_data->trans_hist.total_blks != filesize) { /* somebody else has already extended it, since we are in crit, this is trust-worthy * however, in case of MM, we still need to remap the database */ assert(cs_data->trans_hist.total_blks > filesize); GDSFILEXT_CLNUP; return (SS_NORMAL); } if (run_time && (2 * ((0 < dollar_tlevel) ? sgm_info_ptr->cw_set_depth : cw_set_depth) < cs_addrs->ti->free_blocks)) { if (FALSE == was_crit) { rel_crit(gv_cur_region); return (uint4)(EXTEND_SUSPECT); } /* If free_blocks counter is not ok, then correct it. Do the check again. If still fails, then GTMASSERT. */ if (is_free_blks_ctr_ok() || (2 * ((0 < dollar_tlevel) ? sgm_info_ptr->cw_set_depth : cw_set_depth) < cs_addrs->ti->free_blocks)) GTMASSERT; /* held crit through bm_getfree into gdsfilext and still didn't get it right */ } if (JNL_ENABLED(cs_data)) { if (!jgbl.dont_reset_gbl_jrec_time) SET_GBL_JREC_TIME; /* needed before jnl_ensure_open as that can write jnl records */ jpc = cs_addrs->jnl; jbp = jpc->jnl_buff; /* Before writing to jnlfile, adjust jgbl.gbl_jrec_time if needed to maintain time order * of jnl records. This needs to be done BEFORE the jnl_ensure_open as that could write * journal records (if it decides to switch to a new journal file). */ ADJUST_GBL_JREC_TIME(jgbl, jbp); jnl_status = jnl_ensure_open(); if (jnl_status) { GDSFILEXT_CLNUP; send_msg(VARLSTCNT(6) jnl_status, 4, JNL_LEN_STR(cs_data), DB_LEN_STR(gv_cur_region)); return (uint4)(NO_FREE_SPACE); /* should have better return status */ } } if (dba_mm == cs_addrs->hdr->acc_meth) { #if defined(UNTARGETED_MSYNC) status = msync((caddr_t)cs_addrs->db_addrs[0], (size_t)(cs_addrs->db_addrs[1] - cs_addrs->db_addrs[0]), MS_SYNC); #else cs_addrs->nl->mm_extender_pid = process_id; status = wcs_wtstart(gv_cur_region, 0); cs_addrs->nl->mm_extender_pid = 0; if (0 != cs_addrs->acc_meth.mm.mmblk_state->mmblkq_active.fl) GTMASSERT; status = 0; #endif if (0 == status) { /* Block SIGALRM for the duration when cs_data and cs_addrs are out of sync */ sigprocmask(SIG_BLOCK, &blockalrm, &savemask); need_to_restore_mask = TRUE; tmp_csd = cs_data; cs_data = (sgmnt_data_ptr_t)malloc(sizeof(*cs_data)); memcpy((sm_uc_ptr_t)cs_data, (uchar_ptr_t)tmp_csd, sizeof(*cs_data)); status = munmap((caddr_t)cs_addrs->db_addrs[0], (size_t)(cs_addrs->db_addrs[1] - cs_addrs->db_addrs[0])); #ifdef DEBUG_DB64 if (-1 != status) rel_mmseg((caddr_t)cs_addrs->db_addrs[0]); #endif } else tmp_csd = NULL; if (0 != status) { if (tmp_csd) { free(cs_data); cs_data = tmp_csd; } GDSFILEXT_CLNUP; send_msg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), status); return (uint4)(NO_FREE_SPACE); } cs_addrs->hdr = cs_data; cs_addrs->ti = &cs_data->trans_hist; } if (new_blocks + cs_data->trans_hist.total_blks > MAXTOTALBLKS(cs_data)) { GDSFILEXT_CLNUP; send_msg(VARLSTCNT(1) ERR_TOTALBLKMAX); return (uint4)(NO_FREE_SPACE); } CHECK_TN(cs_addrs, cs_data, cs_data->trans_hist.curr_tn); /* can issue rts_error TNTOOLARGE */ assert(0 < (int)new_blocks); new_total = cs_data->trans_hist.total_blks + new_blocks; new_eof = ((off_t)(cs_data->start_vbn - 1) * DISK_BLOCK_SIZE) + ((off_t)new_total * cs_data->blk_size); buff = (char *)malloc(DISK_BLOCK_SIZE); memset(buff, 0, DISK_BLOCK_SIZE); LSEEKWRITE(udi->fd, new_eof, buff, DISK_BLOCK_SIZE, save_errno); if ((ENOSPC == save_errno) && run_time) { /* try to write it every second, and send message to operator * log every 1/20 of cs_data->wait_disk_space */ wait_period = to_wait = DIVIDE_ROUND_UP(cs_data->wait_disk_space, CDB_STAGNATE + 1); to_msg = (to_wait / 8) ? (to_wait / 8) : 1; /* send around 8 messages during 1 wait_period */ while ((to_wait > 0) && (ENOSPC == save_errno)) { if ((to_wait == cs_data->wait_disk_space) || (to_wait % to_msg == 0)) { send_msg(VARLSTCNT(11) ERR_WAITDSKSPACE, 4, process_id, to_wait + (CDB_STAGNATE - t_tries) * wait_period, DB_LEN_STR(gv_cur_region), ERR_TEXT, 2, RTS_ERROR_TEXT("Please make more disk space available or shutdown GT.M to avoid data loss"), save_errno); gtm_putmsg(VARLSTCNT(11) ERR_WAITDSKSPACE, 4, process_id, to_wait + (CDB_STAGNATE - t_tries) * wait_period, DB_LEN_STR(gv_cur_region), ERR_TEXT, 2, RTS_ERROR_TEXT("Please make more disk space available or shutdown GT.M to avoid data loss"), save_errno); } if (!was_crit) rel_crit(gv_cur_region); hiber_start(1000); to_wait--; if (!was_crit) grab_crit(gv_cur_region); LSEEKWRITE(udi->fd, new_eof, buff, DISK_BLOCK_SIZE, save_errno); } } free(buff); if (0 != save_errno) { GDSFILEXT_CLNUP; if (ENOSPC == save_errno) return (uint4)(NO_FREE_SPACE); send_msg(VARLSTCNT(5) ERR_DBFILERR, 2, DB_LEN_STR(gv_cur_region), save_errno); return (uint4)(NO_FREE_SPACE); } DEBUG_ONLY(prev_extend_blks_to_upgrd = cs_data->blks_to_upgrd;)
boolean_t iosocket_connect(socket_struct *socketptr, int4 timepar, boolean_t update_bufsiz) { int temp_1 = 1; char *errptr; int4 errlen, msec_timeout, real_errno; boolean_t no_time_left = FALSE; short len; d_socket_struct *dsocketptr; ABS_TIME cur_time, end_time; error_def(ERR_SOCKINIT); error_def(ERR_OPENCONN); error_def(ERR_TEXT); error_def(ERR_GETSOCKOPTERR); error_def(ERR_SETSOCKOPTERR); dsocketptr = socketptr->dev; assert(NULL != dsocketptr); dsocketptr->dollar_key[0] = '\0'; if (timepar != NO_M_TIMEOUT) { msec_timeout = timeout2msec(timepar); sys_get_curr_time(&cur_time); add_int_to_abs_time(&cur_time, msec_timeout, &end_time); } do { if (1 != temp_1) { tcp_routines.aa_close(socketptr->sd); } if (-1 == (socketptr->sd = tcp_routines.aa_socket(AF_INET, SOCK_STREAM, 0))) { errptr = (char *)STRERROR(errno); errlen = strlen(errptr); rts_error(VARLSTCNT(5) ERR_SOCKINIT, 3, errno, errlen, errptr); return FALSE; } temp_1 = 1; if (-1 == tcp_routines.aa_setsockopt(socketptr->sd, SOL_SOCKET, SO_REUSEADDR, &temp_1, sizeof(temp_1))) { errptr = (char *)STRERROR(errno); errlen = strlen(errptr); rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, RTS_ERROR_LITERAL("SO_REUSEADDR"), errno, errlen, errptr); return FALSE; } #ifdef TCP_NODELAY temp_1 = socketptr->nodelay ? 1 : 0; if (-1 == tcp_routines.aa_setsockopt(socketptr->sd, IPPROTO_TCP, TCP_NODELAY, &temp_1, sizeof(temp_1))) { errptr = (char *)STRERROR(errno); errlen = strlen(errptr); rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, RTS_ERROR_LITERAL("TCP_NODELAY"), errno, errlen, errptr); return FALSE; } #endif if (update_bufsiz) { if (-1 == tcp_routines.aa_setsockopt(socketptr->sd, SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, sizeof(socketptr->bufsiz))) { errptr = (char *)STRERROR(errno); errlen = strlen(errptr); rts_error(VARLSTCNT(7) ERR_SETSOCKOPTERR, 5, RTS_ERROR_LITERAL("SO_RCVBUF"), errno, errlen, errptr); return FALSE; } } else { temp_1 = sizeof(socketptr->bufsiz); if (-1 == tcp_routines.aa_getsockopt(socketptr->sd, SOL_SOCKET, SO_RCVBUF, &socketptr->bufsiz, &temp_1)) { errptr = (char *)STRERROR(errno); errlen = strlen(errptr); rts_error(VARLSTCNT(7) ERR_GETSOCKOPTERR, 5, RTS_ERROR_LITERAL("SO_RCVBUF"), errno, errlen, errptr); return FALSE; } } temp_1 = tcp_routines.aa_connect(socketptr->sd, (struct sockaddr *)&socketptr->remote.sin, sizeof(socketptr->remote.sin)); if (temp_1 < 0) { real_errno = errno; no_time_left = TRUE; switch (real_errno) { case ETIMEDOUT : /* the other side bound but not listening */ case ECONNREFUSED : if (NO_M_TIMEOUT != timepar) { sys_get_curr_time(&cur_time); cur_time = sub_abs_time(&end_time, &cur_time); if (cur_time.at_sec > 0) no_time_left = FALSE; } break; case EINTR : break; default: errptr = (char *)STRERROR(real_errno); errlen = strlen(errptr); rts_error(VARLSTCNT(6) ERR_OPENCONN, 0, ERR_TEXT, 2, errlen, errptr); break; } if (no_time_left) { return FALSE; } hiber_start(100); } } while (temp_1 < 0); /* handle the local information later. SPRINTF(socketptr->local.saddr_ip, "%s", tcp_routines.aa_inet_ntoa(socketptr->remote.sin.sin_addr)); socketptr->local.port = GTM_NTOHS(socketptr->remote.sin.sin_port); */ socketptr->state = socket_connected; /* update dollar_key */ len = sizeof(ESTABLISHED) - 1; memcpy(&dsocketptr->dollar_key[0], ESTABLISHED, len); dsocketptr->dollar_key[len++] = '|'; memcpy(&dsocketptr->dollar_key[len], socketptr->handle, socketptr->handle_len); len += socketptr->handle_len; dsocketptr->dollar_key[len++] = '|'; memcpy(&dsocketptr->dollar_key[len], socketptr->remote.saddr_ip, strlen(socketptr->remote.saddr_ip)); len += strlen(socketptr->remote.saddr_ip); dsocketptr->dollar_key[len] = '\0'; return TRUE; }
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--; } } }