#!/usr/bin/env bash
#==============================================================================
# 18화 실습 (07) — 온라인과 배치를 같은 시간에 네 판 (Git Bash)          소요 약 MIN × 4 + 1 분 (기본 21분)
#
#   먼저 한 번 : 07a_리소스플랜_만들기_SYSDBA.sql (플랜 · 그룹 · 매핑 · 배치 기록 표)
#   쓰는 법 (이 폴더에서) : ./07_격리_세_판.sh                 (컨테이너를 바꾸려면 C=… · 판 길이는 MIN=…)
#
#   판 A  C18-RM-A  온라인만            — 부하 발생기 2세션 · 생각 시간 0 · P1 은 뺀다 (화면 다섯 조각만)
#   판 B  C18-RM-B  온라인 + 배치 둘     — 같은 온라인 + 07_배치_일꾼 2개 (월마감 집계) · 이 PDB 의 원래 플랜(DEFAULT_PLAN) 그대로
#   판 C  C18-RM-C  온라인 + 배치 둘     — 판 B 와 같고 PDB 에 C18_DAYTIME_PLAN 을 켠다 (온라인 90 · 배치 10 — 우선순위)
#   판 D  C18-RM-D  온라인 + 배치 둘     — C18_CAP_PLAN (위에 더해 배치 utilization_limit 10 — 상한)
#   끝나면 플랜을 원래 돌던 DEFAULT_PLAN 으로 되돌리고 07c_격리_결과.sql 을 돌린다.
#   플랜은 메모리에서만 바꾼다 (SCOPE = MEMORY) — 컨테이너를 다시 띄우면 처음 상태로 돌아온다.
#   ⚠️ 빈 값('')으로 끄지 마라 — 이 PDB 가 원래 돌리던 DEFAULT_PLAN 이 아니라 INTERNAL_PLAN 이 된다 (실측 · 2_파고들기 §7.4)
#
#   ⚠️ CPU 2개짜리 Free 다. 판 B · C 는 일하는 세션이 넷이라 CPU 를 넘친다 — 그게 이 실험이다.
#   ⚠️ 중간에 Ctrl+C 로 끊었으면 반드시 플랜을 끈다 :
#        echo "ALTER SESSION SET CONTAINER = FREEPDB1; ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = 'DEFAULT_PLAN' SCOPE = MEMORY;" | MSYS_NO_PATHCONV=1 docker exec -i ora-hanorder sqlplus -s / as sysdba
#==============================================================================
set -u
C="${C:-ora-hanorder}"
MIN="${MIN:-5}"
HERE="$(cd "$(dirname "$0")" && pwd)"
L1="$HERE/../../00_자료준비/고객사/L1_ora-hanorder"
LOG="${LOGDIR:-${TMPDIR:-/tmp}/c18_logs}"
mkdir -p "$LOG"
ONLINE_W="Q1=30,Q2=5,Q3=10,Q4=40,N1=14,P1=0"

SYS()  { MSYS_NO_PATHCONV=1 docker exec -i "$C" sqlplus -s / as sysdba; }
SQLP() { docker exec -i "$C" sqlplus -s sqlp/sqlp@localhost/FREEPDB1; }

plan() {
SYS <<SQL
SET FEEDBACK OFF HEADING OFF
ALTER SESSION SET CONTAINER = FREEPDB1;
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN = '$1' SCOPE = MEMORY;
SELECT 'resource_manager_plan = [' || value || ']  running = ' || (SELECT name FROM v\$rsrc_plan WHERE is_top_plan = 'TRUE') FROM v\$parameter WHERE name = 'resource_manager_plan';
EXIT
SQL
}

phase() {
  local note="$1" batch="$2" pl="$3"
  echo "== $note  batch=$batch  plan=[$pl]  ($(date +%H:%M:%S))"
  plan "$pl"
  ( cd "$L1" && PROFILE=STEADY MINUTES="$MIN" SESSIONS=2 THINK_MS=0 WEIGHTS="$ONLINE_W" NOTE="$note" C="$C" ./05_부하_돌리기.sh > "$LOG/$note.run.log" 2>&1 ) &
  local drv=$!
  local w=""
  if [ "$batch" = "1" ]; then
    # 발사기가 START_RUN 을 마치고 세션을 띄울 시간을 준다 (부하 발생기 세션은 포스트잇 3,000 장을 먼저 모은다)
    for i in 1 2 3 4 5 6 7 8 9 10; do
      n=$(echo "SET HEADING OFF FEEDBACK OFF
SELECT COUNT(*) FROM v\$session WHERE module = 'LOAD_DRIVER';
EXIT" | SQLP | tr -d '[:space:]')
      [ "${n:-0}" -ge 2 ] 2>/dev/null && break
      sleep 1
    done
    for k in 1 2; do
      { echo "DEFINE minutes=$MIN"; echo "DEFINE note=$note"; echo "DEFINE worker=$k"; cat "$HERE/07_배치_일꾼.sql"; } | SQLP > "$LOG/$note.worker$k.log" 2>&1 &
      w="$w $!"
    done
  fi
  if [ "$pl" != "DEFAULT_PLAN" ]; then
    sleep 20
    echo "-- 세션이 어느 그룹에 있나 (20초째)"
    SYS <<'SQL'
SET LINESIZE 160 PAGESIZE 50 FEEDBACK OFF
COL module FORMAT A14
COL resource_consumer_group FORMAT A18
ALTER SESSION SET CONTAINER = FREEPDB1;
SELECT module, resource_consumer_group, COUNT(*) AS sessions FROM v$session
 WHERE username = 'SQLP' AND module IN ('LOAD_DRIVER', 'MONTH_CLOSE') GROUP BY module, resource_consumer_group ORDER BY 1;
EXIT
SQL
  fi
  wait $drv
  for p in $w; do wait "$p"; done
  if [ "$pl" != "DEFAULT_PLAN" ]; then
    echo "-- V\$RSRC_CONSUMER_GROUP (그 플랜을 켠 뒤 누적 · 판이 끝난 직후)"
    SYS <<'SQL'
SET LINESIZE 200 PAGESIZE 50 FEEDBACK OFF
COL name FORMAT A16
ALTER SESSION SET CONTAINER = FREEPDB1;
SELECT name, ROUND(consumed_cpu_time / 1000) AS cpu_s, ROUND(cpu_wait_time / 1000) AS cpu_wait_s, cpu_waits, yields
  FROM v$rsrc_consumer_group WHERE name IN ('C18_ONLINE_GRP', 'C18_BATCH_GRP', 'OTHER_GROUPS') ORDER BY name;
EXIT
SQL
  fi
  grep -E "^session|ORA-" "$LOG/$note.run.log" | head -5
}

phase C18-RM-A 0 "DEFAULT_PLAN"
phase C18-RM-B 1 "DEFAULT_PLAN"
phase C18-RM-C 1 "C18_DAYTIME_PLAN"
phase C18-RM-D 1 "C18_CAP_PLAN"
echo "== 플랜을 이 PDB 가 원래 돌리던 DEFAULT_PLAN 으로 (빈 값으로 끄면 INTERNAL_PLAN 이 된다)"
plan "DEFAULT_PLAN"
echo "== 결과 (07c)"
SQLP < "$HERE/07c_격리_결과.sql"
echo "== 로그 : $LOG"
