/****************************************************************************
  module      : vkb81
  author      : JuergenA,UweH
  responsible : UweH
  special area: Restart
  see also    :
  description : restart functions of DataAccess components
 
    ========== licence begin  GPL
    Copyright (C) 2001 SAP AG
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end
 
*****************************************************************************/
 
.tt 1 $SAP$LiveCache$VKB81$
.tt 3 $UweH$KB_restart$2000-11-23$
 
Module  : KB_restart
 
Define  :
 
        PROCEDURE
              k81local_restart (VAR t      : tgg00_TransContext;
                    until_date             : tsp00_Date;
                    until_time             : tsp00_Time;
                    is_restore_log         : boolean;
                    activate_state         : tgg00_MessType2;
                    VAR predecessorVersion : tsp00_Version);
 
        PROCEDURE
              k81restart_handling (VAR t  : tgg00_TransContext;
                    is_restore_log        : boolean;
                    until_date            : tsp00_Date;
                    until_time            : tsp00_Time);
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              KB_init_config : VKB06;
 
        PROCEDURE
              k06linit_local_site (VAR t : tgg00_TransContext);
 
        PROCEDURE
              k06termset_init (VAR t : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              KB_locklist : VKB51;
 
        PROCEDURE
              k51restart_locklist (VAR t : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              KB_Logging : VKB560;
 
        PROCEDURE
              kb560InitLogForRestart (TaskId : tsp00_TaskId;
                    VAR TrError : tgg00_BasisError);
 
        PROCEDURE
              kb560StartGCAndWaitForNoHistoryExists (VAR Trans : tgg00_TransContext);
 
        PROCEDURE
              kb560InitLogForRestore (TaskId : tsp00_TaskId;
                    VAR TrError : tgg00_BasisError);
 
      ------------------------------ 
 
        FROM
              KB_restart_record : VKB57;
 
        VAR
              k57restartrec : tkb00_PagePtr;
 
        PROCEDURE
              k57save_restartrecord (TaskId : tsp00_TaskId);
 
      ------------------------------ 
 
        FROM
              KB_RedoManager_interface : VKB811;
 
        PROCEDURE
              kb811ForceOffline (taskid : tsp00_TaskId;
                    error : tgg00_BasisError);
 
        PROCEDURE
              kb811RedoManager (
                    VAR TransContext : tgg00_TransContext;
                    untilDate    : tsp00_Int4;
                    untilTime    : tsp00_Int4;
                    restoreLog   : boolean);
 
      ------------------------------ 
 
        FROM
              KB_sender_receiver : VKB90;
 
        PROCEDURE
              k90init_server_manager (procid : tsp00_TaskId);
 
        PROCEDURE
              k90wait_until_server_finished (procid : tsp00_TaskId);
 
      ------------------------------ 
 
        FROM
              filesysteminterface_1 : VBD01;
 
        PROCEDURE
              bd01CreateCoordinator (VAR t : tgg00_TransContext;
                    VAR FileId : tgg00_FileId;
                    MessType   : tgg00_MessType);
 
        PROCEDURE
              b01end_read_only (VAR t : tgg00_TransContext);
 
        PROCEDURE
              b01filestate (VAR t : tgg00_TransContext;
                    VAR file_id : tgg00_FileId);
 
        PROCEDURE
              b01restart_filesystem (VAR t : tgg00_TransContext;
                    IncrementConvVersion : boolean);
 
      ------------------------------ 
 
        FROM
              error_text_handling : VBD06;
 
        PROCEDURE
              b06create_errortext_file (VAR t : tgg00_TransContext);
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01restart_local       : boolean;
              g01tabid               : tgg_tabid_globals;
              g01ignore_rootid_check : boolean; (* PTS 1114877 UH 2002-03-18 *)
 
        FUNCTION
              g01is_livecache : boolean;
 
        PROCEDURE
              g01optextmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp_int4;
                    msg_label : tsp_c8;
                    msg_text  : tsp_c40);
 
      ------------------------------ 
 
        FROM
              Codetransformation_and_Coding : VGG02;
 
        PROCEDURE
              g02date_time_to_int (
                    date_str     : tsp_date;
                    time_str     : tsp_time;
                    VAR date_int : tsp_int4;
                    VAR time_int : tsp_int4);
 
      ------------------------------ 
 
        FROM
              Regions_and_Longwaits : VGG08;
 
        VAR
              g08server : tsp00_RegionId;
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vbegexcl (pid : tsp_process_id;
                    region  : tsp_region_id);
 
        PROCEDURE
              vendexcl (pid : tsp_process_id;
                    region  : tsp_region_id);
 
        PROCEDURE
              vxparam_save_good_config (
                    is_restart  : boolean;
                    VAR errtext : tsp_errtext;
                    VAR xp_ret  : tsp_xp_return_code);
&       ifdef TRACE
 
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01basis_error (debug : tgg00_Debug;
                    nam   : tsp00_Sname;
                    b_err : tgg00_BasisError);
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenA
.sp
.cp 3
Created : 1980-06-10
.sp
.cp 3
Version : 2002-09-12
.sp
.cp 3
Release :      Date : 2000-11-23
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
.sp
Some HISTORICAL RELICTS of 1979:
.sp
"In a distributed environment that allows subset redundancy,
an additional consistency condition arises. According to this
condition, all copies of a subset must have the same contents, i.e.
a subset that is stored in more than one computer must show the
same update version in each computer.  If this is not the case,
this is known as an external consistency violation".
.sp
"First a check is run to determine whether the contents match the
restart_record.  If yes, it is most probably a matter of
the operating modes of a computer being switched over from
'connect' to 'disconnect' or vice versa or of the entire system
being switched off (SHUTDOWN). When a system is changed over or switched
off, a checkpoint is always written.  Since no additional log pages
follow the checkpoint, no transactions are processed again".
.sp
"In the case of a distribution, LOGGING is activated before the
copy adjustment.  In addition, a PRE_PARTIAL_TRANS_CHECKPOINT
(proc. WRITE.. ] is written before the copy adjustment.
The appropriate procedure briefly activates/deactivates the
CHECKPOINTING for this purpose".
.sp
End HISTORICAL RELICTS.
.sp 4
Actions that bring about the restart of a computer must maintain
the consistency of the serverdb. They must guarantee that the
serverdb, which was in a consistent state before the crash, is
also placed in a consistent state after the restart. This condition
must be fulfilled regardless of whether or not the computer is located
in a distributed environment. An inconsistency in user data can
be the result of a crash while transactions were running and
of the interconnection of buffers in the base layer. For this reason,
when buffering in the BD layer, it must be guaranteed at all times
that no B*tree pointers point 'nowhere'.  However, this does not yet
mean that the BD layer guarantees that operations at a record and file
level that occured before the last file-system checkpoint are
written on the disk.
.sp 3;.cp 5
Procedure K
 
.sp
Main local restart procedure.
.br
.sp 1
After the system parameters have been initialized, the file system,
is restarted, locklist, logcache, logqueue, dialogcache, netserver,
sitemap, and restart page are reset.
.br
The variables RST_LAST_ROOT_VERIFY, RST_LAST_LEAF_VERIFY
and RST_LAST_TREE_VERIFY in the restart record indicate whether
a crash during a previous restart has left the BD-structures in an
inconsistent state. In this case repair procedures are called.
.br
The log is scanned, starting from RST_LOG_FIRST_USED until the
last log page is found. The 'last log page' is
defined as the last page whose log page number is the last to follow the
numerical sequence and whose log-page mode does not yet show 'unused'.
.br
K56LPNO_LASTLOG is determined implicitly by K56RESTART_LOG.
.br
If the last log page contains the current checkpoint (as specified
within the restart record) then the restart is complete, otherwise
KB81REDO_LOG does the rollforward/rollback-handling and writes
a new checkpoint.
.br
Errors that are detected during rollforward/rollback are classified
into two cases:
.in +3;.un 3
1. ignorable errors
.br
They increment the ERROR COUNT without aborting the restart (example:
index errors). The restart reports KB_RESTART_INCOMPLETE, to inform
the user that irregularities have occured. The system
remains in cold mode. A follow up restart will generally
succeed however.
.un 3
2. fatal errors
.br
The restart is aborted immediately, the specific error is reported
to the user. The system remains in cold mode and can generally not
be restarted by repetition of the command.
.sp
.in -3
The variable G01RESTART_LOCAL remains true if the rollforward part
of the local restart decided that the environment is distributed
(G01STAND_ALONE=false). In this case VAK36 triggers a second K05 call
with MM_DISTRIBUTED performing the distributed restart. Within
K81DISTRIBUTED_RESTART the variable G01RESTART_LOCAL is set to false.
In a none dirtibuted environment G01RESTART_LOCAL is set to
false by VAK36.
.sp 2;.cp 5
Procedure KB81CHECK_LAST_VERIFY
.sp
Called when the restart record indicates that BD-structures may
be inconsistent due to a previous crash during restart.
The repair procedure B01TCHECK_TREE is invoked.
.sp 2;.cp 5
Procedure KB81ERROR_MSG
.sp
An errormsg is generated.
.sp 2;.cp 5
Procedure KB81FILESYSTEM_RESTART
.sp
The BD filesystem is restarted and the G01LOG variables are initialized.
.sp 2;.cp 5
Procedure KB81OP_MSG
.sp
Operator message on console.
.sp 2;.cp 5
Procedure KB81REDO_LOG
.sp
Called during the local serverdb restart, when a REDO has to be
performed (i.e. when the last logpage isn't the checkpoint in the
restart page).
.br
The starting point of the redo (REDO_START) is described within
the restart page. It may be a checkpoint or a savepoint (signalled
to K88ROLLFORWARD by USE_SAVEPOINT).
.br
The two following typical situations may be present at call time
of KB81REDO_LOG:
.br;.cp 10
.in +3;.un 3
A) Multiple RESTORE LOGS, each without redo (e.g. due to a
crash before the local restart).
.nf;.cp 8
 
 K57RESTARTREC^.LPNO
   |
   V
--------------------------------------------------------------
| CP1 |   .....   | CP2 |   .....   | CP3 |...................
--------------------------------------------------------------
    <--RESTORE LOG--> <--RESTORE LOG--> <--RESTORE LOG COLD-->
 
.fo;.cp 8
.un 3;B)
.nf;.sp
 K57RESTARTREC^.LPNO   K57RESTARTREC^.RST_SAVEPT_LPNO/LPOS
   |                     |
   V                     V
----------------------------------------------
| CP1 |  ...       | SAVEPOINT |..............
----------------------------------------------
.fo;.in -3
.sp
One execution of the REPEAT-loop covers the log between two
consecutive checkpoints.
The procedure K56LAST_LOG_BEFORE_CHECKP determines this distance.
.br
Then three phases process the log:
.in +3;.un 3
1. VERIFY phase
.br
 If the part of the log does not end with a checkpoint
(e.g. case B, above), then the VERIFY-NOVERIFY pairs are checked
to eliminate BD inconsistencies, before starting the redo.
.un 3
2. ROLLFORWARD phase
.br
Starting from a checkpoint or a savepoint one part of the log
forward until one page before the next checkpoint (if existing)
is redone.
.un 3
3. ROLLBACK phase
.br
For every log portion a rollback for the yet open transactions has
to be performed. Note that this has to be done too for the portions
of the log that have been recoverd by RESTORE LOG.
Reason: The last checkpoint of a RESTORE LOG may be the restart
checkpoint after a DB-crash. Hence redoing the log after
a previous RESTORE DATA is not sufficient, because there exist
open transactions at the time of the checkpoint and they
are redone but not undone.
This is also the reason why the redo progresses only from checkpoint
to checkpoint.
.in -3
.CM *-END-* specification -------------------------------
.in
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
.sp 2
.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      INCREMENT_CONV_VERSION  = true;
      c_save_param_file  = true;
      (* *)
      c_local_failed     = 'LOCAL: failed                           ';
      c_local_incomplete = 'LOCAL: incomplete                       ';
      c_local_ready      = 'LOCAL: ready                            ';
      (* *)
      c_err_until_date   = 'UNTIL DATE is older than last savepoint ';
      c_err_prev_restart = 'previous restart was incomplete         ';
 
 
(*------------------------------*) 
 
PROCEDURE
      k81local_restart (VAR t      : tgg00_TransContext;
            until_date             : tsp00_Date;
            until_time             : tsp00_Time;
            is_restore_log         : boolean;
            activate_state         : tgg00_MessType2;
            VAR predecessorVersion : tsp00_Version);
 
VAR
      bd_restarted  : boolean;
      xp_return     : tsp_xp_return_code;
      xp_errortext  : tsp_errtext;
      errmsg        : tsp00_C40;
      DummyFileId   : tgg00_FileId;
 
BEGIN
t.trError_gg00 := e_ok;
errmsg         := bsp_c40;
(**)
vbegexcl (t.trTaskId_gg00, g08server);
k90wait_until_server_finished (t.trTaskId_gg00);
vendexcl (t.trTaskId_gg00, g08server);
(**)
bd_restarted     := false;
g01restart_local := true;
kb81filesystem_restart (t);
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    bd_restarted := true;
    k51restart_locklist (t)
    END;
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    WITH k57restartrec^ DO
        BEGIN
        predecessorVersion := rstReleaseVersion_kb00;
        CASE activate_state OF
            mm_nil:
                (* normal restart *)
                IF  rstConfigPhase_kb00 <> cfpNone_ekb00
                THEN
                    IF  is_restore_log
                        AND
                        (rstConfigPhase_kb00 = cfpConfigured_ekb00)
                        AND
                        TRUE (* ++++ Savepoint IOSeq is Invalid +++++ *)
                    THEN
                        (* restore log without initial data recovery *)
                        BEGIN
                        rstConfigPhase_kb00 := cfpNone_ekb00;
                        k57save_restartrecord (t.trTaskId_gg00)
                        END
                    ELSE
                        t.trError_gg00 := e_serverdb_must_be_activated;
                    (*ENDIF*) 
                (*ENDIF*) 
            mm_first:
                (* activate: stand alone / after integrate *)
                IF  rstConfigPhase_kb00 = cfpConfigured_ekb00
                THEN
                    BEGIN
                    rstConfigPhase_kb00 := cfpNone_ekb00;
                    k57save_restartrecord (t.trTaskId_gg00)
                    END;
                (*ENDIF*) 
            mm_first_distributed:
                (* integrate *)
                IF  (rstConfigPhase_kb00 <> cfpConfigured_ekb00    ) AND
                    (rstConfigPhase_kb00 <> cfpActivateStart_ekb00)
                THEN
                    t.trError_gg00 := e_serverdb_not_empty;
                (*ENDIF*) 
            OTHERWISE
                t.trError_gg00 := e_not_implemented
            END;
        (*ENDCASE*) 
        IF  rstConfigPhase_kb00 = cfpRestartIncomplete_ekb00
        THEN
            BEGIN
            t.trError_gg00 := e_restart_incomplete;
            errmsg         := c_err_prev_restart
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
IF  (t.trError_gg00 <> e_ok) AND (errmsg <> bsp_c40)
THEN
    g01optextmsg (sp3p_console, sp3m_error,
          kb81RestartErrmsg_csp03, (* PTS 1000283 UH *)
          csp3_n_log, errmsg);
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    IF  is_restore_log
    THEN
        kb560InitLogForRestore (t.trTaskId_gg00, t.trError_gg00)
    ELSE
        kb560InitLogForRestart (t.trTaskId_gg00, t.trError_gg00);
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    IF  k57restartrec^.rstSetEndReadOnly_kb00
    THEN
        b01end_read_only (t)
    (*ENDIF*) 
    END;
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    vbegexcl (t.trTaskId_gg00, g08server);
    k90init_server_manager (t.trTaskId_gg00);
    vendexcl (t.trTaskId_gg00, g08server);
    (* *)
    k06linit_local_site (t)
    END;
(*ENDIF*) 
IF  (t.trError_gg00 = e_ok) AND NOT is_restore_log
THEN
    k81restart_handling (t, is_restore_log, until_date, until_time);
(* PTS 1114877 UH 2002-03-18 begin *)
(*ENDIF*) 
IF  g01ignore_rootid_check AND g01is_livecache
    AND
    (t.trError_gg00 = e_ok)
THEN
    BEGIN
    (* This must be called again here again, because during redo may new undo files be created. *)
    kb560StartGCAndWaitForNoHistoryExists (t);
    g01ignore_rootid_check := false;
    END;
(* PTS 1114877 UH 2002-03-18 end *)
(*ENDIF*) 
IF  (t.trError_gg00 = e_ok) AND g01is_livecache AND NOT is_restore_log
    (* for livecache delay the reading of the objects *)
THEN
    bd01CreateCoordinator (t, DummyFileId, m_get_object);
(* PTS 100217 Frank Hoffmann 1998-02-04 *)
(* PTS 1001564 Torsten Strahl 1998-11-30 *)
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    IF  activate_state = mm_nil
    THEN
        vxparam_save_good_config (c_save_param_file, xp_errortext, xp_return)
    ELSE
        vxparam_save_good_config (NOT c_save_param_file, xp_errortext, xp_return);
    (*ENDIF*) 
    IF  xp_return <> xp_ok
    THEN
        g01optextmsg (sp3p_console, sp3m_error, kb81ParamNotSaved_csp03,
              csp3_n_param, xp_errortext)
    (*ENDIF*) 
    END;
(* PTS 100217 *)
(*ENDIF*) 
IF  t.trError_gg00 <> e_ok
THEN
    (* PTS 1117300 UH 2002-08-16 *)
    (* PTS 1117603 UH 2002-09-12 *)
    kb811ForceOffline (t.trTaskId_gg00, t.trError_gg00);
(******************************************)
(* KERNEL IS OFFLINE NOW                  *)
(******************************************)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      k81restart_handling (VAR t  : tgg00_TransContext;
            is_restore_log        : boolean;
            until_date            : tsp00_Date;
            until_time            : tsp00_Time);
 
VAR
      error_count    : tsp00_Int4;
      until_date_int : tsp00_Int4;
      until_time_int : tsp00_Int4;
 
BEGIN
t.trError_gg00 := e_ok;
error_count    := 0;
g02date_time_to_int (until_date, until_time,
      until_date_int, until_time_int);
IF  until_date_int + until_time_int > 0
THEN
    WITH k57restartrec^.rstLastSavept_kb00 DO
        (* PTS 1120508 mb 2002-02-10 *)
        IF  (until_date_int < svpStartEntryDate_kb00)
            OR
            ((until_date_int = svpStartEntryDate_kb00) AND
            ( until_time_int < svpStartEntryTime_kb00))
        THEN
            BEGIN
            t.trError_gg00 := e_incompatible_log;
            g01optextmsg (sp3p_console, sp3m_error,
                  kb81InvalidUntil_csp03, (* PTS 1000283 UH *)
                  csp3_n_log, c_err_until_date)
            END;
        (*ENDIF*) 
    (*ENDWITH*) 
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    (********************)
    (* PTS 1111525 mb 2001-01-15 restoreLogUntil*)
    kb811RedoManager (t, until_date_int, until_time_int, is_restore_log);
    (********************)
    END;
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    BEGIN
    k06termset_init (t);
    END;
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    b06create_errortext_file (t);
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    g01optextmsg (sp3p_console, sp3m_info,
          kb81LocalReady_csp03, csp3_n_restart, c_local_ready)
ELSE
    IF  t.trError_gg00 = e_restart_incomplete
    THEN
        g01optextmsg (sp3p_console, sp3m_error,
              kb81LocalIncomplete_csp03, csp3_n_restart,
              c_local_incomplete)
    ELSE
        g01optextmsg (sp3p_console, sp3m_error,
              kb81LocalFailed_csp03, csp3_n_restart, c_local_failed);
    (*ENDIF*) 
(*ENDIF*) 
g01restart_local := false;
&ifdef TRACE
t01basis_error (kb, 'end k81resta', t.trError_gg00);
&endif
IF  t.trError_gg00 <> e_ok
THEN
    (* PTS 1117603 UH 2002-09-12 *)
    kb811ForceOffline (t.trTaskId_gg00, t.trError_gg00);
(******************************************)
(* KERNEL IS OFFLINE NOW                  *)
(******************************************)
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      kb81filesystem_restart (VAR t : tgg00_TransContext);
 
BEGIN
t.trError_gg00 := e_ok;
b01restart_filesystem (t, INCREMENT_CONV_VERSION);
IF  t.trError_gg00 = e_ok
THEN
    b01filestate (t, g01tabid.sys1_cat);
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    b01filestate (t, g01tabid.sys2_cat);
(*ENDIF*) 
IF  t.trError_gg00 = e_ok
THEN
    b01filestate (t, g01tabid.sys2_cat)
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
*-PRETTY-*  statements    :         88
*-PRETTY-*  lines of code :        291        PRETTYX 3.10 
*-PRETTY-*  lines in file :        754         1997-12-10 
.PA 
