From 4052b383759a3abacc5df3097d198e8a211bdc93 Mon Sep 17 00:00:00 2001 From: Marcin Szydelski Date: Nov 10 2019 20:47:26 +0000 Subject: Merge pull request #13 from szydell/6.3-001A 6.3-001A --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 40dfce7..8106b49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ foreach(lang ${languages}) endforeach() # Defaults -set(version V6.3-001) +set(version V6.3-001A) if("${version}" STREQUAL "") set(version V9.9-0) endif() diff --git a/README b/README index a8dc82a..c964308 100644 --- a/README +++ b/README @@ -25,16 +25,16 @@ To build GT.M for Linux, do the following steps: 2. Unpack the GT.M sources The GT.M source tarball extracts to a directory with the version number in - the name, fis-gtm-V6.3-001 - $ tar xfz fis-gtm-V6.3-001.tar.gz - $ cd fis-gtm-V6.3-001 + the name, fis-gtm-V6.3-001A + $ tar xfz fis-gtm-V6.3-001A.tar.gz + $ cd fis-gtm-V6.3-001A You should find this README, LICENSE, COPYING and CMakeLists.txt file and sr_* source directories. 3. Building GT.M - can be a sub directory of the source directory, - fis-gtm-V6.3-001, or any other valid path. + fis-gtm-V6.3-001A, or any other valid path. $ mkdir $ cd @@ -53,16 +53,16 @@ To build GT.M for Linux, do the following steps: # # -D CMAKE_INSTALL_PREFIX:PATH=${PWD}/package # - $ cmake -D CMAKE_INSTALL_PREFIX:PATH=${PWD}/package /fis-gtm-V6.3-001 + $ cmake -D CMAKE_INSTALL_PREFIX:PATH=${PWD}/package /fis-gtm-V6.3-001A $ make $ make install - $ cd package/lib/fis-gtm/V6.3-001_x86_64 + $ cd package/lib/fis-gtm/V6.3-001A_x86_64 # Now you are ready to install GT.M. Answer a few questions and install it. - # The recommended installation path is /opt/fis-gtm/V6.3-001_x86_64 + # The recommended installation path is /opt/fis-gtm/V6.3-001A_x86_64 $ sudo ./configure diff --git a/sr_i386/GDEINITSZ.m b/sr_i386/GDEINITSZ.m index 4e35d00..7bff1c1 100644 --- a/sr_i386/GDEINITSZ.m +++ b/sr_i386/GDEINITSZ.m @@ -2,14 +2,14 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; -; Generated by scantypedefs.m at 15:27:52 on 2017-03-08 +; Generated by scantypedefs.m at 10:50:09 on 2017-03-30 ; Build done with GT.M version: GT.M V6.3-000A Linux x86 ; ; Environment variables during run: ; $gtm_dist: /usr/library/V63000A/dbg -; $gtm_exe: /usr/library/V63001/dbg -; $gtm_src: /usr/library/V63001/src -; $gtm_inc: /usr/library/V63001/inc +; $gtm_exe: /usr/library/V63001A/dbg +; $gtm_src: /usr/library/V63001A/src +; $gtm_inc: /usr/library/V63001A/inc ; ; Note this file should not be manually invoked ; diff --git a/sr_i386/GTMDefinedTypesInitDebug.m b/sr_i386/GTMDefinedTypesInitDebug.m index 669f4b8..18b8d61 100644 --- a/sr_i386/GTMDefinedTypesInitDebug.m +++ b/sr_i386/GTMDefinedTypesInitDebug.m @@ -11,14 +11,14 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; -; Generated by scantypedefs.m at 15:27:52 on 2017-03-08 +; Generated by scantypedefs.m at 10:50:09 on 2017-03-30 ; Build done with GT.M version: GT.M V6.3-000A Linux x86 ; ; Environment variables during run: ; $gtm_dist: /usr/library/V63000A/dbg -; $gtm_exe: /usr/library/V63001/dbg -; $gtm_src: /usr/library/V63001/src -; $gtm_inc: /usr/library/V63001/inc +; $gtm_exe: /usr/library/V63001A/dbg +; $gtm_src: /usr/library/V63001A/src +; $gtm_inc: /usr/library/V63001A/inc ; ; Note this file should not be manually invoked ; @@ -10431,7 +10431,7 @@ Init Set gtmtypfldindx("jnl_fence_control","strm_seqno")=4 ; Set gtmtypes("jnl_file_header")="struct" - Set gtmtypes("jnl_file_header",0)=66 + Set gtmtypes("jnl_file_header",0)=67 Set gtmtypes("jnl_file_header","len")=2048 Set gtmtypes("jnl_file_header",1,"name")="jnl_file_header.label" Set gtmtypes("jnl_file_header",1,"off")=0 @@ -10760,11 +10760,16 @@ Init Set gtmtypes("jnl_file_header",65,"len")=4 Set gtmtypes("jnl_file_header",65,"type")="boolean_t" Set gtmtypfldindx("jnl_file_header","last_eof_written")=65 - Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.is_not_latest_jnl" Set gtmtypes("jnl_file_header",66,"off")=1612 - Set gtmtypes("jnl_file_header",66,"len")=436 - Set gtmtypes("jnl_file_header",66,"type")="char" - Set gtmtypfldindx("jnl_file_header","filler")=66 + Set gtmtypes("jnl_file_header",66,"len")=4 + Set gtmtypes("jnl_file_header",66,"type")="boolean_t" + Set gtmtypfldindx("jnl_file_header","is_not_latest_jnl")=66 + Set gtmtypes("jnl_file_header",67,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",67,"off")=1616 + Set gtmtypes("jnl_file_header",67,"len")=432 + Set gtmtypes("jnl_file_header",67,"type")="char" + Set gtmtypfldindx("jnl_file_header","filler")=67 ; Set gtmtypes("jnl_format_buffer")="struct" Set gtmtypes("jnl_format_buffer",0)=14 @@ -26372,8 +26377,8 @@ Init Set gtmtypfldindx("sgmm_addrs","filler")=1 ; Set gtmtypes("sgmnt_addrs")="struct" - Set gtmtypes("sgmnt_addrs",0)=152 - Set gtmtypes("sgmnt_addrs","len")=860 + Set gtmtypes("sgmnt_addrs",0)=153 + Set gtmtypes("sgmnt_addrs","len")=864 Set gtmtypes("sgmnt_addrs",1,"name")="sgmnt_addrs.hdr" Set gtmtypes("sgmnt_addrs",1,"off")=0 Set gtmtypes("sgmnt_addrs",1,"len")=4 @@ -27136,6 +27141,11 @@ Init Set gtmtypes("sgmnt_addrs",152,"len")=4 Set gtmtypes("sgmnt_addrs",152,"type")="int" Set gtmtypfldindx("sgmnt_addrs","tp_hint")=152 + Set gtmtypes("sgmnt_addrs",153,"name")="sgmnt_addrs.statsDB_setup_completed" + Set gtmtypes("sgmnt_addrs",153,"off")=860 + Set gtmtypes("sgmnt_addrs",153,"len")=4 + Set gtmtypes("sgmnt_addrs",153,"type")="boolean_t" + Set gtmtypfldindx("sgmnt_addrs","statsDB_setup_completed")=153 ; Set gtmtypes("sgmnt_data")="struct" Set gtmtypes("sgmnt_data",0)=586 @@ -40290,11 +40300,11 @@ Init Set gtmtypfldindx("unique_file_id","file_id")=5 ; Set gtmtypes("unix_db_info")="struct" - Set gtmtypes("unix_db_info",0)=168 - Set gtmtypes("unix_db_info","len")=928 + Set gtmtypes("unix_db_info",0)=169 + Set gtmtypes("unix_db_info","len")=932 Set gtmtypes("unix_db_info",1,"name")="unix_db_info.s_addrs" Set gtmtypes("unix_db_info",1,"off")=0 - Set gtmtypes("unix_db_info",1,"len")=860 + Set gtmtypes("unix_db_info",1,"len")=864 Set gtmtypes("unix_db_info",1,"type")="sgmnt_addrs" Set gtmtypfldindx("unix_db_info","s_addrs")=1 Set gtmtypes("unix_db_info",2,"name")="unix_db_info.s_addrs.hdr" @@ -41059,81 +41069,86 @@ Init Set gtmtypes("unix_db_info",153,"len")=4 Set gtmtypes("unix_db_info",153,"type")="int" Set gtmtypfldindx("unix_db_info","s_addrs.tp_hint")=153 - Set gtmtypes("unix_db_info",154,"name")="unix_db_info.fn" + Set gtmtypes("unix_db_info",154,"name")="unix_db_info.s_addrs.statsDB_setup_completed" Set gtmtypes("unix_db_info",154,"off")=860 Set gtmtypes("unix_db_info",154,"len")=4 - Set gtmtypes("unix_db_info",154,"type")="addr" - Set gtmtypfldindx("unix_db_info","fn")=154 - Set gtmtypes("unix_db_info",155,"name")="unix_db_info.fd" + Set gtmtypes("unix_db_info",154,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","s_addrs.statsDB_setup_completed")=154 + Set gtmtypes("unix_db_info",155,"name")="unix_db_info.fn" Set gtmtypes("unix_db_info",155,"off")=864 Set gtmtypes("unix_db_info",155,"len")=4 - Set gtmtypes("unix_db_info",155,"type")="int" - Set gtmtypfldindx("unix_db_info","fd")=155 - Set gtmtypes("unix_db_info",156,"name")="unix_db_info.owning_gd" + Set gtmtypes("unix_db_info",155,"type")="addr" + Set gtmtypfldindx("unix_db_info","fn")=155 + Set gtmtypes("unix_db_info",156,"name")="unix_db_info.fd" Set gtmtypes("unix_db_info",156,"off")=868 Set gtmtypes("unix_db_info",156,"len")=4 - Set gtmtypes("unix_db_info",156,"type")="addr" - Set gtmtypfldindx("unix_db_info","owning_gd")=156 - Set gtmtypes("unix_db_info",157,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",156,"type")="int" + Set gtmtypfldindx("unix_db_info","fd")=156 + Set gtmtypes("unix_db_info",157,"name")="unix_db_info.owning_gd" Set gtmtypes("unix_db_info",157,"off")=872 - Set gtmtypes("unix_db_info",157,"len")=20 - Set gtmtypes("unix_db_info",157,"type")="unix_file_id" - Set gtmtypfldindx("unix_db_info","fileid")=157 - Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid.inode" - Set gtmtypes("unix_db_info",158,"off")=872 - Set gtmtypes("unix_db_info",158,"len")=8 - Set gtmtypes("unix_db_info",158,"type")="ino_t" - Set gtmtypfldindx("unix_db_info","fileid.inode")=158 - Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.device" - Set gtmtypes("unix_db_info",159,"off")=880 + Set gtmtypes("unix_db_info",157,"len")=4 + Set gtmtypes("unix_db_info",157,"type")="addr" + Set gtmtypfldindx("unix_db_info","owning_gd")=157 + Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",158,"off")=876 + Set gtmtypes("unix_db_info",158,"len")=20 + Set gtmtypes("unix_db_info",158,"type")="unix_file_id" + Set gtmtypfldindx("unix_db_info","fileid")=158 + Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.inode" + Set gtmtypes("unix_db_info",159,"off")=876 Set gtmtypes("unix_db_info",159,"len")=8 - Set gtmtypes("unix_db_info",159,"type")="dev_t" - Set gtmtypfldindx("unix_db_info","fileid.device")=159 - Set gtmtypes("unix_db_info",160,"name")="unix_db_info.fileid.st_gen" - Set gtmtypes("unix_db_info",160,"off")=888 - Set gtmtypes("unix_db_info",160,"len")=4 - Set gtmtypes("unix_db_info",160,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","fileid.st_gen")=160 - Set gtmtypes("unix_db_info",161,"name")="unix_db_info.semid" + Set gtmtypes("unix_db_info",159,"type")="ino_t" + Set gtmtypfldindx("unix_db_info","fileid.inode")=159 + Set gtmtypes("unix_db_info",160,"name")="unix_db_info.fileid.device" + Set gtmtypes("unix_db_info",160,"off")=884 + Set gtmtypes("unix_db_info",160,"len")=8 + Set gtmtypes("unix_db_info",160,"type")="dev_t" + Set gtmtypfldindx("unix_db_info","fileid.device")=160 + Set gtmtypes("unix_db_info",161,"name")="unix_db_info.fileid.st_gen" Set gtmtypes("unix_db_info",161,"off")=892 Set gtmtypes("unix_db_info",161,"len")=4 - Set gtmtypes("unix_db_info",161,"type")="int" - Set gtmtypfldindx("unix_db_info","semid")=161 - Set gtmtypes("unix_db_info",162,"name")="unix_db_info.gt_sem_ctime" + Set gtmtypes("unix_db_info",161,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","fileid.st_gen")=161 + Set gtmtypes("unix_db_info",162,"name")="unix_db_info.semid" Set gtmtypes("unix_db_info",162,"off")=896 Set gtmtypes("unix_db_info",162,"len")=4 - Set gtmtypes("unix_db_info",162,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=162 - Set gtmtypes("unix_db_info",163,"name")="unix_db_info.shmid" + Set gtmtypes("unix_db_info",162,"type")="int" + Set gtmtypfldindx("unix_db_info","semid")=162 + Set gtmtypes("unix_db_info",163,"name")="unix_db_info.gt_sem_ctime" Set gtmtypes("unix_db_info",163,"off")=900 Set gtmtypes("unix_db_info",163,"len")=4 - Set gtmtypes("unix_db_info",163,"type")="int" - Set gtmtypfldindx("unix_db_info","shmid")=163 - Set gtmtypes("unix_db_info",164,"name")="unix_db_info.gt_shm_ctime" + Set gtmtypes("unix_db_info",163,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=163 + Set gtmtypes("unix_db_info",164,"name")="unix_db_info.shmid" Set gtmtypes("unix_db_info",164,"off")=904 Set gtmtypes("unix_db_info",164,"len")=4 - Set gtmtypes("unix_db_info",164,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=164 - Set gtmtypes("unix_db_info",165,"name")="unix_db_info.ftok_semid" + Set gtmtypes("unix_db_info",164,"type")="int" + Set gtmtypfldindx("unix_db_info","shmid")=164 + Set gtmtypes("unix_db_info",165,"name")="unix_db_info.gt_shm_ctime" Set gtmtypes("unix_db_info",165,"off")=908 Set gtmtypes("unix_db_info",165,"len")=4 - Set gtmtypes("unix_db_info",165,"type")="int" - Set gtmtypfldindx("unix_db_info","ftok_semid")=165 - Set gtmtypes("unix_db_info",166,"name")="unix_db_info.key" + Set gtmtypes("unix_db_info",165,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=165 + Set gtmtypes("unix_db_info",166,"name")="unix_db_info.ftok_semid" Set gtmtypes("unix_db_info",166,"off")=912 Set gtmtypes("unix_db_info",166,"len")=4 - Set gtmtypes("unix_db_info",166,"type")="key_t" - Set gtmtypfldindx("unix_db_info","key")=166 - Set gtmtypes("unix_db_info",167,"name")="unix_db_info.raw" + Set gtmtypes("unix_db_info",166,"type")="int" + Set gtmtypfldindx("unix_db_info","ftok_semid")=166 + Set gtmtypes("unix_db_info",167,"name")="unix_db_info.key" Set gtmtypes("unix_db_info",167,"off")=916 Set gtmtypes("unix_db_info",167,"len")=4 - Set gtmtypes("unix_db_info",167,"type")="boolean_t" - Set gtmtypfldindx("unix_db_info","raw")=167 - Set gtmtypes("unix_db_info",168,"name")="unix_db_info.db_fs_block_size" + Set gtmtypes("unix_db_info",167,"type")="key_t" + Set gtmtypfldindx("unix_db_info","key")=167 + Set gtmtypes("unix_db_info",168,"name")="unix_db_info.raw" Set gtmtypes("unix_db_info",168,"off")=920 Set gtmtypes("unix_db_info",168,"len")=4 - Set gtmtypes("unix_db_info",168,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","db_fs_block_size")=168 + Set gtmtypes("unix_db_info",168,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","raw")=168 + Set gtmtypes("unix_db_info",169,"name")="unix_db_info.db_fs_block_size" + Set gtmtypes("unix_db_info",169,"off")=924 + Set gtmtypes("unix_db_info",169,"len")=4 + Set gtmtypes("unix_db_info",169,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","db_fs_block_size")=169 ; Set gtmtypes("unix_file_id")="struct" Set gtmtypes("unix_file_id",0)=3 diff --git a/sr_i386/GTMDefinedTypesInitRelease.m b/sr_i386/GTMDefinedTypesInitRelease.m index 5b6555c..69bac24 100644 --- a/sr_i386/GTMDefinedTypesInitRelease.m +++ b/sr_i386/GTMDefinedTypesInitRelease.m @@ -11,14 +11,14 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; -; Generated by scantypedefs.m at 15:25:10 on 2017-03-08 +; Generated by scantypedefs.m at 10:47:32 on 2017-03-30 ; Build done with GT.M version: GT.M V6.3-000A Linux x86 ; ; Environment variables during run: ; $gtm_dist: /usr/library/V63000A/pro -; $gtm_exe: /usr/library/V63001/pro -; $gtm_src: /usr/library/V63001/src -; $gtm_inc: /usr/library/V63001/inc +; $gtm_exe: /usr/library/V63001A/pro +; $gtm_src: /usr/library/V63001A/src +; $gtm_inc: /usr/library/V63001A/inc ; ; Note this file should not be manually invoked ; @@ -10411,7 +10411,7 @@ Init Set gtmtypfldindx("jnl_fence_control","strm_seqno")=4 ; Set gtmtypes("jnl_file_header")="struct" - Set gtmtypes("jnl_file_header",0)=66 + Set gtmtypes("jnl_file_header",0)=67 Set gtmtypes("jnl_file_header","len")=2048 Set gtmtypes("jnl_file_header",1,"name")="jnl_file_header.label" Set gtmtypes("jnl_file_header",1,"off")=0 @@ -10740,11 +10740,16 @@ Init Set gtmtypes("jnl_file_header",65,"len")=4 Set gtmtypes("jnl_file_header",65,"type")="boolean_t" Set gtmtypfldindx("jnl_file_header","last_eof_written")=65 - Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.is_not_latest_jnl" Set gtmtypes("jnl_file_header",66,"off")=1612 - Set gtmtypes("jnl_file_header",66,"len")=436 - Set gtmtypes("jnl_file_header",66,"type")="char" - Set gtmtypfldindx("jnl_file_header","filler")=66 + Set gtmtypes("jnl_file_header",66,"len")=4 + Set gtmtypes("jnl_file_header",66,"type")="boolean_t" + Set gtmtypfldindx("jnl_file_header","is_not_latest_jnl")=66 + Set gtmtypes("jnl_file_header",67,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",67,"off")=1616 + Set gtmtypes("jnl_file_header",67,"len")=432 + Set gtmtypes("jnl_file_header",67,"type")="char" + Set gtmtypfldindx("jnl_file_header","filler")=67 ; Set gtmtypes("jnl_format_buffer")="struct" Set gtmtypes("jnl_format_buffer",0)=14 @@ -26167,8 +26172,8 @@ Init Set gtmtypfldindx("sgmm_addrs","filler")=1 ; Set gtmtypes("sgmnt_addrs")="struct" - Set gtmtypes("sgmnt_addrs",0)=152 - Set gtmtypes("sgmnt_addrs","len")=860 + Set gtmtypes("sgmnt_addrs",0)=153 + Set gtmtypes("sgmnt_addrs","len")=864 Set gtmtypes("sgmnt_addrs",1,"name")="sgmnt_addrs.hdr" Set gtmtypes("sgmnt_addrs",1,"off")=0 Set gtmtypes("sgmnt_addrs",1,"len")=4 @@ -26931,6 +26936,11 @@ Init Set gtmtypes("sgmnt_addrs",152,"len")=4 Set gtmtypes("sgmnt_addrs",152,"type")="int" Set gtmtypfldindx("sgmnt_addrs","tp_hint")=152 + Set gtmtypes("sgmnt_addrs",153,"name")="sgmnt_addrs.statsDB_setup_completed" + Set gtmtypes("sgmnt_addrs",153,"off")=860 + Set gtmtypes("sgmnt_addrs",153,"len")=4 + Set gtmtypes("sgmnt_addrs",153,"type")="boolean_t" + Set gtmtypfldindx("sgmnt_addrs","statsDB_setup_completed")=153 ; Set gtmtypes("sgmnt_data")="struct" Set gtmtypes("sgmnt_data",0)=586 @@ -40026,11 +40036,11 @@ Init Set gtmtypfldindx("unique_file_id","file_id")=5 ; Set gtmtypes("unix_db_info")="struct" - Set gtmtypes("unix_db_info",0)=168 - Set gtmtypes("unix_db_info","len")=928 + Set gtmtypes("unix_db_info",0)=169 + Set gtmtypes("unix_db_info","len")=932 Set gtmtypes("unix_db_info",1,"name")="unix_db_info.s_addrs" Set gtmtypes("unix_db_info",1,"off")=0 - Set gtmtypes("unix_db_info",1,"len")=860 + Set gtmtypes("unix_db_info",1,"len")=864 Set gtmtypes("unix_db_info",1,"type")="sgmnt_addrs" Set gtmtypfldindx("unix_db_info","s_addrs")=1 Set gtmtypes("unix_db_info",2,"name")="unix_db_info.s_addrs.hdr" @@ -40795,81 +40805,86 @@ Init Set gtmtypes("unix_db_info",153,"len")=4 Set gtmtypes("unix_db_info",153,"type")="int" Set gtmtypfldindx("unix_db_info","s_addrs.tp_hint")=153 - Set gtmtypes("unix_db_info",154,"name")="unix_db_info.fn" + Set gtmtypes("unix_db_info",154,"name")="unix_db_info.s_addrs.statsDB_setup_completed" Set gtmtypes("unix_db_info",154,"off")=860 Set gtmtypes("unix_db_info",154,"len")=4 - Set gtmtypes("unix_db_info",154,"type")="addr" - Set gtmtypfldindx("unix_db_info","fn")=154 - Set gtmtypes("unix_db_info",155,"name")="unix_db_info.fd" + Set gtmtypes("unix_db_info",154,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","s_addrs.statsDB_setup_completed")=154 + Set gtmtypes("unix_db_info",155,"name")="unix_db_info.fn" Set gtmtypes("unix_db_info",155,"off")=864 Set gtmtypes("unix_db_info",155,"len")=4 - Set gtmtypes("unix_db_info",155,"type")="int" - Set gtmtypfldindx("unix_db_info","fd")=155 - Set gtmtypes("unix_db_info",156,"name")="unix_db_info.owning_gd" + Set gtmtypes("unix_db_info",155,"type")="addr" + Set gtmtypfldindx("unix_db_info","fn")=155 + Set gtmtypes("unix_db_info",156,"name")="unix_db_info.fd" Set gtmtypes("unix_db_info",156,"off")=868 Set gtmtypes("unix_db_info",156,"len")=4 - Set gtmtypes("unix_db_info",156,"type")="addr" - Set gtmtypfldindx("unix_db_info","owning_gd")=156 - Set gtmtypes("unix_db_info",157,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",156,"type")="int" + Set gtmtypfldindx("unix_db_info","fd")=156 + Set gtmtypes("unix_db_info",157,"name")="unix_db_info.owning_gd" Set gtmtypes("unix_db_info",157,"off")=872 - Set gtmtypes("unix_db_info",157,"len")=20 - Set gtmtypes("unix_db_info",157,"type")="unix_file_id" - Set gtmtypfldindx("unix_db_info","fileid")=157 - Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid.inode" - Set gtmtypes("unix_db_info",158,"off")=872 - Set gtmtypes("unix_db_info",158,"len")=8 - Set gtmtypes("unix_db_info",158,"type")="ino_t" - Set gtmtypfldindx("unix_db_info","fileid.inode")=158 - Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.device" - Set gtmtypes("unix_db_info",159,"off")=880 + Set gtmtypes("unix_db_info",157,"len")=4 + Set gtmtypes("unix_db_info",157,"type")="addr" + Set gtmtypfldindx("unix_db_info","owning_gd")=157 + Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",158,"off")=876 + Set gtmtypes("unix_db_info",158,"len")=20 + Set gtmtypes("unix_db_info",158,"type")="unix_file_id" + Set gtmtypfldindx("unix_db_info","fileid")=158 + Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.inode" + Set gtmtypes("unix_db_info",159,"off")=876 Set gtmtypes("unix_db_info",159,"len")=8 - Set gtmtypes("unix_db_info",159,"type")="dev_t" - Set gtmtypfldindx("unix_db_info","fileid.device")=159 - Set gtmtypes("unix_db_info",160,"name")="unix_db_info.fileid.st_gen" - Set gtmtypes("unix_db_info",160,"off")=888 - Set gtmtypes("unix_db_info",160,"len")=4 - Set gtmtypes("unix_db_info",160,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","fileid.st_gen")=160 - Set gtmtypes("unix_db_info",161,"name")="unix_db_info.semid" + Set gtmtypes("unix_db_info",159,"type")="ino_t" + Set gtmtypfldindx("unix_db_info","fileid.inode")=159 + Set gtmtypes("unix_db_info",160,"name")="unix_db_info.fileid.device" + Set gtmtypes("unix_db_info",160,"off")=884 + Set gtmtypes("unix_db_info",160,"len")=8 + Set gtmtypes("unix_db_info",160,"type")="dev_t" + Set gtmtypfldindx("unix_db_info","fileid.device")=160 + Set gtmtypes("unix_db_info",161,"name")="unix_db_info.fileid.st_gen" Set gtmtypes("unix_db_info",161,"off")=892 Set gtmtypes("unix_db_info",161,"len")=4 - Set gtmtypes("unix_db_info",161,"type")="int" - Set gtmtypfldindx("unix_db_info","semid")=161 - Set gtmtypes("unix_db_info",162,"name")="unix_db_info.gt_sem_ctime" + Set gtmtypes("unix_db_info",161,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","fileid.st_gen")=161 + Set gtmtypes("unix_db_info",162,"name")="unix_db_info.semid" Set gtmtypes("unix_db_info",162,"off")=896 Set gtmtypes("unix_db_info",162,"len")=4 - Set gtmtypes("unix_db_info",162,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=162 - Set gtmtypes("unix_db_info",163,"name")="unix_db_info.shmid" + Set gtmtypes("unix_db_info",162,"type")="int" + Set gtmtypfldindx("unix_db_info","semid")=162 + Set gtmtypes("unix_db_info",163,"name")="unix_db_info.gt_sem_ctime" Set gtmtypes("unix_db_info",163,"off")=900 Set gtmtypes("unix_db_info",163,"len")=4 - Set gtmtypes("unix_db_info",163,"type")="int" - Set gtmtypfldindx("unix_db_info","shmid")=163 - Set gtmtypes("unix_db_info",164,"name")="unix_db_info.gt_shm_ctime" + Set gtmtypes("unix_db_info",163,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=163 + Set gtmtypes("unix_db_info",164,"name")="unix_db_info.shmid" Set gtmtypes("unix_db_info",164,"off")=904 Set gtmtypes("unix_db_info",164,"len")=4 - Set gtmtypes("unix_db_info",164,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=164 - Set gtmtypes("unix_db_info",165,"name")="unix_db_info.ftok_semid" + Set gtmtypes("unix_db_info",164,"type")="int" + Set gtmtypfldindx("unix_db_info","shmid")=164 + Set gtmtypes("unix_db_info",165,"name")="unix_db_info.gt_shm_ctime" Set gtmtypes("unix_db_info",165,"off")=908 Set gtmtypes("unix_db_info",165,"len")=4 - Set gtmtypes("unix_db_info",165,"type")="int" - Set gtmtypfldindx("unix_db_info","ftok_semid")=165 - Set gtmtypes("unix_db_info",166,"name")="unix_db_info.key" + Set gtmtypes("unix_db_info",165,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=165 + Set gtmtypes("unix_db_info",166,"name")="unix_db_info.ftok_semid" Set gtmtypes("unix_db_info",166,"off")=912 Set gtmtypes("unix_db_info",166,"len")=4 - Set gtmtypes("unix_db_info",166,"type")="key_t" - Set gtmtypfldindx("unix_db_info","key")=166 - Set gtmtypes("unix_db_info",167,"name")="unix_db_info.raw" + Set gtmtypes("unix_db_info",166,"type")="int" + Set gtmtypfldindx("unix_db_info","ftok_semid")=166 + Set gtmtypes("unix_db_info",167,"name")="unix_db_info.key" Set gtmtypes("unix_db_info",167,"off")=916 Set gtmtypes("unix_db_info",167,"len")=4 - Set gtmtypes("unix_db_info",167,"type")="boolean_t" - Set gtmtypfldindx("unix_db_info","raw")=167 - Set gtmtypes("unix_db_info",168,"name")="unix_db_info.db_fs_block_size" + Set gtmtypes("unix_db_info",167,"type")="key_t" + Set gtmtypfldindx("unix_db_info","key")=167 + Set gtmtypes("unix_db_info",168,"name")="unix_db_info.raw" Set gtmtypes("unix_db_info",168,"off")=920 Set gtmtypes("unix_db_info",168,"len")=4 - Set gtmtypes("unix_db_info",168,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","db_fs_block_size")=168 + Set gtmtypes("unix_db_info",168,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","raw")=168 + Set gtmtypes("unix_db_info",169,"name")="unix_db_info.db_fs_block_size" + Set gtmtypes("unix_db_info",169,"off")=924 + Set gtmtypes("unix_db_info",169,"len")=4 + Set gtmtypes("unix_db_info",169,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","db_fs_block_size")=169 ; Set gtmtypes("unix_file_id")="struct" Set gtmtypes("unix_file_id",0)=3 diff --git a/sr_i386/merrors_ansi.h b/sr_i386/merrors_ansi.h index e8ce24f..ddf134a 100644 --- a/sr_i386/merrors_ansi.h +++ b/sr_i386/merrors_ansi.h @@ -1488,4 +1488,7 @@ const static readonly int error_ansi[] = { 0, /* STATSDBERR */ 0, /* STATSDBINUSE */ 0, /* STATSDBFNERR */ + 0, /* JNLSWITCHRETRY */ + 0, /* JNLSWITCHFAIL */ + 0, /* CLISTRTOOLONG */ }; diff --git a/sr_i386/merrors_ctl.c b/sr_i386/merrors_ctl.c index ab55fe4..47f0528 100644 --- a/sr_i386/merrors_ctl.c +++ b/sr_i386/merrors_ctl.c @@ -1490,6 +1490,9 @@ LITDEF err_msg merrors[] = { { "STATSDBERR", "Error in/at !AD attempting to use a statistics database: !AD", 4 }, { "STATSDBINUSE", "Statistics database !AD is in use with database !AD so cannot also be used with database !AD", 6 }, { "STATSDBFNERR", "This database has no accessible statistics database due to the following error: !AD", 2 }, + { "JNLSWITCHRETRY", "Retrying previously abandoned switch of journal file !AD for database !AD", 4 }, + { "JNLSWITCHFAIL", "Failed to switch journal file !AD for database file !AD", 4 }, + { "CLISTRTOOLONG", "!AZ specified is !UL bytes long which is greater than the allowed maximum of !UL bytes", 3 }, }; LITDEF int ERR_ACK = 150372361; @@ -2969,9 +2972,12 @@ LITDEF int ERR_INVSTATSDB = 150384146; LITDEF int ERR_STATSDBERR = 150384154; LITDEF int ERR_STATSDBINUSE = 150384162; LITDEF int ERR_STATSDBFNERR = 150384170; +LITDEF int ERR_JNLSWITCHRETRY = 150384179; +LITDEF int ERR_JNLSWITCHFAIL = 150384186; +LITDEF int ERR_CLISTRTOOLONG = 150384194; GBLDEF err_ctl merrors_ctl = { 246, "GTM", &merrors[0], - 1477}; + 1480}; diff --git a/sr_linux/release_name.h b/sr_linux/release_name.h index e591366..cc00975 100644 --- a/sr_linux/release_name.h +++ b/sr_linux/release_name.h @@ -11,15 +11,15 @@ ****************************************************************/ #ifdef __CYGWIN__ -#define GTM_RELEASE_NAME "GT.M V6.3-001 CYGWIN x86" +#define GTM_RELEASE_NAME "GT.M V6.3-001A CYGWIN x86" #elif defined(__ia64) -#define GTM_RELEASE_NAME "GT.M V6.3-001 Linux IA64" +#define GTM_RELEASE_NAME "GT.M V6.3-001A Linux IA64" #elif defined(__x86_64__) -#define GTM_RELEASE_NAME "GT.M V6.3-001 Linux x86_64" +#define GTM_RELEASE_NAME "GT.M V6.3-001A Linux x86_64" #elif defined(__s390__) -#define GTM_RELEASE_NAME "GT.M V6.3-001 Linux S390X" +#define GTM_RELEASE_NAME "GT.M V6.3-001A Linux S390X" #else -#define GTM_RELEASE_NAME "GT.M V6.3-001 Linux x86" +#define GTM_RELEASE_NAME "GT.M V6.3-001A Linux x86" #endif #define GTM_PRODUCT "GT.M" #define GTM_VERSION "V6.3" diff --git a/sr_port/bm_getfree.c b/sr_port/bm_getfree.c index b55c9ad..bd0d411 100644 --- a/sr_port/bm_getfree.c +++ b/sr_port/bm_getfree.c @@ -91,7 +91,7 @@ block_id bm_getfree(block_id hint, boolean_t *blk_used, unsigned int cw_work, cw hint_cycled = DIVIDE_ROUND_UP(total_blks, BLKS_PER_LMAP); hint_limit = DIVIDE_ROUND_DOWN(hint, BLKS_PER_LMAP); local_maps = hint_cycled + 2; /* for (up to) 2 wraps */ - for (lcnt = local_maps; lcnt ; lcnt--) /* loop control counts down for slight efficiency; it's not used in locating bit */ + for (lcnt = local_maps + 1; lcnt ; lcnt--) /* loop control counts down for slight efficiency */ { bml = bmm_find_free(hint / BLKS_PER_LMAP, (sm_uc_ptr_t)MM_ADDR(cs_data), local_maps); if ((NO_FREE_SPACE == bml) || (bml >= hint_cycled)) @@ -118,7 +118,7 @@ block_id bm_getfree(block_id hint, boolean_t *blk_used, unsigned int cw_work, cw * free blocks while doing an extend and the fact that it is very easy to make the change to do * a full-pass, the full-pass solution is currently being implemented */ - lcnt = local_maps; /* allow it one extra pass to ensure that it can take advantage of the entension */ + lcnt = local_maps + 2; /* allow it one extra pass to ensure that it can take advantage of the entension */ n_decrements++; /* used only for debugging purposes */ continue; } diff --git a/sr_port/common_startup_init.h b/sr_port/common_startup_init.h index 389d24b..aa6292b 100644 --- a/sr_port/common_startup_init.h +++ b/sr_port/common_startup_init.h @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2014 Fidelity Information Services, Inc * + * Copyright (c) 2014-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -14,4 +15,44 @@ void common_startup_init(enum gtmImageTypes img_type); +#if (defined(DEBUG) || defined(TIMER_DEBUGGING)) +# include "jnl_file_close_timer.h" +GBLREF void (*jnl_file_close_timer_ptr)(void); +# define INIT_JNL_FILE_CLOSE_TIMER_FNPTR jnl_file_close_timer_ptr = &jnl_file_close_timer +#else +# define INIT_JNL_FILE_CLOSE_TIMER_FNPTR +#endif + +#ifdef TIMER_DEBUGGING +# include "fake_enospc.h" +# include "gt_timer.h" +GBLREF void (*fake_enospc_ptr)(void); +GBLREF void (*simple_timeout_timer_ptr)(TID tid, int4 hd_len, boolean_t **timedout); +# define INIT_FAKE_ENOSPC_FNPTR fake_enospc_ptr = &fake_enospc +# define INIT_SIMPLE_TIMEOUT_TIMER_FNPTR simple_timeout_timer_ptr = &simple_timeout_timer +#else +# define INIT_FAKE_ENOSPC_FNPTR +# define INIT_SIMPLE_TIMEOUT_TIMER_FNPTR +#endif + +#ifdef DEBUG +# include "error.h" +GBLREF ch_ret_type (*t_ch_fnptr)(); /* Function pointer to t_ch */ +GBLREF ch_ret_type (*dbinit_ch_fnptr)(); /* Function pointer to dbinit_ch */ +# define INIT_DBINIT_CH_FNPTR dbinit_ch_fnptr = &dbinit_ch +# define INIT_T_CH_FNPTR t_ch_fnptr = &t_ch +#else +# define INIT_DBINIT_CH_FNPTR +# define INIT_T_CH_FNPTR +#endif + +#define INIT_FNPTR_GLOBAL_VARIABLES \ +MBSTART { \ + INIT_JNL_FILE_CLOSE_TIMER_FNPTR; \ + INIT_FAKE_ENOSPC_FNPTR; \ + INIT_SIMPLE_TIMEOUT_TIMER_FNPTR; \ + INIT_DBINIT_CH_FNPTR; \ + INIT_T_CH_FNPTR; \ +} MBEND + #endif diff --git a/sr_port/cre_jnl_file.c b/sr_port/cre_jnl_file.c index d271bec..1fdb66e 100644 --- a/sr_port/cre_jnl_file.c +++ b/sr_port/cre_jnl_file.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2003-2016 Fidelity National Information * + * Copyright (c) 2003-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -89,6 +89,7 @@ GBLREF boolean_t mupip_jnl_recover; GBLREF jnl_process_vector *prc_vec; ZOS_ONLY(error_def(ERR_BADTAG);) +error_def(ERR_FILENAMETOOLONG); error_def(ERR_FILERENAME); error_def(ERR_JNLCRESTATUS); error_def(ERR_JNLFNF); @@ -104,13 +105,14 @@ uint4 cre_jnl_file(jnl_create_info *info) { mstr filestr; int org_fn_len, rename_fn_len, fstat; - char *org_fn, rename_fn[MAX_FN_LEN]; + char *org_fn, rename_fn[MAX_FN_LEN + 1]; boolean_t no_rename; assert(0 != jgbl.gbl_jrec_time); if (!info->no_rename) /* ***MAYBE*** rename is required */ { no_rename = FALSE; + rename_fn_len = ARRAYSIZE(rename_fn); if (SS_NORMAL != (info->status = prepare_unique_name((char *)info->jnl, info->jnl_len, "", "", rename_fn, &rename_fn_len, jgbl.gbl_jrec_time, &info->status2))) { @@ -143,6 +145,11 @@ uint4 cre_jnl_file(jnl_create_info *info) if (no_rename) { STATUS_MSG(info); + if (ERR_FILENAMETOOLONG == info->status) + return EXIT_ERR; + /* Else it is an error from "gtm_file_stat" (invoked from "prepare_unique_name" above). + * It usually means the rename we originally wanted is no longer required. So continue. + */ info->status = info->status2 = SS_NORMAL; info->no_rename = TRUE; /* We wanted to rename, but not required anymore */ info->no_prev_link = TRUE; /* No rename => no prev_link */ @@ -160,7 +167,7 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_ struct_jrec_pini *pini_record; struct_jrec_epoch *epoch_record; struct_jrec_eof *eof_record; - unsigned char *create_fn, fn_buff[MAX_FN_LEN]; + unsigned char *create_fn, fn_buff[MAX_FN_LEN + STR_LIT_LEN(EXT_NEW) + 1]; int create_fn_len, cre_jnl_rec_size, status, write_size, jrecbufbase_size; fd_type channel; char *jrecbuf, *jrecbuf_base; @@ -199,6 +206,7 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_ if (NULL != csa) cre_jnl_file_intrpt_rename(csa); /* deal with *_new.mjl files */ create_fn = &fn_buff[0]; + create_fn_len = ARRAYSIZE(fn_buff); if (SS_NORMAL != (info->status = prepare_unique_name((char *)info->jnl, (int)info->jnl_len, "", EXT_NEW, (char *)create_fn, &create_fn_len, 0, &info->status2))) { @@ -389,7 +397,7 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_ JNL_DO_FILE_WRITE(csa, create_fn, channel, JNL_HDR_LEN, jrecbuf, write_size, info->status, info->status2); STATUS_MSG(info); RETURN_ON_ERROR(info); - UNIX_ONLY(GTM_JNL_FSYNC(csa, channel, status);) + GTM_JNL_FSYNC(csa, channel, status); F_CLOSE(channel, status); /* resets "channel" to FD_INVALID */ /* Now that EOF record has been written, keep csa->jnl->jnl_buff->prev_jrec_time up to date. * One exception is if journaling is not yet turned on but is being turned on by the current caller. @@ -448,13 +456,13 @@ uint4 cre_jnl_file_common(jnl_create_info *info, char *rename_fn, int rename_fn_ else gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT (6) ERR_FILERENAME, 4, info->jnl_len, info->jnl, rename_fn_len, rename_fn); -# ifdef DEBUG - if (gtm_white_box_test_case_enabled && (WBTEST_JNL_CREATE_INTERRUPT == gtm_white_box_test_case_number)) - { - UNIX_ONLY(DBGFPF((stderr, "CRE_JNL_FILE: started a wait\n"))); /* this white-box test is for UNIX */ - LONG_SLEEP(600); - assert(FALSE); /* Should be killed before that */ - } -# endif +# ifdef DEBUG + if (gtm_white_box_test_case_enabled && (WBTEST_JNL_CREATE_INTERRUPT == gtm_white_box_test_case_number)) + { + DBGFPF((stderr, "CRE_JNL_FILE: started a wait\n")); + LONG_SLEEP(600); + assert(FALSE); /* Should be killed before that */ + } +# endif return EXIT_NRM; } diff --git a/sr_port/cre_jnl_file_intrpt_rename.c b/sr_port/cre_jnl_file_intrpt_rename.c index 2bc736b..836f48b 100644 --- a/sr_port/cre_jnl_file_intrpt_rename.c +++ b/sr_port/cre_jnl_file_intrpt_rename.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2003, 2014 Fidelity Information Services, Inc * + * Copyright (c) 2003-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -41,20 +42,24 @@ void cre_jnl_file_intrpt_rename(sgmnt_addrs *csa) mstr filestr; int status1, status2, ext_new_jnl_fn_len; uint4 status, ustatus; - unsigned char ext_new_jnl_fn[MAX_FN_LEN]; + unsigned char ext_new_jnl_fn[MAX_FN_LEN + STR_LIT_LEN(EXT_NEW) + 1]; assert(csa); - UNIX_ONLY(assert(csa->hdr)); /* csa->hdr may not be set, e.g. on VMS for MUPIP SET /JOURNAL */ + assert(csa->hdr); /* We need either crit or standalone to ensure that there are no concurrent switch attempts. */ - UNIX_ONLY(assert(csa->now_crit || (gv_cur_region && FILE_INFO(gv_cur_region)->grabbed_access_sem))); + assert(csa->now_crit || (gv_cur_region && FILE_INFO(gv_cur_region)->grabbed_access_sem)); if (!csa->hdr) return; fn = csa->hdr->jnl_file_name; fn_len = csa->hdr->jnl_file_len; filestr.addr = (char *)fn; filestr.len = fn_len; - prepare_unique_name((char *)fn, fn_len, "", EXT_NEW, (char *)ext_new_jnl_fn, &ext_new_jnl_fn_len, 0, &ustatus); - assert(SS_NORMAL == ustatus); + ext_new_jnl_fn_len = ARRAYSIZE(ext_new_jnl_fn); + status = prepare_unique_name((char *)fn, fn_len, "", EXT_NEW, (char *)ext_new_jnl_fn, &ext_new_jnl_fn_len, 0, &ustatus); + /* We have allocated enough space in ext_new_jnl_fn array to store EXT_NEW suffix. + * So no way the above "prepare_unique_name" call can fail. Hence the below assert. + */ + assert(SS_NORMAL == status); status1 = gtm_file_stat(&filestr, NULL, NULL, FALSE, &ustatus); if (FILE_STAT_ERROR == status1) { @@ -83,18 +88,11 @@ void cre_jnl_file_intrpt_rename(sgmnt_addrs *csa) if (SYSCALL_ERROR(status)) { if (IS_GTM_IMAGE) - { - VMS_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_RENAMEFAIL, 4, filestr.len, - filestr.addr, fn_len, fn, status, ustatus)); - UNIX_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len, - filestr.addr, fn_len, fn, status)); - } else - { - VMS_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(8) ERR_RENAMEFAIL, 4, filestr.len, - filestr.addr, fn_len, fn, status, ustatus)); - UNIX_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len, - filestr.addr, fn_len, fn, status)); - } + send_msg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len, + filestr.addr, fn_len, fn, status); + else + gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(7) ERR_RENAMEFAIL, 4, filestr.len, + filestr.addr, fn_len, fn, status); } else { if (IS_GTM_IMAGE) @@ -113,18 +111,11 @@ void cre_jnl_file_intrpt_rename(sgmnt_addrs *csa) if (SYSCALL_ERROR(status)) { if (IS_GTM_IMAGE) - { - VMS_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_FILEDELFAIL, 2, filestr.len, - filestr.addr, status, ustatus)); - UNIX_ONLY(send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len, - filestr.addr, status)); - } else - { - VMS_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_FILEDELFAIL, 2, filestr.len, - filestr.addr, status, ustatus)); - UNIX_ONLY(gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len, - filestr.addr, status)); - } + send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len, + filestr.addr, status); + else + gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_FILEDELFAIL, 2, filestr.len, + filestr.addr, status); } else { if (IS_GTM_IMAGE) diff --git a/sr_port/dse.hlp b/sr_port/dse.hlp index b722b64..e51fd8c 100644 --- a/sr_port/dse.hlp +++ b/sr_port/dse.hlp @@ -1216,8 +1216,8 @@ o With -ALL specified, DSE includes all region of the current global directory for cache recovery. - o Attempt DSE -RECOVER only if a DSE CACHE -VERIFY commands reports the - cache is "NOT clean". + o Attempt DSE CACHE -RECOVER only if a DSE CACHE -VERIFY commands + reports the cache is "NOT clean". -SH[OW] @@ -1551,11 +1551,11 @@ File /home/jdoe/.fis-gtm/V6.1-000_x86_64/g/gtm.dat Region DEFAULT Date/Time 27-JAN-2014 03:13:40 [$H = 63214,11620] - Access method BG Global Buffers 1024 + Access method MM Global Buffers 1024 Reserved Bytes 0 Block size (in bytes) 1024 Maximum record size 256 Starting VBN 513 - Maximum key size 64 Total blocks 0x000000C9 - Null subscripts NEVER Free blocks 0x00000056 + Maximum key size 64 Total blocks 0x00000065 + Null subscripts NEVER Free blocks 0x0000005E Standard Null Collation FALSE Free space 0x00000000 Last Record Backup 0x0000000000000001 Extension Count 100 Last Database Backup 0x0000000000000001 Number of local maps 1 @@ -1563,18 +1563,14 @@ In critical section 0x00000000 Timers pending 0 Cache freeze id 0x00000000 Flush timer 00:00:01:00 Freeze match 0x00000000 Flush trigger 960 - Current transaction 0x0000000000002712 No. of writes/flush 7 + Freeze online FALSE Freeze online autorelease FALSE + Current transaction 0x0000000000000006 No. of writes/flush 7 Maximum TN 0xFFFFFFFF83FFFFFF Certified for Upgrade to V6 Maximum TN Warn 0xFFFFFFFD93FFFFFF Desired DB Format V6 Master Bitmap Size 496 Blocks to Upgrade 0x00000000 Create in progress FALSE Modified cache blocks 0 Reference count 1 Wait Disk 0 - Journal State [inactive] ON Journal Before imaging TRUE - Journal Allocation 2048 Journal Extension 2048 - Journal Buffer Size 2312 Journal Alignsize 4096 - Journal AutoSwitchLimit 8386560 Journal Epoch Interval 30 - Journal Yield Limit 8 Journal Sync IO FALSE - Journal File: /home/jdoe/.fis-gtm/V6.1-000_x86_64/g/gtm.mjl + Journal State DISABLED Mutex Hard Spin Count 128 Mutex Sleep Spin Count 128 Mutex Queue Slots 1024 KILLs in progress 0 Replication State OFF Region Seqno 0x0000000000000001 @@ -1582,6 +1578,10 @@ Endian Format LITTLE Commit Wait Spin Count 16 Database file encrypted FALSE Inst Freeze on Error FALSE Spanning Node Absent TRUE Maximum Key Size Assured TRUE + Defer allocation TRUE Spin sleep time mask 0x00000000 + Async IO OFF WIP queue cache blocks 0 + DB is auto-created FALSE DB shares gvstats TRUE + LOCK shares DB critical section FALSE Note that the certain fileheader elements appear depending on the current state of database. For example, if Journaling is not enabled in the @@ -2941,7 +2941,7 @@ 1 Copyright Copyright - Copyright 2016 + Copyright 2017 Fidelity National Information Services, Inc. and/or its subsidiaries. All rights reserved. @@ -2963,7 +2963,7 @@ **Note** - This help file is a concise representation of revision V6.3-000 of the + This help file is a concise representation of revision V6.3-001 of the UNIX Administration and Operations Guide. To obtain a copy of the current revision, go to www.fis-gtm.com and then click on the User Documentation tab. diff --git a/sr_port/gbldefs.c b/sr_port/gbldefs.c index 82f161f..766bf52 100644 --- a/sr_port/gbldefs.c +++ b/sr_port/gbldefs.c @@ -861,6 +861,10 @@ GBLDEF void (*cache_table_relobjs)(void); /* Function pointer to call cache_t GBLDEF ch_ret_type (*ht_rhash_ch)(); /* Function pointer to hashtab_rehash_ch */ GBLDEF ch_ret_type (*jbxm_dump_ch)(); /* Function pointer to jobexam_dump_ch */ GBLDEF ch_ret_type (*stpgc_ch)(); /* Function pointer to stp_gcol_ch */ +#ifdef DEBUG +GBLDEF ch_ret_type (*t_ch_fnptr)(); /* Function pointer to t_ch */ +GBLDEF ch_ret_type (*dbinit_ch_fnptr)(); /* Function pointer to dbinit_ch */ +#endif GBLDEF cache_rec_ptr_t pin_fail_cr; /* Pointer to the cache-record that we failed while pinning */ GBLDEF cache_rec pin_fail_cr_contents; /* Contents of the cache-record that we failed while pinning */ GBLDEF cache_rec_ptr_t pin_fail_twin_cr; /* Pointer to twin of the cache-record that we failed to pin */ diff --git a/sr_port/gde.hlp b/sr_port/gde.hlp index 8eeeb37..b0d0e95 100644 --- a/sr_port/gde.hlp +++ b/sr_port/gde.hlp @@ -132,59 +132,55 @@ A Global Directory looks like this: - *** TEMPLATES *** + *** TEMPLATES *** Std Inst - Def Rec Key Null Null Freeze Qdb Epoch - Region Coll Size Size Subs Coll Jnl on Error Rndwn Taper - ----------------------------------------------------------------------------------------------------------- - 0 4080 255 NEVER Y Y DISABLED DISABLED ENABLED - Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch - ------------------------------------------------------------------------------------------ - Y 2312 2048 2048 8386560 + Def Rec Key Null Null Freeze Qdb Epoch LOCK + Region Coll Size Size Subs Coll Jnl on Err Rndwn Taper AutoDB Stats Crit + ---------------------------------------------------------------------------------------------------------------------- + 0 256 64 NEVER N N N N Y N Y Sep Segment Active Acc Typ Block Alloc Exten Options ------------------------------------------------------------------------------ - * BG DYN 4096 5000 10000 GLOB =1000 - LOCK = 40 + * BG DYN 4096 100 100 GLOB =1024 + LOCK = 40 RES = 0 ENCR = OFF MSLT =1024 - MM DYN 4096 5000 10000 DEFER - LOCK = 40 + DALL = YES + AIO = OFF + MM DYN 4096 100 100 DEFER + LOCK = 40 MSLT =1024 + DALL = YES *** NAMES *** Global Region ------------------------------------------------------------------------------ * DEFAULT *** REGIONS *** - Std Inst - Dynamic Def Rec Key Null Null Freeze Qdb Epoch - Region Segment Coll Size Size Subs Coll Jnl on Error Rndwn Taper - --------------------------------------------------------------------------------------------------------------------------------- - DEFAULT DEFAULT 0 4080 255 NEVER Y Y DISABLED DISABLED ENABLED - *** JOURNALING INFORMATION *** - Region Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch - -------------------------------------------------------------------------------------------------------- - DEFAULT $gtmdir/$gtmver/g/gtm.mjl - Y 2312 2048 2048 8386560 + Std Inst + Dynamic Def Rec Key Null Null Freeze Qdb Epoch LOCK + Region Segment Coll Size Size Subs Coll Jnl on Err Rndwn Taper AutoDB Stats Crit + ------------------------------------------------------------------------------------------------------------------------------------------- + DEFAULT DEFAULT 0 256 64 NEVER N N N N Y N Y Sep *** SEGMENTS *** Segment File (def ext: .dat)Acc Typ Block Alloc Exten Options ------------------------------------------------------------------------------------------- - DEFAULT $gtmdir/$gtmver/g/gtm.dat - BG DYN 4096 5000 10000 GLOB=1000 + DEFAULT mumps.dat BG DYN 4096 100 100 GLOB=1024 LOCK= 40 RES = 0 - ENCR=OFF + ENCR= OFF MSLT=1024 + DALL= YES + AIO = OFF *** MAP *** - - - - - - - - - - Names - - - - - - - - - - From Up to Region / Segment / File(def ext: .dat) -------------------------------------------------------------------------------------------------------------------------- % ... REG = DEFAULT SEG = DEFAULT - FILE = $gtmdir/$gtmver/g/gtm.dat + FILE = mumps.dat LOCAL LOCKS REG = DEFAULT SEG = DEFAULT - FILE = $gtmdir/$gtmver/g/gtm.dat + FILE = mumps.dat There are five primary sections in a Global Directory: @@ -259,27 +255,34 @@ qualifiers, see "GDE Command Summary". Abbreviation Full Form - Acc ACCESS_METHOD - Alloc ALLOCATION - AutoSwitch AUTOSWITCHLIMIT - Block BLOCK_SIZE - Buff BUFFER_SIZE - Def Coll COLLATION_DEFAULT - Exten EXTENSION_COUNT - File FILE_NAME - GLOB GLOBAL_BUFFER_COUNT - Inst Freeze On Error INST_FREEZE_ON_ERROR - JNL JOURNAL - KeySize KEY_SIZE - LOCK LOCK_SPACE - MSLT MUTEX_SLOTS - Null Subs NULL_SUBSCRIPTS - Qdb Rndwn QDBRUNDOWN - Std Null Coll STDNULLCOLL - Rec Size RECORD_SIZE - RES RESERVED_BYTES - Region REGION - Typ DYNAMIC_SEGMENT + -------------------------------------------------- + Acc -ACCESS_METHOD + AIO -[NO]ASYNCIO + Alloc -ALLOCATION + AutoDB -[NO]AUTODB + AutoSwitch -AUTOSWITCHLIMIT + Block -BLOCK_SIZE + Buff -BUFFER_SIZE + Dall -[NO]DEFER_ALLOCATE + Def Coll -COLLATION_DEFAULT + Epoch Taper -[NO]EPOCHTAPER + Exten -EXTENSION_COUNT + File -FILE_NAME + GLOB -GLOBAL_BUFFER_COUNT + Inst Freeze On Error -[NO]INST_FREEZE_ON_ERROR + JNL -[NO]JOURNAL + Key Size -KEY_SIZE + LOCK -LOCK_SPACE + LOCK Crit -[NO]LOCK_CRIT + MSLT -MUTEX_SLOTS + Null Subs -[HO]NULL_SUBSCRIPTS + Qdb Rndwn -[NO]QDBRUNDOWN + Std Null Coll -[NO]STDNULLCOLL + Rec Size -RECORD_SIZE + RES -RESERVED_BYTES + Region -REGION + Stats -[NO[STATS + Typ -DYNAMIC_SEGMENT 2 Customizing_a_Global_Directory Customizing a Global Directory @@ -306,7 +309,7 @@ Region Jnl File (def ext: .mjl) Before Buff Alloc Exten AutoSwitch ------------------------------------------------------------------------------------------ DEFAULT $gtmdir/$gtmver/g/gtm.mjl - Y 2312 2048 2048 8386560 + Y 2308 2048 2048 8386560 1 Using_GDE Using GDE @@ -1176,6 +1179,18 @@ The following -REGION qualifiers can be used with the ADD, CHANGE, or TEMPLATE commands. + -[NO]AU[TODB] + + Specifies whether GT.M should implicitly create a database file for the + region if none exists when a process attempts to access it. Because it + carries lower operational risk and provides better operational control, + the common practice is to create database files with MUPIP CREATE. + However, AUTODB may simplify operations when you have scratch or temporary + databases which are best deleted and recreated as a part of standard + operation procedures. + + The default is NOAUTODB. + -C[OLLATION_DEFAULT]=number Specifies the number of the collation sequence definition to be used as @@ -1290,7 +1305,7 @@ Example: - CHANGE -REGION DEFAULT -JOURNAL=(ALLOCATION=2048,AUTOSWITCHLIMIT=8386560,BEFORE_IMAGE,BUFFER_SIZE=2312,EXTENSION=2048) + CHANGE -REGION DEFAULT -JOURNAL=(ALLOCATION=2048,AUTOSWITCHLIMIT=8386560,BEFORE_IMAGE,BUFFER_SIZE=2308,EXTENSION=2048) Summary @@ -1316,7 +1331,19 @@ For example, the key ^ACN ("Name", "Type") internally occupies 17 bytes. - By default, GDE uses a KEY_SIZE of 64 bytes. + By default, GDE uses a KEY_SIZE of 64 bytes + + -[NO]L[OCK_CRIT] + + Specifies whether GT.M should share the resource management between a + database and its corresponding LOCKs or use separate and different + resource management for the two. Because, in the current implementation, + FIS has not identified any reason to share resource management between + LOCKs and database actions, we have no recommendations other than to + choose what seems to work better for your application. + + By default, GDE uses NOLOCK_CRIT-Sep(arate) resource management for LOCKs + and database actions. -[NO]N[ULL_SUBSCRIPTS]=[ALWAYS|NEVER|EXISTING] @@ -1387,7 +1414,17 @@ By default, GDE uses a RECORD_SIZE of 256 bytes. - -[NO]STDNULLCOLL + -[NO][STA[TS] + + Specifies whether GT.M should permit processes to share their database + access statistics for other processes to monitor. There may be operational + or security reasons to prohibit sharing of statistics. For example, GT.M + does not share statistics on database files that exist solely to support + GT.M features. + + By default, GDE uses STATS. + + -[NO]STD[NULLCOLL] Determines whether GT.M null subscripts collate in conformance to the M standard. @@ -1410,6 +1447,8 @@ |-----------------------------------------------------------------------------| | QUALIFIER | DEFAULT | MINIMUM | MAXIMUM | |--------------------------------------------+----------+---------+-----------| + |-[NO]AU[TODB] |Disabled |- |- | + |--------------------------------------------+----------+---------+-----------| |-C[OLLATION_DEFAULT]=number (integer) |0 |0 |255 | |--------------------------------------------+----------+---------+-----------| |-D[YNAMIC_SEGMENT] =segment-name (char) |- |1 |16 | @@ -1422,14 +1461,20 @@ |--------------------------------------------+----------+---------+-----------| |-K[EY_SIZE]=size in bytes (integer) |64 |3 |1,019 | |--------------------------------------------+----------+---------+-----------| + | |Disabled | | | + |-[NO]L[OCK_CRIT] |(not |- |- | + | |shared) | | | + |--------------------------------------------+----------+---------+-----------| |-N[ULL_SUBSCRIPTS]=[ALWAYS|NEVER|EXISTING] |NEVER |- |- | |--------------------------------------------+----------+---------+-----------| + |-[NO]Q[DBRNWDWN] |Disabled |- |- | + |--------------------------------------------+----------+---------+-----------| |-R[ECORD_SIZE]=size in bytes (integer) |256 |7 |1,048,576 | | | | |(1 MiB) | |--------------------------------------------+----------+---------+-----------| - |-[NO]Q[DBRUNDOWN] |DISABLED |- |- | + |-[NO]STA[TS] |ENABLED |- |- | |--------------------------------------------+----------+---------+-----------| - |-[NO]STDNULLCOLL |N |- |- | + |-[NO]STD[NULLCOLL] |No |- |- | +-----------------------------------------------------------------------------+ 2 Segment_Qualifiers @@ -1460,10 +1505,10 @@ is a greater reliance on the OS/file system for database performance. * MM supports NOBEFORE_IMAGE journaling only. GT.M issues an error - if you use MM with BEFORE_IMAGE Journaling. MM also supports - MUPIP JOURNAL -RECOVER -FORWARD. MM does not support MUPIP - JOURNAL -RECOVER -BACKWARD and only supports MUPIP JOURNAL - -ROLLBACK to generate lost and broken transaction files. + if you use MM with BEFORE_IMAGE Journaling. MM supports MUPIP + JOURNAL -RECOVER -FORWARD and MUPIP JOURNAL -ROLLBACK -FORWARD. + With MM, MUPIP JOURNAL -RECOVER -BACKWARD only generates lost and + broken transaction files but cannot recover the database. * Depending on your file system, MM may be an option when you need performance advantage in situations where the above restrictions are acceptable. @@ -1498,6 +1543,92 @@ file for a length of time consistent with your UNIX file reorganization schedule. + --[NO]AS[YNCIO] + + Determines whether an access method BG database file uses asynchronous I/O + rather than using synchronous I/O through the file system cache. + + The performance characteristics of asynchronous IO are likely to be quite + different from the traditional sequential IO. Although asynchronous IO in + theory should be more efficient than synchronous IO by eliminating the + need for the UNIX file buffer cache and eliminating certain filesystem + locks, in practice asynchronous IO is likely to emerge from the starting + gate under-performing synchronous IO because of the years that synchronous + IO has been the common IO model operating systems and filesystems have had + used by applications. So, you should anticipate extensive benchmarking and + tuning for your application to achieve the best performance it can with + asynchronous IO. Some notes and observations that we have to share: + + o As asynchronous IO dispenses with the UNIX file buffer cache, GT.M + global buffers are the sole caching mechanism. To make asynchronous IO + perform well, you will likely need to increase the number of global + buffers considerably. With GT.M's limit of 2GiB per shared memory + segment, a database segment with 4KiB blocks has a limit of almost two + million global buffers. + o A large number of global buffers potentially implies a large number of + dirty global buffers to be flushed at an epoch. You should investigate + the impact on application response time of GT.M epoch tapering vs. + turning off epoch tapering and using a separate stand-alone process + that executes a line of code such as: for set x="" for set + x=$view("gvnext",x) quit:""=x view "dbflush":x,"dbsync":x,"epoch":x + hang n where n is a number that causes each region to be flushed at an + appropriate interval. If you choose this option, remember to turn off + epoch tapering, and to set the epoch interval in the file header to be + large enough to prevent application processes from performing epochs, + and consider scripted timely switching of journal files by other than + application processes (switching journal files involves an epoch). + o On AIX, consider mounting file systems with the CIO mount option. The + CIO mount option drops support for the file buffer cache (unused by + asynchronous IO), and also eliminates a lock that is a potential + bottleneck to GT.M performance on the AIX jfs2 filesystem. + o For Linux x86_64, the gtm_aio_nr_events environment variable controls + the number of structures a process has per global directory to manage + asynchronous writes, and therefore determines the number of concurrent + writes a process can manage across all regions within a global + directory. If not specified, the value controlled by gtm_aio_nr_events + defaults to 128. If a process encounters a situation where it needs to + perform an asynchronous write, but has no available slots with which + to manage an additional one, it either falls back to synchronous + writing if the write is blocking other actions, and otherwise defers + the write until a slot becomes available as other writes complete. + Linux allocates the structures on a system-wide basis with the setting + of /proc/sys/fs/aio-max-nr. Therefore you should configure this + parameter to account for the needs (as determined by gtm_aio_nr_events + or the default) of all processes using asynchronous I/O. When + processes use multiple global directories with asynchronous I/O, their + need for the system resources increases accordingly. For example, if + an environment runs 10,000 processes each of which open two global + directories and /proc/sys/fs/aio-max-nr is set to a value of 200,000 + then gtm_aio_nr_events needs to be set to a value <= 200,000 / (10,000 + * 2) = 10. Conversely if gtm_aio_nr_events is set to a value of 20, + then aio-max-nr needs to be bumped up to (10,000 * 2 * 20) = 400,000. + GT.M captures the number of errors encountered when attempting to + write database blocks for a region, and, barring problems with the + storage subsystem, hitting an asynchronous write limit would + constitute primary (probably only) contribution to that value, which + you can access with the following: + + $$^%PEEKBYNAME("sgmnt_data.wcs_wterror_invoked_cntr",) + + o Limited experience with solid-state storage (SSDs) on Linux in the + GT.M development environment suggests a considerable difference in + asynchronous IO performance on the same underlying hardware, with f2fs + performing better than xfs, which in turn performed better than ext4. + + In GT.M development, we have not benchmarked asynchronous IO on the types + of storage commonly used for enterprise scale applications (as workloads + vary widely, we do not routinely benchmark workloads in development). + Please consider the above observations in this light. + + By default GDE uses NOASYNCIO. On segments with an access method of MM, + GT.M ignores this setting. + + -[NO]ENcryption + + Specifies whether or not the database file for a segment is flagged for + encryption. Note that MUPIP CREATE acquires an encryption key for this + file and puts a cryptographic hash of the key in the database file header. + -BL[OCK_SIZE]=size Specifies the size, in bytes, of each database block in the file system. @@ -1737,9 +1868,15 @@ |-----------------------------+-----------+-------+----------------------| | -AL[LOCATION]=size (blocks) | 100 | 10 | 1,040,187,392(992Mi) | |-----------------------------+-----------+-------+----------------------| + | -[NO]AS[YNCIO] | FALSE | - | - | + |-----------------------------+-----------+-------+----------------------| | -BL[OCK_SIZE]=size (bytes) | 1,024 | 512 | 65,024 | |-----------------------------+-----------+-------+----------------------| - | -[NO]EN[CRYPTION] | 0 | | | + | -[NO]DEFER_ALLOCATE | TRUE | - | - | + |-----------------------------+-----------+-------+----------------------| + | -[NO]ENCRYPTION | FALSE | - | - | + |-----------------------------+-----------+-------+----------------------| + | -[NO]EPOCHTAPER | TRUE | - | - | |-----------------------------+-----------+-------+----------------------| | -EX[TENSION_COUNT]=size | 100 | 0 | 65,535 | | (blocks) | | | | @@ -1937,12 +2074,22 @@ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-AL[LOCATION]=size(blocks) |100 |10 |1,040,187,392(992Mi) |- |- |X | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| + |-[NO]AS[YNCIO] |FALSE |- |- |- |- |X | + |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| + |-[NO]AU[TODB] |FALSE |- |- |- |X |- | + |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-BL[OCK_SIZE]=size(bytes) |1024 |512 |65024 |- |- |X | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-C[OLLATION_DEFAULT]=id-number (integer) |0 |0 |255 |- |X |- | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| + |-[NO]DEFER_ALLOCATE |TRUE |- |- |- |- |X | + |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-D[YNAMIC_SEGMENT]=segment-name (chars) |* |1A |16A/N |- |X |- | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| + |-[NO]ENCRYPTION |FALSE |- |- |- |- |X | + |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| + |-[NO]EPOCHTAPER |TRUE |- |- |- |- |X | + |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-EX[TENSION_COUNT]=size (blks) |100 |0 |65535 |- |- |X | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-F[ILE_NAME]=file-name (chars) |** |1A |255A/N |- |- |X | @@ -1952,6 +2099,8 @@ |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-K[EY_SIZE]=size (bytes) |64 |3 |1,019 |- |X |- | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| + |-[NO]L[OCK_CRIT] |FALSE |- |- |- |X |- | + |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-L[OCK_SPACE]=size (pages) |40 |10 |65,536 |- |- |X | |--------------------------------------------+-------+-------+----------------------+-----+-----+-----| |-M[UTEX_SLOTS]=integer |1,024 |1,024 |32,768 |- |- |X | @@ -1977,7 +2126,7 @@ 1 Copyright Copyright - Copyright 2016 + Copyright 2017 Fidelity National Information Services, Inc. and/or its subsidiaries. All rights reserved. @@ -1999,7 +2148,7 @@ **Note** - This help file is a concise representation of revision V6.3-000 of the + This help file is a concise representation of revision V6.3-001 of the UNIX Administration and Operations Guide. To obtain a copy of the current revision, go to www.fis-gtm.com and then click on the User Documentation tab. diff --git a/sr_port/gds_rundown.h b/sr_port/gds_rundown.h index b00bac4..b4165dc 100644 --- a/sr_port/gds_rundown.h +++ b/sr_port/gds_rundown.h @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -13,8 +13,10 @@ #ifndef GDS_RUNDOWN_INCLUDED #define GDS_RUNDOWN_INCLUDED -#ifdef UNIX -int4 gds_rundown(void); +#define CLEANUP_UDI_FALSE FALSE +#define CLEANUP_UDI_TRUE TRUE + +int4 gds_rundown(boolean_t cleanup_udi); #define CAN_BYPASS(SEMVAL, CSD, INST_IS_FROZEN) \ (INST_IS_FROZEN || FROZEN_CHILLED(CSD) \ @@ -48,8 +50,4 @@ int4 gds_rundown(void); # define PROC_FACTOR 20 #endif -#else -void gds_rundown(void); -#endif - #endif /* GDS_RUNDOWN_INCLUDED */ diff --git a/sr_port/gdsfhead.h b/sr_port/gdsfhead.h index 1325c52..f0a3d01 100644 --- a/sr_port/gdsfhead.h +++ b/sr_port/gdsfhead.h @@ -302,37 +302,44 @@ gtm_uint64_t verify_queue(que_head_ptr_t qhdr); # define MEM_UNMAP_SYSCALL "munmap()" # endif -#define GVKEY_INIT(GVKEY, KEYSIZE) \ -MBSTART { \ - GBLREF gv_key *gv_altkey; \ - GBLREF gv_key *gv_currkey; \ - gv_key *new_KEY, *old_KEY; \ - int4 keySZ; \ - \ - old_KEY = GVKEY; \ - keySZ = KEYSIZE; \ - /* KEYSIZE should have been the output of a DBKEYSIZE command so \ - * should be a multiple of 4. Assert that. \ - */ \ - assert(ROUND_UP2(keySZ, 4) == keySZ); \ - new_KEY = (gv_key *)malloc(SIZEOF(gv_key) - 1 + keySZ); \ - assert((DBKEYSIZE(MAX_KEY_SZ) == KEYSIZE) \ - || ((GVKEY != gv_currkey) && (GVKEY != gv_altkey))); \ - if (NULL != old_KEY) \ - { \ - assert(FALSE); /* don't call GVKEY_INIT twice for same key */ \ - assert(KEYSIZE >= old_KEY->top); \ - assert(old_KEY->top > old_KEY->end); \ - memcpy(new_KEY, old_KEY, SIZEOF(gv_key) + old_KEY->end); \ - free(old_KEY); \ - } else \ - { \ - new_KEY->base[0] = '\0'; \ - new_KEY->end = 0; \ - new_KEY->prev = 0; \ - } \ - new_KEY->top = keySZ; \ - GVKEY = new_KEY; \ +#define GVKEY_INIT(GVKEY, KEYSIZE) \ +MBSTART { \ + GBLREF gv_key *gv_altkey; \ + GBLREF gv_key *gv_currkey; \ + gv_key *new_KEY, *old_KEY; \ + int4 keySZ; \ + DEBUG_ONLY(DCL_THREADGBL_ACCESS); \ + \ + DEBUG_ONLY(SETUP_THREADGBL_ACCESS); \ + old_KEY = GVKEY; \ + keySZ = KEYSIZE; \ + /* KEYSIZE should have been the output of a DBKEYSIZE command so \ + * should be a multiple of 4. Assert that. \ + */ \ + assert(ROUND_UP2(keySZ, 4) == keySZ); \ + new_KEY = (gv_key *)malloc(SIZEOF(gv_key) - 1 + keySZ); \ + assert((DBKEYSIZE(MAX_KEY_SZ) == KEYSIZE) \ + || ((GVKEY != gv_currkey) && (GVKEY != gv_altkey))); \ + if (NULL != old_KEY) \ + { \ + /* Don't call GVKEY_INIT twice for same key. The only exception \ + * is if we are called from COPY_PREV_KEY_TO_GVT_CLUE in a \ + * restartable situation but TREF(donot_commit) should have \ + * been set to a special value then so check that. \ + */ \ + assert(TREF(donot_commit) | DONOTCOMMIT_COPY_PREV_KEY_TO_GVT_CLUE); \ + assert(KEYSIZE >= old_KEY->top); \ + assert(old_KEY->top > old_KEY->end); \ + memcpy(new_KEY, old_KEY, SIZEOF(gv_key) + old_KEY->end); \ + free(old_KEY); \ + } else \ + { \ + new_KEY->base[0] = '\0'; \ + new_KEY->end = 0; \ + new_KEY->prev = 0; \ + } \ + new_KEY->top = keySZ; \ + GVKEY = new_KEY; \ } MBEND #define GVKEY_FREE_IF_NEEDED(GVKEY) \ @@ -569,6 +576,26 @@ MBSTART { \ } \ } +/* The below macro is modeled pretty much like OPEN_BASEREG_IF_STATSREG except that this asserts that the + * other macro is not needed. And that whatever that macro sets up is already set up that way. + */ +#ifdef DEBUG +#define ASSERT_BASEREG_OPEN_IF_STATSREG(MAP) \ +{ \ + gd_region *baseDBreg, *statsDBreg; \ + \ + statsDBreg = MAP->reg.addr; \ + if (IS_STATSDB_REGNAME(statsDBreg)) \ + { \ + STATSDBREG_TO_BASEDBREG(statsDBreg, baseDBreg); \ + assert(baseDBreg->open); \ + assert(statsDBreg->open); \ + } \ +} +#else +#define ASSERT_BASEREG_OPEN_IF_STATSREG(MAP) +#endif + /* Calculate the # of subscripts in "KEY" and stores that in "NSUBS" */ #define GET_NSUBS_IN_GVKEY(PTR, LEN, NSUBS) \ MBSTART { \ @@ -603,6 +630,7 @@ MBSTART { \ if (WAS_OPEN) \ { \ REG->was_open = TRUE; \ + TREF(was_open_reg_seen) = TRUE; \ assert(DBKEYSIZE(REG->max_key_size) <= gv_keysize); \ } else \ GVKEYSIZE_INIT_IF_NEEDED; /* sets up "gv_keysize", "gv_currkey" and "gv_altkey" in sync */ \ @@ -1662,20 +1690,20 @@ enum tp_ntp_blkmod_type /* used for accounting in cs_data->tp_cdb_sc_blkmod[] * * the restart will anyway be detected before commit. In this cases, this variable will take on non-zero values. * The commit logic will assert that this variable is indeed zero after validation but before proceeding with commit. */ -#define DONOTCOMMIT_TPHIST_BLKTARGET_MISMATCH (1 << 0) /* Restartable situation encountered in tp_hist */ -#define DONOTCOMMIT_GVCST_DELETE_BLK_CSE_TLEVEL (1 << 1) /* Restartable situation encountered in gvcst_delete_blk */ -#define DONOTCOMMIT_JNLGETCHECKSUM_NULL_CR (1 << 2) /* Restartable situation encountered in jnl_get_checksum.h */ -#define DONOTCOMMIT_GVCST_KILL_ZERO_TRIGGERS (1 << 3) /* Restartable situation encountered in gvcst_kill */ -#define DONOTCOMMIT_GVCST_BLK_BUILD_TPCHAIN (1 << 4) /* Restartable situation encountered in gvcst_blk_build */ +#define DONOTCOMMIT_TPHIST_BLKTARGET_MISMATCH (1 << 0) /* Restartable situation seen in tp_hist */ +#define DONOTCOMMIT_GVCST_DELETE_BLK_CSE_TLEVEL (1 << 1) /* Restartable situation seen in gvcst_delete_blk */ +#define DONOTCOMMIT_JNLGETCHECKSUM_NULL_CR (1 << 2) /* Restartable situation seen in jnl_get_checksum.h */ +#define DONOTCOMMIT_GVCST_KILL_ZERO_TRIGGERS (1 << 3) /* Restartable situation seen in gvcst_kill */ +#define DONOTCOMMIT_GVCST_BLK_BUILD_TPCHAIN (1 << 4) /* Restartable situation seen in gvcst_blk_build */ #define DONOTCOMMIT_T_QREAD_BAD_PVT_BUILD (1 << 5) /* Restartable situation due to bad private build in t_qread */ -#define DONOTCOMMIT_GVCST_SEARCH_LEAF_BUFFADR_NOTSYNC (1 << 6) /* Restartable situation encountered in gvcst_search */ -#define DONOTCOMMIT_GVCST_SEARCH_BLKTARGET_MISMATCH (1 << 7) /* Restartable situation encountered in gvcst_search */ -#define DONOTCOMMIT_REALLOCATE_BITMAP_BMLMOD (1 << 8) /* Restartable situation encountered in reallocate_bitmap */ -#define DONOTCOMMIT_T_WRITE_CSE_DONE (1 << 9) /* Restartable situation encountered in t_write */ -#define DONOTCOMMIT_T_WRITE_CSE_MODE (1 << 10) /* Restartable situation encountered in t_write */ -#define DONOTCOMMIT_TRIGGER_SELECT_XECUTE (1 << 11) /* Restartable situation encountered in trigger_select */ -#define DONOTCOMMIT_JNL_FORMAT (1 << 12) /* Restartable situation encountered in jnl_format */ -#define DONOTCOMMIT_GVCST_PUT_SPLIT_TO_RIGHT (1 << 13) /* Restartable situation encountered in gvcst_put */ +#define DONOTCOMMIT_GVCST_SEARCH_LEAF_BUFFADR_NOTSYNC (1 << 6) /* Restartable situation seen in gvcst_search */ +#define DONOTCOMMIT_GVCST_SEARCH_BLKTARGET_MISMATCH (1 << 7) /* Restartable situation seen in gvcst_search */ +#define DONOTCOMMIT_GVCST_PUT_SPLIT_TO_RIGHT (1 << 8) /* Restartable situation seen in gvcst_put */ +#define DONOTCOMMIT_T_WRITE_CSE_DONE (1 << 9) /* Restartable situation seen in t_write */ +#define DONOTCOMMIT_T_WRITE_CSE_MODE (1 << 10) /* Restartable situation seen in t_write */ +#define DONOTCOMMIT_TRIGGER_SELECT_XECUTE (1 << 11) /* Restartable situation seen in trigger_select */ +#define DONOTCOMMIT_JNL_FORMAT (1 << 12) /* Restartable situation seen in jnl_format */ +#define DONOTCOMMIT_COPY_PREV_KEY_TO_GVT_CLUE (1 << 13) /* Restartable situation seen in COPY_PREV_KEY_TO_GVT_CLUE */ #define TAB_BG_TRC_REC(A,B) B, enum bg_trc_rec_type @@ -1875,7 +1903,7 @@ typedef struct sgmnt_data_struct */ volatile boolean_t filler_wc_blocked; /* Now moved to node_local */ boolean_t mumps_can_bypass; /* Allow mumps processes to bypass flushing, access control, and ftok semaphore - * in gds_rundown(). This was done to improve shutdown performance. + * in "gds_rundown". This was done to improve shutdown performance. */ boolean_t epoch_taper; /* If TRUE, GT.M tries to reduce dirty buffers as epoch approaches */ uint4 epoch_taper_time_pct; /* in the last pct we start tapering for time */ @@ -2400,7 +2428,7 @@ typedef struct gd_region_struct */ bool freeze_on_fail; bool mumps_can_bypass; /* Allow mumps processes to bypass flushing, access control, and ftok semaphore - * in gds_rundown(). This was done to improve shutdown performance. + * in "gds_rundown". This was done to improve shutdown performance. */ unsigned char jnl_file_len; unsigned char jnl_file_name[JNL_NAME_SIZE]; @@ -2571,6 +2599,10 @@ typedef struct sgmnt_addrs_struct boolean_t needs_post_freeze_online_clean; /* Perform cleanup of online freeze */ boolean_t needs_post_freeze_flushsync; /* Perform post-freeze flush/sync */ block_id tp_hint; /* last tp (allocation) hint for this process in this region */ + boolean_t statsDB_setup_completed; /* TRUE if ^%YGS node has been added to this statsDB file. + * Is a copy of reg->statsDB_setup_completed but is present in "csa" + * too to handle was_open regions. + */ } sgmnt_addrs; typedef struct gd_binding_struct @@ -3278,8 +3310,13 @@ MBSTART { \ if (NULL == GVT->prev_key) \ GVKEY_INIT(GVT->prev_key, GVT->clue.top); \ if (gv_altkey->end >= GVT->prev_key->top) \ - { \ - assert(FALSE); /* this means we have GVSUBOFLOW integ error */ \ + { /* Note that this is possible in case of concurrency issues (i.e. we are in \ + * a restartable situation (see comment at bottom of gvcst_expand_key.c which \ + * talks about a well-formed key. Since we cannot easily signal a restart here, \ + * we reallocate to ensure the COPY_KEY does not cause a buffer overflow and \ + * the caller will eventually do the restart. \ + */ \ + DEBUG_ONLY(TREF(donot_commit) |= DONOTCOMMIT_COPY_PREV_KEY_TO_GVT_CLUE;) \ GVKEY_INIT(GVT->prev_key, DBKEYSIZE(gv_altkey->end)); \ } \ COPY_KEY(GVT->prev_key, gv_altkey); \ diff --git a/sr_port/gtm_rename.h b/sr_port/gtm_rename.h index f99ce86..04ef296 100644 --- a/sr_port/gtm_rename.h +++ b/sr_port/gtm_rename.h @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2003, 2014 Fidelity Information Services, Inc * + * Copyright (c) 2003-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -17,16 +18,12 @@ #define RENAME_NOT_REQD 1 #define RENAME_FAILED 2 -#ifdef UNIX -# define JNLSWITCH_TM_FMT "_%Y%j%H%M%S" /* yearjuliandayhoursminutesseconds */ -#else -# define JNLSWITCH_TM_FMT "|!Y4|!H04!M0!S0|" /* 'julian' day is added by append_time_stamp() explicitly */ -#endif +#define JNLSWITCH_TM_FMT "_%Y%j%H%M%S" /* yearjuliandayhoursminutesseconds */ +#define JNLSWITCH_TM_FMT_LEN 14 /* SIZE of string produced by STRFTIME(JNLSWITCH_TM_FNT) */ int rename_file_if_exists(char *org_fn, int org_fn_len, char *rename_fn, int *rename_fn_len, uint4 *ustatus); uint4 gtm_rename(char *org_fn, int org_fn_len, char *rename_fn, int rename_len, uint4 *ustatus); uint4 prepare_unique_name(char *org_fn, int org_fn_len, char *prefix, char *suffix, char *rename_fn, int *rename_fn_len, jnl_tm_t now, uint4 *ustatus); -uint4 append_time_stamp(char *fn, int *fn_len, jnl_tm_t now); #endif diff --git a/sr_port/gtm_threadgbl_defs.h b/sr_port/gtm_threadgbl_defs.h index c7a1b43..7d6ac0c 100644 --- a/sr_port/gtm_threadgbl_defs.h +++ b/sr_port/gtm_threadgbl_defs.h @@ -87,7 +87,6 @@ THREADGBLDEF(window_token, char) /* current scanner token from advancewindo /* Database */ THREADGBLDEF(dbinit_max_delta_secs, uint4) /* max time before we bail out in db_init */ THREADGBLDEF(dollar_zmaxtptime, int4) /* tp timeout in seconds */ -THREADGBLDEF(donot_commit, boolean_t) /* debug-only - see gdsfhead.h for purpose */ THREADGBLDEF(donot_write_inctn_in_wcs_recover, boolean_t) /* TRUE if wcs_recover should NOT write INCTN */ THREADGBLDEF(gbuff_limit, mval) /* holds a GTM_POOLLIMIT value for REORG or DBG */ THREADGBLDEF(gd_targ_tn, trans_num) /* number that is incremented for every gvcst_spr* @@ -457,8 +456,10 @@ THREADGBLDEF(crit_reg_count, int4) /* A count of the number of regions/jnlpoo * has crit */ THREADGBLDEF(ok_to_see_statsdb_regs, boolean_t) /* FALSE implies statsdb regions are hidden at "gd_load" time */ +THREADGBLDEF(was_open_reg_seen, boolean_t) /* TRUE => there is at least one region with reg->was_open = TRUE */ /* Debug values */ #ifdef DEBUG +THREADGBLDEF(donot_commit, boolean_t) /* debug-only - see gdsfhead.h for purpose */ THREADGBLDEF(continue_proc_cnt, int) /* Used by whitebox secshr test to count time * process was continued. */ THREADGBLDEF(gtm_test_fake_enospc, boolean_t) /* DEBUG-only option to enable/disable anticipatory diff --git a/sr_port/gv_bind_name.c b/sr_port/gv_bind_name.c index cb5ba4c..59a3c86 100644 --- a/sr_port/gv_bind_name.c +++ b/sr_port/gv_bind_name.c @@ -52,16 +52,55 @@ error_def(ERR_GVIS); gvnh_reg_t *gv_bind_name(gd_addr *addr, mname_entry *gvname) { gd_binding *map; - ht_ent_mname *tabent; + ht_ent_mname *tabent, *tabent1; gd_region *reg; gvnh_reg_t *gvnh_reg; - int keylen; + int keylen, count; char format_key[MAX_MIDENT_LEN + 1]; /* max key length + 1 byte for '^' */ gv_namehead *tmp_gvt; sgmnt_addrs *csa; + hash_table_mname *tab_ptr; assert(MAX_MIDENT_LEN >= gvname->var_name.len); - if (NULL != (tabent = lookup_hashtab_mname((hash_table_mname *)addr->tab_ptr, gvname))) + tab_ptr = addr->tab_ptr; + if (NULL == (tabent = lookup_hashtab_mname((hash_table_mname *)tab_ptr, gvname))) + { + count = tab_ptr->count; /* Note down current # of valid entries in hash table */ + map = gv_srch_map(addr, gvname->var_name.addr, gvname->var_name.len, SKIP_BASEDB_OPEN_FALSE); + reg = map->reg.addr; + if (!reg->open) + gv_init_reg(reg); + if (IS_STATSDB_REG(reg)) + { /* In case of a statsDB, it is possible that "gv_srch_map" or "gv_init_reg" calls above end up doing + * a "op_gvname/gv_bind_name" if they in turn invoke "gvcst_init_statsDB". In that case, the hash table + * could have been updated since we did the "lookup_hashtab_mname" call above. So redo the lookup. + */ + tabent = lookup_hashtab_mname((hash_table_mname *)tab_ptr, gvname); + } else + { /* If not a statsDB, then the above calls to "gv_srch_map" or "gv_init_reg" should not have changed + * the hashtable status of "gvname". There is an exception in that if gvname is "%YGS" (STATSDB_GBLNAME), + * then it is possible that the open of the statsDB failed (e.g. gtm_statsdir env var too long etc.) in + * which case the gvname would have been dynamically remapped to the baseDB. Assert that. + * Since we want to avoid a memcmp against STATSDB_GBLNAME, we check if the hashtable count has changed + * since we noted it down at function entry and if so redo the lookup hashtab in pro. Since only additions + * happen in this particular hashtable, it is enough to check for "count < tab_ptr->count". + */ +# ifdef DEBUG + tabent1 = lookup_hashtab_mname((hash_table_mname *)tab_ptr, gvname); + assert((tabent1 == tabent) + || ((gvname->var_name.len == STATSDB_GBLNAME_LEN) + && (0 == memcmp(gvname->var_name.addr, STATSDB_GBLNAME, STATSDB_GBLNAME_LEN)) + && (count < tab_ptr->count))); +# endif + if (count < tab_ptr->count) + tabent = lookup_hashtab_mname((hash_table_mname *)tab_ptr, gvname); + } + } + if (NULL == tabent) + { + tmp_gvt = targ_alloc(reg->max_key_size, gvname, reg); + GVNH_REG_INIT(addr, tab_ptr, map, tmp_gvt, reg, gvnh_reg, tabent); + } else { gvnh_reg = (gvnh_reg_t *)tabent->value; assert(NULL != gvnh_reg); @@ -72,14 +111,6 @@ gvnh_reg_t *gv_bind_name(gd_addr *addr, mname_entry *gvname) assert((0 == gvnh_reg->gvt->clue.end) || IS_STATSDB_REG(reg)); /* A statsDB open writes to itself */ } tmp_gvt = gvnh_reg->gvt; - } else - { - map = gv_srch_map(addr, gvname->var_name.addr, gvname->var_name.len, SKIP_BASEDB_OPEN_FALSE); - reg = map->reg.addr; - if (!reg->open) - gv_init_reg(reg); - tmp_gvt = targ_alloc(reg->max_key_size, gvname, reg); - GVNH_REG_INIT(addr, addr->tab_ptr, map, tmp_gvt, reg, gvnh_reg, tabent); } if (((keylen = gvname->var_name.len) + 2) > reg->max_key_size) /* caution: embedded assignment of "keylen" */ { diff --git a/sr_port/gv_rundown.c b/sr_port/gv_rundown.c index 7968c48..e0b69c7 100644 --- a/sr_port/gv_rundown.c +++ b/sr_port/gv_rundown.c @@ -86,8 +86,9 @@ void gv_rundown(void) { for (r_local = addr_ptr->regions, r_top = r_local + addr_ptr->n_regions; r_local < r_top; r_local++) { - if (r_local->open && !r_local->was_open && dba_cm != r_local->dyn.addr->acc_meth) - { /* Rundown has already occurred for GT.CM client regions through gvcmy_rundown() above. + if (r_local->open && (dba_cm != r_local->dyn.addr->acc_meth)) + { + /* Rundown has already occurred for GT.CM client regions through gvcmy_rundown() above. * Hence the (dba_cm != ...) check in the if above. Note that for GT.CM client regions, * region->open is TRUE although cs_addrs is NULL. */ @@ -107,62 +108,7 @@ void gv_rundown(void) # endif gv_cur_region = r_local; tp_change_reg(); - rundown_status |= gds_rundown(); - /* Now that gds_rundown is done, free up the memory associated with the region. - * Ideally the following memory freeing code should go to gds_rundown, but - * GT.CM calls gds_rundown() and we want to reuse memory for GT.CM. - */ - if (NULL != cs_addrs) - { - if (NULL != cs_addrs->dir_tree) - FREE_CSA_DIR_TREE(cs_addrs); - if (cs_addrs->sgm_info_ptr) - { - si = cs_addrs->sgm_info_ptr; - /* It is possible we got interrupted before initializing all fields of "si" - * completely so account for NULL values while freeing/releasing those fields. - */ - assert((si->tp_csa == cs_addrs) || (NULL == si->tp_csa)); - if (si->jnl_tail) - { - PROBE_FREEUP_BUDDY_LIST(si->format_buff_list); - PROBE_FREEUP_BUDDY_LIST(si->jnl_list); - } - PROBE_FREEUP_BUDDY_LIST(si->recompute_list); - PROBE_FREEUP_BUDDY_LIST(si->new_buff_list); - PROBE_FREEUP_BUDDY_LIST(si->tlvl_info_list); - PROBE_FREEUP_BUDDY_LIST(si->tlvl_cw_set_list); - PROBE_FREEUP_BUDDY_LIST(si->cw_set_list); - if (NULL != si->blks_in_use) - { - free_hashtab_int4(si->blks_in_use); - free(si->blks_in_use); - si->blks_in_use = NULL; - } - if (si->cr_array_size) - { - assert(NULL != si->cr_array); - if (NULL != si->cr_array) - free(si->cr_array); - } - if (NULL != si->first_tp_hist) - free(si->first_tp_hist); - free(si); - } - if (cs_addrs->jnl) - { - assert(&FILE_INFO(cs_addrs->jnl->region)->s_addrs == cs_addrs); - if (cs_addrs->jnl->jnllsb) - { - assert(FALSE); - free(cs_addrs->jnl->jnllsb); - } - free(cs_addrs->jnl); - } - } - assert(gv_cur_region->dyn.addr->file_cntl->file_info); - free(gv_cur_region->dyn.addr->file_cntl->file_info); - free(gv_cur_region->dyn.addr->file_cntl); + rundown_status |= gds_rundown(CLEANUP_UDI_TRUE); } r_local->open = r_local->was_open = FALSE; } diff --git a/sr_port/gv_srch_map.c b/sr_port/gv_srch_map.c index b0309dd..a88124d 100644 --- a/sr_port/gv_srch_map.c +++ b/sr_port/gv_srch_map.c @@ -102,6 +102,14 @@ gd_binding *gv_srch_map_linear(gd_binding *start_map, char *key, int key_len) ) for ( ; ; map++) { + /* Currently, the only callers of this function are gvcst_spr_* functions (e.g. "gvcst_spr_data" etc.). + * And most of them (except gvcst_spr_query/gvcst_start_queryget) start an implicit TP transaction right + * after this call. And since statsDB init is deferred once in TP, it is preferable to do the init before + * the TP begins. So we include the OPEN_BASEREG_IF_STATSREG macro call here instead of in each of the + * caller. This can be moved back to the individual callers if new callers of this function happen which + * don't need this macro. + */ + OPEN_BASEREG_IF_STATSREG(map); /* can modify map->reg.addr if statsDBReg */ assert(map < &addr->maps[addr->n_maps]); res = memcmp(key, &map->gvkey.addr[0], key_len); if (0 < res) @@ -137,6 +145,13 @@ gd_binding *gv_srch_map_linear_backward(gd_binding *start_map, char *key, int ke ) for ( ; ; map--) { + /* Currently, the only caller of this function is "gvcst_spr_zprevious". And it starts an implicit TP transaction + * right after this call. And since statsDB init is deferred once in TP, it is preferable to do the init before + * the TP begins. So we include the OPEN_BASEREG_IF_STATSREG macro call here instead of in each of the + * caller. This can be moved back to the individual callers if new callers of this function happen which + * don't need this macro. + */ + OPEN_BASEREG_IF_STATSREG(map); /* can modify map->reg.addr if statsDBReg */ assert(map >= addr->maps); res = memcmp(key, &map->gvkey.addr[0], key_len); if (0 < res) diff --git a/sr_port/gvcst_init.c b/sr_port/gvcst_init.c index e7455d5..9caca60 100644 --- a/sr_port/gvcst_init.c +++ b/sr_port/gvcst_init.c @@ -87,6 +87,7 @@ GBLREF uint4 update_array_size, cumul_update_array_size; GBLREF ua_list *first_ua, *curr_ua; GBLREF short crash_count; GBLREF uint4 dollar_tlevel; +GBLREF uint4 dollar_trestart; GBLREF jnl_format_buffer *non_tp_jfb_ptr; GBLREF boolean_t mupip_jnl_recover; GBLREF buddy_list *global_tlvl_info_list; @@ -291,15 +292,18 @@ void gvcst_init(gd_region *reg) DBGRDB((stderr, "gvcst_init: reg->open return\n")); return; } - /* At this point, the baseDB is open but the statsDB is not automatically opened. This is possible - * if TREF(statshare_opted_in) is FALSE. In that case, this call to "gvcst_init" is coming through - * a direct reference to the statsDB (e.g. ZWR ^%YGS). But if the TREF is TRUE, then the statsDB - * should have been opened as part of the baseDB "gvcst_init" done above. Since it did not, that - * means some sort of error occurred that has sent messages to the user console or syslog so return - * right away to the caller which would silently adjust gld map entries so they do not point to this - * statsDB anymore (NOSTATS should already be set in the baseDB in this case, assert that). + /* At this point, the baseDB is open but the statsDB is not automatically opened. This is possible if + * a) TREF(statshare_opted_in) is FALSE. In that case, this call to "gvcst_init" is coming through + * a direct reference to the statsDB (e.g. ZWR ^%YGS). OR + * b) baseDBreg->was_open is TRUE. In that case, the statsDB open would have been short-circuited + * in "gvcst_init". + * c) Neither (a) nor (b). This means an open of the statsDB was attempted as part of the baseDB + * "gvcst_init" done above. Since it did not, that means some sort of error occurred that + * has sent messages to the user console or syslog so return right away to the caller which + * would silently adjust gld map entries so they do not point to this statsDB anymore + * (NOSTATS should already be set in the baseDB in this case, assert that). */ - if (TREF(statshare_opted_in)) + if (TREF(statshare_opted_in) && !baseDBreg->was_open) { assert(RDBF_NOSTATS & baseDBreg->reservedDBFlags); return; @@ -384,6 +388,26 @@ void gvcst_init(gd_region *reg) * have the same timer-id added twice due to the nested call). */ DBGRDB((stderr, "gvcst_init: !baseDBnl->statsdb_created\n")); + if (IS_TP_AND_FINAL_RETRY && baseDBcsa->now_crit) + { /* If this is a TP transaction and in the final retry, we are about to request the ftok + * sem lock on baseDBreg while already holding crit on baseDBReg. That is an out-of-order + * request which can lead to crit/ftok deadlocks so release crit before requesting it. + * This code is similar to the TPNOTACID_CHECK macro with the below exceptions. + * a) We do not want to issue the TPNOTACID syslog message since there is no ACID + * violation here AND + * b) We have to check for baseDBcsa->now_crit in addition to IS_TP_AND_FINAL_RETRY + * as it is possible this call comes from "tp_restart -> gv_init_reg -> gvcst_init" + * AND t_tries is still 3 but we do not hold crit on any region at that point + * (i.e. "tp_crit_all_regions" call is not yet done) and in that case we should + * not decrement t_tries (TP_FINAL_RETRY_DECREMENT_T_TRIES_IF_OK call below) + * as it would result in we later starting the final retry with t_tries = 2 but + * holding crit on all regions which is an out-of-design situation. + */ + TP_REL_CRIT_ALL_REG; + assert(!baseDBcsa->now_crit); + assert(!mupip_jnl_recover); + TP_FINAL_RETRY_DECREMENT_T_TRIES_IF_OK; + } DEFER_INTERRUPTS(INTRPT_IN_GVCST_INIT, prev_intrpt_state); if (!ftok_sem_lock(baseDBreg, FALSE)) { @@ -700,8 +724,7 @@ void gvcst_init(gd_region *reg) csa->regcnt++; /* Increment # of regions that point to this csa */ return; } - /* Assert that two base regions pointing to the same basedb can never have different statsdbs */ - assert(!is_statsDB || !baseDBreg->was_open); + /* Note that if we are opening a statsDB, it is possible baseDBreg->was_open is TRUE at this point. */ reg->was_open = FALSE; /* We shouldn't have crit on any region unless we are in TP and in the final retry or we are in mupip_set_journal * trying to switch journals across all regions. WBTEST_HOLD_CRIT_ENABLED is an exception because it exercises a diff --git a/sr_port/gvcst_reservedDB_funcs.c b/sr_port/gvcst_reservedDB_funcs.c index a26dfac..9e86e94 100644 --- a/sr_port/gvcst_reservedDB_funcs.c +++ b/sr_port/gvcst_reservedDB_funcs.c @@ -159,6 +159,7 @@ void gvcst_init_statsDB(gd_region *baseDBreg, boolean_t do_statsdb_init) SETUP_THREADGBL_ACCESS; BASEDBREG_TO_STATSDBREG(baseDBreg, statsDBreg_located); + assert(!statsDBreg_located->statsDB_setup_completed); assert(baseDBreg->open); assert(dba_cm != baseDBreg->dyn.addr->acc_meth); baseDBcsa = &FILE_INFO(baseDBreg)->s_addrs; @@ -193,7 +194,6 @@ void gvcst_init_statsDB(gd_region *baseDBreg, boolean_t do_statsdb_init) } break; } - assert(!baseDBreg->was_open); if (0 < dollar_tlevel) { /* We are inside a transaction. We cannot do this inside a transaction for two reasons: * @@ -246,8 +246,8 @@ void gvcst_init_statsDB(gd_region *baseDBreg, boolean_t do_statsdb_init) /* Create a condition handler so the above saved items can be undone on an error to restore the environment */ ESTABLISH_NORET(gvcst_statsDB_init_ch, longjmp_done2); if (longjmp_done2) - { /* We returned here due to an error encountered somewhere below. Restore the things that were saved, - * then REVERT our handler and drive the next handler on the list via DRIVECH(). + { /* We returned here due to an error encountered somewhere below. + * Restore the things that were saved, then REVERT our handler. */ REVERT; RESTORE_SAVED_VALUES; @@ -334,7 +334,8 @@ void gvcst_init_statsDB(gd_region *baseDBreg, boolean_t do_statsdb_init) if (!statsDBcsa->orig_read_write) /* Database was opened read/only as this process has no privs to write to it - raise error */ rts_error_csa(CSA_ARG(statsDBcsa) VARLSTCNT(4) ERR_DBPRIVERR, 2, DB_LEN_STR(statsDBreg)); - if (!statsDBreg->statsDB_setup_completed) + assert(!statsDBreg->statsDB_setup_completed); + if (!statsDBcsa->statsDB_setup_completed) { /* If initialization was never completed, do it now */ assert(IS_STATSDB_REG(statsDBreg)); /* Step 2: Now figure out the alignment pad size needed to make record fields align in memory */ @@ -357,8 +358,6 @@ void gvcst_init_statsDB(gd_region *baseDBreg, boolean_t do_statsdb_init) op_gvput(&statsDBrec_mval); /* Step 3: Now we have written a record - set the DB to R/O */ assert(statsDBcsa == &FILE_INFO(statsDBreg)->s_addrs); - statsDBreg->read_only = TRUE; - statsDBcsa->read_write = FALSE; /* Maintain read_only/read_write in parallel */ assert(statsDBcsa->orig_read_write); /* Step 4: Locate the newly written record and update the csa->gvstats_rec_p so new stats updates occur * in shared memory instead of process-private. @@ -374,8 +373,11 @@ void gvcst_init_statsDB(gd_region *baseDBreg, boolean_t do_statsdb_init) baseDBcsa->gvstats_rec_p = (gvstats_rec_t *)(bh->buffaddr + sizewkey + padsize); /* ==> Start of gvstats_rec_t */ assert(0 == (((UINTPTR_T)baseDBcsa->gvstats_rec_p) & 0x7)); /* Verify 8 byte alignment */ - statsDBreg->statsDB_setup_completed = TRUE; + statsDBcsa->statsDB_setup_completed = TRUE; } + statsDBreg->read_only = TRUE; + statsDBcsa->read_write = FALSE; /* Maintain read_only/read_write in parallel */ + statsDBreg->statsDB_setup_completed = TRUE; REVERT; /* Restore previous region's setup */ RESTORE_SAVED_VALUES; @@ -469,7 +471,7 @@ void gvcst_remove_statsDB_linkage(gd_region *baseDBreg) i2mval(&pid_mval, process_id); /* Step 1: Locate the existing ^%YGS(region,pid) node. This locates the existing record for us so we can * copy the gvstats_rec data back to private storage in cs_addrs but also sets up the key for the - * op_kill() call to kill that record. + * "op_gvkill" call to kill that record. */ save_gd_header = gd_header; /* save "gd_header" before tampering with global variable */ gd_header = baseDBreg->owning_gd; /* direct "op_gvname" to search for maps in this gld */ @@ -484,34 +486,45 @@ void gvcst_remove_statsDB_linkage(gd_region *baseDBreg) assert(statsDBreg->statsDB_setup_completed); /* Step 2: Need to switch the database back to R/W so we can do the KILL */ assert(statsDBcsa == &FILE_INFO(statsDBreg)->s_addrs); - statsDBreg->read_only = FALSE; - statsDBcsa->read_write = TRUE; /* Maintain read_only/read_write in parallel */ - assert(statsDBcsa->orig_read_write); - /* Step 3: Copy the shared gvstats_rec_t data back to private and for debug, verify record address in DEBUG but only - * if the baseDB is actually still open. + /* Note that if multiple statsDB regions map to the same statsDB file, it is possible to have + * statsDBreg->statsDB_setup_completed TRUE for more than one such region in which case all of them + * would map to the same statsDBcsa and might end up calling this function more than once for the same statsDBcsa. + * In that case, do the removal of ^%YGS node only once. The below check accomplishes that. */ - if (baseDBreg->open) + statsDBreg->read_only = FALSE; + if (statsDBcsa->statsDB_setup_completed) { - baseDBcsa = &FILE_INFO(baseDBreg)->s_addrs; -# ifdef DEBUG - gvcst_get(&stats_rec); /* Fetch record to set history for DEBUG mode validation */ - bh = gv_target->hist.h; - assert(0 != bh->curr_rec.match); /* Shouldn't be possible to create a GVT with this call */ - assert((gv_currkey->end + 1) == bh->curr_rec.match); - assert(SIZEOF(blk_hdr) == bh->curr_rec.offset); /* We should find 1st record in block */ - recptr = (rec_hdr *)(bh->buffaddr + SIZEOF(blk_hdr)); - recsize = recptr->rsiz; - /* The gvstats_rec_t part of the record is the last part of the record */ - gvstats_rec_p = (gvstats_rec_t *)((char *)recptr + (recsize - SIZEOF(gvstats_rec_t))); - assert(gvstats_rec_p == baseDBcsa->gvstats_rec_p); -# else - gvstats_rec_p = baseDBcsa->gvstats_rec_p; -# endif - memcpy(&baseDBcsa->gvstats_rec, gvstats_rec_p, SIZEOF(gvstats_rec_t)); - baseDBcsa->gvstats_rec_p = &baseDBcsa->gvstats_rec; /* ==> Reset start of gvstats_rec_t to private */ + statsDBcsa->read_write = TRUE; /* Maintain read_only/read_write in parallel */ + assert(statsDBcsa->orig_read_write); + /* Step 3: Copy the shared gvstats_rec_t data back to private and for debug, verify record address in DEBUG but only + * if the baseDB is actually still open. + */ + if (baseDBreg->open) + { + baseDBcsa = &FILE_INFO(baseDBreg)->s_addrs; +# ifdef DEBUG + gvcst_get(&stats_rec); /* Fetch record to set history for DEBUG mode validation */ + bh = gv_target->hist.h; + assert(0 != bh->curr_rec.match); /* Shouldn't be possible to create a GVT with this call */ + assert((gv_currkey->end + 1) == bh->curr_rec.match); + assert(SIZEOF(blk_hdr) == bh->curr_rec.offset); /* We should find 1st record in block */ + recptr = (rec_hdr *)(bh->buffaddr + SIZEOF(blk_hdr)); + recsize = recptr->rsiz; + /* The gvstats_rec_t part of the record is the last part of the record */ + gvstats_rec_p = (gvstats_rec_t *)((char *)recptr + (recsize - SIZEOF(gvstats_rec_t))); + assert(gvstats_rec_p == baseDBcsa->gvstats_rec_p); +# else + gvstats_rec_p = baseDBcsa->gvstats_rec_p; +# endif + memcpy(&baseDBcsa->gvstats_rec, gvstats_rec_p, SIZEOF(gvstats_rec_t)); + baseDBcsa->gvstats_rec_p = &baseDBcsa->gvstats_rec; /* ==> Reset start of gvstats_rec_t to private */ + } + /* Step 4: Kill the record */ + op_gvkill(); + statsDBcsa->statsDB_setup_completed = FALSE; } - /* Step 4: Kill the record */ - op_gvkill(); + statsDBreg->statsDB_setup_started = FALSE; + statsDBreg->statsDB_setup_completed = FALSE; /* Restore previous region's setup */ TP_CHANGE_REG(save_cur_region); gv_target = save_gv_target; @@ -529,24 +542,26 @@ void gvcst_remove_statsDB_linkage(gd_region *baseDBreg) void gvcst_statshare_optin(void) { gd_addr *gdhdr_addr; - gd_region *r_top, *r_save, *r_local; - gd_region *statsDBreg; + gd_region *r_save, *r_top; + gd_region *baseDBreg, *statsDBreg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; assert(0 == dollar_tlevel); TREF(statshare_opted_in) = TRUE; - for (gdhdr_addr = get_next_gdr(NULL); gdhdr_addr; gdhdr_addr = get_next_gdr(gdhdr_addr)) + for (gdhdr_addr = get_next_gdr(NULL); NULL != gdhdr_addr; gdhdr_addr = get_next_gdr(gdhdr_addr)) { /* For each global directory */ - for (r_local = gdhdr_addr->regions, r_top = r_local + gdhdr_addr->n_regions; r_local < r_top; r_local++) - {/* For each region */ - if (r_local->open && !r_local->was_open && (dba_cm != r_local->dyn.addr->acc_meth) - && !IS_STATSDB_REG(r_local) && !(RDBF_NOSTATS & r_local->reservedDBFlags)) + for (baseDBreg = gdhdr_addr->regions, r_top = baseDBreg + gdhdr_addr->n_regions; baseDBreg < r_top; baseDBreg++) + { /* For each region */ + if (!IS_REG_BG_OR_MM(baseDBreg) || IS_STATSDB_REG(baseDBreg)) + continue; + if (RDBF_NOSTATS & baseDBreg->reservedDBFlags) + continue; + if (baseDBreg->open) { /* Initialize statsDB for the given baseDB region */ - BASEDBREG_TO_STATSDBREG(r_local, statsDBreg); - assert(!statsDBreg->statsDB_setup_started); + BASEDBREG_TO_STATSDBREG(baseDBreg, statsDBreg); statsDBreg->statsDB_setup_started = TRUE; - gvcst_init_statsDB(r_local, DO_STATSDB_INIT_TRUE); + gvcst_init_statsDB(baseDBreg, DO_STATSDB_INIT_TRUE); } } } @@ -556,29 +571,24 @@ void gvcst_statshare_optin(void) void gvcst_statshare_optout(void) { gd_addr *gdhdr_addr; - gd_region *r_top, *r_save, *baseDBreg, *statsDBreg, *save_cur_region; + gd_region *r_top, *r_save, *baseDBreg, *statsDBreg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; assert(0 == dollar_tlevel); - save_cur_region = gv_cur_region; for (gdhdr_addr = get_next_gdr(NULL); gdhdr_addr; gdhdr_addr = get_next_gdr(gdhdr_addr)) { /* For each global directory */ for (baseDBreg = gdhdr_addr->regions, r_top = baseDBreg + gdhdr_addr->n_regions; baseDBreg < r_top; baseDBreg++) { /* For each region */ - if (baseDBreg->open && !baseDBreg->was_open && (dba_cm != baseDBreg->dyn.addr->acc_meth) - && !IS_STATSDB_REG(baseDBreg) && !(RDBF_NOSTATS & baseDBreg->reservedDBFlags)) - { /* baseDB is open and is not a statsDB and we are collecting stats on the baseDB */ + if (!IS_REG_BG_OR_MM(baseDBreg) || IS_STATSDB_REG(baseDBreg)) + continue; + if (RDBF_NOSTATS & baseDBreg->reservedDBFlags) + continue; + if (baseDBreg->open) + { BASEDBREG_TO_STATSDBREG(baseDBreg, statsDBreg); if (statsDBreg->open && statsDBreg->statsDB_setup_completed) - { /* statsDB is open and was initialized */ - assert(!statsDBreg->was_open); gvcst_remove_statsDB_linkage(baseDBreg); - /* temporarily switch "gv_cur_region" for call to "gds_rundown" */ - TP_CHANGE_REG(statsDBreg); - gds_rundown(); - TP_CHANGE_REG(save_cur_region); - } } } } @@ -603,11 +613,8 @@ void gvcst_remove_statsDB_linkage_all(void) { /* For each global directory */ for (statsDBreg = gdhdr_addr->regions, r_top = statsDBreg + gdhdr_addr->n_regions; statsDBreg < r_top; statsDBreg++) { - if (statsDBreg->open && IS_STATSDB_REG(statsDBreg) - && statsDBreg->statsDB_setup_completed) + if (statsDBreg->open && IS_STATSDB_REG(statsDBreg) && statsDBreg->statsDB_setup_completed) { /* We really are an OPEN and initialized statsDB - remove the link */ - if (statsDBreg->was_open) /* StatsDB open under different name */ - continue; /* Nothing to do */ STATSDBREG_TO_BASEDBREG(statsDBreg, baseDBreg); assert(NULL != baseDBreg); gvcst_remove_statsDB_linkage_wrapper(baseDBreg, statsDBreg); @@ -641,6 +648,7 @@ void gvcst_remove_statsDB_linkage_wrapper(gd_region *baseDBreg, gd_region *stats void gvcst_deferred_init_statsDB(void) { statsDB_deferred_init_que_elem *sdiqeptr, *sdiqeptr_next; + gd_region *baseDBreg, *statsDBreg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; @@ -648,14 +656,16 @@ void gvcst_deferred_init_statsDB(void) return; assert(0 == dollar_tlevel); assert(NULL != TREF(statsDB_init_defer_anchor)); - for (sdiqeptr = TREF(statsDB_init_defer_anchor), sdiqeptr_next = sdiqeptr->next; sdiqeptr; - sdiqeptr = sdiqeptr_next) + for (sdiqeptr = TREF(statsDB_init_defer_anchor), sdiqeptr_next = sdiqeptr->next; sdiqeptr; sdiqeptr = sdiqeptr_next) { /* For each statsDB on the queue, perform initialization and free the deferred init block */ sdiqeptr_next = sdiqeptr->next; /* Next entry on queue or NULL */ /* We wanted to initialize it earlier but couldn't because we were in a transaction. Now the baseDB * still needs to be open and not re-opened and we can't have completed initialization elsewhere. */ - if (sdiqeptr->baseDBreg->open && !sdiqeptr->baseDBreg->was_open && !sdiqeptr->statsDBreg->statsDB_setup_completed) + baseDBreg = sdiqeptr->baseDBreg; + statsDBreg = sdiqeptr->statsDBreg; + assert(baseDBreg->open); + if (!statsDBreg->statsDB_setup_completed) gvcst_init_statsDB(sdiqeptr->baseDBreg, DO_STATSDB_INIT_TRUE); TREF(statsDB_init_defer_anchor) = sdiqeptr_next; /* Remove current entry from queue */ free(sdiqeptr); diff --git a/sr_port/jnl.h b/sr_port/jnl.h index 212e042..ba3fad3 100644 --- a/sr_port/jnl.h +++ b/sr_port/jnl.h @@ -72,21 +72,14 @@ error_def(ERR_JNLENDIANLITTLE); */ #define JRT_MAX_V24 JRT_ULGTRIG /* Max jnlrec type in GDSJNL24/GDSJNL25 that can be input to replication filter */ -#ifdef UNIX -# define JNL_ALLOC_DEF 2048 -# define JNL_ALLOC_MIN 2048 -#elif defined(VMS) -# define JNL_ALLOC_DEF 100 -# define JNL_ALLOC_MIN 10 -#endif +#define JNL_ALLOC_DEF 2048 +#define JNL_ALLOC_MIN 2048 -#ifdef UNIX /* The journal buffer size (specified in pages of size DISK_BLOCK_SIZE) should be large enough for one largest record, * which is equivalent to the largest possible value (of size MAX_STRLEN) and largest possible key (of size MAX_KEY_SZ), * plus the overhead of storing the journal records. */ -# define JNL_BUFFER_MIN ((MAX_LOGI_JNL_REC_SIZE + ROUND_UP(2 * MAX_IO_BLOCK_SIZE, DISK_BLOCK_SIZE)) / DISK_BLOCK_SIZE + 1) -#endif +#define JNL_BUFFER_MIN ((MAX_LOGI_JNL_REC_SIZE + ROUND_UP(2 * MAX_IO_BLOCK_SIZE, DISK_BLOCK_SIZE)) / DISK_BLOCK_SIZE + 1) #define JNL_BUFFER_MAX 32768 /* # of 512-byte blocks = 16Mb journal buffer size */ /* JNL_EXTEND_DEF allocation size / 10 @@ -95,13 +88,8 @@ error_def(ERR_JNLENDIANLITTLE); */ #define JNL_EXTEND_MIN 0 -#ifdef UNIX -# define JNL_EXTEND_DEF 2048 -# define JNL_EXTEND_MAX 1073741823 -#else -# define JNL_EXTEND_DEF 100 -# define JNL_EXTEND_MAX 65535 -#endif +#define JNL_EXTEND_DEF 2048 +#define JNL_EXTEND_MAX 1073741823 #define JNL_MIN_WRITE 32768 #define JNL_MAX_WRITE 65536 /* FE was changed to EB because, the bit pattern there seems to vary more than the one for "FE". @@ -111,11 +99,7 @@ error_def(ERR_JNLENDIANLITTLE); /* In Unix, with sync_io, we do journal writes to disk at filesystem block size boundaries. * In VMS, the writes are at 512-byte boundaries only. */ -#ifdef UNIX -# define JNL_WRT_START_MODULUS(jb) jb->fs_block_size -#elif defined(VMS) -# define JNL_WRT_START_MODULUS(jb) 512 -#endif +#define JNL_WRT_START_MODULUS(jb) jb->fs_block_size #define JNL_WRT_START_MASK(jb) ~(JNL_WRT_START_MODULUS(jb) - 1) /* mask defining where the next physical write needs to * happen as follows from the size of JNL_WRT_START_MODULUS */ @@ -123,21 +107,12 @@ error_def(ERR_JNLENDIANLITTLE); #define JNL_WRT_END_MODULUS 8 #define JNL_WRT_END_MASK ((uint4)~(JNL_WRT_END_MODULUS - 1)) -#ifdef UNIX -# define JNL_MIN_ALIGNSIZE (1 << 12) /* 4096 disk blocks effectively 2M alignsize */ -# define JNL_DEF_ALIGNSIZE (1 << 12) /* 4096 disk blocks effectively 2M alignsize */ -#else -# define JNL_MIN_ALIGNSIZE (1 << 5) /* 32 disk blocks effectively 16K alignsize */ -# define JNL_DEF_ALIGNSIZE (1 << 7) /* 128 disk blocks effectively 64K alignsize */ -#endif +#define JNL_MIN_ALIGNSIZE (1 << 12) /* 4096 disk blocks effectively 2M alignsize */ +#define JNL_DEF_ALIGNSIZE (1 << 12) /* 4096 disk blocks effectively 2M alignsize */ #define JNL_MAX_ALIGNSIZE (1 << 22) /* 4194304 disk blocks effectively 2G alignsize */ #define JNL_REC_START_BNDRY 8 -#ifdef UNIX /* maximum logical journal record size */ -# define MAX_LOGI_JNL_REC_SIZE (ROUND_UP(MAX_STRLEN, DISK_BLOCK_SIZE) + ROUND_UP(MAX_KEY_SZ, DISK_BLOCK_SIZE)) -#else -# define MAX_LOGI_JNL_REC_SIZE (MAX_DB_BLK_SIZE) /* maximum logical journal record size */ -#endif +#define MAX_LOGI_JNL_REC_SIZE (ROUND_UP(MAX_STRLEN, DISK_BLOCK_SIZE) + ROUND_UP(MAX_KEY_SZ, DISK_BLOCK_SIZE)) /* one more disk-block for PBLK record header/footer */ #define MAX_JNL_REC_SIZE (MAX_LOGI_JNL_REC_SIZE + DISK_BLOCK_SIZE) /* Very large records require spanning nodes, which only happen in TP. */ @@ -170,15 +145,9 @@ error_def(ERR_JNLENDIANLITTLE); #define MAX_YIELD_LIMIT 2048 #define DEFAULT_YIELD_LIMIT 8 -#ifdef UNIX /* Have a minimum jnl-file-auto-switch-limit of 4 align boundaries (currently each align boundary is 2M) */ #define JNL_AUTOSWITCHLIMIT_MIN (4 * JNL_MIN_ALIGNSIZE) #define JNL_AUTOSWITCHLIMIT_DEF 8386560 /* Instead of 8388607 it is adjusted for default allocation = extension = 2048 */ -#else -/* Have a minimum jnl-file-auto-switch-limit of 128 align boundaries (currently each align boundary is 16K) */ -#define JNL_AUTOSWITCHLIMIT_MIN (128 * JNL_MIN_ALIGNSIZE) -#define JNL_AUTOSWITCHLIMIT_DEF 8388600 /* Instead of 8388607 it is adjusted for default allocation = extension = 100 */ -#endif /* options (4-bytes unsigned integer) to wcs_flu() (currently flush_hdr, write_epoch, sync_epoch) are bit-wise ored */ #define WCSFLU_NONE 0 @@ -653,7 +622,7 @@ typedef struct This offset was supposed to have EOF_RECORD before recover switched journal. A non-zero value means this journal was recovered and had the turn around point. */ off_jnl_t virtual_size; /* Allocation + n * Extension (in blocks). jnl_file_extend updates it */ - boolean_t crash; /* crashed before jnl_file_close() completed */ + boolean_t crash; /* crashed before "jnl_file_close" completed */ boolean_t recover_interrupted; /* true when recover creates the journal file; false after success. */ off_jnl_t turn_around_offset; /* At turn around point journal record's (EPOCH) offset */ jnl_tm_t turn_around_time; /* At turn around point journal record's timestamp */ @@ -664,11 +633,7 @@ typedef struct uint4 autoswitchlimit;/* Limit in disk blocks (max 4GBytes) when jnl should be auto switched */ uint4 jnl_alq; /* initial allocation (in blocks) */ uint4 jnl_deq; /* extension (in blocks) */ -#ifdef VMS - boolean_t update_disabled;/* If the secondary side has database update disabled. For rollback. */ -#else boolean_t filler_update_disabled; /* obsoleted as part of multi-site replication changes */ -#endif int4 max_jrec_len; /* Maximum length in bytes of a journal record. * Although computed from the database block size, we need this * stored as well in case database is not available */ @@ -693,8 +658,11 @@ typedef struct seq_num strm_start_seqno[MAX_SUPPL_STRMS]; seq_num strm_end_seqno[MAX_SUPPL_STRMS]; boolean_t last_eof_written; /* No more records may be written to the file due to autoswitch */ + boolean_t is_not_latest_jnl; /* Set to TRUE if this jnl becomes a previous generation jnl file + * at some point in time (relied upon by mur_tp_resolve_time). + */ /* filler remaining */ - char filler[436]; + char filler[432]; } jnl_file_header; typedef struct @@ -1114,17 +1082,6 @@ typedef struct mu_set_reglist boolean_t before_images; } mu_set_rlist; -/* The enum codes below correspond to code-paths that can call set_jnl_file_close() in VMS */ -typedef enum -{ - SET_JNL_FILE_CLOSE_BACKUP = 1, /* just for safety a non-zero value to start with */ - SET_JNL_FILE_CLOSE_SETJNL, - SET_JNL_FILE_CLOSE_EXTEND, - SET_JNL_FILE_CLOSE_RUNDOWN, - SET_JNL_FILE_CLOSE_REORG_ENCRYPT, - SET_JNL_FILE_CLOSE_INVALID_OP -} set_jnl_file_close_opcode_t; - typedef void (*pini_addr_reset_fnptr)(sgmnt_addrs *csa); typedef struct @@ -1201,12 +1158,7 @@ typedef struct /* pass address of jnl_buffer to get address of expanded jnl file name */ #define JNL_GDID_PVT(CSA) ((CSA)->jnl->fileid) - -#ifdef UNIX #define JNL_GDID_PTR(CSA) ((gd_id_ptr_t)(&((CSA)->nl->jnl_file.u))) -#else -#define JNL_GDID_PTR(CSA) ((gd_id_ptr_t)(&((CSA)->nl->jnl_file.jnl_file_id))) -#endif /* Note that since "cycle" (in jpc and jb below) can rollover the 4G limit back to 0, it should * only be used to do "!=" checks and never to do ordered checks like "<", ">", "<=" or ">=". @@ -1240,7 +1192,6 @@ typedef struct * reach mur_close_files, we should no longer be in an active transaction and so we don't need to make any adjustments. * VMS does not support supplementary instances so the below macro does not apply there at all. */ -#ifdef UNIX #define MUR_ADJUST_STRM_REG_SEQNO_IF_NEEDED(CSD, DST) \ { \ int strm_num; \ @@ -1266,9 +1217,6 @@ typedef struct } \ } \ } -#else -#define MUR_ADJUST_STRM_REG_SEQNO_IF_NEEDED(CSD, DST) -#endif /* Given a journal record, GET_TN returns the tn field */ @@ -1304,11 +1252,7 @@ typedef struct * are identical in VMS where it is currently 2K. */ #define REAL_JNL_HDR_LEN SIZEOF(jnl_file_header) -#ifdef UNIX -# define JNL_HDR_LEN 64 * 1024 -#elif defined(VMS) -# define JNL_HDR_LEN REAL_JNL_HDR_LEN -#endif +#define JNL_HDR_LEN 64 * 1024 #define JNL_FILE_FIRST_RECORD JNL_HDR_LEN /* Minimum possible journal file size */ @@ -1332,7 +1276,6 @@ typedef struct /* the following macro uses 8-byte quantities (gtm_uint64_t) to perform additions that might cause a 4G overflow */ #define DISK_BLOCKS_SUM(freeaddr, jrec_size) DIVIDE_ROUND_UP((((gtm_uint64_t)(freeaddr)) + (jrec_size)), DISK_BLOCK_SIZE) -#if defined(UNIX) /* For future portability JNLBUFF_ALLOC is defined in jnl.h instead of jnlsp.h */ #define JPC_ALLOC(csa) \ { \ @@ -1349,26 +1292,6 @@ typedef struct csa->nl->jnl_file.u.inode = 0; \ csa->nl->jnl_file.u.device = 0; \ } -#elif defined(VMS) -#define JPC_ALLOC(csa) \ -{ \ - vms_lock_sb *tmp_jnllsb; \ - if (NULL == csa->jnl) \ - { \ - csa->jnl = (jnl_private_control *)malloc(SIZEOF(*csa->jnl)); \ - memset(csa->jnl, 0, SIZEOF(*csa->jnl)); \ - csa->jnl->jnllsb = malloc(SIZEOF(vms_lock_sb)); \ - } else \ - { \ - tmp_jnllsb = csa->jnl->jnllsb; \ - memset(csa->jnl, 0, SIZEOF(*csa->jnl)); \ - csa->jnl->jnllsb = tmp_jnllsb; \ - } \ - memset(csa->jnl->jnllsb, 0, SIZEOF(vms_lock_sb)); \ -} -#define ASSERT_JNLFILEID_NOT_NULL(csa) assert(0 != memcmp(csa->nl->jnl_file.jnl_file_id.fid, zero_fid, SIZEOF(zero_fid))); -#define NULLIFY_JNL_FILE_ID(csa) memset(&csa->nl->jnl_file.jnl_file_id, 0, SIZEOF(gds_file_id)) -#endif #define JNL_INIT(csa, reg, csd) \ { \ csa->jnl_state = csd->jnl_state; \ @@ -1395,7 +1318,7 @@ typedef struct */ \ lcl_channel = CHANNEL; \ CHANNEL = NOJNL; \ - F_CLOSE(lcl_channel, RC); /* resets "lcl_channel" to FD_INVALID */ \ + CLOSEFILE_RESET(lcl_channel, RC); /* resets "lcl_channel" to FD_INVALID */ \ assert(SS_NORMAL == RC); \ } @@ -1410,16 +1333,9 @@ typedef struct * MAX_STRLEN for the actual database record. But that only takes care of the value part of the record. * The key can still be MAX_KEY_SZ long. So take that into account as well. */ -#ifdef UNIX # define JNL_MAX_SET_KILL_RECLEN(CSD) (uint4)ROUND_UP2((FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE) \ + MAX_KEY_SZ + MAX_STRLEN \ + SIZEOF(jnl_str_len_t) + SIZEOF(mstr_len_t), JNL_REC_START_BNDRY) -#else -# define JNL_MAX_SET_KILL_RECLEN(CSD) (uint4)ROUND_UP2(FIXED_UPD_RECLEN + JREC_SUFFIX_SIZE \ - + ((CSD)->blk_size - SIZEOF(blk_hdr) - SIZEOF(rec_hdr)) \ - + SIZEOF(jnl_str_len_t) + SIZEOF(mstr_len_t), JNL_REC_START_BNDRY) \ - /* fixed size part of update record + MAX possible (key + data) len + keylen-len + datalen-len */ -#endif #define JNL_MAX_PBLK_RECLEN(CSD) (uint4)ROUND_UP2(MIN_PBLK_RECLEN + (CSD)->blk_size, JNL_REC_START_BNDRY) @@ -1526,12 +1442,8 @@ typedef struct DEST = jnl_buffer_adj_value; \ } -#ifdef UNIX # define CURRENT_JNL_IO_WRITER(JB) JB->io_in_prog_latch.u.parts.latch_pid # define CURRENT_JNL_FSYNC_WRITER(JB) JB->fsync_in_prog_latch.u.parts.latch_pid -#else -# define CURRENT_JNL_IO_WRITER(JB) JB->now_writer -#endif /* This macro is invoked by callers just before grabbing crit to check if a db fsync is needed and if so do it. * Note that we can do the db fsync only if we already have the journal file open. If we do not, we will end @@ -1614,18 +1526,11 @@ void jnl_write_poolonly(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_format_buffer *jnl_format(jnl_action_code opcode, gv_key *key, mval *val, uint4 nodeflags); -#ifdef VMS -void finish_active_jnl_qio(void); -void jnl_start_ast(jnl_private_control *jpc); -uint4 jnl_permit_ast(jnl_private_control *jpc); -void jnl_qio_end(jnl_private_control *jpc); -#endif - void wcs_defer_wipchk_ast(jnl_private_control *jpc); -uint4 set_jnl_file_close(set_jnl_file_close_opcode_t set_jnl_file_close_opcode); +uint4 set_jnl_file_close(void); uint4 jnl_file_open_common(gd_region *reg, off_jnl_t os_file_size, char *err_str); uint4 jnl_file_open_switch(gd_region *reg, uint4 sts); -void jnl_file_close(gd_region *reg, bool clean, bool dummy); +void jnl_file_close(gd_region *reg, boolean_t clean, boolean_t in_jnl_switch); /* Consider putting followings in a mupip only header file : Layek 2/18/2003 */ boolean_t mupip_set_journal_parse(set_jnl_options *jnl_options, jnl_create_info *jnl_info); @@ -1639,5 +1544,7 @@ unsigned char *ext2jnlcvt(char *ext_buff, int4 ext_len, unsigned char **tr, int char *ext2jnl(char *ptr, jnl_record *rec, seq_num saved_jnl_seqno, seq_num saved_strm_seqno); char *jnl2extcvt(jnl_record *rec, int4 jnl_len, char **ext_buff, int *extract_bufsiz); char *jnl2ext(char *jnl_buff, char *ext_buff); +void jnl_set_cur_prior(gd_region *reg, sgmnt_addrs *csa, sgmnt_data *csd); +void jnl_set_fd_prior(int jnl_fd, sgmnt_addrs* csa, sgmnt_data* csd, jnl_file_header *jfh); #endif /* JNL_H_INCLUDED */ diff --git a/sr_port/jnl_ensure_open.c b/sr_port/jnl_ensure_open.c index 8eac757..227e933 100644 --- a/sr_port/jnl_ensure_open.c +++ b/sr_port/jnl_ensure_open.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2010-2016 Fidelity National Information * + * Copyright (c) 2010-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -68,7 +68,7 @@ uint4 jnl_ensure_open(gd_region *reg, sgmnt_addrs *csa) if (IS_GTCM_GNP_SERVER_IMAGE) gtcm_jnl_switched(reg); /* Reset pini_addr of all clients that had any older journal file open */ first_open_of_jnl = (0 == csa->nl->jnl_file.u.inode); - jnl_status = jnl_file_open(reg, first_open_of_jnl, NULL); + jnl_status = jnl_file_open(reg, first_open_of_jnl); } # ifdef DEBUG else diff --git a/sr_port/jnl_file_close.c b/sr_port/jnl_file_close.c index ff1610b..48da9d9 100644 --- a/sr_port/jnl_file_close.c +++ b/sr_port/jnl_file_close.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2003-2016 Fidelity National Information * + * Copyright (c) 2003-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -59,7 +59,7 @@ error_def(ERR_JNLWRERR); error_def(ERR_PREMATEOF); error_def(ERR_TEXT); -void jnl_file_close(gd_region *reg, bool clean, bool dummy) +void jnl_file_close(gd_region *reg, boolean_t clean, boolean_t in_jnl_switch) { jnl_file_header *header; unsigned char hdr_base[REAL_JNL_HDR_LEN + MAX_IO_BLOCK_SIZE]; @@ -172,15 +172,14 @@ void jnl_file_close(gd_region *reg, bool clean, bool dummy) assert(header->eov_tn >= header->bov_tn); header->end_seqno = eof_record.jnl_seqno; } -# ifdef UNIX for (idx = 0; idx < MAX_SUPPL_STRMS; idx++) header->strm_end_seqno[idx] = csd->strm_reg_seqno[idx]; if (jgbl.forw_phase_recovery) { /* If MUPIP JOURNAL -ROLLBACK, might need some adjustment. See macro definition for comments */ MUR_ADJUST_STRM_REG_SEQNO_IF_NEEDED(csd, header->strm_end_seqno); } -# endif header->last_eof_written = jb->last_eof_written; + header->is_not_latest_jnl = in_jnl_switch; header->crash = FALSE; JNL_DO_FILE_WRITE(csa, csd->jnl_file_name, jpc->channel, 0, header, read_write_size, jpc->status, jpc->status2); diff --git a/sr_port/jnl_file_lost.c b/sr_port/jnl_file_lost.c index 0ef3270..d10126e 100644 --- a/sr_port/jnl_file_lost.c +++ b/sr_port/jnl_file_lost.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2001, 2014 Fidelity Information Services, Inc * + * Copyright (c) 2001-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -12,13 +13,6 @@ #include "mdef.h" #include "gtm_inet.h" -#ifdef VMS -#include -#include -#include -#include -#include -#endif #include "gdsroot.h" #include "gtm_facility.h" @@ -28,29 +22,20 @@ #include "filestruct.h" #include "ccp.h" #include "jnl.h" -#ifdef VMS -#include "locks.h" -#endif #include "send_msg.h" #include "repl_msg.h" #include "gtmsource.h" -#ifdef UNIX #include "anticipatory_freeze.h" -#endif GBLREF jnlpool_addrs jnlpool; GBLREF gd_region *gv_cur_region; GBLREF volatile boolean_t in_wcs_recover; GBLREF int process_exiting; -#ifdef UNIX GBLREF jnlpool_ctl_ptr_t jnlpool_ctl; -#endif error_def(ERR_JNLCLOSED); error_def(ERR_REPLJNLCLOSED); -static const unsigned short zero_fid[3]; - uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat) { /* Notify operator and terminate journaling */ unsigned int status; @@ -69,24 +54,18 @@ uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat) break; default: assertpro(FALSE && jpc->region->dyn.addr->acc_meth); + /* no break */ } -# ifdef VMS - /* The following assert has been removed as it could be FALSE if the caller is "jnl_file_extend" - * assert(0 != memcmp(csa->nl->jnl_file.jnl_file_id.fid, zero_fid, SIZEOF(zero_fid))); - */ -# endif assert(csa->now_crit); - /* We issue an rts_error (instead of shutting off journaling) in the following cases : {BYPASSOK} + /* We issue an rts_error (instead of shutting off journaling) in the following cases : {BYPASSOK} * 1) $gtm_error_on_jnl_file_lost is set to issue runtime error (if not already issued) in case of journaling issues. * 2) The process has the given message set in $gtm_custom_errors (indicative of instance freeze on error setup) * in which case the goal is to never shut-off journaling */ - UNIX_ONLY(assert(jnlpool.jnlpool_ctl == jnlpool_ctl)); - UNIX_ONLY(instfreeze_environ = INST_FREEZE_ON_MSG_ENABLED(csa, jnl_stat)); - VMS_ONLY(instfreeze_environ = FALSE); + assert(jnlpool.jnlpool_ctl == jnlpool_ctl); + instfreeze_environ = INST_FREEZE_ON_MSG_ENABLED(csa, jnl_stat); if ((JNL_FILE_LOST_ERRORS == TREF(error_on_jnl_file_lost)) || instfreeze_environ) { - VMS_ONLY(assert(FALSE)); /* Not fully implemented / supported on VMS. */ if (!process_exiting || instfreeze_environ || !csa->jnl->error_reported) { csa->jnl->error_reported = TRUE; @@ -114,25 +93,6 @@ uint4 jnl_file_lost(jnl_private_control *jpc, uint4 jnl_stat) &jnlseqno, &jnlseqno); } else send_msg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLCLOSED, 3, DB_LEN_STR(jpc->region), &csa->ti->curr_tn); -#ifdef VMS - /* We can get a jnl_file_lost before the file is even created, so locking is done only if the lock exist */ - if (0 != csa->jnl->jnllsb->lockid) - { - was_lockid = TRUE; - status = gtm_enqw(EFN$C_ENF, LCK$K_EXMODE, csa->jnl->jnllsb, LCK$M_CONVERT | LCK$M_NODLCKBLK, - NULL, 0, NULL, 0, NULL, PSL$C_USER, 0); - if (SS$_NORMAL == status) - status = csa->jnl->jnllsb->cond; - } - jnl_file_close(jpc->region, FALSE, FALSE); - if (was_lockid) - { - if (SS$_NORMAL == status) - status = gtm_deq(csa->jnl->jnllsb->lockid, NULL, PSL$C_USER, 0); - assertpro(SS$_NORMAL == status); - } -# else - jnl_file_close(jpc->region, FALSE, FALSE); -#endif + jnl_file_close(jpc->region, FALSE, TRUE); return EXIT_NRM; } diff --git a/sr_port/jnl_file_open_common.c b/sr_port/jnl_file_open_common.c index 381f9db..e3d1656 100644 --- a/sr_port/jnl_file_open_common.c +++ b/sr_port/jnl_file_open_common.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2003-2016 Fidelity National Information * + * Copyright (c) 2003-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -51,25 +51,26 @@ GBLREF jnl_process_vector *prc_vec; GBLREF jnl_gbls_t jgbl; GBLREF uint4 mu_reorg_encrypt_in_prog; +error_def(ERR_CRYPTJNLMISMATCH); error_def(ERR_FILEIDMATCH); +error_def(ERR_JNLBADRECFMT); error_def(ERR_JNLOPNERR); +error_def(ERR_JNLPREVRECOV); error_def(ERR_JNLRDERR); -error_def(ERR_JNLBADRECFMT); error_def(ERR_JNLRECTYPE); +error_def(ERR_JNLSWITCHRETRY); error_def(ERR_JNLTRANSGTR); error_def(ERR_JNLTRANSLSS); -error_def(ERR_JNLWRERR); error_def(ERR_JNLVSIZE); +error_def(ERR_JNLWRERR); error_def(ERR_PREMATEOF); -error_def(ERR_JNLPREVRECOV); -error_def(ERR_CRYPTJNLMISMATCH); #define RETURN_AND_SET_JPC(ERR, ERR2, BUF) \ -{ \ +MBSTART { \ jpc->status = ERR2; \ jpc->err_str = BUF; \ return ERR; \ -} +} MBEND /* note: returns 0 on success */ uint4 jnl_file_open_common(gd_region *reg, off_jnl_t os_file_size, char *buff) @@ -247,6 +248,10 @@ uint4 jnl_file_open_common(gd_region *reg, off_jnl_t os_file_size, char *buff) jb->next_epoch_time = (uint4)(MID_TIME(prc_vec->jpv_time) + jb->epoch_interval); jb->max_jrec_len = header->max_jrec_len; memcpy(&header->who_opened, prc_vec, SIZEOF(jnl_process_vector)); + if (header->is_not_latest_jnl) + { /* Magic message to indicate that we should try a switch without cutting links. */ + RETURN_AND_SET_JPC(ERR_JNLSWITCHRETRY, 0, buff); + } header->crash = TRUE; /* in case this processes is crashed, this will remain TRUE */ JNL_DO_FILE_WRITE(csa, csd->jnl_file_name, jpc->channel, 0, header, read_write_size, jpc->status, jpc->status2); if (SS_NORMAL != jpc->status) diff --git a/sr_port/jnl_file_open_switch.c b/sr_port/jnl_file_open_switch.c index 8cff125..5653e06 100644 --- a/sr_port/jnl_file_open_switch.c +++ b/sr_port/jnl_file_open_switch.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2003, 2014 Fidelity Information Services, Inc * + * Copyright (c) 2003-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -30,7 +31,8 @@ GBLREF jnl_gbls_t jgbl; error_def(ERR_JNLFILOPN); -error_def(ERR_JNLINVALID); +error_def(ERR_JNLSWITCHFAIL); +error_def(ERR_JNLSWITCHRETRY); error_def(ERR_PREVJNLLINKCUT); uint4 jnl_file_open_switch(gd_region *reg, uint4 sts) @@ -48,7 +50,8 @@ uint4 jnl_file_open_switch(gd_region *reg, uint4 sts) csa = &FILE_INFO(reg)->s_addrs; jpc = csa->jnl; assert(sts GTMTRIG_ONLY(|| TREF(in_trigger_upgrade))); - assert(!sts || ((ERR_JNLFILOPN != sts) && (NOJNL != jpc->channel)) || ((ERR_JNLFILOPN == sts) && (NOJNL == jpc->channel))); + assert(!sts || ((ERR_JNLFILOPN != sts) && (NOJNL != jpc->channel)) || ((ERR_JNLFILOPN == sts) && (NOJNL == jpc->channel)) + || (ERR_JNLSWITCHRETRY == sts)); if (NOJNL != jpc->channel) JNL_FD_CLOSE(jpc->channel, status); /* sets jpc->channel to NOJNL */ if (sts) @@ -58,7 +61,10 @@ uint4 jnl_file_open_switch(gd_region *reg, uint4 sts) create.status = create.status2 = SS_NORMAL; create.prev_jnl = &prev_jnl_fn[0]; set_jnl_info(reg, &create); - create.no_prev_link = TRUE; + /* ERR_JNLSWITCHRETRY indicates that jnl_file_open_common found that the current journal had been marked for a + * switch, but the switch failed at a later point, so don't cut links in that case. + */ + create.no_prev_link = (ERR_JNLSWITCHRETRY != sts); create.no_rename = FALSE; assert(!jgbl.forw_phase_recovery || WBTEST_ENABLED(WBTEST_RECOVER_ENOSPC) || WBTEST_ENABLED(WBTEST_JNL_CREATE_FAIL)); if (!jgbl.dont_reset_gbl_jrec_time) @@ -69,7 +75,7 @@ uint4 jnl_file_open_switch(gd_region *reg, uint4 sts) { jpc->status = create.status; jpc->status2 = create.status2; - return ERR_JNLINVALID; + return ERR_JNLSWITCHFAIL; } else { jpc->status = SS_NORMAL; diff --git a/sr_port/jnl_set_cur_prior.c b/sr_port/jnl_set_cur_prior.c new file mode 100644 index 0000000..01e0d4a --- /dev/null +++ b/sr_port/jnl_set_cur_prior.c @@ -0,0 +1,67 @@ +/**************************************************************** + * * + * Copyright (c) 2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + + +#include "mdef.h" +#include "gdsroot.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "jnl.h" +#include "gtmio.h" +#include "anticipatory_freeze.h" + +/* For use when disabling journaling in standalone to mark the current journal file as being a prior journal file. + * The journal file is not always present/usable/writable, in which case we can't change it, so ignore errors. + */ +void jnl_set_cur_prior(gd_region *reg, sgmnt_addrs *csa, sgmnt_data *csd) +{ + int jnl_fd; + unix_db_info *udi; + + udi = FILE_INFO(reg); + assert('\0' == csd->jnl_file_name[csd->jnl_file_len]); + assert(udi->grabbed_access_sem || (csa->now_crit && !csa->nl->jnl_file.u.inode)); + OPENFILE((char *)csd->jnl_file_name, O_RDWR, jnl_fd); + if (FD_INVALID != jnl_fd) + jnl_set_fd_prior(jnl_fd, csa, csd, NULL); +} + +/* Same as above, but for when we already have the file open. + * If jfh is non-NULL, it is assumed correct, updated, and written; otherwise, a fresh copy is read from the file. + */ +void jnl_set_fd_prior(int jnl_fd, sgmnt_addrs* csa, sgmnt_data* csd, jnl_file_header *jfh) +{ + int status1, status2; + jnl_file_header header, *jfh_checked = NULL; + + if (NULL == jfh) + { + DO_FILE_READ(jnl_fd, 0, &header, SIZEOF(header), status1, status2); + assert(SS_NORMAL == status1); + if (SS_NORMAL == status1) + { + CHECK_JNL_FILE_IS_USABLE(&header, status1, FALSE, 0, NULL); + assert(SS_NORMAL == status1); + if ((SS_NORMAL == status1) && !header.is_not_latest_jnl) + jfh_checked = &header; + } + } else + jfh_checked = jfh; + if (NULL != jfh_checked) + { + jfh_checked->is_not_latest_jnl = TRUE; + JNL_DO_FILE_WRITE(csa, csd->jnl_file_name, jnl_fd, 0, jfh_checked, get_fs_block_size(jnl_fd), status1, status2); + assert(SS_NORMAL == status1); + } + JNL_FD_CLOSE(jnl_fd, status1); +} diff --git a/sr_port/lke.hlp b/sr_port/lke.hlp index f63984d..e57a822 100644 --- a/sr_port/lke.hlp +++ b/sr_port/lke.hlp @@ -555,7 +555,7 @@ 1 Copyright Copyright - Copyright 2016 + Copyright 2017 Fidelity National Information Services, Inc. and/or its subsidiaries. All rights reserved. @@ -577,7 +577,7 @@ **Note** - This help file is a concise representation of revision V6.3-000 of the + This help file is a concise representation of revision V6.3-001 of the UNIX Administration and Operations Guide. To obtain a copy of the current revision, go to www.fis-gtm.com and then click on the User Documentation tab. diff --git a/sr_port/merrors.msg b/sr_port/merrors.msg index bc2e239..3ccc13e 100644 --- a/sr_port/merrors.msg +++ b/sr_port/merrors.msg @@ -1655,6 +1655,9 @@ INVSTATSDB /error/fao=4!/ansi=0 STATSDBINUSE /error/fao=6!/ansi=0 STATSDBFNERR /error/fao=2!/ansi=0 +JNLSWITCHRETRY /info/fao=4!/ansi=0 +JNLSWITCHFAIL /error/fao=4!/ansi=0 +CLISTRTOOLONG /error/fao=3!/ansi=0 ! ! If there are UNUSEDMSG* lines unused for more than one year and at least two non-patch releases, use them before adding new lines. ! diff --git a/sr_port/mumps.hlp b/sr_port/mumps.hlp index 84db6d0..4b03711 100644 --- a/sr_port/mumps.hlp +++ b/sr_port/mumps.hlp @@ -114,7 +114,7 @@ 2 Copyright Copyright - Copyright 1987 - 2003, 2013 - 2016 + Copyright 1987 - 2003, 2013 - 2017 Fidelity Information Services, Inc. All rights reserved. @@ -911,7 +911,7 @@ |------------------------+-----------------------------------------------| | | The $ZPIECE() function returns a sequence of | | | bytes delimited by a specified byte sequence | - | $ZPiece() | made up of one or more bytes. In M, $ZPIECE() | + | $ZPIece() | made up of one or more bytes. In M, $ZPIECE() | | | typically returns a logical field from a | | | logical record. | |------------------------+-----------------------------------------------| @@ -2454,6 +2454,11 @@ # binary operator for modulo, that is, causes M to produce the remainder from integer division of the first argument by the second. + Because of the practice of using it to intentionally induce an error, GT.M + does not produce a DIVZERO error at compile time, only at run time, for + divide or integer divide by a literal expression that evaluates to zero + (0). + Remember that precedence is left to right for all arithmetic operators. Example: @@ -2857,7 +2862,10 @@ commands except commands that themselves have a conditional aspect accept a command postconditional. Among the M standard commands, ELSE, FOR, and IF do not accept command postconditionals. All the GT.M command extensions - accept command postconditionals. + accept command postconditionals. When a postconditional evaluates to a + literal FALSE (0), GT.M discards the command and its arguments at compile + time, which means it does not perform any validity checking on the + arguments. 4 Argument_Postconditionals Argument Postconditionals @@ -3116,7 +3124,7 @@ Example: - GTM>SET from="B",to="^A(15),x="" + GTM>SET from="B",to="^A(15)",x="" GTM>FOR SET x=$O(@from@(x)) Q:x="" S @to@(x)=@from@(x) This example uses name indirection to copy the level contents of a local @@ -3579,6 +3587,40 @@ SET ^ID(NEXT)=RECORD,^XID(ZIP,NEXT)="" TCOMMIT + * pvtmods - Is always less than or equal to blkmods. This means it can + be 1 only if "blkmods" is also 1. If it is 1, it means that process P1 + was planning to UPDATE (not just READ) the block number (indicated as + "blk: ..." in the TPRESTART message) as part of its TP transaction. + * blkmods - Is either 1 or 0. 1 implies the transaction restarted + because this process (P1) is attempting to READ/UPDATE a block that + has concurrently been updated by another process (P2) since P1 access + the block as part of its TP transaction. This means the "code: ..." + output in the TPRESTART message will have L as the last letter. 0 + implies the restart occurred because of a different reason. The "code: + ..." then has something other than "L" as the last letter. Note that + each letter in "code: ..." corresponds to the failure code in each + try/retry in the order of occurrence. + * blklvl - Is the level in the GDS structure of the block ("blk: ..." + field in the TPRESTART message) that caused the TP restart. + * type - A value of 0,1,2,4 shows the restart occurred in the TP + transaction BEFORE executing TCOMMIT; whether it is a 0 or 1 or 2 or 4 + should not matter to the user. These values would typically be used + for debugging by Fidelity. A value of 3 shows the restart occurred at + TCOMMIT time. + * readset - The number of GDS blocks that accessed as part of this TP + transaction in the region containing the global ("glbl: ..." in the + TPRESTART message). + * writeset - Out of the readset number, the number of GDS blocks this + process was attempted to UPDATE as part of this TP transaction in the + region containing the global ("glbl: ..." in the TPRESTART message). + * local_tn - This is a never-decreasing counter (starting at 1 at + process startup) incremented for every new TP transaction, TP restart, + and TP rollback. Two TPRESTART messages by the same process should + never have the same value of local_tn. The difference between the + local_tn values of two messages from the same process indicates the + number of TP transactions done by that process in the time interval + between the two messages. + 1 Commands Commands @@ -3925,7 +3967,10 @@ the line. When IF has an argument, it updates $TEST with the truth value of its evaluated argument. GT.M executes the remainder of a line after an IF statement when $TEST is 1 (TRUE). When $TEST is 0 (FALSE), GT.M does - not execute the rest of the line. + not execute the rest of the line. When the IF argument evaluates to a + literal FALSE (0), GT.M discards the command and its arguments at compile + time, which means it does not perform any validity checking on the + remainder of the line. The format of the IF command is: @@ -3940,9 +3985,12 @@ An IF with more than one argument behaves as if those arguments were logically "ANDed." However, execution of the line ceases with the evaluation of the first false argument. For IF argument expressions - containing the "AND" operator (&), execution still ceases with the - evaluation of the first false argument. Any global references within the - expression act in sequence to maintain the naked reference. + containing the "AND" operator (&), by default, execution still ceases with + the evaluation of the first false argument, however any global references + within the expression act in sequence to maintain the naked reference. The + "FULL_BOOLEAN" and "SIDE_EFFECTS" compiler settings modify this behavior + if you desire GT.M to provide side effects it would otherwise bypass due + to short-circiuting of Boolean expressions. 3 Examples Examples @@ -5218,6 +5266,29 @@ particularly useful for long running processes which would periodically like to restart the counting without requiring a shut down and restart. +4 [NO]STATSHARE + [NO]STATSHARE + + Opt in or out of sharing process statistics for monitoring by other + processes. + + GT.M provides a fast and efficient mechanism for processes to share their + database access statistics for other processes to monitor. Processes opt + in or out with the VIEW "[NO]STATSHARE" command, defaulting to VIEW + "NOSTATSHARE". At process startup, a value of 1, or any case-independent + string or leading substrings of "TRUE" or "YES" in the environment + variable gtm_statshare provides an initial setting of VIEW "STATSHARE". + When a process changes whether it is opting in or out, there is no change + to the output of a ZSHOW "G" within that process. GT.M does not permit + this form of the VIEW command within a TP transaction. Monitoring the + statistics of other processes does not require opting-in. + + Processes opted-in place their statistics as binary data in database files + located in the directory specified by the gtm_statsdir environment + variable. All processes that share statistics MUST use the same value for + $gtm_statsdir. The ^%YGBLSTAT utility program gathers and reports + statistics. + 4 STP_GCOL STP_GCOL @@ -6651,6 +6722,29 @@ DEX : # of times a process extends the database file [NT]B[WR] mnemonics are satisfied by either disk access or, for databases that use the BG (buffered global) access method, global buffers in shared memory. ZTR : # of ZTRIGGER command operations + DFL : # of Database FLushes + DFS : # of Database FSyncs + JFL : # of Journal FLushes + JFS : # of Journal FSyncs + JBB : # of Bytes written to Journal Buffer + JFB : # of Bytes written to Journal File + JFW : # of Journal File Writes + JRL : # of Logical Journal Records + JRP : # of Pblk Journal Records + JRE : # of Regular Epoch Journal Records + JRI : # of Idle epoch Journal Records + JRO : # of Other Journal Records + JEX : # of Journal file EXtensions + DEX : # of Database file EXtensions + CAT : # of crit acquired total successes + CFE : # of attempts in CFT caused by epochs + CFS : sum of squares grab crit failed + CFT : # of grab crit failures + CQS : sum of squares grab crit queued sleeps + CQT : # of grab crit queued sleeps + CYS : sum of squares grab crit yields + CYT : # of grab crit yields + BTD : # of Block Transitions to Dirty When $PRINCIPAL input and output are different devices, ZSHOW "D" shows them as separate items identified as 0 for input and 0-out for output. @@ -6705,14 +6799,16 @@ GLD:*,REG:*,SET:205,KIL:0,GET:1,DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0,LKF:0,CTN:0,DRD:9,DWT:15, NTW:203,NTR:4,NBW:212,NBR:414,NR0:0,NR1:0,NR2:0,NR3:0,TTW:1,TTR:0,TRB:0,TBW:2,TBR:6, - TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0 + TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0,JFS:0,JBB:0,JFB:0,JFW:0,JRL:0,JRP:0, + JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0 GLD:/home/gtmuser1/.fis-gtm/V5.4-002B_x86/g/mumps.gld,REG:DEFAULT,SET:205,KIL:0,GET:1, DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0,LKF:0,CTN:411,DRD:9,DWT:15,NTW:2 03,NTR:4,NBW:212,NBR:414,NR0:0,NR1:0,NR2:0,NR3:0,TTW:1,TTR:0,TRB:0,TBW:2,TBR:6,TR0:0, TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0 GLD:/tmp/tst/test.gld,REG:DEFAULT,SET:205,KIL:0,GET:1,DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0,LKF:0, CTN:411,DRD:9,DWT:15,NTW:203,NTR:4,NBW:212,NBR:414,NR0:0,NR1:0,NR2:0,NR3:0,TTW:1,TTR:0,TRB:0, - TBW:2,TBR:6,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0 + TBW:2,TBR:6,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0,JFS:0,JBB:0,JFB:0,JFW:0, + JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0 Example: @@ -6727,10 +6823,12 @@ TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0 GLD:/tmp/x1.gld,REG:REG1,SET:0,KIL:0,GET:0,DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0,LKF:0,CTN:0,DRD:0, DWT:0,NTW:0,NTR:0,NBW:0,NBR:0,NR0:0,NR1:0,NR2:0,NR3:0,TTW:0, - TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0 + TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0,JFS:0,JBB:0, + JFB:0,JFW:0,JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0 GLD:/tmp/x1.gld,REG:REG2,SET:0,KIL:0,GET:0,DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0,LKF:0,CTN:0,DRD:0, DWT:0,NTW:0,NTR:0,NBW:0,NBR:0,NR0:0,NR1:0,NR2:0,NR3:0,TTW:0, - TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0 + TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0,JFS:0,JBB:0, + JFB:0,JFW:0,JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0 Example: @@ -6740,13 +6838,16 @@ zgbl("G",0)="GLD:*,REG:*,SET:0,KIL:0,GET:0,DTA:0,ORD:0, ZPR:0,QRY:0,LKS:0,LKF:0,CTN:0,DRD:0,DWT:0,NTW:0,NTR:0,NBW:0,NBR:0,NR0:0,NR1:0,NR2:0,NR3:0,TTW:0, - TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0" + TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0,JFS:0,JBB:0, + JFB:0,JFW:0,JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0" zgbl("G",1)="GLD:/tmp/x1.gld,REG:REG1,SET:0,KIL:0,GET:0,DTA:0,ORD:0,ZPR:0,QRY:0, LKS:0,LKF:0,CTN:0,DRD:0,DWT:0,NTW:0,NTR:0,NBW:0,NBR:0,NR0:0,NR1:0,NR2:0, - NR3:0,TTW:0,TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0" + NR3:0,TTW:0,TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0, + JFS:0,JBB:0,JFB:0,JFW:0,JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0" zgbl("G",2)="GLD:/tmp/x1.gld,REG:REG2,SET:0,KIL:0,GET:0,DTA:0,ORD:0,ZPR:0,QRY:0,LKS:0, LKF:0,CTN:0,DRD:0,DWT:0,NTW:0,NTR:0,NBW:0,NBR:0,NR0:0,NR1:0,NR2:0, - NR3:0,TTW:0,TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0" + NR3:0,TTW:0,TTR:0,TRB:0,TBW:0,TBR:0,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:0,DFL:0,DFS:0,JFL:0, + JFS:0,JBB:0,JFB:0,JFW:0,JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0,CAT:4,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:0" Example: @@ -8492,135 +8593,270 @@ GT.M permits modification of the factors accessible with $VIEW(), the VIEW command generally provides the means for effecting the change. - +----------------------------------------------------------------------------------------------------------------------------------------------------+ - | $VIEW() Argument Keywords | - |----------------------------------------------------------------------------------------------------------------------------------------------------| - | ARG 1 | ARG 2 | RETURN VALUE | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"BADCHAR" |none |In UTF-8 mode processes, enables or disable the generation of an error when character-oriented functions encounter | - | | |malformed byte sequences (illegal characters). The default is 1. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"BREAKMSG" |none |Value of the break message mask; GT.M defaults this to 31. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"FREEBLOCKS" |region |Number of free database blocks in a given region. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |Process-id of a process that has frozen the database associated with the region specified (using DSE or MUPIP). | - |"FREEZE" |region | | - | | |If the region is currently not frozen, returns zero. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |Returns a string describing the current compiler setting. The default is "GT.M Boolean short-circuit". | - |"FULL_BOOLEAN" |none |$VIEW("FULL_BOOLEAN") reports "Standard Boolean evaluation side effects" when it is not explicitly set, but that | - | | |mode of operation is required by the setting of gtm_side_effects, and "Standard Boolean side-effect warning" when | - | | |warnings have been specified. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |Truth Value indicating whether Database block certification is currently enabled or disabled. | - |"GDSCERT" |none | | - | | |To enable or disable Database block certification, use the VIEW "GDSCERT" command. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"GVACCESS_METHOD"|region |Access method of the region. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"GVFILE" |region |Name of the database associated with the region. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"GVFIRST" |none |Name of the first database region in the current global directory; functionally equivalent to $VIEW("GVNEXT",""). | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"GVNEXT" |region |Name of the next database region after the given one in alphabetical order (or M collation sequence); "" for region| - | | |starts with the first region. A return value of "" means that the global directory defines no additional regions. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |When | - | | | | - |"GVSTAT" |region |read-only processes are the active in a database, they cannot update the database including the file header where | - | | |GVSTATS are stored. Therefore their counts are only stored in associated shared memory and must be flushed to the | - | | |file header by a process with write access, which might be a MUPIP RUNDOWN. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |Number of indirection cache hits since GT.M process startup. | - |"ICHITS" |none | | - | | |Indirection cache is a pool of compiled expressions that GT.M maintains for indirection and XECUTE. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"ICMISS" |none |Number of indirection cache misses since GT.M process startup. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |can return the following values: | - | | | | - |"JNLACTIVE" |region | o -1 (internal error) | - | | | o 0 journaling is disabled | - | | | o 1 journaling is enabled but closed (OFF) | - | | | o 2 journaling is enabled and open (ON) | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"JNLFILE" |region |Journal file name associated with the region. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"JNLTRANSACTION" |none |Index showing how many ZTSTART transaction fences have been opened (and not closed). | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"LABELS" |none |Truth value showing whether label case sensitivity is ON (1 for "LOWER") or OFF (0 for "UPPER"); GT.M defaults to | - | | |1. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"LINK" |none |Returns the current relink recursive setting of ZLINK. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | |local variable|returns the number of references by alias containers to the array associated with an unsubscripted local variable | - |"LV_CREF" |name (lvn) |name specified as a second expr (for example a quoted string); it returns a zero for a variable without any | - | | |associated alias container. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"LV_GCOL" |none |returns the number of data-spaces recovered during a local variable data-space garbage collection it triggers; such| - | | |collections normally happen automatically at appropriate times. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"LV_REF" |local variable|returns the total number of references to the data-space associated with an unsubscripted local variable name | - | |name (lvn) |specified as a second expr (for example a quoted string). | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"LVNULLSUBS" |none |Truth value showing whether null subscripts are permitted in local arrays (1 for "LVNULLSUBS") or not (0 for | - | | |"NOLVNULLSUBS"); GT.M defaults to 1. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |The current isolation-status of the specified global variable which must have a leading "^" in its specification. | - | | | | - | | |This function returns 1 if GT.M has been instructed to not enforce the ACID property of Isolation (that is, | - |"NOISOLATION" |global |"NOISOLATION" has been specified) and 0 otherwise. | - | | | | - | | |By default, GT.M ensures Isolation, that is, a $VIEW command will return 0. The isolation-status of a global | - | | |variable can be turned on and off by the VIEW "NOISOLATION" command. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"PATCODE" |none |Name of the active patcode table; GT.M defaults this to "M". | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"POOLLIMIT" |region |The current limit on global buffers for the region . | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"PROBECRIT" |region |Acquires and releases a critical section for the region (the "probe"), returning a string with the following | - | | |fields: | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |Name of the region(s) holding the specified gvn. | - | | | | - | | |If gvn spans more than one region, this function returns region name in an order where the first region is the | - | | |region to which the unsubscripted global variable name maps; and other regions are in the order in which they would| - |"REGION" |gvn |be encountered by traversing the subscripts of gvn in order (with duplicates removed). | - | | | | - | | |gvn is a subscripted or unsubscripted global variable name in the same form as that generated by $NAME(). You can | - | | |use $NAME() inside $VIEW() to ensure that subscripts are in a correct form, for example, | - | | |$VIEW("REGION",$NAME(^abcd(1,2E4))) instead of $VIEW("REGION","^abcd(1,20000)"). | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"RTNCHECKSUM" |routine name |Source code check-sum for the most recently ZLINK'd version of the specified routine name (these check-sums use a | - | | |128 bit hash based on the MurmurHash3 algorithm). | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"RTNNEXT" |routine name |Name of the next routine in the image after the given one; "" (empty string) for routinename starts with the first | - | | |routine in ASCII collating sequence and a return value of the empty string indicates the end of the list. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | | |Number of bytes in the currently allocated as process working storage. GT.M manages this space as what is commonly | - |"SPSIZE" |none |called a heap, and uses the term stringpool to refer to it. The GT.M garbage collector reclaims unused space from | - | | |the stringpool from time to time, and GT.M automatically expands the stringpool as needed by the application | - | | |program. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"STKSIZ" |none |Returns the GT.M stack size in bytes. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"TOTALBLOCKS" |region |Total number of database blocks in a given region. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - | |NULL |Transaction ID specified in the particular level (when the transaction level is specified). The first level TSTART | - | | |is returned if the level is not specified as second argument. | - | |or | | - |"TRANSACTIONID" | | **Note** | - | |transaction | | - | |level |A NULL string is returned if the specified level (explicitly or implicitly) is greater than the current value of | - | | |$TLEVEL. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"UNDEF" |none |Truth value showing whether undefined variables should be treated as having a null value (1 for "UNDEF"; 0 for | - | | |"NOUNDEF"); GT.M defaults to 0. | - |-----------------+--------------+-------------------------------------------------------------------------------------------------------------------| - |"ZDATE_FORM" |none |Integer value showing whether four digit year code is active for $ZDATE(); GT.M defaults to 0 (for "YY" format). | - | | |Use the environment variable gtm_zdate_form to set the initial value of this factor. | - +----------------------------------------------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------+ + | $VIEW() Argument Keywords | + |------------------------------------------------------------------------| + | ARG 1 | ARG 2 | RETURN VALUE | + |-------------------+--------------+-------------------------------------| + | | | In UTF-8 mode processes, enables or | + | | | disable the generation of an error | + | "BADCHAR" | none | when character-oriented functions | + | | | encounter malformed byte sequences | + | | | (illegal characters). The default | + | | | is 1. | + |-------------------+--------------+-------------------------------------| + | "BREAKMSG" | none | Value of the break message mask; | + | | | GT.M defaults this to 31. | + |-------------------+--------------+-------------------------------------| + | "FREEBLOCKS" | region | Number of free database blocks in a | + | | | given region. | + |-------------------+--------------+-------------------------------------| + | | | Process-id of a process that has | + | | | frozen the database associated with | + | | | the region specified (using DSE or | + | "FREEZE" | region | MUPIP). | + | | | | + | | | If the region is currently not | + | | | frozen, returns zero. | + |-------------------+--------------+-------------------------------------| + | | | Returns a string describing the | + | | | current compiler setting. The | + | | | default is "GT.M Boolean | + | | | short-circuit". | + | | | $VIEW("FULL_BOOLEAN") reports | + | "FULL_BOOLEAN" | none | "Standard Boolean evaluation side | + | | | effects" when it is not explicitly | + | | | set, but that mode of operation is | + | | | required by the setting of | + | | | gtm_side_effects, and "Standard | + | | | Boolean side-effect warning" when | + | | | warnings have been specified. | + |-------------------+--------------+-------------------------------------| + | | | Truth Value indicating whether | + | | | Database block certification is | + | | | currently enabled or disabled. | + | "GDSCERT" | none | | + | | | To enable or disable Database block | + | | | certification, use the VIEW | + | | | "GDSCERT" command. | + |-------------------+--------------+-------------------------------------| + | "GVACCESS_METHOD" | region | Access method of the region. | + |-------------------+--------------+-------------------------------------| + | "GVFILE" | region | Name of the database associated | + | | | with the region. | + |-------------------+--------------+-------------------------------------| + | | | Name of the first database region | + | "GVFIRST" | none | in the current global directory; | + | | | functionally equivalent to | + | | | $VIEW("GVNEXT",""). | + |-------------------+--------------+-------------------------------------| + | | | Name of the next database region | + | | | after the given one in alphabetical | + | | | order (or M collation sequence); "" | + | "GVNEXT" | region | for region starts with the first | + | | | region. A return value of "" means | + | | | that the global directory defines | + | | | no additional regions. | + |-------------------+--------------+-------------------------------------| + | | | When | + | | | | + | | | read-only processes are the active | + | | | in a database, they cannot update | + | | | the database including the file | + | "GVSTAT" | region | header where GVSTATS are stored. | + | | | Therefore their counts are only | + | | | stored in associated shared memory | + | | | and must be flushed to the file | + | | | header by a process with write | + | | | access, which might be a MUPIP | + | | | RUNDOWN. | + |-------------------+--------------+-------------------------------------| + | | | Number of indirection cache hits | + | | | since GT.M process startup. | + | | | | + | "ICHITS" | none | Indirection cache is a pool of | + | | | compiled expressions that GT.M | + | | | maintains for indirection and | + | | | XECUTE. | + |-------------------+--------------+-------------------------------------| + | "ICMISS" | none | Number of indirection cache misses | + | | | since GT.M process startup. | + |-------------------+--------------+-------------------------------------| + | | | can return the following values: | + | | | | + | | | o -1 (internal error) | + | "JNLACTIVE" | region | o 0 journaling is disabled | + | | | o 1 journaling is enabled but | + | | | closed (OFF) | + | | | o 2 journaling is enabled and | + | | | open (ON) | + |-------------------+--------------+-------------------------------------| + | "JNLFILE" | region | Journal file name associated with | + | | | the region. | + |-------------------+--------------+-------------------------------------| + | | | Index showing how many ZTSTART | + | "JNLTRANSACTION" | none | transaction fences have been opened | + | | | (and not closed). | + |-------------------+--------------+-------------------------------------| + | | | Truth value showing whether label | + | "LABELS" | none | case sensitivity is ON (1 for | + | | | "LOWER") or OFF (0 for "UPPER"); | + | | | GT.M defaults to 1. | + |-------------------+--------------+-------------------------------------| + | "LINK" | none | Returns the current relink | + | | | recursive setting of ZLINK. | + |-------------------+--------------+-------------------------------------| + | | | returns the number of references by | + | | | alias containers to the array | + | | local | associated with an unsubscripted | + | "LV_CREF" | variable | local variable name specified as a | + | | name (lvn) | second expr (for example a quoted | + | | | string); it returns a zero for a | + | | | variable without any associated | + | | | alias container. | + |-------------------+--------------+-------------------------------------| + | | | returns the number of data-spaces | + | | | recovered during a local variable | + | "LV_GCOL" | none | data-space garbage collection it | + | | | triggers; such collections normally | + | | | happen automatically at appropriate | + | | | times. | + |-------------------+--------------+-------------------------------------| + | | | returns the total number of | + | | local | references to the data-space | + | "LV_REF" | variable | associated with an unsubscripted | + | | name (lvn) | local variable name specified as a | + | | | second expr (for example a quoted | + | | | string). | + |-------------------+--------------+-------------------------------------| + | | | Truth value showing whether null | + | | | subscripts are permitted in local | + | "LVNULLSUBS" | none | arrays (1 for "LVNULLSUBS") or not | + | | | (0 for "NOLVNULLSUBS"); GT.M | + | | | defaults to 1. | + |-------------------+--------------+-------------------------------------| + | | | The current isolation-status of the | + | | | specified global variable which | + | | | must have a leading "^" in its | + | | | specification. | + | | | | + | | | This function returns 1 if GT.M has | + | | | been instructed to not enforce the | + | | | ACID property of Isolation (that | + | "NOISOLATION" | global | is, "NOISOLATION" has been | + | | | specified) and 0 otherwise. | + | | | | + | | | By default, GT.M ensures Isolation, | + | | | that is, a $VIEW command will | + | | | return 0. The isolation-status of a | + | | | global variable can be turned on | + | | | and off by the VIEW "NOISOLATION" | + | | | command. | + |-------------------+--------------+-------------------------------------| + | "PATCODE" | none | Name of the active patcode table; | + | | | GT.M defaults this to "M". | + |-------------------+--------------+-------------------------------------| + | "POOLLIMIT" | region | The current limit on global buffers | + | | | for the region . | + |-------------------+--------------+-------------------------------------| + | | | Acquires and releases a critical | + | "PROBECRIT" | region | section for the region (the | + | | | "probe"), returning a string with | + | | | the following fields: | + |-------------------+--------------+-------------------------------------| + | | | Name of the region(s) holding the | + | | | specified gvn. | + | | | | + | | | If gvn spans more than one region, | + | | | this function returns region name | + | | | in an order where the first region | + | | | is the region to which the | + | | | unsubscripted global variable name | + | | | maps; and other regions are in the | + | | | order in which they would be | + | | | encountered by traversing the | + | "REGION" | gvn | subscripts of gvn in order (with | + | | | duplicates removed). | + | | | | + | | | gvn is a subscripted or | + | | | unsubscripted global variable name | + | | | in the same form as that generated | + | | | by $NAME(). You can use $NAME() | + | | | inside $VIEW() to ensure that | + | | | subscripts are in a correct form, | + | | | for example, | + | | | $VIEW("REGION",$NAME(^abcd(1,2E4))) | + | | | instead of | + | | | $VIEW("REGION","^abcd(1,20000)"). | + |-------------------+--------------+-------------------------------------| + | | | Source code check-sum for the most | + | | | recently ZLINK'd version of the | + | "RTNCHECKSUM" | routine name | specified routine name (these | + | | | check-sums use a 128 bit hash based | + | | | on the MurmurHash3 algorithm). | + |-------------------+--------------+-------------------------------------| + | | | Name of the next routine in the | + | | | image after the given one; "" | + | | | (empty string) for routinename | + | "RTNNEXT" | routine name | starts with the first routine in | + | | | ASCII collating sequence and a | + | | | return value of the empty string | + | | | indicates the end of the list. | + |-------------------+--------------+-------------------------------------| + | | | Returns a string with three comma | + | | | separated values: Number of bytes | + | | | currently allocated as process | + | | | working storage: GT.M manages this | + | | | space as what is commonly called a | + | | | heap, and uses the term stringpool | + | | | to refer to it. The GT.M garbage | + | | | collector reclaims unused space | + | | | from the stringpool from time to | + | "SPSIZE" | none | time, and GT.M automatically | + | | | expands the stringpool as needed by | + | | | the application program; Number of | + | | | bytes currently used by the | + | | | process; Number of bytes reserved: | + | | | The reserved space is used to | + | | | reduce the active memory usage, for | + | | | example, when a process uses a | + | | | large amount of memory then | + | | | subsequently uses a significantly | + | | | reduced amount. | + |-------------------+--------------+-------------------------------------| + | "STKSIZ" | none | Returns the GT.M stack size in | + | | | bytes. | + |-------------------+--------------+-------------------------------------| + | "TOTALBLOCKS" | region | Total number of database blocks in | + | | | a given region. | + |-------------------+--------------+-------------------------------------| + | | | Transaction ID specified in the | + | | | particular level (when the | + | | | transaction level is specified). | + | | NULL | The first level TSTART is returned | + | | | if the level is not specified as | + | | or | second argument. | + | "TRANSACTIONID" | | | + | | transaction | **Note** | + | | level | | + | | | A NULL string is returned if the | + | | | specified level (explicitly or | + | | | implicitly) is greater than the | + | | | current value of $TLEVEL. | + |-------------------+--------------+-------------------------------------| + | | | Truth value showing whether | + | | | undefined variables should be | + | "UNDEF" | none | treated as having a null value (1 | + | | | for "UNDEF"; 0 for "NOUNDEF"); GT.M | + | | | defaults to 0. | + |-------------------+--------------+-------------------------------------| + | | | Integer value showing whether four | + | | | digit year code is active for | + | "ZDATE_FORM" | none | $ZDATE(); GT.M defaults to 0 (for | + | | | "YY" format). Use the environment | + | | | variable gtm_zdate_form to set the | + | | | initial value of this factor. | + +------------------------------------------------------------------------+ **Important** @@ -8661,9 +8897,11 @@ Example: GTM>write $view("GVSTAT","DEFAULT") - SET:203,KIL:12,GET:203,DTA:2,ORD:23,ZPR:21,QRY:0,LKS:0,LKF:0,CTN:44,DRD:103,DWT: - 59,NTW:24,NTR:55,NBW:27,NBR:138,NR0:0,NR1:0,NR2:0,NR3:0,TTW:17,TTR:5,TRB:0,TBW:3 - 2,TBR:80,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:7 + SET:203,KIL:12,GET:203,DTA:2,ORD:23,ZPR:21,QRY:0,LKS:0,LKF:0,CTN:44,DRD:103,DWT:59, + NTW:24,NTR:55,NBW:27,NBR:138,NR0:0,NR1:0,NR2:0,NR3:0,TTW:17,TTR:5,TRB:0,TBW:32, + TBR:80,TR0:0,TR1:0,TR2:0,TR3:0,TR4:0,TC0:0,TC1:0,TC2:0,TC3:0,TC4:0,ZTR:7,DFL:9, + DFS:0,JFL:0,JFS:0,JBB:0,JFB:0,JFW:0,JRL:0,JRP:0,JRE:0,JRI:0,JRO:0,JEX:0,DEX:0, + CAT:35,CFE:0,CFS:0,CFT:0,CQS:0,CQT:0,CYS:0,CYT:0,BTD:13 GTM> Example: @@ -8770,6 +9008,64 @@ $ZWRTAC="" $ +2 $ZAscii() + $ZAscii() + + Returns the numeric byte value (0 through 255) of a given sequence of + octets (8-bit bytes). + + The format for the $ASCII function is: + + $ZA[SCII](expr[,intexpr]) + +3 Examples + Examples + + Example: + + GTM>for i=0:1:4 write !,$zascii("*",i) + + -1 + 228 + 184 + 187 + -1 + GTM> + + This UTF-8 mode example displays the result of $ZASCII() specifying a byte + position before, first, second and third positions, and after the sequence + of octets (8-bit bytes) represented by *. In the above example, 228, 184, + and 187 represents the numeric byte value of the three-byte in the + sequence of octets (8-bit bytes) represented by *. + +2 $ZATRansform + $ZATRansform + + Returns the transformed representation of the first argument expr in a + normalized form using the alternative transform specified by the second + argument intexpr; the return can be used as an operand to the follows (]) + or sorts-after (]]) operator such that, if both operands are in the + normalized form, the result is independent of alternative collation. The + format for the $ZATRANSFORM() function is: + + $ZTRANSFORM(expr,intexpr[,{0|1}][,{0|1}]) + + Please see the section on $ZCOLLATE() for a similar alternative. + +3 Examples + Examples + + Example: + + GTM>write $ztransform("John Smythe",1)]$zatransform("Jane Smith",2) + 0 + GTM> + + This example uses $ZATRANSFORM() and two (here unspecified) collation + definitions to compare the ordering of two (literal) expressions as GT.M + would collate them if there was a way to collate them together. The result + indicates that the first would collate before the second. + 2 $ZBIT_Functions $ZBIT Functions @@ -9082,36 +9378,6 @@ invalid bits that exist at the end of the character string. In this case there are zero invalid bits. -2 $ZAscii() - $ZAscii() - - Returns the numeric byte value (0 through 255) of a given sequence of - octets (8-bit bytes). - - The format for the $ASCII function is: - - $ZA[SCII](expr[,intexpr]) - -3 Examples - Examples - - Example: - - GTM>for i=0:1:4 write !,$zascii("*",i) - - -1 - 228 - 184 - 187 - -1 - GTM> - - This UTF-8 mode example displays the result of $ZASCII() specifying a byte - position before, first, second and third positions, and after the sequence - of octets (8-bit bytes) represented by *. In the above example, 228, 184, - and 187 represents the numeric byte value of the three-byte in the - sequence of octets (8-bit bytes) represented by *. - 2 $ZCHar() $ZCHar() @@ -9134,6 +9400,43 @@ This example WRITEs the byte sequence represented by * and signals the terminal bell. +2 $ZCOllate() + $ZCOllate() + + Returns the transformed representation of the first argument glvn in a + normalized form using the alternative transform specified by the second + argument intexpr; the return can be used as an operand to the follows (]) + or sorts-after (]]) operator such that, if both operands are in the + normalized form, the result is independent of alternative collation. + + The format for the $ZCOLLATE() function is: + + $ZCO[llate](glvn,intexpr[,{0|1}]) + + Note that because the forward transform is to the GDS global storage + format, the reverse transform always shows a global form. This is not + material when the result is used for most comparisons, but for some uses + the applcation might need to remove the leading up-arrow (^). + + Please see the section on $ZATRANSFORM() for a similar alternative. + +3 Example_of_$ZCOllate() + Example of $ZCOllate() + + Example: + + GTM>write $zwrite($zcollate("A(""foo"")",0)) + "A"_$C(0,255)_"foo"_$C(0,0) + GTM>write $zcollate($zcollate("A(""foo"")",0),0,1) + ^A("foo") + GTM> + + The first WRITE in this example shows the readable form or the value + produced by the $ZCOLLATE() revealing the details of how GT.M internally + represents this key using default (M) collation. The second WRITE shows + how the combination of the transform and reverse transform restores the + value to the original representation. + 2 $ZCOnvert() $ZCOnvert() @@ -9770,15 +10073,15 @@ This example illustrates the output produced for each of the possible values for the second argument. -2 $ZPiece() - $ZPiece() +2 $ZPIece() + $ZPIece() Return a sequence of bytes delimited by a specified byte sequence made up of one or more bytes. The format for the $ZPIECE function is: - $ZP[IECE](expr1,expr2[,intexpr1[,intexpr2]]) + $ZPI[ECE](expr1,expr2[,intexpr1[,intexpr2]]) 3 Examples Examples @@ -9812,7 +10115,7 @@ Example: - For p=1:1:$ZLength(x,"/") Write ?p-1*10,$ZPiece(x,"/",p) + For p=1:1:$ZLength(x,"/") Write ?p-1*10,$ZPIece(x,"/",p) This loop uses $ZLENGTH() and $ZPIECE() to display all the pieces of x in columnar format. @@ -10481,11 +10784,11 @@ $ZWRITE(expr[,intexpr]) - o The first expression specifies the string to convert to or from the + o The first argument specifies the string to convert to or from the ZWRITE format. - o The second integer expression specifies the direction of conversion. - When intexpr is not specified or evaluates to zero, $zwrite() converts - the first argument to the ZWRITE format. When intexpr evaluates to a + o The second argument specifies the direction of conversion. When + intexpr is not specified or evaluates to zero, $zwrite() converts the + first argument to the ZWRITE format. When intexpr evaluates to a non-zero value, $ZWRITE() treats the first argument as being in ZWRITE format and attempts to convert it to a string with embedded non-graphic characters; if it is not in ZWRITE format, it returns an @@ -10823,9 +11126,9 @@ $Reference $R[EFERENCE] contains the last global reference. Until the first global - reference is made by an M program, $REFERENCE contains the empty string - (""). This way it is useful in determining if the usage of a naked - reference is valid. + reference is made by an M program or after a global reference with an + invalid key, $REFERENCE contains the empty string (""). This way it is + useful in determining if the usage of a naked reference is valid. A typical way of using this is: @@ -11118,9 +11421,11 @@ character set used by a GT.M process by the value of $ZCHSET. $ZCHSET can have only two values --"M", or "UTF-8". - GT.M only supports Unicode on certain platforms. On platforms where it is - not supported, the intrinsic variable $ZCHSET is always "M" ignoring the - value of the environment variable gtm_chset even if it is defined. + **Warning** + + GT.M performs operations on literals at compile time and the character set + may have an impact on such operations. Therefore, always compile with the + same character set as that used at runtime. Example: @@ -11447,7 +11752,7 @@ piece is an offset in seconds to UTC. For any valid UTC time offset, the fourth piece is a number between -43200 (for UTC-12:00) and +50400 (for UTC+14:00). The value of the fourth piece remains constant all through the - year expect for those places that observe daylight saving time. To obtain + year except for those places that observe daylight saving time. To obtain the $HOROLOG representation of UTC, add the fourth piece to the second piece of $ZHOROLOG and proceed as follows: @@ -11882,6 +12187,12 @@ variable gtm_patnumeric and does not allow the process to change the value. + **Warning** + + GT.M performs operations on literals at compile time and the pattern codes + settings may have an impact on such operations. Therefore, always compile + with the same pattern code settings as those used at runtime. + For characters in Unicode, GT.M assigns patcodes based on the default classification of the Unicode character set by the ICU library with three adjustments: @@ -12514,9 +12825,11 @@ ZSTEP command. $ZSTEP provides the ZSTEP action only when the ZSTEP command does not specify an action. - $ZSTEP initially contains the string "B" to enter direct mode. $ZSTEP is a - read-write Intrinsic Special Variable, (i.e., it can appear on the left - side of the equal sign (=) in the argument to the SET command). + $ZSTEP initially contains the the value of the $gtm_zstep environment + variable or string "B" if $gtm_zstep is not defined; note that the default + "B" causes the process to enter direct mode. $ZSTEP is a read-write + Intrinsic Special Variable, (that is, it can appear on the left side of + the equal sign (=) in the argument to the SET command). Example: @@ -12754,6 +13067,11 @@ M routines cannot modify $ZVERSION. + **Warning** + + GT.M treats $ZVERSION as a literal at compile time. Therefore, always + compile with the same version as that used at runtime. + Example: GTM>w $zversion @@ -13164,8 +13482,18 @@ | CTRAP=expr | U | Controls vectoring on trapped | | | | characters. | |-----------------------+---------+--------------------------------------| + | [NO]EDITING | U | Controls the editing mode for | + | | | $PRINCIPAL. | + |-----------------------+---------+--------------------------------------| + | | | Control whether an "Erase" character | + | [NO]EMPTERM | U | on an empty input line should | + | | | terminate a READ or READ # command. | + |-----------------------+---------+--------------------------------------| | [NO]ESCAPE | U | Controls escape sequence processing. | |-----------------------+---------+--------------------------------------| + | [NO]INSERT | U | Controls insert or overstrike on | + | | | input. | + |-----------------------+---------+--------------------------------------| | | | Controls interpretation by the | | [NO]PASTHRU | U | operating system of special control | | | | characters (for example ). | @@ -13266,8 +13594,8 @@ (LF), U+0000D (CR), U+000D followed by U+000A (CRLF), U+0085 (NEL), U+000C (FF), U+2028 (LS) and U+2029 (PS). -3 READ_/_WRITE_Operations - READ / WRITE Operations +3 READ/WRITE_Operations + READ/WRITE Operations The following table describes all READ and WRITE operations for STREAM, VARIABLE, and FIXED format sequential files having automatic record @@ -13363,6 +13691,10 @@ characters o In M mode, the last setting of RECORDSIZE or WIDTH for the device determines WIDTH + o In M Mode, a WRITE to a sequential device after setting $X to a value + greater than the device WIDTH or a reducing WIDTH to less than the + current $X acts as if the first character caused $X to exceed the + WIDTH induces an immediate WRAP, if WRAP is enabled o In UTF-8 mode, RECORDSIZE is in bytes and WIDTH is in characters and the smaller acts as the WIDTH limit in the table. o In UTF-8 mode, FIXED mode writes to the RECORDSIZE when the next @@ -14035,7 +14367,7 @@ for read x quit:$zeof use $principal write x,! use p1 close p1 quit - cont1 + cont1 if $zeof quit if a=0 set a=i/2 set z=$za @@ -14049,10 +14381,9 @@ . for j=1:1:a read x use $principal write j,"-",x,! use p1 quit - This demonstrates WRITEs to a PIPE device with blocking. The WRITE loop - has no READ to force the input pipe to fill up which blocks the cat - output, causing cat to stop reading its input, letting the pipe acting as - input on the PIPE device to fill up and creating the blocked condition. + This demonstrates how to deal with write blocking of a PIPE device. The + loop doing the WRITE does not READ from the PIPE. Eventually causing the + output of cat to block on its output and stop reading input from the pipe. When the process takes the $ZTRAP to cont1 it tests $DEVICE to determine if the trap is caused by the full pipe. If so, it uses the for loop to read half the number of lines output by the main loop. It decrements i and @@ -14060,6 +14391,175 @@ with the WRITEs to the pipe. Depending upon the configuration of the environment, it may trap several times before processing all lines. + Example: + + sh> mumps -run pipexample induceEAGAIN + The active device is pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEAGAIN^pipexample" STDERR="piperr" + $ZSTATUS="11,pipexample+9^pipexample,%SYSTEM-E-ENO11, Resource temporarily unavailable" + + sh> mumps -run retry^pipexample induceEAGAIN + Try 0 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEAGAIN^pipexample 0" STDERR="piperr" + ...Failed to perform non-blocked writes... Retrying write # 54 + ...Failed to perform non-blocked writes... Retrying write # 63 + ...Failed to perform non-blocked writes... Retrying write # 69 + ...Failed to perform non-blocked writes... Retrying write # 78 + Writes completed + + + This example demonstrates handling WRITE errors, like ENO11 or EAGAIN, + that do not terminate the PIPE device. The PIPE device does non-blocking + writes. If a process tries to WRITE to a full PIPE and the WRITE would + block, the device implicitly tries to complete the operation up to a + default of 10 times. GT.M sleeps 100 micro seconds between each retry. + When dealing with programs that can take a while to process input, it's a + good idea to either schedule a delay between WRITEs or come up with a + mechanism to back off the WRITEs when the buffer fills up. + + sh> mumps -run pipexample induceEPIPE + The active device is pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample" STDERR="piperr" + stdout:My PID is 12808 + stderr:%GTM-F-FORCEDHALT, Image HALTed by MUPIP STOP + $ZSTATUS="32,pipexample+9^pipexample,%SYSTEM-E-ENO32, Broken pipe" + + sh> mumps -run retry^pipexample induceEPIPE + Try 0 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample 0" STDERR="piperr" + ...Caught on try 0, write 49... 32,retry+13^pipexample,%SYSTEM-E-ENO32, Broken pipe + stdout:My PID is 16252 + stderr:%GTM-F-FORCEDHALT, Image HALTed by MUPIP STOP + Try 1 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample 1" STDERR="piperr" + ...Caught on try 1, write 697... 32,retry+13^pipexample,%SYSTEM-E-ENO32, Broken pipe + stdout:My PID is 16403 + stdout:$ZSTATUS="150373210,induceEPIPE+5^pipexample,%GTM-E-DIVZERO, Attempt to divide by zero" + Try 2 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample 2" STDERR="piperr" + Writes completed + + + This example demonstrates how to create a separate STDERR pipe device from + which to read the STDERR output of the program(s) inside the pipe. Reading + the STDERR is important when dealing with failures from Unix programs. It + is possible to read the errors without creating a STDERR pipe device, + however the error messages are commingled with the output of the programs + inside the pipe which could make diagnosis of the underlying problem + harder. Notice that GT.M writes fatal errors, GTM-F types, to STDERR, but + all others go to STDOUT. + + Additionally, this example demonstrates handling errors that terminate the + PIPE device. In this example, the PIPE device is terminated when a program + inside the pipe terminates before reading all of the driving MUMPS + program's output causing an EPIPE or ENO32, a broken pipe. In such a + situation the MUMPS program must capture the error that caused the + termination and respond accordingly. The program may need to call out to + other programs to determine the status of a service it is using or to + alert the operator of an error with an external program or service. To + operate successfully, the program must recreate the pipe and retry the + operation. + + Example: + + ; Example program that starts another program in a pipe and traps the errors. The called + ; programs intentionally induce errors + pipexample + set $etrap="do readfrompipe(.pipe,.piperr) use $p zwrite $zstatus zhalt 99" + set pipe="pipe" + set piperr="piperr" + set writesize=1024 + set cmd=$piece($zcmdline," ") set:'$length(cmd) cmd="induceEPIPE" + open pipe:(shell="/bin/bash":command="$gtm_dist/mumps -run "_cmd_"^pipexample":stderr=piperr)::"pipe" + zshow "D":devicelist write "The active device is ",devicelist("D",2),! + use pipe + for i=1:1:1024 write $tr($justify(i,writesize)," ","X"),! + close pipe + quit + ; Same as above, but without defining the PIPE's standard error + nostderr + set $etrap="do readfrompipe(.pipe) use $p zshow ""*"" zhalt 99" + set pipe="pipe" + set writesize=1024 + set cmd=$piece($zcmdline," ",2) set:'$length(cmd) cmd="induceEAGAIN" + open pipe:(shell="/bin/bash":command="$gtm_dist/mumps -run "_cmd_"^pipexample")::"pipe" + zshow "D":devicelist write "The active device is ",devicelist("D",2),! + write !,! + use pipe + for i=1:1:1024 write $tr($justify(i,writesize)," ","X"),! + close pipe + quit + ; This routine intentionally delays reading from the pipe to induce an EAGAIN + induceEAGAIN + set $etrap="use $p zwrite $zstatus zhalt 99" + set hangtime=+$zcmdline set:'hangtime hangtime=5 set add=1 + for i=1:1:1024 read x(i) quit:$zeof do + . set delay(i)=1/(add+$random(hangtime)) + . hang delay(i) + . set:i=30 add=10 + halt + ; This routine intentionally induces an EPIPE by immediately sending a SIGTERM to itself causing + ; a FORCEDHALT error which goes to STDERR. Subsequently, a random DIVZERO error occurs, but this + ; error goes to STDOUT since it is not a fatal error + induceEPIPE + set $etrap="use $p zwrite $zstatus zhalt 99" + set divzero=150373210 ; DIVZERO goes to stdout + write "My PID is ",$job,! + zsystem:'$zcmdline "kill -15 "_$job ; FORCEDHALT error goes to stderr + for i=1:1 read x(i) quit:$zeof zmessage:'$random(1000) divzero + halt + ; Read the contents of the pipe on failure. Messages from the programs inside the pipe aid + ; in undestanding the underlying problem(s) + readfrompipe(pipe,piperr) + new i + new $etrap + set $etrap="set x=$zjobexam() zhalt 88" + use pipe + for i=1:1 read pipe(i):0 quit:'$test!$zeof + zkill pipe(i) + do:$data(piperr) + . use piperr + . for i=1:1 read piperr(i):0 quit:'$test!$zeof + . zkill piperr(i) + close pipe + use $p + for i=1:1 quit:'$data(pipe(i)) write ?4,"stdout:",pipe(i),! + for i=1:1 quit:'$data(piperr(i)) write ?4,"stderr:",piperr(i),! + quit + ; Example of trapping an error and retrying the operation as necessary. Error conditions + ; used are EPIPE, aka "Broken pipe" or ENO32, and EAGAIN, aka ENO11. + retry + set $etrap="use $p zshow ""*"" zhalt 99" + set pipe="pipe" + set piperr="piperr" + set writesize=1024 + set cmd=$piece($zcmdline," ") set:'$length(cmd) cmd="induceEPIPE" + for try=0:1 do quit:$get(readcomplete,0) + . new $etrap set $etrap="goto retryEPIPE" + . open pipe:(shell="/bin/bash":command="$gtm_dist/mumps -run "_cmd_"^pipexample "_try:stderr=piperr)::"pipe" + . zshow "D":devicelist write "Try ",try,$char(9),devicelist("D",2),! + . use pipe + . for i=1:1:1024 do + . . new $etrap set $etrap="goto retryEAGAIN^pipexample" + . . write $tr($justify(i,writesize)," ","X"),! + . set readcomplete=1 + close pipe + use $p + write ?4,"Writes completed",! + quit + retryEPIPE + quit:$zstatus'["ENO32" + use $p + write "...Caught on try ",try,", write ",i,"... ",$zstatus,! + set $ecode="" + do readfrompipe(.pipe,.piperr) + quit + retryEAGAIN + quit:$zstatus'["ENO11" + use $p + write "...Failed to perform non-blocked writes... Retrying write # ",$increment(i,-1),! + set $ecode="" + hang 1+$random(5) + use pipe + quit + + This example demonstrates how to handle PIPE device errors, whether with + the device itself or from programs inside the PIPE device. + 3 PIPE_Deviceparameter_Summary PIPE Deviceparameter Summary @@ -14098,7 +14598,7 @@ | | | which the created process writes any standard | | STDERR=string | o | error output. The GT.M process can USE, READ, and | | | | CLOSE it, but cannot WRITE to it. When the GT.M | - | | | process CLOSEs the PIPE device the PIPE device | + | | | process CLOSEs the PIPE device, the PIPE device | | | | CLOSEs STDERR, if still OPEN. | |----------------+---+---------------------------------------------------| | WRITEONLY | o | Specifies that the GT.M process may only WRITE to | @@ -14154,7 +14654,7 @@ From an application perspective, the transport layers used by a socket device are stream-oriented, with no provisions for implicit application messages. Therefore, the following are two common protocols used to - segment application messages.. + segment application messages. 1. One method is to use a, typically small, fixed length message containing the length of the next, variable length, message. In GT.M a @@ -14175,8 +14675,8 @@ application message. The protocol breaks if a message ever includes a delimiter as part of its content. - The SOCKET device provides a facility for recognizing delimiters to simply - parsing messages. + The SOCKET device provides a facility for recognizing delimiters to + simplify parsing messages. 3 Socket_Read_Operation Socket Read Operation @@ -14329,7 +14829,7 @@ WRITE ! inserts the character(s) of the first I/O delimiter (if any) to the sending buffer. If "ZFF=expr" has been specified, WRITE # inserts the - characters of expr . Otherwise WRITE # has no effect. WRITE ! and WRITE # + characters of expr. Otherwise WRITE # has no effect. WRITE ! and WRITE # always maintain $X and $Y in a fashion that emulates a terminal cursor position except when the device is OPENed with a UTF CHSET because the units for $X and $Y for terminals are in display columns while for sockets @@ -14346,7 +14846,7 @@ /W[AIT][(timeout)] - where timeout is anumeric expression that specifies how long in seconds a + where timeout is a numeric expression that specifies how long in seconds a server waits for a connection or data to become available on one of the sockets in the current Socket Device. @@ -14364,7 +14864,7 @@ o If a numeric targetpid is specified, GT.M matches the value against the process id ($JOB) of the process receiving the sockets. GT.M uses a system service to perform this check on platforms that support it - - currently: Linux, and AIX. If the pids do not match, GT.M issues a + currently: Linux and AIX. If the pids do not match, GT.M issues a PEERPIDMISMATCH error and does not transfer the sockets. o If a numeric timeout is specified, GT.M sets $TEST to 1 if the transfer completes within the specified time, and otherwise sets $TEST @@ -14421,38 +14921,55 @@ socket connection itself, the socket handle, and buffered socket data (if any). - WRITE /TLS(option[,[timeout][,tlsid]]) + WRITE /TLS(option[,[timeout][,tlsid[,cfg-file-options]]) - SOCKET devices support encrypt connections with TLS using an encryption + SOCKET devices support encrypted connections with TLS using an encryption plugin. GT.M ships with a reference implementation of the plugin which uses OpenSSL; the reference implementation also supports TLS for GT.M replication streams. OpenSSL options are controlled by a configuration file. The WRITE /TLS command activates this feature for connected sockets. - o option is "server" or "client" indicating which TLS role to assume. - The server role requires a certificate specified in the configuration - file section with the label matching tlsid. The client role may - require a certificate depending on the OpenSSL options. If the - argument specifies a timeout, GT.M sets $TEST to 1 if the command - successfully completed or to 0 if it timed out. $DEVICE provides - status information in case of an error. ZSHOW "D" includes "TLS" in - the second line of the output for an encrypted socket. - o Note that SOCKET device actions may produce the following errors: - TLSDLLOPEN, TLSINIT, TLSCONVSOCK, TLSHANDSHAKE, TLSCONNINFO, - TLSIOERROR, and TLSRENEGOTIATE. - - When placing the private key for a certificate at the beginning of the - certificate file, you may omit the "key" item from the configuration file. - The format of the combined file is: - - -----BEGIN RSA PRIVATE KEY----- - [encoded key] - -----END RSA PRIVATE KEY----- - [empty line] - -----BEGIN CERTIFICATE----- - [encoded certificate] - -----END CERTIFICATE----- - [empty line] + o option is "server", "client", or "renegotiate". "server" or "client" + indicates which TLS role to assume. The server role requires a + certificate specified in the configuration file section with the label + matching tlsid. The client role may require a certificate depending on + the OpenSSL options. If a timeout is specified for options "client" or + "server", GT.M sets $TEST to 1 if the command successfully completed + or to 0 if it timed out. $DEVICE provides status information in case + of an error. ZSHOW "D" includes "TLS" in the second line of the output + for an encrypted socket. + o "renegotiate" applies only to a server socket. It allows applications + to request a TLS renegotiation. Renegotiation requires the suspension + of application communication and the application must read all pending + data before initiating a renegotiation. This means that in the + communication protocol used, both parties must be at a known state + when renegotiating keys. For example, in GT.M replication, one party + sends a renegotiation request and waits for an acknowledgement before + initiating the renegotiation. + o tlsid refers to the name of a section in the configuration file + specified by the gtmcrypt_config environment variable. If tlsid is not + specified with the "renegotiate" option and cfg-file-options are + specified, GT.M creates a virtual section by appending "-RENEGOTIATE" + to the tlsid used to enable TLS on the socket. If no section named + tlsid is present in the configuration file, GT.M creates a virtual + section with that name for the life of the process. + o cfg-file-options specifies configuration file options. Note + cfg-file-options override those options if they are already specified + in the configuration file except ssl-options and verify-level which + are merged. + o Supported cfg-file-options for the "renegotiate" command are + (case-sensitive): verify-depth, verify-level, verify-mode, + session-id-hex, and CAfile. WRITE /TLS ignores all other configuration + file options whether given on the command or in the configuration + file. For more information on the supported configuration options, + refer to the Creating a Configuration File section of the + Administration and Operations Guide. + + **Note** + + Note that SOCKET device actions may produce the following errors: + TLSDLLOPEN, TLSINIT, TLSCONVSOCK, TLSHANDSHAKE, TLSCONNINFO, TLSIOERROR, + and TLSRENEGOTIATE. GT.M buffers WRITEs to TLS enabled sockets until a subsequent USE :FLUSH, WRITE !, WRITE #, or an internal 400 millisecond timer expires. @@ -14472,10 +14989,10 @@ Each socket may have one or more sockets waiting for either an incoming connection or data available to READ (observable through $ZKEY). $ZKEY - contains semi-colon (";") separated list of entries detailing any waiting + contains semi- colon (";") separated list of entries detailing any waiting sockets for a current SOCKET device. - For more information on $KEY and $ZKEY, refer to Chapter 8: "ISV". + For more information on $KEY and $ZKEY, refer to "ISV". 3 Socket_Deviceparameter_Summary Socket Deviceparameter Summary @@ -14529,14 +15046,14 @@ +------------------------------------------------------------------------+ +------------------------------------------------------------------------+ - | Socket Establishment/Disconnect Deviceparameters | + | Buffer Deviceparameters | |------------------------------------------------------------------------| | DEVICEPARAMETER | COMMAND | COMMENT | |------------------+---------+-------------------------------------------| - | ZBFSIZE =intexpr | O | Allocates a buffer used by GT.M when | + | ZBFSIZE =intexpr | O/U | Allocates a buffer used by GT.M when | | | | reading from a socket. | |------------------+---------+-------------------------------------------| - | ZIBFSIZE=intexpr | O | Sets the buffer size used by the network | + | ZIBFSIZE=intexpr | O/U | Sets the buffer size used by the network | | | | software (setsockopt SO_RCVBUF). | +------------------------------------------------------------------------+ @@ -14606,10 +15123,9 @@ $gtm_dist/mumps -r start^server When start^server begins, the $PRINCIPAL device is the current device - connected a socket and $KEY contains - "ESTABLISHED|socket_handle|remote_ip_address". In most cases, a USE - command near the beginning of the routine sets various device parameters - such as delimiters. + connected a socket and $KEY contains "ESTABLISHED|socket_handle| + remote_ip_address". In most cases, a USE command near the beginning of the + routine sets various device parameters such as delimiters. The ZSHOW "D" command reports available information on both the local and remote sides of a TCP socket including local and remove addresses and @@ -15075,11 +15591,13 @@ 5 ICHSET ICHSET - ICHSET=expr Applies to: All devices + ICHSET=expr + + Applies to: All devices - Establishes the character encoding of the input device being OPENed in the - UTF-8 mode. The value of the expression can be M, UTF-8, UTF-16, UTF-16LE, - or UTF-16BE. In M mode, ICHSET has no effect. + Establishes the character encoding of an input device being OPENed and + USEed in the UTF-8 mode. The value of the expression can be M, UTF-8, + UTF-16, UTF-16LE, or UTF-16BE. In M mode, ICHSET has no effect. If ICHSET is not specified, GT.M assumes UTF-8 as the default character set for input from the device. @@ -15090,9 +15608,9 @@ **Note** - ICHSET is a deviceparameter of the OPEN command and not the USE command. - Since GT.M implicitly OPENs $PRINCIPAL before any application code is - executed, ICHSET does not apply to $Principal. + ICHSET is a deviceparameter of both the OPEN and USE commands. As ICHSET + can change the character set of an already OPENed device, it can help deal + with binary data intermixed with character data. 5 INDEPENDENT INDEPENDENT @@ -15368,8 +15886,8 @@ OCHSET=expr Applies to: All devices - Establishes the character encoding of the output device being OPENed in - the UTF-8 mode. The value of the expression can be M, UTF-8, UTF-16, + Establishes the character encoding of the output device OPENed and USEed + in the UTF-8 mode. The value of the expression can be M, UTF-8, UTF-16, UTF-16LE, or UTF-16BE. In M mode, OCHSET has no effect. If *CHSET is not specified, GT.M assumes UTF-8 as the default character @@ -15381,9 +15899,9 @@ **Note** - OCHSET is a deviceparameter of the OPEN command not the USE command. Since - GT.M implicitly OPENs $PRINCIPAL before any application code is executed, - OCHSET does not apply to $Principal. + OCHSET is a deviceparameter of both the OPEN and USE commands. As OCHSET + can change the character set of an already OPENed device, it can help deal + with binary data intermixed with character data. Example: @@ -16034,7 +16552,7 @@ |----------------------+-----+----+------+------+------+-----| | [NO]EMPT[ERM] | X | | | | | | |----------------------+-----+----+------+------+------+-----| - | EXCEPTION=expr | X | X | X | | X | X | + | EXCEPTION=expr | X | X | X | X | X | X | |----------------------+-----+----+------+------+------+-----| | FIFO | | | X | | | | |----------------------+-----+----+------+------+------+-----| @@ -16044,16 +16562,18 @@ |----------------------+-----+----+------+------+------+-----| | GROUP=expr | | X | X | | | | |----------------------+-----+----+------+------+------+-----| - | KEY | | X | X | X | | | + | ICHSET=encoding | X | X | X | X | X | X | |----------------------+-----+----+------+------+------+-----| | IKEY | | X | X | X | | | |----------------------+-----+----+------+------+------+-----| - | ICHSET=encoding | X | X | X | X | X | X | - |----------------------+-----+----+------+------+------+-----| | INDEPENDENT | | | | X | | | |----------------------+-----+----+------+------+------+-----| | IOERROR=expr | | | | | | X | |----------------------+-----+----+------+------+------+-----| + | KEY | | X | X | X | | | + |----------------------+-----+----+------+------+------+-----| + | LISTEN=expr | | | | | | X | + |----------------------+-----+----+------+------+------+-----| | [NO]NEWVERSION | | X | X | | | | |----------------------+-----+----+------+------+------+-----| | OCHSET=encoding | X | X | X | X | X | X | @@ -16086,10 +16606,10 @@ |----------------------+-----+----+------+------+------+-----| | WORLD=expr | | X | X | | | | |----------------------+-----+----+------+------+------+-----| - | [NO]WRITEONLY | | | | X | | | - |----------------------+-----+----+------+------+------+-----| | [NO]WRAP | X | X | X | X | X | X | |----------------------+-----+----+------+------+------+-----| + | [NO]WRITEONLY | | X | X | X | | | + |----------------------+-----+----+------+------+------+-----| | ZBFSIZE | | | | | | X | |----------------------+-----+----+------+------+------+-----| | Z[NO]DELAY | | | | | | X | @@ -16097,8 +16617,6 @@ | Z[NO]FF | | | | | | X | |----------------------+-----+----+------+------+------+-----| | ZIBFSIZE | | | | | | X | - |----------------------+-----+----+------+------+------+-----| - | LISTEN=expr | | | | | | X | +------------------------------------------------------------+ 3 Use @@ -16137,11 +16655,11 @@ **Note** - A socket does not carry I[O]CHSET with it while being moved. Such a socket - uses the I[O]CHSET of the device it is ATTACHed to. If there is input - still buffered, this may cause unintentional consequences in the - application if I[O]CHSET changes. GT.M does not detect (or report) a - change in I[O]CHSET due to DETACH/ATTACH. + A socket does not carry [I|O]CHSET with it while being moved. Such a + socket uses the [I|O]CHSET of the device it is ATTACHed to. If there is + input still buffered, this may cause unintentional consequences in the + application if [I|O]CHSET changes. GT.M does not detect (or report) a + change in [I|O]CHSET due to DETACH/ATTACH. 5 CANONICAL CANONICAL @@ -16308,11 +16826,11 @@ **Note** A socket can move from one device to another using DETACH/ATTACH. A socket - does not carry I[O]CHSET with it while being moved. Such a socket uses the - I[O]CHSET of the device it is ATTACHed to. If there is input still + does not carry [I|O]CHSET with it while being moved. Such a socket uses + the [I|O]CHSET of the device it is ATTACHed to. If there is input still buffered, this may cause unintentional consequences in the application if - I[O]CHSET changes. GT.M does not detect (or report) a change in I[O]CHSET - due to DETACH/ATTACH. + [I|O]CHSET changes. GT.M does not detect (or report) a change in + [I|O]CHSET due to DETACH/ATTACH. Example: @@ -16622,6 +17140,22 @@ SEEK. Use this deviceparameter with $PRINCIPAL when redirected from a file. +5 INSERT + INSERT + + [NO]INSERT Applies to: TRM + + Enables or disables insert mode for the $PRINCIPAL device. If INSERT mode + is enabled, GT.M inserts input characters at the logical position in the + input stream designated by the virtual cursor as defined by $X and $Y, for + example in the middle of the line/record. If INSERT mode is disabled, + input characters overwrite the existing characters in the input stream at + the logical position designated by the virtual cursor. You can toggle the + insert mode within a direct mode line or if EDITING is enabled for a + single READ argument's input using the terminal's INSERT key. The INSERT + mode is reset to the default or what was last specified with USE at the + beginning of each direct mode line or READ argument. + 5 IOERROR IOERROR @@ -17111,8 +17645,8 @@ Note that LOCAL sockets ignore the ZIBFSIZE deviceparameter. -4 Summary - Summary +4 _Summary + Summary +-----------------------------------------------------------+ | USE Deviceparameters | @@ -17137,6 +17671,8 @@ |---------------------+-----+----+------+------+------+-----| | [NO]CENABLE | X | | | | | | |---------------------+-----+----+------+------+------+-----| + | [I|O]CHSET | X | X | X | X | X | X | + |---------------------+-----+----+------+------+------+-----| | CLEARSCREEN | X | | | | | | |---------------------+-----+----+------+------+------+-----| | CONNECT | | | | | | X | @@ -17151,39 +17687,37 @@ |---------------------+-----+----+------+------+------+-----| | DOWNSCROLL | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | [NO]EBCDIC | | | | | | | - |---------------------+-----+----+------+------+------+-----| | [NO]ECHO | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | [NO]EMPT[ERM] | X | | | | | | + | [NO]EMPTERM | X | | | | | | |---------------------+-----+----+------+------+------+-----| | ERASELINE | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | ERASETAPE | | | | | | | - |---------------------+-----+----+------+------+------+-----| | [NO]ESCAPE | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | EXCEPTION=expr | X | X | X | | X | X | + | EXCEPTION=expr | X | X | X | X | X | X | |---------------------+-----+----+------+------+------+-----| | [NO]FILTER[=expr] | X | | | | X | X | |---------------------+-----+----+------+------+------+-----| - | FLUSH | X | | | | | | + | FLUSH | X | | | | | X | |---------------------+-----+----+------+------+------+-----| | [NO]FOLLOW | | X | | | | | |---------------------+-----+----+------+------+------+-----| | [NO]HOSTSYNC | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | KEY | | X | X | X | | | - |---------------------+-----+----+------+------+------+-----| | IKEY | | X | X | X | | | |---------------------+-----+----+------+------+------+-----| - | IOERROR | | | | | | X | - |---------------------+-----+----+------+------+------+-----| | INREWIND | | X | | | | | |---------------------+-----+----+------+------+------+-----| | INSEEK | | X | | | | | |---------------------+-----+----+------+------+------+-----| - | [Z]LENGTH=expr | X | X | X | | X | X | + | IOERROR | | | | | | X | + |---------------------+-----+----+------+------+------+-----| + | KEY | | X | X | X | | | + |---------------------+-----+----+------+------+------+-----| + | [Z]LENGTH=expr | X | X | X | X | X | X | + |---------------------+-----+----+------+------+------+-----| + | LISTEN | | | | | | X | |---------------------+-----+----+------+------+------+-----| | OKEY | | X | X | X | | | |---------------------+-----+----+------+------+------+-----| @@ -17193,20 +17727,12 @@ |---------------------+-----+----+------+------+------+-----| | [NO]PASTHRU | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | [NO]RCHK | | | | | | | - |---------------------+-----+----+------+------+------+-----| - | [NO]RETRY | | | | | | | - |---------------------+-----+----+------+------+------+-----| | REWIND | | X | | | | | |---------------------+-----+----+------+------+------+-----| | SEEK=strexpr | | X | | | | | |---------------------+-----+----+------+------+------+-----| - | SKIPFILE=intexpr | | | | | | | - |---------------------+-----+----+------+------+------+-----| | SOCKET | | | | | | X | |---------------------+-----+----+------+------+------+-----| - | SPACE=intexpr | | | | | | | - |---------------------+-----+----+------+------+------+-----| | TERMINATOR[=expr] | X | | | | | | |---------------------+-----+----+------+------+------+-----| | [NO]TRUNCATE | | X | | | | | @@ -17215,16 +17741,10 @@ |---------------------+-----+----+------+------+------+-----| | UPSCROLL | X | | | | | | |---------------------+-----+----+------+------+------+-----| - | [NO]WCHK | | | | | | | - |---------------------+-----+----+------+------+------+-----| | [Z]WIDTH=intexpr | X | X | X | X | X | X | |---------------------+-----+----+------+------+------+-----| | [NO]WRAP | X | X | X | X | X | X | |---------------------+-----+----+------+------+------+-----| - | WRITELB=expr | | | | | | | - |---------------------+-----+----+------+------+------+-----| - | WRITETM | | | | | | | - |---------------------+-----+----+------+------+------+-----| | X=intexpr | X | | | | X | | |---------------------+-----+----+------+------+------+-----| | Y=intexpr | X | | | | X | | @@ -17235,9 +17755,7 @@ |---------------------+-----+----+------+------+------+-----| | Z[NO]FF | | | | | | X | |---------------------+-----+----+------+------+------+-----| - | ZIBUFSIZE | | | | | | X | - |---------------------+-----+----+------+------+------+-----| - | LISTEN | | | | | | X | + | ZIBFSIZE | | | | | | X | +-----------------------------------------------------------+ 3 Close @@ -17296,31 +17814,27 @@ | | | SOC: Valid for Socket devices | |-----------------------------------------------| - | DELETE | | X | X | | + | DELETE | | X | X | X | |-----------------------+-----+----+------+-----| | DESTROY | | X | X | X | |-----------------------+-----+----+------+-----| - | ERASETAPE=expr | | | | | - |-----------------------+-----+----+------+-----| - | EXCEPTION=expr | X | X | X | X | + | EXCEPTION | X | X | X | X | |-----------------------+-----+----+------+-----| - | GROUP=expr | | X | | | + | GROUP | | X | X | | |-----------------------+-----+----+------+-----| - | OWNER=expr | | X | | | + | OWNER | | X | X | | |-----------------------+-----+----+------+-----| - | RENAME=expr | | X | | | + | RENAME | | X | X | | |-----------------------+-----+----+------+-----| - | REWIND | | | | | + | REWIND | | X | | | |-----------------------+-----+----+------+-----| | SOCKET | | | | X | |-----------------------+-----+----+------+-----| - | SPACE | | | | | - |-----------------------+-----+----+------+-----| - | SYSTEM=expr | | X | | | + | SYSTEM | | X | X | | |-----------------------+-----+----+------+-----| - | UIC=group name | | X | | | + | UIC | | X | X | | |-----------------------+-----+----+------+-----| - | WORLD=expr | | X | | | + | WORLD | | X | X | | +-----------------------------------------------+ **Note** @@ -17712,13 +18226,10 @@ entryref: return-value routine-name (parameter, parameter, ... ) - where entryref is an M entryref, - - return-value is gtm_long_t, gtm_status_t, or void. - - and + where entryref is an M entryref, return-value is gtm_long_t, gtm_status_t, + or void, and parameters are in the format: - parameters are in the format: direction:type [num] + direction:type [num] where [num] indicates a pre-allocation value explained later in this chapter. @@ -19834,6 +20345,15 @@ where tablename is the name of the patcode table within the file pointed to by gtm_pattern_file. + **Warning** + + GT.M performs operations on literals at compile time and the pattern codes + settings may have an impact on such operations. Therefore, it is safest to + either always compile with the same pattern code settings as those used at + runtime. If changes to pattern codes are required at run time, "hide" any + patterns used on literal expressions from the compiler (which are + uncommon) using XECUTE commands or indirection. + Within an active process, the patcode table is established using the M VIEW command and the %PATCODE utility. Before invoking the %PATCODE utility, you may use VIEW to load pattern definition files for GT.M. The @@ -20773,6 +21293,11 @@ region-disambiguator identifies a region which holds a trigger that is not mapped by $ZGBLDIR, these features treat the trigger as not found. + ZPRINT or $TEXT() of trigger code may be out-of-date if the process + previously loaded the code, but a $ZTRIGGER() or MUPIP TRIGGER has since + changed the code. In other words, execution of a trigger (not $TEXT()) + ensures that trigger code returned with $TEXT() is current. + Appendix A. M Coding Standards - Do's and Don'ts 2 M_Coding_Standards_-_Do's_and_Don'ts diff --git a/sr_port/mupip.hlp b/sr_port/mupip.hlp index b5ad96f..5071e66 100644 --- a/sr_port/mupip.hlp +++ b/sr_port/mupip.hlp @@ -92,6 +92,12 @@ on the circumstances it encounters and the qualifiers with which it is invoked. + **Note** + + MUPIP commands that need standalone access issue a MUUSERLBK error on a + crashed replication-enabled database and MUUSERECOV error in case of a + non-replicated-but-journaled database. + 2 Syntax Syntax @@ -459,7 +465,8 @@ **Note** The replication instance file should always be backed up with the database - file. + file. The source server for the instance must be started at least once + before backing up the replication instance file. The format of the REPLINSTANCE qualifier is: @@ -673,9 +680,25 @@ The MUPIP DOWNGRADE command changes the file header format to V4 or V5. The format of the MUPIP DOWNGRADE command is: - D[OWNGRADE] -V[ERSION]={V4|V5} file-name + D[OWNGRADE] -V[ERSION]={V4|V5|V63000A} file-name - For V4: + **Note** + + You must perform a GT.M database integrity check using the -noonline + parameter prior to downgrading a database. The integrity check verifies + and clears database header fields required for an orderly downgrade. If an + integrity check is not possible due to time constraints, please rely on a + rolling upgrade scheme using replication and / or take a backup prior to + upgrading the database. + +3 VERSION + VERSION + + V4 and V5 specifies file header format. For more information on the + downgrade criteria for your database, refer to the release notes document + of your current GT.M version. + + V4: o It reduces the size from 8 bytes to 4 bytes for fields like current transaction (CTN), maximum tn (MTN) and others that contain @@ -685,21 +708,12 @@ In such a case, perform a MUPIP EXTRACT -FORMAT=ZWR operation on the V5 database and then perform a MUPIP LOAD operation on a V4 database. -3 VERSION - VERSION - - Specifies file header format. For more information on the downgrade - criteria for your database, refer to the release notes document of your - current GT.M version. + V63000A: - **Note** - - You must perform a GT.M database integrity check using the -noonline - parameter prior to downgrading a database. The integrity check verifies - and clears database header fields required for an orderly downgrade. If an - integrity check is not possible due to time constraints, please rely on a - rolling upgrade scheme using replication and / or take a backup prior to - upgrading the database. + V63000A downgrades to any release older than V6.3-001. All releases up to + V6.3-000A have an empty 512-bytes block logically after the last usable + database block. VERSION=V63000A changes this terminating block from having + the current size of a database block to 512-bytes. 3 Examples Examples @@ -710,6 +724,62 @@ This command changes the file-header of mumps.dat to V4 format. +2 DUMPFHEAD + DUMPFHEAD + + The MUPIP DUMPFHEAD command displays information about one or more + database files. The format of the MUPIP DUMPFHEAD command is: + + DU[MPFHEAD] {-FI[LE] file-name |-REG[ION] region-list} + +3 FILE + FILE + + Specifies the name of the database file for the MUPIP DUMPFHEAD operation. + -FILE does not require a Global Directory. The format of the FILE + qualifier is: + + -FI[LE] database-file-name + + o The database file name must include the absolute or relative path. + o The -FILE qualifier is incompatible with the -REGION qualifier. + +3 REGION + REGION + + Specifies that the INTEG parameter identifies one or more regions rather + than a database file. The format of the REGION qualifier is: + + -R[EGION] region-list + + o The region-list identifies the target of DUMPFHEAD. region-list may + specify more than one region of the current global directory in a + list. Regions are case-insensitive, separated by a comma, and + wildcards can be used to specify them. Any region-name may include the + wildcard characters * and ? (remember to escape them to protect them + from inappropriate expansion by the shell). Any region name expansion + occurs in M (ASCII) collation order. + o The region-list argument may specify more than one region of the + current Global Directory in a list separated with commas. DUMPFHEAD + -REGION requires the environment variable gtmgbldir to specify a valid + Global Directory. + o The -REGION qualifier is incompatible with the -FILE qualifier. + +3 Examples + Examples + + Example: + + $ mupip dumpfhead -file mumps.dat + + This command lists information about the database file mumps.dat in the + current working directory. + + $ mupip dumpfhead -region "*" + + This command lists information about all the database files mapped by the + global directory specified by $gtmgbldir. + 2 ENDIANCVT ENDIANCVT @@ -1115,7 +1185,7 @@ The format of the MUPIP FREEZE command is: - F[REEZE] {-OF[F] [-OV[ERRIDE]]|-ON [-R[ECORD]]} region-list + F[REEZE] {-OF[F] [-OV[ERRIDE]]|-ON [[-ONL[INE] [-[NO]AUTORELEASE]] | [-NOONL[INE]] [-R[ECORD]]]} region-list o The region-list identifies the target of the FREEZE. region-list may specify more than one region of the current global directory in a @@ -1124,10 +1194,11 @@ wildcard characters * and % (remember to escape them to protect them from inappropriate expansion by the shell). Any region name expansion occurs in M (ASCII) collation order. - o MUPIP FREEZE waits for one minute so that concurrent KILL or MUPIP - REORG operations can complete. If the KILL or MUPIP REORG commands do - not complete within one minute, MUPIP FREEZE terminates operations and - unfreezes any regions it had previously marked as frozen. + o MUPIP FREEZE waits for up to one minute so that concurrent KILL or + MUPIP REORG operations can complete. If the KILL or MUPIP REORG + commands do not complete within one minute, MUPIP FREEZE unfreezes any + regions it had previously marked as frozen and terminates with an + error. o To ensure that a copy or reorganized version of a database file contains a consistent set of records, concurrent MUPIP utilities, such as BACKUP (without the ONLINE qualifier) and EXTRACT, include @@ -1136,11 +1207,19 @@ qualifier with BACKUP. o A MUPIP FREEZE can be removed only by the user who sets the FREEZE or by using -OVERRIDE. - o After MUPIP FREEZE -ON, processes that are attempting updates "hang" - until the FREEZE is removed by the MUPIP FREEZE -OFF command or DSE. - Make sure that procedures for using MUPIP FREEZE, whether manual or - automated, include provisions for removing the FREEZE in all - appropriate cases, including when errors disrupt the normal flow. + o A MUPIP FREEZE -ON can specify either -NOONLINE, the default, or + -ONLINE, and if -ONLINE, can specify either -AUTORELEASE, the default, + or -NOAUTORELEASE. + o A FREEZE specifying -ONLINE attempts to minimize the impact of the + FREEZE on concurrently updating processes. + o A FREEZE specifying -ONLINE -AUTORELEASE allows updates to continue + immediately when GT.M needs to update the database file. + o After MUPIP FREEZE -ON -NOONLINE, processes that are attempting + updates "hang" until the FREEZE is removed by the MUPIP FREEZE -OFF + command or DSE. Make sure that procedures for using MUPIP FREEZE, + whether manual or automated, include provisions for removing the + FREEZE in all appropriate cases, including when errors disrupt the + normal flow. o A -RECOVER/-ROLLBACK for a database reverts to a prior database update state. Therefore, a -RECOVER/-ROLLBACK immediately after a MUPIP FREEZE -ON removes the freeze. However, -RECOVER/-ROLLBACK does not @@ -1155,8 +1234,10 @@ The optional qualifiers are: + -[NO]A[UTORELEASE] - only valid with -ONLINE + -ON[LINE] - only valid with -ON -OV[ERRIDE] - -R[ECORD] + -R[ECORD] - only valid with -ON 3 OFf OFf @@ -1167,6 +1248,10 @@ OF[F] + o A FREEZE -OFF which turns off a FREEZE -ONLINE -AUTORELEASE produces a + OFRZNOTHELD warning to indicate that the freeze was automatically + released and therefore did not protect whatever concurrent actions it + was intended to guard. o When used with -OVERRIDE, -OFF stops a freeze operation set by a process with a different userid. o Incompatible with: -ON, -RECORD @@ -1181,6 +1266,75 @@ Incompatible with: -OFF, -OVERRIDE +3 [NO]A[UTORELEASE + [NO]A[UTORELEASE + + Controls the behavior of a FREEZE specified with -ONLINE when GT.M must + write to a database file. The format of the AUTORELEASE qualifier is: + + -[NO]A[UTORELEASE] + + o -AUTORELEASE, the default, causes GT.M to release the freeze if it + needs to update the file before a FREEZE -OFF. + o -NOAUTORELEASE causes GT.M to hold off actions that need to update the + database file until someone issues a MUPIP FREEZE -OFF. + o -The actions that require GT.M to write to the database file are: + + o Insufficient global buffers to hold updates - GT.M must flush + buffers to make space to do any additional updates + o Insufficient space in the database to hold updates - GT.M must + extend the file + o The journal file reaches its maximum size or someone issues a + MUPIP SET -JOURNAL command - GT.M must create a new journal file + o An epoch comes due - GT.M must create a checkpoint + o Someone issues a MUPIP BACKUP command - GT.M must record state + information to mark the beginning of the backup + + o When an -AUTORELEASE abandons a FREEZE, any actions that depend on the + stability of the database file on secondary storage, such as a + database copy, lose that protection and are not reliable, so they + likely need to be repeated at a time when an -AUTORELEASE is less + likely or when -NOONLINE is more appropriate. + o An -AUTORELEASE action produces an OFRZAUTOREL message in the operator + log. + o An -AUTORELEASE action requires a FREEZE -OFF to reestablish a normal + database state. + o Incompatible with: -OFF, -NOONLINE + +3 ONLine + ONLine + + Controls the potential impact of a FREEZE on concurrently updating + processes. The format of the ONLINE qualifier is: + + -[NO]ONL[INE] + + o ON -NOONLINE, the default, causes the freeze to last until OFF, and + makes management of the FREEZE straightforward. + o ON -ONLINE, causes GT.M to attempt to minimize the impact of the + FREEZE on concurrently updating processesby taking a number of + actions, as appropriate: + + o Switching journal files to provide maximum space + o Performing an epoch to provide maximum time to the next epoch + o Flushing the global buffers to make all available to hold updates + o Incompatible with: -AUTORELEASE, -OFF + + o After performing these preparations, -ONLINE allows updating processes + to make updates to global buffers but defer flushing them to the + database file. + o -ONLINE cannot apply to MM databases, so a FREEZE -ONLINE skips any MM + regions it encounters. + o Refer to -AUTORELEASE above for additional information. + o Incompatible with: -OFF + + **Note** + + If a database is nearly full, and you about to use MUPIP FREEZE -ON + -ONLINE, you may want to use MUPIP EXTEND first as a database file + extension will either AUTORELEASE or "harden" the -ONLINE freeze + effectively into a -NOONLINE freeze. + 3 OVerride OVerride @@ -1192,7 +1346,7 @@ o OVERRIDE should not be necessary (and may even be dangerous) in most schemes. - o Incompatible with: -ON, -RECORD + o Incompatible with: -AUTORELEASE, -ON, -ONLINE -RECORD 3 Record Record @@ -1661,7 +1815,7 @@ subscripts with a colon (:). -SUBSCRIPT cannot detect incorrectly marked busy errors. The format of the SUBSCRIPT qualifier is: - -S[UBSCRIPT]=subscript + -SU[BSCRIPT]=subscript Specify SUBSCRIPT only if the path to the keys in the subscript is not damaged. If the path is questionable or known to be damaged, use DSE to @@ -1669,6 +1823,23 @@ Incompatible with: -BLOCK, -TN_RESET +3 Stats + Stats + + Specifies INTEG to check any active statistics database associated with + the region(s) specified for the command. The format of the STATS qualifier + is: + + -[NO]ST[ATS] + + Specify STATS only if you have reason to understand that statistics + reporting is failing with database errors or reporting incorrect results. + Because -FILE requires standalone access and statistic databases are + automatically created and removed it is incompatible with -STATS. The + default is NOSTATS. + + Incompatible with: -BLOCK, -FILE, -TN_RESET + 3 TN_reset TN_reset @@ -2188,7 +2359,7 @@ -S[ELECT]=global-name-list -T[RUNCATE][=percentage] -UP[GRADE] - -REG[ION]=region-list + -REG[ION] region-list ] **Note** @@ -2319,6 +2490,15 @@ instances, FIS recommends running this operation on replicating secondary instances, rather than on originating primary instances. + **Note** + + MUPIP REORG -ENCRYPT does not enable switching between encryption + algorithms. To migrate databases from Blowfish CFB to AES CFB requires + that the data be extracted and loaded into newly created database files. + To minimize the time your application is unavailable, you can deploy your + application in a Logical Multi-Site (LMS) configuration, and migrate using + a rolling upgrade technique. + 3 Exclude Exclude @@ -2433,7 +2613,7 @@ The format of the REGION qualifier is: - -R[EGION]=region-list + -R[EGION] region-list region-list may specify more than one region of the current global directory in a list. Regions are case-insensitive, separated by a comma, @@ -2676,6 +2856,9 @@ A successful MUPIP RUNDOWN of a database region removes any current MUPIP FREEZE. + RUNDOWN -FILE can be directed to a statistics database file and works even + if the corresponding actual database file does not exist. + To ensure database integrity, all system shutdown algorithms should include scripts that stop at GT.M processes and perform RUNDOWN on all database files. @@ -2689,7 +2872,9 @@ If the RUNDOWN command does not specify either -File or -Region, it checks all the IPC resources (shared memory) on the system and if they are - associated with a GT.M database, attempts to rundown that file. + associated with a GT.M database, attempts to rundown that file. MUPIP + RUNDOWN with no argument removes any statistics database file resources + associated with actual database file resources it can remove. 3 File File @@ -2761,7 +2946,8 @@ The format of the SET command is: SE[T] {-FI[LE] file-name|-JN[LFILE] journal-file-name|-REG[ION] region-list|-REP[LICATION]={ON|OFF}} - -A[CCESS_METHOD]={BG|MM} + -AC[CESS_METHOD]={BG|MM} + -[NO]AS[YNCIO] -[NO]DE[FER_TIME][=seconds] -[NO]DEFER_ALLOCATE -E[XTENSION_COUNT]=integer(no of blocks) @@ -2772,6 +2958,7 @@ -K[EY_SIZE]=bytes -L[OCK_SPACE]=integer -M[UTEX_SLOTS]=integer + -[NO]LCK_SHARES_DB_CRIT -PA[RTIAL_RECOV_BYPASS] -[NO]Q[DBRUNDOWN] -REC[ORD_SIZE]=bytes @@ -2780,7 +2967,8 @@ -RES[ERVED_BYTES]=integer] -SLEE[P_SPIN_COUNT]=integer -SPIN[_SLEEP_LIMIT]=nanoseconds - -S[TANDALONENOT] + -STAN[DALONENOT] + -[NO]STAT[S] -V[ERSION]={V4|V6} -W[AIT_DISK]=integer @@ -2842,14 +3030,25 @@ Incompatible with: -FILE, -JNLFILE and -REGION -3 Access_method - Access_method +3 ACcess_method + ACcess_method Specifies the access method (GT.M buffering strategy) for storing and retrieving data from the global database file. The format of the ACCESS_METHOD qualifier is: - -A[CCESS_METHOD]=code + -AC[CESS_METHOD]=code + +3 ASyncIO + ASyncIO + + Specifies whether to use asynchronous I/O for an access method BG + database, rather than using synchronous I/O through the file system cache. + ASYNCIO is incompatible with the MM access method and an attempt to + combine the two with MUPIP SET produces a ASYNCIONOMM error. The format of + the ASYNCIO qualifier is: + + -[NO]AS[YNCIO] 3 Defer_time Defer_time @@ -3003,6 +3202,17 @@ -M[UTEX_SLOTS]=integer +3 Lck_shares_db_crit + Lck_shares_db_crit + + Specifies whether LOCK actions share the same resource and management as + the database or use a separate resource and management. The format of the + LCK_SHARES_DB_CRIT qualifier is: + + -[NO]LC[K_SHARES_DB_CRIT] + + The default is Sep(arate)/FALSE. + 3 Qdbrundown Qdbrundown @@ -3115,6 +3325,15 @@ and unless, you have data from testing and benchmarking that demonstrates a benefit from a change. +3 STATs + STATs + + Specifies specifies whether GT.M should permit statistics sharing for this + region. This characteristic permits operational exclusion of statistics + sharing for a region. The format of the STATS qualifier is: + + -[NO]STAT[S] + 3 Version Version @@ -3240,6 +3459,12 @@ o If -HEURISTIC is not specified, MUPIP SIZE uses the ARSAMPLE,SAMPLE=1000 estimation technique. + The 2 sigma column for the two sampling techniques shows the dispersion of + the samples (in blocks) and the probability (rounded to a whole + percentage) that the actual value falls farther away from the reported + value by more than two sigma. With the scan method the "sample" is + "complete," so any inaccuracy comes from concurrent updates. + **Important** For large databases, MUPIP SIZE is faster than MUPIP INTEG -FAST -FULL. @@ -3956,7 +4181,7 @@ current journal-buffer-size as part of an online switch of the journal files. - The default value is 2312 blocks. The minimum BUFFER_SIZE is 2307 blocks. + The default value is 2308 blocks. The minimum BUFFER_SIZE is 2307 blocks. The maximum BUFFER_SIZE is 32K blocks which means that the maximum buffer you can set for your journal file output is 16MB. @@ -5926,7 +6151,7 @@ Command Syntax: - mupip replicate -instance_create -name= [-noreplace] [-supplementary] + mupip replicate -instance_create -name= [-noreplace] [-supplementary] [-noqdbrundown] Qualifiers: @@ -5959,6 +6184,40 @@ Specifies that the replication instance file is suitable for use in a supplementary instance. + -noqdbrundown + + Permits more than 32,767 udpating processes to concurrently the + replication instance file and database file(s). The default + (-noqdbrundown) permits up to 32,767 concurrent updating processes to + access a database file or a replication instance file. + + This permission is effected by the QDBRUNDOWN flags in database file + headers and in replication instance files. When an open database file or + replication instance file with QDBRUNDOWN set is first concurrently + accessed by more than 32,767 processes, GT.M: + + 1. logs a NOMORESEMCNT message in the system log, and + 2. stops counting the number of attached processes. This means that GT.M + cannot recognize when the number of attached processes reaches zero + (0) in order to release the corresponding shared resources, and + therefore requires explicit manual clean up of resources for an + orderly shutdown. + + Except in application configurations that require it, FIS recommends not + setting QDBRUNDOWN. Not setting QDBRUNDOWN allows GT.M to clean up + resources, instead of putting the burden on the operational procedures. + Where GT.M cannot perform an orderly shutdown, an explicit, clean shutdown + must be performed as follows: + + 1. Replicated instances require a mupip journal -rollback -backward "*" + executed after the mupip replicate -source -shutdown command (remember + that even instances receiving a replication stream have one or more + Source Servers). + 2. Database files that are journaled but not part of a replication + instance require a mupip journal -recover -backward command. + 3. For database files that are not journaled (and hence not replicated), + perform a mupip rundown, or if appropriate, delete and recreate them. + Example: $ export gtm_repl_instance=mutisite.repl @@ -5978,6 +6237,7 @@ -edit[instance] {|-source -jnlpool} {-show [-detail]|-change [-offset=] [-size=] [-value=]} [-name=] + [-[no]qdbrundown] -editinstance @@ -6048,6 +6308,12 @@ displays the content of the replication instance file. When used with -jnlpool, it displays the content of the journal pool. + -[no]qdbrundown + + Controls the setting of the "HDR Quick database rundown is active" field + in a replication instance file. For more information about this setting, + refer to "Create instance". + Example: $ mupip replicate -editinstance -show -detail multisite.repl @@ -6137,13 +6403,13 @@ -buffsize= Specifies the size of the Journal Pool. The server rounds the size up or - down to suit its needs. Any size less than 1 MB is rounded up to 1 MB. If - you do not specify a qualifier, the size defaults to the GT.M default - value of 64 MB. Remember that you cannot exceed the system-provided + down to suit its needs. Any size less than 1 MiB is rounded up to 1 MiB. + If you do not specify a qualifier, the size defaults to the GT.M default + value of 64 MiB. Remember that you cannot exceed the system-provided maximum shared memory. For systems with high update rates, specify a larger buffer size to avoid the overflows and file I/O that occur when the Source Server reads journal records from journal files. The maximum value - is 4GiB - 1. + is 4294967288(4GiB-8). -filter= @@ -6428,12 +6694,13 @@ must provide the compression library. The GT.M interface for compression libraries accepts the zlib compression libraries without any need for adaptation. These libraries are included in many UNIX distributions and - are downloadable from the zlib home page. If you prefer to use other - compression libraries, you need to configure or adapt them to provide the - same API provided by zlib. Simple instructions for compiling zlib on a - number of platforms follow. Although GT.M uses zlib, zlib is not FIS - software and FIS does not support zlib. These instructions are merely - provided as a convenience to you. + are downloadable from the zlib home page. GT.M supports the use of the IBM + provided zlib library for AIX. If you prefer to use other compression + libraries, you need to configure or adapt them to provide the same API + provided by zlib. Simple instructions for compiling zlib on a number of + platforms follow. Although GT.M uses zlib, zlib is not FIS software and + FIS does not support zlib. These instructions are merely provided as a + convenience to you. If a package for zlib is available with your operating system, FIS suggests that you use it rather than building your own. @@ -6539,7 +6806,9 @@ Command syntax: - mupip replicate -source -shutdown [-timeout=] + mupip replicate -source -shutdown + [-timeout=] + [-zerobacklog] Qualifiers: @@ -6554,6 +6823,11 @@ the default timeout period is 120 seconds. If you specify -timeout=0 , shutdown occurs immediately. + -zerobacklog + + Shuts down the Source Server either when the backlog goes to zero or the + timeout expires, whichever occurs first. + 2 Activate_Passive_Source_Server Activate Passive Source Server @@ -7448,162 +7722,189 @@ Summary +------------------------------------------------------------------------------+ - | COMMAND | OBJECTS | MAIN QUALIFIER | - |-------------+----------------+-----------------------------------------------| - | | |-BK[UPDBJNL]=DISABLE | OFF | - | | |-B[YTESTREAM] -NET[TIMEOUT]=seconds | - | | |-C[OMPREHENSIVE] | - | | |-DA[TABASE] -REPLA[CE] | - | | |-DBG | - | | |-I[NCREMENTAL] | - | |region-name |-[NO]J[OURNAL][=journal-options-list] | - |B[ACKUP] | | | - | |file-name |-NETTIMEOUT | - | | |-[NO]NEWJNLFILES[=[NO]PREVLINK],[NO]S[YNC_IO] | - | | |-O[NLINE] | - | | |-RECORD | - | | |-REPLI[NSTANCE]=OFF | ON | - | | |-S[INCE]={DATABASE|BYTESTREAM|RECORD} | - | | |-T[RANSACTION=hexa;transaction_number] | - |-------------+----------------+-----------------------------------------------| - |CR[EATE] |- |-R[EGION]=region-name | - |-------------+----------------+-----------------------------------------------| - | | |-OUTDB= | - |EN[DIANCVT] |file-name | | - | | |-OV[ERRIDE] | - |-------------+----------------+-----------------------------------------------| - |EXI[T] |- |- | - |-------------+----------------+-----------------------------------------------| - |EXTE[ND] |region-name |-B[LOCKS]=blocks | - |-------------+----------------+-----------------------------------------------| - | | |-FO[RMAT]=GO|B[INARY]|Z[WR] | - | | |-FR[EEZE] | - | | |-LA[BEL]=text | - |EXTR[ACT] |- |-[NO]L[OG] | - | | |-S[ELECT]=global-name-list | - | | |-O[CHSET]=character-set | - | | |-R[EGION=region-list | - |-------------+----------------+-----------------------------------------------| - | | |-DBG | - | | |-OF[F] | - |F[REEZE] |region-list | | - | | |-OV[ERRIDE] | - | | |-ON[-R[ECORD]] | - |-------------+----------------+-----------------------------------------------| - | | |-D[B] | - |FT[OK] |File-name |-J[NLPOOL] | - | | |-R[ECVPOOL] | - |-------------+----------------+-----------------------------------------------| - |H[ELP] |command-option |- | - |-------------+----------------+-----------------------------------------------| - | | |-A[DJACENCY]=integer] | - | | |-BL[OCK]=hexa;block-number] | - | | |-BR[IEF] | - | | |-FA[ST] | - | | |-FI[LE] | - | | |-FU[LL] | - | |File-name or | | - |I[NTEG] |region-list |-NO]K[EYRANGES | - | | |-[NO][MAP]=integer | - | | |-[NO]MAXK[EYSIZE]=integer | - | | |-R[EGION] | - | | |-S[UBSCRIPT]=subscript | - | | |-TN[_RESET] | - | | |-[NO]TR[ANSACTION][=integer] | - |-------------+----------------+-----------------------------------------------| - | | |-EX[TRACT][=file-specification|-stdout] | - | | |-REC[OVER] | -RO[LLBACK] | - |J[OURNAL] |file-name |-SH[OW][=show-option-list] | - | | |-[NO]V[ERIFY] | - | | |-BA[CKWARD] | -FO[RWARD] | - |-------------+----------------+-----------------------------------------------| - | | |-BE[GIN]=integer | - | | |-BLOCK_DENSITY | - | | |-E[ND]=integer | - |L[OAD] |file-name |-FI[LLFACTOR]=integer | - | | |-FO[RMAT]=GO|B[INARY]|Z[WR] | - | | |-S[TDIN] | - | | |-O[NERROR] | - |-------------+----------------+-----------------------------------------------| - | | |-DOWNGRADE | - | | |-E[XCLUDE]=global-name-list | - | | |-FI[LL_FACTOR]=integer | - | | |-I[NDEX_FILL_FACTOR]=integer | - | | |-REG[ION] | - | | |-RES[UME] | - |REO[RG] | |-SA[FEJNL] | - | | |-S[ELECT]=global-name-list | - | | |-STA[RTBLK]=hexa | - | | |-STO[PBLK]=hexa | - | | |-T[RUNCATE][=percentage] | - | | |-UP[GRADE] | - | | |-USER_DEFINED_REORG=reorg_list | - |-------------+----------------+-----------------------------------------------| - | | |-E[DITINSTANCE] | - | | |-I[NSTANCE_CREATE] | - | | |-R[ECEIVER | - |REP[LICATE] |file-name | | - | | |-S[OURCE] | - | | |-UPDA[TEPROC] | - | | |-UPDH[ELPER] | - |-------------+----------------+-----------------------------------------------| - |RE[STORE] |file-name or |-[NO]E[XTEND] | - | |file-list | | - |-------------+----------------+-----------------------------------------------| - | | |-F[ILE] | - | |file-name or |-R[EGION] | - |RU[NDOWN] |region-name | | - | | |-RELINKCTL [dir] | - | | |-OVERRIDE | - |-------------+----------------+-----------------------------------------------| - | | |-A[CCESS_METHOD=BG|MM] | - | | |-B[YPASS] | - | | |-DB[FILENAME]=database_file | - | | |-DE[FER_TIME]=seconds | - | | |-E[XTENSION_COUNT]=integer(no of blocks) | - | | |-FILE | - | | |-F[LUSH_TIME]= integer | - | | |-G[LOBAL_BUFFERS]=integer | - | | |-JN[LFILE] | - | |file-name or |-JO[URNAL]=journal-option-list | - |SE[T] |region-name | | - | | |-L[OCK_SPACE]=integer | - | | |-PA[RTIAL_RECOV_BYPASS] | - | | |-PR[EVJNLFILE]=jnl_file_name | - | | |-RE[GION] | - | | |-REPLI[CATION]=ON|OFF | - | | |-REPL_[STATE]=ON|OFF | - | | |-RES[ERVED_BYTES]=integer | - | | |-S[TANDALONENOT] | - | | |-V[ERSION]=V4|V5 | - | | |-W[AIT_DISK]=integer | - |-------------+----------------+-----------------------------------------------| - | | |-TRIG[GERFILE]= | - | | |-NOPR[OMPT] | - |TRIGGER |- | | - | | |-SELE[CT][=name-list|*][] | - | | |-UPGRADE | - |-------------+----------------+-----------------------------------------------| - |ST[OP] |process-id |process-id | - |-------------+----------------+-----------------------------------------------| - |UP[GRADE] |- |- | + | COMMAND | OBJECTS | MAIN QUALIFIER | + |-----------+--------------+---------------------------------------------------| + | | |-BK[UPDBJNL]=DISABLE | OFF | + | | |-B[YTESTREAM] -NET[TIMEOUT]=seconds | + | | |-C[OMPREHENSIVE] | + | | |-DA[TABASE] -REPLA[CE] | + | | |-DBG | + | | |-I[NCREMENTAL] | + | |region-name |-[NO]J[OURNAL][=journal-options-list] | + |B[ACKUP] | | | + | |file-name |-NETTIMEOUT | + | | |-[NO]NEWJNLFILES[=[NO]PREVLINK],[NO]S[YNC_IO] | + | | |-O[NLINE] | + | | |-RECORD | + | | |-REPLI[NSTANCE]=OFF | ON | + | | |-S[INCE]={DATABASE|BYTESTREAM|RECORD} | + | | |-T[RANSACTION=hexa;transaction_number] | + |-----------+--------------+---------------------------------------------------| + |CR[EATE] |- |-R[EGION]=region-name | + |-----------+--------------+---------------------------------------------------| + |DO[WNGRADE]|file-name |-V[ERION]={V4|V5} | + |-----------+--------------+---------------------------------------------------| + |DU[MPFHEAD]|file-name or |- | + | |region-list | | + |-----------+--------------+---------------------------------------------------| + | | |-OUTDB= | + |EN[DIANCVT]|file-name | | + | | |-OV[ERRIDE] | + |-----------+--------------+---------------------------------------------------| + |EXI[T] |- |- | + |-----------+--------------+---------------------------------------------------| + |EXTE[ND] |region-name |-B[LOCKS]=blocks | + |-----------+--------------+---------------------------------------------------| + | | |-FO[RMAT]=GO|B[INARY]|Z[WR] | + | | |-FR[EEZE] | + | | |-LA[BEL]=text | + |EXTR[ACT] |- |-[NO]L[OG] | + | | |-S[ELECT]=global-name-list | + | | |-O[CHSET]=character-set | + | | |-R[EGION=region-list | + |-----------+--------------+---------------------------------------------------| + | | |-DBG | + |F[REEZE] |region-list |-OF[F] [-OV[ERRIDE]] | + | | |-ON [-[NO]ONL[INE] [-[NO]A[UTORELEASE]] | + | | |[-R[ECORD]]] | + |-----------+--------------+---------------------------------------------------| + | | |-D[B] | + |FT[OK] |File-name |-J[NLPOOL] | + | | |-R[ECVPOOL] | + |-----------+--------------+---------------------------------------------------| + |H[ELP] |command-option|- | + |-----------+--------------+---------------------------------------------------| + | | |-A[DJACENCY]=integer] | + | | |-BL[OCK]=hexa;block-number] | + | | |-BR[IEF] | + | | |-FA[ST] | + | | |-FI[LE] | + | | |-FU[LL] | + | |File-name or |-NO]K[EYRANGES | + |I[NTEG] |region-list | | + | | |-[NO][MAP]=integer | + | | |-[NO]MAXK[EYSIZE]=integer | + | | |-R[EGION] | + | | |-[NO]ST[ATS] | + | | |-SU[BSCRIPT]=subscript | + | | |-TN[_RESET] | + | | |-[NO]TR[ANSACTION][=integer] | + |-----------+--------------+---------------------------------------------------| + | | |-EX[TRACT][=file-specification|-stdout] | + | | |-REC[OVER] | -RO[LLBACK] | + |J[OURNAL] |file-name |-SH[OW][=show-option-list] | + | | |-[NO]V[ERIFY] | + | | |-BA[CKWARD] | -FO[RWARD] | + |-----------+--------------+---------------------------------------------------| + | | |-BE[GIN]=integer | + | | |-BLOCK_DENSITY | + | | |-E[ND]=integer | + |L[OAD] |file-name |-FI[LLFACTOR]=integer | + | | |-FO[RMAT]=GO|B[INARY]|Z[WR] | + | | |-S[TDIN] | + | | |-O[NERROR] | + |-----------+--------------+---------------------------------------------------| + | | |-ENCR[YPT]=key | + | | |-E[XCLUDE]=global-name-list | + | | |-FI[LL_FACTOR]=integer | + | | |-I[NDEX_FILL_FACTOR]=integer | + | | |-REG[ION] | + |REO[RG] | | | + | | |-R[ESUME] | + | | |-S[ELECT]=global-name-list | + | | |-T[RUNCATE][=percentage] | + | | |-UP[GRADE] | + | | |-REG[ION] region-list | + |-----------+--------------+---------------------------------------------------| + | | |-E[DITINSTANCE] | + | | |-I[NSTANCE_CREATE] | + | | |-R[ECEIVER | + |REP[LICATE]|file-name | | + | | |-S[OURCE] | + | | |-UPDA[TEPROC] | + | | |-UPDH[ELPER] | + |-----------+--------------+---------------------------------------------------| + |RE[STORE] |file-name or |-[NO]E[XTEND] | + | |file-list | | + |-----------+--------------+---------------------------------------------------| + | | |-F[ILE] | + | |file-name or |-R[EGION] | + |RU[NDOWN] |region-name | | + | | |-RELINKCTL [dir] | + | | |-OVERRIDE | + |-----------+--------------+---------------------------------------------------| + | | |SE[T] {-FI[LE] file-name|-JN[LFILE] | + | | |journal-file-name|-REG[ION] | + | | |region-list|-REP[LICATION]={ON|OFF}} | + | | |-AC[CESS_METHOD]={BG|MM} | + | | |-[NO]AS[YNCIO] | + | | |-[NO]DE[FER_TIME][=seconds] | + | | |-[NO]DEFER_ALLOCATE | + | | |-E[XTENSION_COUNT]=integer(no of blocks) | + | | |-F[LUSH_TIME]=integer | + | | |-G[LOBAL_BUFFERS]=integer | + | | |-[NO]INST[_FREEZE_ON_ERROR] | + | | |-JN[LFILE]journal-file-name | + | | |-K[EY_SIZE]=bytes | + | | |-L[OCK_SPACE]=integer | + | |file-name or | | + |SE[T] |region-name |-M[UTEX_SLOTS]=integer | + | | |-[NO]LCK_SHARES_DB_CRIT | + | | |-PA[RTIAL_RECOV_BYPASS] | + | | |-[NO]Q[DBRUNDOWN] | + | | |-REC[ORD_SIZE]=bytes | + | | |-REG[ION] region-list | + | | |-REP[LICATION]={ON|OFF} | + | | |-RES[ERVED_BYTES]=integer] | + | | |-SLEE[P_SPIN_COUNT]=integer | + | | |-SPIN[_SLEEP_LIMIT]=nanoseconds | + | | |-STAN[DALONENOT] | + | | |-[NO]STAT[S] | + | | |-V[ERSION]={V4|V6} | + | | |-W[AIT_DISK]=integer | + |-----------+--------------+---------------------------------------------------| + | | |-TRIG[GERFILE]= | + | | |-NOPR[OMPT] | + |TRIGGER |- | | + | | |-SELE[CT][=name-list|*][] | + | | |-UPGRADE | + |-----------+--------------+---------------------------------------------------| + |ST[OP] |process-id |process-id | + |-----------+--------------+---------------------------------------------------| + |UP[GRADE] |file-name |- | +------------------------------------------------------------------------------+ + The following table summarizes the qualifiers. + +------------------------------------------------------------------------------------------------------------+ | Main Qualifier | MUPIP Command | Options/Qualifiers | |--------------------------------------+--------------------------+------------------------------------------| | | |-CHANGE | | | |-DETAIL | | | |-OFFSET=hexa | - |-EDITINSTANCE |REPLICATE | | - | | |-VALUE=hexa | + |-EDITINSTANCE |REPLICATE |-VALUE=hexa | | | |-SIZE=hexa | | | |-VALUE=hexa | + | | |-[NO]QDBRUNDOWN | |--------------------------------------+--------------------------+------------------------------------------| | | |ALWAYS | |-FENCES= |JOURNAL-RECOVER-ROLLBACK |NONE | | | |PROCESS | |--------------------------------------+--------------------------+------------------------------------------| + | | |-OVERRIDE | + |-OFF |FREEZE | | + | | |-RECORD | + |--------------------------------------+--------------------------+------------------------------------------| + | | |-[NO]ONLINE | + |-ON |FREEZE | | + | | |-[NO]AUTORELEASE | + |--------------------------------------+--------------------------+------------------------------------------| + | | |-NAME | + | | |-NOREPLACE | + |-INSTANCE_CREATE |REPLICATE | | + | | |-SUPPLEMENTARY | + | | |-[NO]QDBRUNDOWN | + |--------------------------------------+--------------------------+------------------------------------------| | | |ALIGNSIZE=integer | | | |ALLOCATION=integer | | | |AUTOSWITCHLIMIT=integer | @@ -7630,17 +7931,23 @@ | | |-CMPLVL=integer | | | |-FILTER=filter_name | | | |-he[lpers]=[m[,n]] | + | | |-INITIALIZE | + | | |-CMPLVL=n | | | |-LISTENPORT=integer | | | |-LOG=logfile | - |-RECEIVER |REPLICATE |-LOG_INTERVAL=integer | + | | |-LOG_INTERVAL=integer | + |-RECEIVER |REPLICATE |-NORESYNC | + | | |-RESUME=strm_num | + | | |-REUSE=instname | | | |-SHOWBACKLOG | | | |-SHUTDOWN | | | |-START | | | |-STATSLOG=[ON|OFF] | | | |-STOPSOURCEFILTER | | | |TIMEOUT=seconds | + | | |TLSID=label | | | |-UPDATEONLY | - | | |-UPDATERESYNC | + | | |-UPDATERESYNC=/path/to/bkup-orig-inst | |--------------------------------------+--------------------------+------------------------------------------| | | |-AFTER=time | | | |-APPLY_AFTER_IMAGE | @@ -7725,14 +8032,18 @@ | | |-DEACTIVATE | | | |-DETAIL | | | |-FILTER=filter_name | + | | |-FREEZE=on|off | + | | |-[NO]COMMENT=string | | | |-INSTSECONDARY=secondary_instance name | + | | |-NOJNLFILEONLY | | | |-JNLPOOL-LOG=log_file | | | |-LOG_INTERVAL=integer | - |-SO[URCE] |REPLICATE | | | | |-LOSTTNCOMPLETE | - | | |-NEEDRESTART | + |-SO[URCE] |REPLICATE |-NEEDRESTART | | | |-PASSIVE | + | | |-[NO]PLAINTEXTFALLBACK | | | |-PROPAGATEPRIMARY | + | | |-RENEGOTIATE_INTERVAL=minutes | | | |-ROOTPRIMARY | | | |-SECONDARY=secondary_instance_name | | | |-SHOWBACKLOG | @@ -7741,12 +8052,20 @@ | | |-STATSLOG | | | |-STOPSOURCEFILTER | | | |-TIMEOUT=seconds | + | | |-TLSID=label | + | | |-UPDOK | + | | |-UPDNOTOK | + | | |-ZEROBACKLOG | + |--------------------------------------+--------------------------+------------------------------------------| + | |DOWNGRADE | | + |-VERSION={V4|V5} | |file-name | + | |UPGRADE | | +------------------------------------------------------------------------------------------------------------+ 1 Copyright Copyright - Copyright 2016 + Copyright 2017 Fidelity National Information Services, Inc. and/or its subsidiaries. All rights reserved. @@ -7768,7 +8087,7 @@ **Note** - This help file is a concise representation of revision V6.3-000 of the + This help file is a concise representation of revision V6.3-001 of the UNIX Administration and Operations Guide. To obtain a copy of the current revision, go to www.fis-gtm.com and then click on the User Documentation tab. diff --git a/sr_port/mupip_backup.c b/sr_port/mupip_backup.c index 11cc3b4..a920278 100644 --- a/sr_port/mupip_backup.c +++ b/sr_port/mupip_backup.c @@ -147,6 +147,7 @@ error_def(ERR_FILEPARSE); error_def(ERR_FREEZECTRL); error_def(ERR_JNLCREATE); error_def(ERR_JNLDISABLE); +error_def(ERR_JNLFILOPN); error_def(ERR_JNLFNF); error_def(ERR_JNLNOCREATE); error_def(ERR_JNLPOOLSETUP); @@ -1168,7 +1169,7 @@ repl_inst_bkup_done2: !keep_prev_link || !JNL_ENABLED(cs_data)) ? TRUE : FALSE; if (JNL_ENABLED(cs_data) && (0 != cs_addrs->nl->jnl_file.u.inode)) { /* Note: following will again call wcs_flu() */ - if (SS_NORMAL != (status = set_jnl_file_close(SET_JNL_FILE_CLOSE_BACKUP))) + if (SS_NORMAL != (status = set_jnl_file_close())) { util_out_print("!/Journal file !AD not closed:", TRUE, jnl_info.jnl_len, jnl_info.jnl); @@ -1195,6 +1196,7 @@ repl_inst_bkup_done2: error_mupip = TRUE; continue; } + jnl_set_cur_prior(gv_cur_region, cs_addrs, cs_data); jnl_info.no_rename = (FILE_NOT_FOUND == jnl_fstat); } wcs_flu(WCSFLU_FSYNC_DB | WCSFLU_FLUSH_HDR | WCSFLU_MSYNC_DB); diff --git a/sr_port/mupip_set_jnl_cleanup.c b/sr_port/mupip_set_jnl_cleanup.c index 4135bdb..d4e5f2c 100644 --- a/sr_port/mupip_set_jnl_cleanup.c +++ b/sr_port/mupip_set_jnl_cleanup.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -40,7 +40,7 @@ void mupip_set_jnl_cleanup(void) { mu_set_rlist *rptr; file_control *fc; - int4 rundown_status = EXIT_NRM; /* if gds_rundown went smoothly */ + int4 rundown_status = EXIT_NRM; /* if "gds_rundown" went smoothly */ for (rptr = grlist; NULL != rptr; rptr = rptr->fPtr) { @@ -73,7 +73,7 @@ void mupip_set_jnl_cleanup(void) tp_change_reg(); assert(NULL != gv_cur_region->dyn.addr->file_cntl && NULL != rptr->sd); if (NULL != gv_cur_region->dyn.addr->file_cntl && NULL != rptr->sd) - rundown_status |= gds_rundown(); + rundown_status |= gds_rundown(CLEANUP_UDI_TRUE); /* Note: We did not allocate, so we do not deallocate rptr->sd */ rptr->sd = NULL; } diff --git a/sr_port/mupip_set_journal.c b/sr_port/mupip_set_journal.c index 04f793f..412e785 100644 --- a/sr_port/mupip_set_journal.c +++ b/sr_port/mupip_set_journal.c @@ -46,6 +46,7 @@ #include "gtmio.h" #include "is_file_identical.h" #include "interlock.h" +#include "anticipatory_freeze.h" #define DB_OR_REG_SIZE MAX(STR_LIT_LEN(FILE_STR), STR_LIT_LEN(REG_STR)) + 1 /* trailing null byte */ @@ -221,10 +222,10 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) { gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_OFRZACTIVE, 2, DB_LEN_STR(gv_cur_region)); exit_status |= EXIT_WRN; - gds_rundown_status = gds_rundown(); + gds_rundown_status = gds_rundown(CLEANUP_UDI_TRUE); exit_status |= gds_rundown_status; rptr->sd = NULL; - rptr->state = NONALLOCATED; /* This means do not call gds_rundown() again for this region + rptr->state = NONALLOCATED; /* This means do not call "gds_rundown" again for this region * and do not process this region anymore. */ continue; } @@ -235,10 +236,10 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) if (EXIT_NRM != (status = mupip_set_journal_newstate(&jnl_options, &jnl_info, rptr))) { exit_status |= status; - gds_rundown_status = gds_rundown(); + gds_rundown_status = gds_rundown(CLEANUP_UDI_TRUE); exit_status |= gds_rundown_status; rptr->sd = NULL; - rptr->state = NONALLOCATED; /* This means do not call gds_rundown() again for this region + rptr->state = NONALLOCATED; /* This means do not call "gds_rundown" again for this region * and do not process this region anymore. */ continue; } @@ -265,8 +266,10 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) (repl_closed != repl_curr_state && repl_closed == rptr->repl_new_state) || (repl_closed == repl_curr_state && repl_open == rptr->repl_new_state)) { - /* Since we did gvcst_init() and now will call mu_rndwn_file() */ - gds_rundown_status = gds_rundown(); + /* Rundown the database file since we did "gvcst_init" and now will call "mu_rndwn_file". + * Since we are going to reuse the udi etc. that was allocated, use CLEANUP_UDI_FALSE. + */ + gds_rundown_status = gds_rundown(CLEANUP_UDI_FALSE); exit_status |= gds_rundown_status; rptr->state = NONALLOCATED; rptr->sd = csd = NULL; @@ -347,14 +350,16 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) this_iter_prevlinkcut_error = do_prevlinkcut_error; do_prevlinkcut_error = FALSE; next_rptr = rptr->fPtr; + if (NULL == rptr->sd) + continue; + assert(NONALLOCATED != rptr->state); gv_cur_region = rptr->reg; if (gv_cur_region->read_only) continue; - tp_change_reg(); /* cs_data and cs_addrs are used in functions called from here */ + /* cs_data and cs_addrs are used in functions called from here */ + cs_addrs = &FILE_INFO(gv_cur_region)->s_addrs; + assert(rptr->sd == cs_addrs->hdr); cs_data = csd = rptr->sd; - assert(NULL != csd || NONALLOCATED == rptr->state); - if (NULL == csd) /* Just to be safe. May be this is not necessary. */ - continue; jnl_curr_state = (enum jnl_state_codes)csd->jnl_state; repl_curr_state = (enum repl_state_codes)csd->repl_state; jnl_info.csd = csd; @@ -552,7 +557,8 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) */ assert('\0' == jnlfile.addr[jnlfile.len]); jnlfile.addr[jnlfile.len] = '\0'; /* just in case above assert is FALSE */ - OPENFILE(jnlfile.addr, O_RDONLY, jnl_fd); + OPENFILE(jnlfile.addr, ((FILE_READONLY & curr_stat_res) ? O_RDONLY : O_RDWR), jnl_fd); + } else if (FILE_PRESENT & new_stat_res) { /* Check if the new journal file (that we know exists) points back to this database file. * If not, the journal file prev links should be cut in the new journal file. @@ -562,7 +568,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) OPENFILE((char *)jnl_info.jnl, O_RDONLY, jnl_fd); } else jnl_fd = FD_INVALID; - if (0 <= jnl_fd) + if (FD_INVALID != jnl_fd) { DO_FILE_READ(jnl_fd, 0, &header, SIZEOF(header), status1, status2); if (SS_NORMAL == status1) @@ -576,8 +582,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) header.data_file_name[header.data_file_name_length] = '\0'; assert('\0' == jnl_info.fn[jnl_info.fn_len]); jnl_info.fn[jnl_info.fn_len] = '\0'; - if (is_file_identical((char *)header.data_file_name, - (char *)jnl_info.fn)) + if (is_file_identical((char *)header.data_file_name, (char *)jnl_info.fn)) jnl_points_to_db = TRUE; header_is_usable = TRUE; } @@ -592,7 +597,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) if ((FILE_PRESENT & curr_stat_res) && !noprevlink_requested) { keep_prev_link = jnl_points_to_db; - safe_to_switch = (jnlname_same && keep_prev_link); + safe_to_switch = (jnlname_same && jnl_points_to_db); } else if ((FILE_PRESENT & new_stat_res) && !noprevlink_requested) { keep_prev_link = FALSE; @@ -655,7 +660,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) jpc = cs_addrs->jnl; if (cs_addrs->nl->jnl_file.u.inode) { - if (SS_NORMAL != (status = set_jnl_file_close(SET_JNL_FILE_CLOSE_SETJNL))) + if (SS_NORMAL != (status = set_jnl_file_close())) { /* Invoke jnl_file_lost to turn off journaling and retry journal creation * to create fresh journal files. */ @@ -664,12 +669,12 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) * information message */ next_rptr = rptr; continue; - } - header.crash = FALSE; /* Even if the journal was crashed, that - * should be fixed now */ + } else + header.crash = FALSE; /* Even if the journal was crashed, that + * should be fixed now */ } else { /* Ideally, no other process should have a journal file for this database open. - * But, As part of C9I03-002965, we realized it is possible for processes accessing + * But, as part of C9I03-002965, we realized it is possible for processes accessing * the older journal file to continue to write to it even though * csa->nl->jnl_file.u.inode field is 0. The only way to signal other proceses, that * have the jnl file open, of a concurrent journal file switch, is by incrementing @@ -678,11 +683,16 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) */ assert(NULL != jpc); jpc->jnl_buff->cycle++; + if (header_is_usable && !(FILE_READONLY & curr_stat_res)) + { + jnl_set_fd_prior(jnl_fd, cs_addrs, cs_data, &header); + jnl_fd = NOJNL; /* Mark the fd as closed */ + } } /* Cut the link if the journal is crashed and there is no shared memory around */ if (header_is_usable && header.crash) keep_prev_link = FALSE; - /* For MM, set_jnl_file_close() can call wcs_flu() which can remap the file. + /* For MM, "set_jnl_file_close" can call wcs_flu() which can remap the file. * So reset csd and rptr->sd since their value may have changed. */ assert((dba_mm == cs_data->acc_meth) || (csd == cs_data)); @@ -694,6 +704,10 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) assert((dba_mm == cs_data->acc_meth) || (csd == cs_data)); rptr->sd = csd = cs_data; } + } else if (curr_jnl_present && header_is_usable && !(FILE_READONLY & curr_stat_res)) + { /* Close out journal in standalone case */ + jnl_set_fd_prior(jnl_fd, cs_addrs, cs_data, &header); + jnl_fd = NOJNL; /* Mark the fd as closed */ } if (newjnlfiles) { @@ -713,9 +727,9 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) } } if ((jnl_closed == jnl_curr_state) && (NULL != cs_addrs->nl)) - { /* Cleanup the jnl file info in shared memory before switching journal file. - This case occurs if mupip set -journal is run after jnl_file_lost() closes - journaling on a region */ + { /* Cleanup the jnl file info in shared memory before switching journal file. This case + * occurs if mupip set -journal is run after jnl_file_lost() closes journaling on a region. + */ NULLIFY_JNL_FILE_ID(cs_addrs); } jnl_info.blks_to_upgrd = csd->blks_to_upgrd; @@ -744,7 +758,7 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) jnl_info.jnl_len, jnl_info.jnl, DB_LEN_STR(gv_cur_region)); } } - /* Following jnl_before_image, jnl_state, repl_state are unique charecteristics per region */ + /* Following jnl_before_image, jnl_state, repl_state are unique characteristics per region */ csd->jnl_before_image = jnl_info.before_images; csd->jnl_state = rptr->jnl_new_state; csd->repl_state = jnl_info.repl_state; @@ -778,7 +792,11 @@ uint4 mupip_set_journal(unsigned short db_fn_len, char *db_fn) csd->jnl_sync_io = jnl_options.sync_io; csd->yield_lmt = jnl_options.yield_limit; } else - { /* Journaling is to be disabled for this region. Reset all fields */ + { /* Journaling is to be disabled for this region. */ + /* Mark the current journal as switched, if possible. */ + if (jnl_open == csd->jnl_state) + jnl_set_cur_prior(gv_cur_region, NULL, csd); + /* Reset all fields */ csd->jnl_before_image = FALSE; csd->jnl_state = jnl_notallowed; csd->repl_state = repl_closed; diff --git a/sr_port/mupip_set_journal_parse.c b/sr_port/mupip_set_journal_parse.c index 18008aa..79a6df0 100644 --- a/sr_port/mupip_set_journal_parse.c +++ b/sr_port/mupip_set_journal_parse.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2001, 2014 Fidelity Information Services, Inc * + * Copyright (c) 2001-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -11,11 +12,6 @@ #include "mdef.h" -#if defined(VMS) -#include -#include /* needed for handling of epoch_interval (EPOCH_SECOND2SECOND macro uses ceil) */ -#endif - #include "gtm_string.h" /* for memcpy() */ #include "gdsroot.h" @@ -74,7 +70,6 @@ boolean_t mupip_set_journal_parse(set_jnl_options *jnl_options, jnl_create_info jnl_info->before_images = TRUE; } else if (CLI_NEGATED == cli_status1) { - VMS_ONLY(assert(CLI_PRESENT != jnl_options->cli_replic_on);) jnl_options->image_type_specified = TRUE; jnl_info->before_images = FALSE; } else @@ -169,19 +164,24 @@ boolean_t mupip_set_journal_parse(set_jnl_options *jnl_options, jnl_create_info return FALSE; } } - temp_jnl_fn_len = jnl_info->jnl_len = MAX_FN_LEN + 1; - if (jnl_options->filename_specified = cli_get_str("FILENAME", (char *)jnl_info->jnl, &temp_jnl_fn_len)) - jnl_info->jnl_len = temp_jnl_fn_len; - else + if (jnl_options->filename_specified = (CLI_PRESENT == cli_present("FILENAME"))) + { + temp_jnl_fn_len = jnl_info->jnl_len = ARRAYSIZE(jnl_info->jnl) - 1; /* leave 1 byte for null terminator */ + jnl_info->jnl[temp_jnl_fn_len] = '\0'; /* null terminate string in case "cli_get_str" returns file name that fills + * up all allocated bytes (i.e. temp_jnl_fn_len bytes long). + */ + if (cli_get_str("FILENAME", (char *)jnl_info->jnl, &temp_jnl_fn_len)) + jnl_info->jnl_len = temp_jnl_fn_len; + else + return FALSE; + } else jnl_info->jnl_len = 0; - if ((CLI_PRESENT == (cli_status1 = cli_present(UNIX_ONLY("SYNC_IO") VMS_ONLY("CACHE")))) || (CLI_NEGATED == cli_status1)) + if ((CLI_PRESENT == (cli_status1 = cli_present("SYNC_IO"))) || (CLI_NEGATED == cli_status1)) { jnl_options->sync_io_specified = TRUE; - jnl_options->sync_io = (UNIX_ONLY(CLI_PRESENT) VMS_ONLY(CLI_NEGATED) == cli_status1) ? TRUE: FALSE; - } - else + jnl_options->sync_io = (CLI_PRESENT == cli_status1) ? TRUE: FALSE; + } else jnl_options->sync_io_specified = FALSE; - UNIX_ONLY( if (jnl_options->yield_limit_specified = (CLI_PRESENT == cli_present("YIELD_LIMIT"))) { if (!cli_get_int("YIELD_LIMIT", &jnl_options->yield_limit)) @@ -197,6 +197,5 @@ boolean_t mupip_set_journal_parse(set_jnl_options *jnl_options, jnl_create_info return FALSE; } } - ) return TRUE; } diff --git a/sr_port/mur_close_files.c b/sr_port/mur_close_files.c index 48bd845..774eb20 100644 --- a/sr_port/mur_close_files.c +++ b/sr_port/mur_close_files.c @@ -55,6 +55,7 @@ #include "util.h" #include "wcs_flu.h" #include "gtm_sem.h" +#include "gtm_file_stat.h" #ifdef DEBUG #include "wbox_test_init.h" #endif @@ -117,16 +118,16 @@ error_def(ERR_RLBKSTRMSEQ); boolean_t mur_close_files(void) { - char *head_jnl_fn, *rename_fn, fn[MAX_FN_LEN + 1]; + char *head_jnl_fn, *rename_fn, fn[MAX_FN_LEN + STR_LIT_LEN(PREFIX_ROLLED_BAK) + 1]; int head_jnl_fn_len, wrn_count = 0, rename_fn_len; reg_ctl_list *rctl, *rctl_top; jnl_ctl_list jctl_temp, *jctl, *prev_jctl, *end_jctl; gd_region *reg; sgmnt_addrs *csa; sgmnt_data *csd, csd_temp; - uint4 ustatus; + uint4 ustatus, ustatus2; int4 status; - int4 rundown_status = EXIT_NRM; /* if gds_rundown went smoothly */ + int4 rundown_status = EXIT_NRM; /* if "gds_rundown" went smoothly */ int idx, finish_err_code, save_errno; const char *fini_str = NULL; const char *termntd_str; @@ -146,7 +147,9 @@ boolean_t mur_close_files(void) jnl_private_control *jpc; jnl_buffer_ptr_t jb; uint4 jnl_status; - DEBUG_ONLY(int semval;) +# ifdef DEBUG + int semval; +# endif DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; @@ -157,11 +160,11 @@ boolean_t mur_close_files(void) } call_on_signal = NULL; /* Do not recurs via call_on_signal if there is an error */ SET_PROCESS_EXITING_TRUE; /* In case the database is encrypted, this value is used to avoid using - * mur_ctl->csd in mur_fopen as it would be invalid due to the gds_rundown() done below. + * mur_ctl->csd in mur_fopen as it would be invalid due to the "gds_rundown" done below. */ csd = &csd_temp; assert(murgbl.losttn_seqno == murgbl.save_losttn_seqno); - /* If journaling, gds_rundown will need to write PINI/PFIN records. The timestamp of that journal record will + /* If journaling, "gds_rundown" will need to write PINI/PFIN records. The timestamp of that journal record will * need to be adjusted to the current system time to reflect that it is recovery itself writing that record * instead of simulating GT.M activity. Reset jgbl.dont_reset_gbl_jrec_time to allow for adjustments to gbl_jrec_time. */ @@ -212,7 +215,7 @@ boolean_t mur_close_files(void) * "mupfndfil" path (e.g. journal file names were explicitly specified for a journal extract command) so it * would not have done gvcst_init in that case. But we would have set rctl->csa to a non-NULL value in order * to be able to switch amongst regions in mur_forward. So we should check for gd->open below to know for - * sure if a gvcst_init was done which in turn requires a gds_rundown to be done. + * sure if a gvcst_init was done which in turn requires a "gds_rundown" to be done. */ if (reg->open) { /* gvcst_init was called */ @@ -223,7 +226,7 @@ boolean_t mur_close_files(void) * signal (say MUPIP STOP) that causes exit handling processing which invokes this function. * In this case, cs_addrs would still be set to a non-NULL value so use that instead of rctl->csa. */ - assert((NULL != rctl->csa) && (rctl->csa == cs_addrs) || (NULL == rctl->csa) && !murgbl.clean_exit); + assert(((NULL != rctl->csa) && (rctl->csa == cs_addrs)) || ((NULL == rctl->csa) && !murgbl.clean_exit)); csa = cs_addrs; csd = mur_options.forward ? &csd_temp : csa->hdr; assert(NULL != csa); @@ -239,8 +242,11 @@ boolean_t mur_close_files(void) assert((!(mur_options.update ^ csa->nl->donotflush_dbjnl)) || !murgbl.clean_exit); if (mur_options.update && (murgbl.clean_exit || !rctl->db_updated) && (NULL != csa->nl)) csa->nl->donotflush_dbjnl = FALSE; /* shared memory is now clean for dbjnl flushing */ + /* Note: udi/csa is used a little later after the "gds_rundown" call (e.g. by "jnl_set_cur_prior") + * so pass CLEANUP_UDI_FALSE as the parameter. + */ if (mur_options.forward) - rundown_status = gds_rundown(); + rundown_status = gds_rundown(CLEANUP_UDI_FALSE); if (EXIT_NRM != rundown_status) { wrn_count++; @@ -286,14 +292,14 @@ boolean_t mur_close_files(void) assert(mur_options.update); /* For MUPIP JOURNAL -RECOVER -FORWARD or MUPIP JOURNAL -ROLLBACK -FORWARD, we are * done "gds_rundown" at this point and so have a clean database state at this point. - * For RECOVER/ROLLBACK -BACKWARD, even though we haven't done the gds_rundown yet, + * For RECOVER/ROLLBACK -BACKWARD, even though we haven't done the "gds_rundown" yet, * we still hold the standalone access and so no new process can attach to the database. * For the -ONLINE version of RECOVER/ROLLBACK -BACKWARD, we haven't released the access * control lock as well as the critical section lock, so no new processes can attach to * the database and no existing process can continue from their hung state(waiting for * crit). So, in all cases, it should be okay to safely set csd->file_corrupt to FALSE. * The only issue is if we get crashed AFTER setting csd->file_corrupt to FALSE, but - * before doing the gds_rundown in which case, all the processes starting up will see + * before doing the "gds_rundown" in which case, all the processes starting up will see * it just like any other system crash warranting a ROLLBACK/RECOVER. */ csd->file_corrupt = FALSE; @@ -347,6 +353,11 @@ boolean_t mur_close_files(void) } } } + /* If we just did forward recovery, and the current journal is available, + * then we are leaving journaling disabled, so mark the journal as switched. + */ + if (mur_options.forward && (jnl_open == csd->intrpt_recov_jnl_state)) + jnl_set_cur_prior(reg, csa, csd); /* Reset save_strm_reg_seqno[]. Do it even for -recover (not just for -rollback) * so a successful -recover after an interrupted -rollback clears these fields. * Take this opportunity to reset intrpt_recov_resync_strm_seqno[] as well. @@ -480,6 +491,7 @@ boolean_t mur_close_files(void) assert(jctl->turn_around_offset); jctl->jfh->turn_around_offset = 0; jctl->jfh->turn_around_time = 0; + jctl->jfh->is_not_latest_jnl = TRUE; jctl->jfh->crash = FALSE; jctl->jfh->end_of_data = jctl->turn_around_offset; jctl->jfh->eov_timestamp = jctl->turn_around_time; @@ -522,18 +534,25 @@ boolean_t mur_close_files(void) JNL_DO_FILE_WRITE(NULL, NULL, end_jctl->channel, 0, end_jctl->jfh, REAL_JNL_HDR_LEN, end_jctl->status, end_jctl->status2); WARN_STATUS(end_jctl); - /* Rename journals whose entire contents have been undone with - * the rolled_bak prefix. user can decide to delete these */ + /* Rename journals whose entire contents have been undone with the rolled_bak prefix. + * User can decide to delete these. + */ rename_fn = fn; - prepare_unique_name((char *)end_jctl->jnl_fn, end_jctl->jnl_fn_len, - PREFIX_ROLLED_BAK, "", rename_fn, &rename_fn_len, 0, &ustatus); - WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa); - /* wait for instance freeze before journal file renames */ + rename_fn_len = ARRAYSIZE(fn); + ustatus = prepare_unique_name((char *)end_jctl->jnl_fn, end_jctl->jnl_fn_len, + PREFIX_ROLLED_BAK, "", rename_fn, &rename_fn_len, 0, &ustatus2); + /* We have allocated enough space in rename_fn/fn array to store PREFIX_ROLLED_BAK + * prefix. So no way the above "prepare_unique_name" call can fail. Hence the assert. + */ + assert(SS_NORMAL == ustatus); + WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa); /* wait for instance freeze + * before journal file renames. + */ if (SS_NORMAL == gtm_rename((char *)end_jctl->jnl_fn, end_jctl->jnl_fn_len, - rename_fn, rename_fn_len, &ustatus)) + rename_fn, rename_fn_len, &ustatus2)) { - gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT (6) ERR_FILERENAME, 4, end_jctl->jnl_fn_len, - end_jctl->jnl_fn, rename_fn_len, rename_fn); + gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT (6) ERR_FILERENAME, 4, + end_jctl->jnl_fn_len, end_jctl->jnl_fn, rename_fn_len, rename_fn); } else { gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(6) ERR_RENAMEFAIL, 4, @@ -735,7 +754,7 @@ boolean_t mur_close_files(void) udi = (NULL != reg->dyn.addr->file_cntl) ? FILE_INFO(reg) : NULL; if (reg->open) { - assert(!mur_options.forward); /* for forward recovery, gds_rundown should have been done before */ + assert(!mur_options.forward); /* for forward recovery, "gds_rundown" should have been done before */ gv_cur_region = reg; TP_CHANGE_REG(reg); assert(!jgbl.onlnrlbk || (cs_addrs->now_crit && cs_addrs->hold_onto_crit) || !murgbl.clean_exit); @@ -743,10 +762,10 @@ boolean_t mur_close_files(void) if (jgbl.onlnrlbk) { /* This is an online rollback. If "gtm_mupjnl_parallel" is not 1, multiple child processes were * started to operate on different regions in the forward phase. Any updates they made would not - * have been flushed since the children did not go through gds_rundown. If multiple child processes - * were not started, it is possible some GT.M processes (which were active before the online - * rollback started) have taken over the flush timers so the rollback process could not get any - * timer slots. In either case, it is better to flush the jnl records to disk right away as the + * have been flushed since the children did not go through "gds_rundown". If multiple child + * processes were not started, it is possible some GT.M processes (which were active before the + * online rollback started) have taken over the flush timers so the rollback process could not get + * any timer slots. In either case, it is better to flush the jnl records to disk right away as the * source server could be waiting for these and the sooner it gets them, the better. In the * multiple-child processes case, not doing the flush here can actually cause the source server to * timeout with a SEQNUMSEARCHTIMEOUT error (if no GT.M processes have any flush timers active and @@ -755,7 +774,10 @@ boolean_t mur_close_files(void) assert(!FROZEN_CHILLED(cs_data)); wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_WRITE_EPOCH | WCSFLU_SYNC_EPOCH); } - rundown_status = gds_rundown(); /* does the final rel_crit */ + /* Note: udi/csa is used a little later after the "gds_rundown" call to determine if "db_ipcs_reset" + * can be called so pass CLEANUP_UDI_FALSE as the parameter. + */ + rundown_status = gds_rundown(CLEANUP_UDI_FALSE); /* does the final rel_crit */ if (EXIT_NRM != rundown_status) wrn_count++; assert((EXIT_NRM != rundown_status) || !rctl->standalone @@ -767,7 +789,7 @@ boolean_t mur_close_files(void) */ assert(!mur_options.update || rctl->standalone || !murgbl.clean_exit); if (rctl->standalone && (EXIT_NRM == rundown_status)) - /* Avoid db_ipcs_reset if gds_rundown did not remove shared memory */ + /* Avoid db_ipcs_reset if "gds_rundown" did not remove shared memory */ if ((NULL != udi) && udi->shm_deleted && !db_ipcs_reset(reg)) wrn_count++; rctl->standalone = FALSE; diff --git a/sr_port/mur_merge_sort_extfmt.c b/sr_port/mur_merge_sort_extfmt.c index 78ae057..a4478d9 100755 --- a/sr_port/mur_merge_sort_extfmt.c +++ b/sr_port/mur_merge_sort_extfmt.c @@ -475,6 +475,7 @@ int mur_merge_sort_extfmt(void) /* Argument journal -extract=-stdout ? */ if (!mur_options.extr_fn_is_stdout[recstat]) { + rename_fn_len = ARRAYSIZE(rename_fn); if (RENAME_FAILED == rename_file_if_exists(fn_out, extr_fn_len, rename_fn, &rename_fn_len, &status)) { diff --git a/sr_port/mur_output_show.c b/sr_port/mur_output_show.c index 20ba633..71aad6d 100644 --- a/sr_port/mur_output_show.c +++ b/sr_port/mur_output_show.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2003-2016 Fidelity National Information * + * Copyright (c) 2003-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -163,6 +163,8 @@ void mur_show_header(jnl_ctl_list * jctl) util_out_print(" Jnlfile Extension !16UL [0x!XL] blocks", TRUE, DOUBLE_ARG(hdr->jnl_deq)); util_out_print(" Maximum Journal Record Length !16UL [0x!XL]", TRUE, DOUBLE_ARG(hdr->max_jrec_len)); util_out_print(" Turn Around Point Offset !10UL [0x!XL]", TRUE, DOUBLE_ARG(hdr->turn_around_offset)); + util_out_print(" Last EOF Written !AD", TRUE, 5, (hdr->last_eof_written ? " TRUE" : "FALSE")); + util_out_print(" Was a Previous Generation Journal File !AD", TRUE, 5, (hdr->is_not_latest_jnl ? " TRUE" : "FALSE")); if (hdr->turn_around_time) time_len = format_time(hdr->turn_around_time, time_str, SIZEOF(time_str), SHORT_TIME_FORMAT); else @@ -173,8 +175,7 @@ void mur_show_header(jnl_ctl_list * jctl) util_out_print(" Turn Around Point Time !20AD", TRUE, time_len, time_str); util_out_print(" Start Region Sequence Number !20@UQ [0x!16@XQ]", TRUE, &hdr->start_seqno, &hdr->start_seqno); util_out_print(" End Region Sequence Number !20@UQ [0x!16@XQ]", TRUE, &hdr->end_seqno, &hdr->end_seqno); - /* Dump stream seqnos for upto 16 streams if any are non-zero. - */ + /* Dump stream seqnos for upto 16 streams if any are non-zero */ for (idx = 0; idx < MAX_SUPPL_STRMS; idx++) { /* Dump stream seqnos. Dont dump them unconditionally as they will swamp the output. * We usually expect 1 or 2 streams to have non-zero values so dump it only if non-zero. diff --git a/sr_port/mur_process_intrpt_recov.c b/sr_port/mur_process_intrpt_recov.c index 1e7a407..1764a4e 100644 --- a/sr_port/mur_process_intrpt_recov.c +++ b/sr_port/mur_process_intrpt_recov.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2003-2016 Fidelity National Information * + * Copyright (c) 2003-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -13,17 +13,8 @@ #include "mdef.h" #include "gtm_string.h" -#if defined(UNIX) #include "gtm_unistd.h" #include "eintr_wrappers.h" -#elif defined(VMS) -#include -#include -#include -#include -#include -#include "iosb_disk.h" -#endif #include "gdsroot.h" #include "gtm_rename.h" @@ -66,7 +57,7 @@ uint4 mur_process_intrpt_recov() jnl_ctl_list *jctl, *last_jctl; reg_ctl_list *rctl, *rctl_top; int rename_fn_len, save_name_len, idx; - char prev_jnl_fn[MAX_FN_LEN + 1], rename_fn[MAX_FN_LEN + 1], save_name[MAX_FN_LEN + 1]; + char prev_jnl_fn[MAX_FN_LEN + 1], rename_fn[MAX_FN_LEN + 1]; jnl_create_info jnl_info; uint4 status, status2; uint4 max_autoswitchlimit, max_jnl_alq, max_jnl_deq, freeblks; @@ -207,7 +198,6 @@ uint4 mur_process_intrpt_recov() assert(!FROZEN_CHILLED(csd)); wcs_flu(WCSFLU_FLUSH_HDR | WCSFLU_FSYNC_DB); assert(cs_addrs->ti->curr_tn == jctl->turn_around_tn); -# ifdef UNIX if (jgbl.onlnrlbk) { if (dba_bg == cs_addrs->hdr->acc_meth) @@ -238,12 +228,6 @@ uint4 mur_process_intrpt_recov() { /* set earliest bt TN to be the turn-around TN (taken from bt_refresh()) */ SET_OLDEST_HIST_TN(cs_addrs, cs_addrs->ti->curr_tn - 1); } -# else - if (dba_bg == csd->acc_meth) - { /* set earliest bt TN to be the turn-around TN (taken from bt_refresh()) */ - SET_OLDEST_HIST_TN(cs_addrs, cs_addrs->ti->curr_tn - 1); - } -# endif csd->turn_around_point = FALSE; assert(OLDEST_HIST_TN(cs_addrs) == (cs_addrs->ti->curr_tn - 1)); /* In case this is MM and wcs_flu() remapped an extended database, reset rctl->csd */ @@ -272,6 +256,7 @@ uint4 mur_process_intrpt_recov() ; assert(rctl->csd->jnl_file_len == jctl->jnl_fn_len); /* latest gener file name */ assert(0 == memcmp(rctl->csd->jnl_file_name, jctl->jnl_fn, jctl->jnl_fn_len)); /* should match db header */ + rename_fn_len = ARRAYSIZE(rename_fn); if (SS_NORMAL != (status = prepare_unique_name((char *)jctl->jnl_fn, jctl->jnl_fn_len, "", "", rename_fn, &rename_fn_len, now, &status2))) return status; @@ -378,7 +363,6 @@ uint4 mur_process_intrpt_recov() gtm_putmsg_csa(CSA_ARG(rctl->csa) VARLSTCNT(4) ERR_JNLNOCREATE, 2, jnl_info.jnl_len, jnl_info.jnl); return jnl_info.status; } -# ifdef UNIX if (jgbl.onlnrlbk) { cs_addrs = rctl->csa; @@ -388,7 +372,6 @@ uint4 mur_process_intrpt_recov() jpc->jnl_buff->cycle++; /* so that, all other processes knows to switch to newer journal file */ jpc->cycle--; /* decrement cycle so "jnl_ensure_open" knows to reopen the journal */ } -# endif if (NULL != rctl->jctl_alt_head) /* remove the journal files created by last interrupted recover process */ { mur_rem_jctls(rctl); diff --git a/sr_port/mur_tp_resolve_time.c b/sr_port/mur_tp_resolve_time.c index 750752a..63f8a10 100644 --- a/sr_port/mur_tp_resolve_time.c +++ b/sr_port/mur_tp_resolve_time.c @@ -1,6 +1,6 @@ /**************************************************************** * - * Copyright (c) 2005-2015 Fidelity National Information * + * Copyright (c) 2005-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -36,6 +36,7 @@ void mur_tp_resolve_time(jnl_tm_t max_lvrec_time) { int reg_total; reg_ctl_list *rctl, *rctl_top; + jnl_ctl_list *jctl; jnl_tm_t reg_tp_resolve_time; boolean_t all_reg_before_image; @@ -83,18 +84,26 @@ void mur_tp_resolve_time(jnl_tm_t max_lvrec_time) } for (rctl = mur_ctl, rctl_top = mur_ctl + reg_total; rctl < rctl_top; rctl++) { + jctl = rctl->jctl; /* Assumption : It is guaranteed to see an EPOCH in every - * "rctl->jctl->jfh->epoch_interval + MAX_EPOCH_DELAY" seconds. */ - assert(max_lvrec_time >= rctl->jctl->jfh->epoch_interval + MAX_EPOCH_DELAY); + * "jctl->jfh->epoch_interval + MAX_EPOCH_DELAY" seconds. + */ + assert(max_lvrec_time >= jctl->jfh->epoch_interval + MAX_EPOCH_DELAY); /* Calculate this region's TP resolve time based on the maximum of the last valid record across regions. If the - * region is properly closed (typically this means that the journal file's crash field is FALSE. But, with online + * region is properly closed (typically this means that the journal file's crash field is FALSE). But, with online * rollback, crash field being TRUE, does not mean the journal file is crashed (as long as the shared memory for * that region existed when the region was opened). So, use jctl->properly_closed to determine whether the journal * file for the region is really crashed. If it is properly closed, the region's TP resolve time is the * max_lvrec_time. If not, we need to go back by an epoch interval in addition to the MAX_EPOCH_DELAY. + * There is one exception to this rule and that is if the latest generation journal file of a region is properly + * closed but was once a previous generation journal file (possible for example if the user moves mumps.mjl out + * of the way and renames mumps.mjl_ back as mumps.mjl). In that case, we want to treat the + * tp_resolve_time for this region as the last valid record timestamp in this journal file. */ - if (!rctl->jctl->properly_closed) - reg_tp_resolve_time = max_lvrec_time - rctl->jctl->jfh->epoch_interval - MAX_EPOCH_DELAY; + if (!jctl->properly_closed) + reg_tp_resolve_time = max_lvrec_time - jctl->jfh->epoch_interval - MAX_EPOCH_DELAY; + else if (jctl->jfh->is_not_latest_jnl) + reg_tp_resolve_time = rctl->lvrec_time; else reg_tp_resolve_time = max_lvrec_time; if (rctl->lvrec_time > reg_tp_resolve_time) diff --git a/sr_port/mutex_deadlock_check.c b/sr_port/mutex_deadlock_check.c index edbbbf1..bc7a126 100644 --- a/sr_port/mutex_deadlock_check.c +++ b/sr_port/mutex_deadlock_check.c @@ -119,8 +119,9 @@ void mutex_deadlock_check(mutex_struct_ptr_t criticalPtr, sgmnt_addrs *csa) if (is_replicator || mu_reorg_process) { ++crit_deadlock_check_cycle; - repl_csa = ((NULL != jnlpool.jnlpool_dummy_reg) && jnlpool.jnlpool_dummy_reg->open) - ? &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs : NULL; + repl_csa = (NULL != jnlpool.jnlpool_dummy_reg) ? &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs : NULL; + assert((NULL == jnlpool.jnlpool_dummy_reg) || jnlpool.jnlpool_dummy_reg->open + || (repl_csa->critical != criticalPtr)); if (!dollar_tlevel) { if ((NULL != repl_csa) && (repl_csa->critical == criticalPtr)) diff --git a/sr_port/op_tcommit.c b/sr_port/op_tcommit.c index 3fef579..a1ad76b 100644 --- a/sr_port/op_tcommit.c +++ b/sr_port/op_tcommit.c @@ -271,7 +271,7 @@ enum cdb_sc op_tcommit(void) csd = cs_data; cnl = csa->nl; is_mm = (dba_mm == csa->hdr->acc_meth); - csa->tp_hint = cnl->tp_hint; + csa->tp_hint = 0; /* will be set to non-zero later if we invoke "bm_getfree" */ si->cr_array_index = 0; # ifdef DEBUG if (WBTEST_ENABLED(WBTEST_MM_CONCURRENT_FILE_EXTEND) @@ -357,6 +357,13 @@ enum cdb_sc op_tcommit(void) TRAVERSE_TO_LATEST_CSE(first_cse); old_db_addrs[0] = csa->db_addrs[0]; old_db_addrs[1] = csa->db_addrs[1]; + if (0 == csa->tp_hint) + { /* We are about to do a "bm_getfree" call for this database + * for the first time in this TP transaction. Copy over the + * allocation hint from shared memory. + */ + csa->tp_hint = cnl->tp_hint; + } /* cse->blk could be a real block or a chain; we can't use a chain but * the following statement is unconditional because, in general, the region * hint works at least as well as the block, which is what we use in non-TP diff --git a/sr_port/prepare_unique_name.c b/sr_port/prepare_unique_name.c index 2a0a649..3f23db5 100644 --- a/sr_port/prepare_unique_name.c +++ b/sr_port/prepare_unique_name.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2003, 2013 Fidelity Information Services, Inc * + * Copyright (c) 2003-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -18,14 +19,12 @@ #include "gtm_file_stat.h" #include "gtm_rename.h" #include "gtmmsg.h" +#include "eintr_wrappers.h" -#define MAX_CHARS_APPEND 10 +#define MAX_CHARS_APPEND 10 +#define DIR_FILE_SEPARATOR '/' -#if defined(UNIX) -# define DIR_FILE_SEPARATOR '/' -#elif defined(VMS) -# define DIR_FILE_SEPARATOR ']' -#endif +error_def(ERR_FILENAMETOOLONG); /* Given org_fn this will create rename_fn * a) If prefix is not null, rename_fn = prefix + org_fn @@ -33,6 +32,9 @@ * c) If prefix and suffix are both null, then * rename_fn = org_fn + timestamp * If rename_fn exists, add numbers to make it non-existance file + * d) Note: This function cannot handle the case wehre prefix and suffix are both non-null. Callers ensure that. + * At function entry, "rename_fn_len" points to the allocated length of the "rename_fn" char array. + * On a successful function exit, "rename_fn_len" is set to the length of "rename_fn". */ uint4 prepare_unique_name(char *org_fn, int org_fn_len, char *prefix, char *suffix, char *rename_fn, int *rename_fn_len, jnl_tm_t now, uint4 *ustatus) @@ -41,18 +43,26 @@ uint4 prepare_unique_name(char *org_fn, int org_fn_len, char *prefix, char *suf char *filename_begin, append_char[MAX_CHARS_APPEND] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; int prefix_len, suffix_len, cnt, length; struct tm *tm_struct; - int file_stat; + int file_stat, rename_alloc_len; uint4 status1; - - error_def(ERR_FILENAMETOOLONG); + boolean_t nonnull_prefix, nonnull_suffix; + time_t tt_now; + size_t tm_str_len, avail_len; + char *tm_str; *ustatus = SS_NORMAL; - if (0 != prefix[0]) + rename_alloc_len = *rename_fn_len; /* Note we need space for null terminator too at end of the renamed file name */ + assert(rename_alloc_len); /* ensure caller has set this */ + nonnull_prefix = (0 != prefix[0]); + nonnull_suffix = (0 != suffix[0]); + assert(!nonnull_prefix || !nonnull_suffix); /* both prefix & suffix cannot be non-null */ + if (nonnull_prefix) { prefix_len = STRLEN(prefix); assert('\0' == org_fn[org_fn_len]); + if ((prefix_len + org_fn_len) >= rename_alloc_len) + return ERR_FILENAMETOOLONG; filename_begin = strrchr(org_fn, DIR_FILE_SEPARATOR); - length = 0; if (NULL != filename_begin) { length = (int4)(filename_begin - org_fn + 1); @@ -60,56 +70,72 @@ uint4 prepare_unique_name(char *org_fn, int org_fn_len, char *prefix, char *suf memcpy(rename_fn, org_fn, length); org_fn_len -= length; org_fn += length; - } + } else + length = 0; memcpy(rename_fn + length, prefix, prefix_len); memcpy(rename_fn + length + prefix_len, org_fn, org_fn_len); *rename_fn_len = length + prefix_len + org_fn_len; } - if (0 != suffix[0]) + if (nonnull_suffix) { suffix_len = STRLEN(suffix); + if ((org_fn_len + suffix_len) >= rename_alloc_len) + return ERR_FILENAMETOOLONG; memcpy(rename_fn, org_fn, org_fn_len); memcpy(rename_fn + org_fn_len, suffix, suffix_len); *rename_fn_len = org_fn_len + suffix_len; } - if (0 != prefix[0] || 0 != suffix[0]) + if (nonnull_prefix || nonnull_suffix) { + assert(*rename_fn_len < rename_alloc_len); rename_fn[*rename_fn_len] = 0; /* Ensure it to be NULL terminated */ return SS_NORMAL; } - memcpy(rename_fn, org_fn, org_fn_len); + /* Append formatted timestamp to "rename_fn" */ + if (rename_alloc_len <= org_fn_len) + return ERR_FILENAMETOOLONG; + tm_str = &rename_fn[org_fn_len]; + avail_len = rename_alloc_len - org_fn_len; + tt_now = (time_t)now; + GTM_LOCALTIME(tm_struct, &tt_now); + STRFTIME(tm_str, avail_len, JNLSWITCH_TM_FMT, tm_struct, tm_str_len); + if (!tm_str_len) /* STRFTIME can return 0 if space is not enough to store entire time string including null terminator */ + return ERR_FILENAMETOOLONG; + assert(JNLSWITCH_TM_FMT_LEN == tm_str_len); + memcpy(rename_fn, org_fn, org_fn_len); /* Copy original file name to "rename_fn" */ filestr.addr = rename_fn; - filestr.len = org_fn_len; - rename_fn[filestr.len] = 0; - assert(filestr.len + 1 < MAX_FN_LEN); - if (SS_NORMAL != (status1 = append_time_stamp(rename_fn, &filestr.len, now))) - return status1; + filestr.len = org_fn_len + (int)tm_str_len; + assert(rename_alloc_len > filestr.len); + assert('\0' == rename_fn[filestr.len]); if (FILE_PRESENT == (file_stat = gtm_file_stat(&filestr, NULL, NULL, FALSE, ustatus))) /* One already exists */ { /* new name refers to an existing file - stuff numbers on the end until its unique */ - rename_fn[filestr.len] = '_'; + assert(rename_alloc_len > filestr.len); + rename_fn[filestr.len] = '_'; /* this access is safe from buffer overflow because of the above assert */ filestr.len += 2; /* 2 is for "_" + "append_char[]" */ - for ( ; filestr.len < MAX_FN_LEN; filestr.len++) + for ( ; ; filestr.len++) { + if (rename_alloc_len <= filestr.len) + return ERR_FILENAMETOOLONG; rename_fn[filestr.len] = '\0'; - filestr.len = filestr.len; - for (cnt = 0; cnt < MAX_CHARS_APPEND; cnt++) + for (cnt = 0; MAX_CHARS_APPEND > cnt; cnt++) { rename_fn[filestr.len - 1] = append_char[cnt]; if (FILE_NOT_FOUND == gtm_file_stat(&filestr, NULL, NULL, FALSE, ustatus)) break; } - if (cnt < MAX_CHARS_APPEND) /* found one non existance file */ + if (MAX_CHARS_APPEND > cnt) /* found one non-existing file */ break; } *ustatus = SS_NORMAL; - if (MAX_FN_LEN <= filestr.len) - return ERR_FILENAMETOOLONG; /* no parameter for this message */ } else if (FILE_STAT_ERROR == file_stat) { status1 = *ustatus; + assert(SS_NORMAL != status1); *ustatus = SS_NORMAL; return status1; } + assert(rename_alloc_len > filestr.len); *rename_fn_len = filestr.len; + assert('\0' == rename_fn[filestr.len]); return SS_NORMAL; } diff --git a/sr_port/rename_file_if_exists.c b/sr_port/rename_file_if_exists.c index 2a0a36a..238dd3a 100644 --- a/sr_port/rename_file_if_exists.c +++ b/sr_port/rename_file_if_exists.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2003-2015 Fidelity National Information * + * Copyright (c) 2003-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -45,8 +45,6 @@ int rename_file_if_exists(char *org_fn, int org_fn_len, char *rename_fn, int *re int status; jnl_tm_t now; - memcpy(rename_fn, org_fn, org_fn_len + 1); /* Ensure it to be NULL terminated */ - *rename_fn_len = org_fn_len; orgfile.addr = org_fn; orgfile.len = org_fn_len; if (FILE_NOT_FOUND == (status = gtm_file_stat(&orgfile, NULL, NULL, FALSE, ustatus))) diff --git a/sr_port/stp_gcol_src.h b/sr_port/stp_gcol_src.h index 9a09705..10af08a 100644 --- a/sr_port/stp_gcol_src.h +++ b/sr_port/stp_gcol_src.h @@ -350,13 +350,9 @@ error_def(ERR_STPEXPFAIL); if (HTENT_VALID_ADDR(tabent_addr, zwr_alias_var, zav)) \ { \ x = &zav->zwr_var; \ - /* Regular varnames are already accounted for in other ways so \ - * we need to avoid putting this mstr into the process array twice. \ - * The only var names we need worry about are $ZWRTACxxx so make \ - * simple check for var names starting with '$'. \ - */ \ - if (x->len && ('$' == x->addr[0])) \ - MSTR_STPG_ADD(x); \ + /* Protect MSTRs we are using to process the zwrite */ \ + assert(x->len); /* if it is valid it should have a non-zero length */ \ + MSTR_STPG_ADD(x); \ } \ } \ } \ diff --git a/sr_port/tp_tend.c b/sr_port/tp_tend.c index 3d74b8d..fc02c5c 100644 --- a/sr_port/tp_tend.c +++ b/sr_port/tp_tend.c @@ -1437,6 +1437,15 @@ boolean_t tp_tend() ctn = csd->trans_hist.curr_tn; ASSERT_CURR_TN_EQUALS_EARLY_TN(csa, ctn); csd->trans_hist.early_tn = ctn + 1; + /* If this process had used "cnl->tp_hint" and done some block allocations in "bm_getfree", now that + * all history validation is complete and this transaction is going to commit, take this opportunity + * to update the shared memory hint to reflect this process' allocations in this TP transaction. + */ + if (csa->tp_hint) + { + cnl = csa->nl; + cnl->tp_hint = csa->tp_hint; /* update the region hint to reflect any (successful) allocations */ + } com_csum = 0; /* Write non-logical records (PBLK) if applicable */ if (JNL_ENABLED(csa)) @@ -1883,10 +1892,10 @@ boolean_t tp_tend() tp_cr_array = si->cr_array; ASSERT_CR_ARRAY_IS_UNPINNED(si->tp_csd, tp_cr_array, si->cr_array_index); si->cr_array_index = 0; - csa = cs_addrs; - cnl = csa->nl; if (!is_mm) { /* In BG, now that two-phase commit is done, decrement counter */ + csa = cs_addrs; + cnl = csa->nl; DECR_WCS_PHASE2_COMMIT_PIDCNT(csa, cnl); /* Phase 2 commits are completed for the current region. See if we had done a snapshot * init (csa->snapshot_in_prog == TRUE). If so, try releasing the resources obtained @@ -1898,7 +1907,6 @@ boolean_t tp_tend() SS_RELEASE_IF_NEEDED(csa, cnl); } } - cnl->tp_hint = csa->tp_hint; /* update the region hint to reflect any (successful) allocations */ } assert(!si->cr_array_index); si->tp_csa->t_commit_crit = FALSE; @@ -2273,6 +2281,7 @@ enum cdb_sc reallocate_bitmap(sgm_info *si, cw_set_element *bml_cse) is_mm = (dba_mm == csd->acc_meth); /* This optimization should only be used if blocks are being allocated (not if freed) in this bitmap. */ assert(0 <= bml_cse->reference_cnt); + bml = bml_cse->blk; if (!is_mm && bml_cse->cr->in_tend) { /* Possible if this cache-record no longer contains the bitmap block we think it does. In this case restart. * Since we hold crit at this point, the block that currently resides should not be a bitmap block since @@ -2284,7 +2293,6 @@ enum cdb_sc reallocate_bitmap(sgm_info *si, cw_set_element *bml_cse) assert(is_mm || (FALSE == bml_cse->cr->in_tend)); assert(is_mm || (FALSE == bml_cse->cr->data_invalid)); offset = 0; - bml = bml_cse->blk; total_blks = is_mm ? csa->total_blks : csa->ti->total_blks; map_size = (ROUND_DOWN2(total_blks, BLKS_PER_LMAP) == bml) ? total_blks - bml : BLKS_PER_LMAP; assert(bml >= 0 && bml < total_blks); @@ -2300,20 +2308,27 @@ enum cdb_sc reallocate_bitmap(sgm_info *si, cw_set_element *bml_cse) assert(gds_t_acquired == cse->mode); assert(GDSVCURR == cse->ondsk_blkver); assert(*b_ptr == (cse->blk - bml)); - /* If bm_find_blk is passed a hint (first arg) it assumes it is less than map_size and gives invalid results (for - * values >= map_size). Instead of changing bm_find_blk we do the check here and assert that "hint" < "map_size" in - * bm_find_blk. - */ do { - assert(offset <= map_size); - if ((offset >= map_size) || (NO_FREE_SPACE == (free_bit = bm_find_blk(offset, /* WARNING assignment */ - (sm_uc_ptr_t)bml_cse->old_block + SIZEOF(blk_hdr), map_size, &blk_used)))) + /* If "bm_find_blk" is passed a hint (first arg) it assumes it is less than map_size and gives invalid + * results (for values >= map_size). Instead of changing "bm_find_blk" we do the check here and assert + * that "hint" < "map_size" in "bm_find_blk". + */ + if (offset >= map_size) + return cdb_sc_bmlmod; + free_bit = bm_find_blk(offset, (sm_uc_ptr_t)bml_cse->old_block + SIZEOF(blk_hdr), map_size, &blk_used); + if (NO_FREE_SPACE == free_bit) return cdb_sc_bmlmod; cse->blk = bml + free_bit; if (cse->blk >= total_blks) return cdb_sc_lostbmlcr; - /* re-point before-images into cse->old_block if necessary; if not available: restart */ + /* Re-point before-images into cse->old_block if necessary; if not available: restart. + * Set cse->blk_prior_state before invoking BEFORE_IMAGE_NEEDED macro (as it needs this field set). + */ + if (blk_used) + BIT_SET_RECYCLED_AND_CLEAR_FREE(cse->blk_prior_state); + else + BIT_CLEAR_RECYCLED_AND_SET_FREE(cse->blk_prior_state); BEFORE_IMAGE_NEEDED(read_before_image, cse, csa, csd, cse->blk, before_image_needed); if (!before_image_needed) { @@ -2325,9 +2340,7 @@ enum cdb_sc reallocate_bitmap(sgm_info *si, cw_set_element *bml_cse) assert(CR_NOTVALID != (sm_long_t)cr); if ((NULL == cr) || (CR_NOTVALID == (sm_long_t)cr) || (0 <= cr->read_in_progress)) { /* if this before image is not at hand don't wait for it in crit */ - if (free_bit == offset) /* see if we have been through the bitmap; if so, */ - return cdb_sc_lostbmlcr; /* restart - we hold crit so it won't change */ - offset = free_bit; /* otherwise, try further in this bitmap */ + offset = free_bit + 1; /* try further in this bitmap */ continue; } /* if we had not read a before-image previously (because cse->blk was not a reused block previously) @@ -2341,6 +2354,11 @@ enum cdb_sc reallocate_bitmap(sgm_info *si, cw_set_element *bml_cse) { /* Bitmap reallocation resulted in a situation where checksums etc. must be recomputed */ cse->old_block = (sm_uc_ptr_t)GDS_REL2ABS(cr->buffaddr); old_block = (blk_hdr_ptr_t)cse->old_block; + /* Note: cse->cr needs to be set BEFORE the JNL_GET_CHECKSUM_ACQUIRED macro call + * as the macro relies on this. + */ + cse->cr = cr; + cse->cycle = cr->cycle; if (!WAS_FREE(cse->blk_prior_state) && (NULL != jbp)) { if (old_block->tn < jbp->epoch_tn) @@ -2350,20 +2368,14 @@ enum cdb_sc reallocate_bitmap(sgm_info *si, cw_set_element *bml_cse) bsiz = old_block->bsiz; if (bsiz > csd->blk_size) { /* if this before image is not valid don't wait for it in crit */ - if (free_bit == offset) /* if exhausted this map */ - return cdb_sc_lostbmlcr; /* restart (see above) */ - offset = free_bit; + offset = free_bit + 1; /* try further in this bitmap */ continue; } JNL_GET_CHECKSUM_ACQUIRED_BLK(cse, csd, csa, old_block, bsiz); } else cse->blk_checksum = 0; } - cse->cr = cr; - cse->cycle = cr->cycle; } - blk_used ? BIT_SET_RECYCLED_AND_CLEAR_FREE(cse->blk_prior_state) - : BIT_CLEAR_RECYCLED_AND_SET_FREE(cse->blk_prior_state); } else { /* in MM, although mm_update does not use cse->old_block, tp_tend uses it to write before-images. * therefore, fix it to point to the reallocated block's buffer address diff --git a/sr_port/updhelper_writer.c b/sr_port/updhelper_writer.c index fbffc50..9f0559a 100644 --- a/sr_port/updhelper_writer.c +++ b/sr_port/updhelper_writer.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2005-2016 Fidelity National Information * + * Copyright (c) 2005-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -71,8 +71,7 @@ #define UPDHELPER_EARLY_EPOCH 5 #define THRESHOLD_FOR_PAUSE 10 -GBLDEF jnlpool_addrs jnlpool; - +GBLREF jnlpool_addrs jnlpool; GBLREF void (*call_on_signal)(); GBLREF recvpool_addrs recvpool; GBLREF upd_helper_entry_ptr_t helper_entry; diff --git a/sr_port/zshow_zwrite.c b/sr_port/zshow_zwrite.c index 8e76f6f..e745ec8 100644 --- a/sr_port/zshow_zwrite.c +++ b/sr_port/zshow_zwrite.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2001, 2007 Fidelity Information Services, Inc * + * Copyright (c) 2001-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -25,16 +26,17 @@ GBLREF uint4 pat_everything[]; GBLREF mstr_len_t sizeof_pat_everything; +LITREF mval literal_one; + void zshow_zwrite(zshow_out *output) { - mval mv,pat; + mval pat; zshow_output(output,0); pat.mvtype = MV_STR; pat.str.addr = (char *)&pat_everything[0]; pat.str.len = INTCAST(sizeof_pat_everything - 1); - MV_FORCE_MVAL(&mv,ZWRITE_ASTERISK) ; - n2s(&mv); - op_lvpatwrite(VARLSTCNT(3) (UINTPTR_T)output, &pat, &mv); + /* ZWRITE_ASTERISK is equivalent to literal_one */ + op_lvpatwrite(VARLSTCNT(3) (UINTPTR_T)output, &pat, &literal_one); return; } diff --git a/sr_port_cm/gtcmd_rundown.c b/sr_port_cm/gtcmd_rundown.c index ffd8252..bdede34 100644 --- a/sr_port_cm/gtcmd_rundown.c +++ b/sr_port_cm/gtcmd_rundown.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -51,7 +51,7 @@ void gtcmd_rundown(connection_struct *cnx, bool clean_exit) jnl_buffer_ptr_t jbp; int refcnt; boolean_t was_crit; - int4 rundown_status = EXIT_NRM; /* if gds_rundown went smoothly */ + int4 rundown_status = EXIT_NRM; /* if "gds_rundown" went smoothly */ for (ptr = cnx->region_root; ptr;) { @@ -96,11 +96,13 @@ void gtcmd_rundown(connection_struct *cnx, bool clean_exit) */ assert(0 <= refcnt); if (0 == refcnt) - { /* free up only as little as needed to facilitate structure reuse when the region is opened again */ + { /* Free up only as little as needed to facilitate structure reuse when the region is opened again. + * Hence the CLEANUP_UDI_FALSE use below. + */ assert(region->head.fl == region->head.bl); if (JNL_ALLOWED(cs_data)) jpc->pini_addr = 0; - UNIX_ONLY(rundown_status |=) gds_rundown(); + rundown_status |= gds_rundown(CLEANUP_UDI_FALSE); gd_ht_kill(region->reg_hash, TRUE); /* TRUE to free up the table and the gv_targets it holds too */ FREE_CSA_DIR_TREE(cs_addrs); cm_del_gdr_ptr(gv_cur_region); diff --git a/sr_port_cm/gvcmy_open.c b/sr_port_cm/gvcmy_open.c index 6ac96cc..71b7960 100644 --- a/sr_port_cm/gvcmy_open.c +++ b/sr_port_cm/gvcmy_open.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -12,16 +12,10 @@ #include "mdef.h" -#ifdef VMS -# include -# include -# include -#elif defined(UNIX) -# include "gtm_unistd.h" -# include -# include "parse_file.h" -# include "gtm_stdlib.h" -#endif +#include "gtm_unistd.h" +#include +#include "parse_file.h" +#include "gtm_stdlib.h" #include "gdsroot.h" #include "gtm_facility.h" @@ -54,11 +48,7 @@ error_def(ERR_SYSCALL); #define GTCM_ENVVAR_PFX "GTCM_" #define GTCM_ENVVAR_PFXLEN (SIZEOF(GTCM_ENVVAR_PFX) - 1) -#ifdef VMS -void gvcmy_open(gd_region *reg, struct NAM *nb) -#else void gvcmy_open(gd_region *reg, parse_blk *pb) -#endif { struct CLB *clb_ptr; link_info *li; @@ -71,25 +61,13 @@ void gvcmy_open(gd_region *reg, parse_blk *pb) mstr task1, task2; unsigned char buff[256], lbuff[MAX_HOST_NAME_LEN + GTCM_ENVVAR_PFXLEN]; short temp_short; - VMS_ONLY($DESCRIPTOR(task, "GTCMSVR");) - UNIX_ONLY(MSTR_DEF(task, 0, NULL);) + MSTR_DEF(task, 0, NULL); + DCL_THREADGBL_ACCESS; /* needed by TREF usage inside SET_REGION_OPEN_TRUE macro */ + SETUP_THREADGBL_ACCESS; /* needed by TREF usage inside SET_REGION_OPEN_TRUE macro */ ESTABLISH(gvcmy_open_ch); if (reg->is_spanned) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_REMOTEDBNOSPGBL, 2, REG_LEN_STR(reg)); -#ifdef VMS - if (!nb->nam$b_node) - rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVNETFILNM); - top = nb->nam$l_esa + nb->nam$b_esl; - fn = nb->nam$l_node + nb->nam$b_node; - node.dsc$b_dtype = task.dsc$b_dtype = 14; - node.dsc$b_class = task.dsc$b_class = 1; - node.dsc$w_length = nb->nam$b_node - 2; - node.dsc$a_pointer = nb->nam$l_node; - task1.addr = "GTCMSVRNAM"; - task1.len = SIZEOF("GTCMSVRNAM") - 1; - status = TRANS_LOG_NAME(&task1, &task2, (char *)buff, SIZEOF(buff), dont_sendmsg_on_log2long); -#elif defined(UNIX) if (!pb->b_node) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_INVNETFILNM); fn = (unsigned char *)pb->l_dir; @@ -119,29 +97,18 @@ void gvcmy_open(gd_region *reg, parse_blk *pb) status = SS_LOG2LONG; } else status = SS_NOLOGNAM; -#else -# error "Undefined platform" -#endif if (SS_NOLOGNAM != status) { if (SS_NORMAL != status) { -# ifdef UNIX if (SS_LOG2LONG == status) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_LOGTOOLONG, 3, task1.len, task1.addr, SIZEOF(buff) - 1); else -# endif rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) status); } - VMS_ONLY( - task.dsc$a_pointer = buff; - task.dsc$w_length = task2.len; - ); - UNIX_ONLY( - task.addr = (char *)task2.addr; - task.len = task2.len; - ); + task.addr = (char *)task2.addr; + task.len = task2.len; } clb_ptr = cmu_getclb(&node, &task); if (!clb_ptr) /* If link not open */ diff --git a/sr_unix/aio_shim.c b/sr_unix/aio_shim.c index 0961344..2b2c3aa 100644 --- a/sr_unix/aio_shim.c +++ b/sr_unix/aio_shim.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2016 Fidelity National Information * + * Copyright (c) 2016-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -164,6 +164,7 @@ MBSTART { \ STATICFNDCL void *io_getevents_multiplexer(void *arg); STATICFNDCL int io_getevents_internal(aio_context_t ctx); STATICFNDCL void clean_wip_queue(unix_db_info *udi); +STATICFNDCL void aio_gld_clean_wip_queue(gd_addr *input_gd, gd_addr *match_gd); STATICFNDCL int aio_shim_setup(aio_context_t *ctx); STATICFNDCL int aio_shim_thread_init(gd_addr *gd); @@ -460,10 +461,11 @@ void aio_shim_destroy(gd_addr *gd) struct gd_info *gdi; int ret; char *eventfd_str = "GTMROCKS"; - gd_region *r_local, *r_top; - unix_db_info *udi; mstr *gldname; + gd_addr *addr_ptr; + DCL_THREADGBL_ACCESS; + SETUP_THREADGBL_ACCESS; gdi = gd->thread_gdi; if (NULL == gdi) { /* A write didn't happen. */ @@ -485,28 +487,49 @@ void aio_shim_destroy(gd_addr *gd) assert(0 == ret); if (-1 == ret) ISSUE_SYSCALL_RTS_ERROR_WITH_GD(gd, "aio_shim_destroy::io_destroy", errno); - /* Iterate over all the regions in the global directory and clean their WIP queues */ - for (r_local = gd->regions, r_top = r_local + gd->n_regions; r_local < r_top; r_local++) + /* If there was at least one region with reg->was_open = TRUE, then it is possible regions in other glds + * (different from "gd" have a "udi" with "udi->owning_gd" == "gd". So we would need to look at all regions + * across all glds opened by this process. If no was_open region was ever seen by this process, then it is + * enough to look at regions in just the current gld ("gd"). + */ + if (TREF(was_open_reg_seen)) + { + /* Iterate over all the regions in the global directory and clean their WIP queues */ + for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr)) + aio_gld_clean_wip_queue(addr_ptr, gd); + } else + aio_gld_clean_wip_queue(gd, gd); + /* By this point, we must have no more outstanding IOs */ + assert(0 == gdi->num_ios); + /* Delete the thread_gdi to leave us in a state consistent with no thread existing. */ + gtm_free(gdi); + gd->thread_gdi = NULL; +} + +void aio_gld_clean_wip_queue(gd_addr *input_gd, gd_addr *match_gd) +{ + unix_db_info *udi; + gd_region *reg, *r_top; + struct gd_info *gdi; + + gdi = match_gd->thread_gdi; + assert(NULL != gdi); + for (reg = input_gd->regions, r_top = reg + input_gd->n_regions; reg < r_top; reg++) { - if (r_local->open && !r_local->was_open && r_local->dyn.addr->asyncio - && dba_cm != r_local->dyn.addr->acc_meth) + assert(input_gd == reg->owning_gd); + if (reg->open && reg->dyn.addr->asyncio && (dba_cm != reg->dyn.addr->acc_meth)) { - udi = FILE_INFO(r_local); - /* We don't call clean_wip_queue() if we don't have any outstanding IOs - * in the region. - * This reduces wip queue header lock contention if lots of processes - * exit at the same time. + udi = FILE_INFO(reg); + /* We don't call clean_wip_queue() if we don't have any outstanding IOs in the region. + * This reduces wip queue header lock contention if lots of processes exit at the same time. + * Note that in case multiple regions map to same db file, it is possible udi->owning_gd + * points to a gld different from "match_gd". In that case, skip the wip queue clean as we are + * interested only in cleaning up aio writes issued from "match_gd". */ - assert(udi->owning_gd == r_local->owning_gd); - if (0 < udi->owning_gd->thread_gdi->num_ios) + if ((udi->owning_gd == match_gd) && (0 < gdi->num_ios)) clean_wip_queue(udi); } } - /* By this point, we must have no more outstanding IOs */ - assert(0 == gd->thread_gdi->num_ios); - /* Delete the thread_gdi to leave us in a state consistent with no thread existing. */ - gtm_free(gd->thread_gdi); - gd->thread_gdi = NULL; } /* Lazily loads the multiplexing thread and submits an IO. */ diff --git a/sr_unix/append_time_stamp.c b/sr_unix/append_time_stamp.c deleted file mode 100644 index 7599ce6..0000000 --- a/sr_unix/append_time_stamp.c +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************** - * * - * Copyright 2003, 2013 Fidelity Information Services, Inc * - * * - * This source code contains the intellectual property * - * of its copyright holder(s), and is made available * - * under a license. If you do not know the terms of * - * the license, please stop and do not read further. * - * * - ****************************************************************/ - -#include "mdef.h" - -#include -#include "gtm_string.h" -#include "gtm_time.h" -#include "gtm_rename.h" - -#include "eintr_wrappers.h" -#include "iosp.h" - -/* Append the formatted timestamp to the file name (fn); *fn_len contains the current length of the filename and at exit from this - * function, it is updated to reflect the new length. - */ -uint4 append_time_stamp(char *fn, int *fn_len, jnl_tm_t now) -{ - struct tm *tm_struct; - time_t tt_now; - size_t tm_str_len; - - assert(0 < MAX_FN_LEN - *fn_len - 1); - tt_now = (time_t)now; - GTM_LOCALTIME(tm_struct, &tt_now); - STRFTIME(&fn[*fn_len], MAX_FN_LEN - *fn_len - 1, JNLSWITCH_TM_FMT, tm_struct, tm_str_len); - *fn_len += (int)tm_str_len; - return SS_NORMAL; -} - diff --git a/sr_unix/cli.c b/sr_unix/cli.c index 304624f..e1c5981 100644 --- a/sr_unix/cli.c +++ b/sr_unix/cli.c @@ -1,6 +1,7 @@ /**************************************************************** * * - * Copyright 2001, 2014 Fidelity Information Services, Inc * + * Copyright (c) 2001-2017 Fidelity National Information * + * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * * of its copyright holder(s), and is made available * @@ -23,6 +24,10 @@ #include "util.h" #include "cli_parse.h" #include "min_max.h" +#include "gtmimagename.h" +#include "gtmmsg.h" + +error_def(ERR_CLISTRTOOLONG); /* * -------------------------------------------------- @@ -271,7 +276,14 @@ boolean_t cli_get_str(char *entry, char *dst, unsigned short *max_len) } DEBUG_ONLY(TREF(cli_get_str_max_len) = 0;) /* for use inside cli_get_value -> get_parm_entry ... */ copylen = strlen(buf); - copylen = MIN(copylen, maxdstlen); + if (maxdstlen < copylen) + { + if (!IS_GTM_IMAGE) + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_CLISTRTOOLONG, 3, entry, copylen, maxdstlen); + else + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(5) ERR_CLISTRTOOLONG, 3, entry, copylen, maxdstlen); + return FALSE; + } memset(dst, 0, maxdstlen); memcpy(dst, buf, copylen); *max_len = (unsigned short) copylen; diff --git a/sr_unix/dse.c b/sr_unix/dse.c index ff963d4..d0b696b 100644 --- a/sr_unix/dse.c +++ b/sr_unix/dse.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -110,6 +110,7 @@ int main(int argc, char *argv[]) TREF(no_spangbls) = TRUE; /* dse operates on a per-region basis irrespective of global mapping in gld */ TREF(skip_file_corrupt_check) = TRUE; /* do not let csd->file_corrupt flag cause errors in dse */ op_open_ptr = op_open; + INIT_FNPTR_GLOBAL_VARIABLES; patch_curr_blk = get_dir_root(); err_init(util_base_ch); UNICODE_ONLY(gtm_strToTitle_ptr = >m_strToTitle); diff --git a/sr_unix/err_init.c b/sr_unix/err_init.c index 012e274..9310c95 100644 --- a/sr_unix/err_init.c +++ b/sr_unix/err_init.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2015 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -15,6 +15,8 @@ #include #include #include +#include "gtm_string.h" + #include "unistd.h" #include "gtm_stdlib.h" #include "gtm_stdio.h" @@ -27,10 +29,11 @@ #include "eintr_wrappers.h" #define COREDUMPFILTERFN "/proc/%i/coredump_filter" -#define FILTERPARMSIZE (8 + 1) -#define FILTERENABLEBITS 0x00000073 /* Represents bits 0, 1, 4, 5, 6 */ +#define FILTERPARMSIZE (7 + 2 + 1) /* 7 bytes for number, 2 bytes for 0x, and 1 null terminator */ +#define FILTERENABLEBITS 0x0000073 /* Bits 0, 1, 4, 5, 6 - 32-bit can only handle 10 bytes total */ GBLREF enum gtmImageTypes image_type; +GBLDEF char **gtmenvp; error_def(ERR_SYSCALL); @@ -40,6 +43,14 @@ error_def(ERR_SYSCALL); */ void err_init(void (*x)()) { +# ifdef __linux__ + int rc; + unsigned int filterbits; + char procfn[SIZEOF(COREDUMPFILTERFN) + MAX_DIGITS_IN_INT]; /* File name of file to update */ + char filter[FILTERPARMSIZE], *filterend; /* Value read in & written out */ + char *rcc, *bytes_buf; + FILE *filterstrm; /* filter stream file block */ +# endif chnd = (condition_handler *)malloc((CONDSTK_INITIAL_INCR + CONDSTK_RESERVE) * SIZEOF(condition_handler)); chnd[0].ch_active = FALSE; chnd[0].save_active_ch = NULL; @@ -57,71 +68,78 @@ void err_init(void (*x)()) * kernel supports the ELF loader or not. To date, all Linux flavors GT.M supports use ELF so we regard this as largely * mandatory though in the future it may happen that GT.M works yet runs with something other than ELF. In that case, * we'd need to change the below to avoid the operator log messages every time GT.M initializes. + * + * Note use simple basic methods since this early in initialization not everything is necessarily setup to + * be able to properly use the *print*() wrapper functions. + * */ + bytes_buf = GETENV("gtm_coredump_filter"); + if ((NULL == bytes_buf) || (0 != strncmp("-1", bytes_buf, 3))) { - int rc; - unsigned int filterbits; - char procfn[SIZEOF(COREDUMPFILTERFN) + MAX_DIGITS_IN_INT]; /* File name of file to update */ - char filter[FILTERPARMSIZE], *filterend; /* Value read in & written out */ - char *rcc; - FILE *filterstrm; /* filter stream file block */ - /* Note use simple basic methods since this early in initialization not everything is necessarily setup to - * be able to properly use the *print*() wrapper functions. - */ rc = snprintf(procfn, SIZEOF(procfn), COREDUMPFILTERFN, getpid()); if (0 > rc) { send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("sprintf()"), CALLFROM, rc); return; } - Fopen(filterstrm, procfn, "r"); - if (NULL == filterstrm) + if (NULL == bytes_buf) { - rc = errno; - send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fopen()"), CALLFROM, rc); - return; - } - rcc = fgets(filter, SIZEOF(filter), filterstrm); - if (NULL == rcc) - { - send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fgets()"), CALLFROM, rc); - return; - } - FCLOSE(filterstrm, rc); - if (0 > rc) - { - send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fclose()"), CALLFROM, rc); - return; - } - filterend = filter + SIZEOF(filter); - filterbits = (unsigned int)strtol(filter, &filterend, 16); - if (FILTERENABLEBITS != (filterbits & FILTERENABLEBITS)) - { /* At least one flag was missing - reset them */ - filterbits = filterbits | FILTERENABLEBITS; - Fopen(filterstrm, procfn, "w"); + /* If $gtm_coredump_filter is not defined, set the filter to provide a full dump including huge pages */ + Fopen(filterstrm, procfn, "r"); if (NULL == filterstrm) { rc = errno; - send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fopen()"), - CALLFROM, rc); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, + RTS_ERROR_LITERAL("fopen()"), CALLFROM, rc); return; } - rc = fprintf(filterstrm, "0x%08x", filterbits); - if (0 > rc) + rcc = fgets(filter, SIZEOF(filter), filterstrm); + if (NULL == rcc) { - send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fprintf"), - CALLFROM, rc); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, + RTS_ERROR_LITERAL("fgets()"), CALLFROM, rc); return; } FCLOSE(filterstrm, rc); if (0 > rc) { - send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fclose()"), - CALLFROM, rc); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, + RTS_ERROR_LITERAL("fclose()"), CALLFROM, rc); return; } + filterend = filter + SIZEOF(filter); + filterbits = (unsigned int)strtol(filter, &filterend, 16); + if (FILTERENABLEBITS != (filterbits & FILTERENABLEBITS)) + { /* At least one flag was missing - reset them */ + filterbits = filterbits | FILTERENABLEBITS; + } + snprintf(filter, FILTERPARMSIZE, "0x%07x", filterbits); + bytes_buf = filter; } + Fopen(filterstrm, procfn, "w"); + if (NULL == filterstrm) + { + rc = errno; + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fopen()"), + CALLFROM, rc); + return; + } + rc = fprintf(filterstrm, "%s", bytes_buf); + if (0 > rc) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fprintf"), + CALLFROM, rc); + return; + } + FCLOSE(filterstrm, rc); + if (0 > rc) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fclose()"), + CALLFROM, rc); + return; + } + } # endif } diff --git a/sr_unix/errorsp.h b/sr_unix/errorsp.h index 4bcff05..f04d9f8 100644 --- a/sr_unix/errorsp.h +++ b/sr_unix/errorsp.h @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -408,8 +408,11 @@ MBSTART { \ CONTINUE; \ } -/* Should never unwind a condition handler established with ESTABLISH_NOUNWIND. Currently t_ch and dbinit_ch are the only ones. */ -#define UNWINDABLE(unw_ch) ((&t_ch != unw_ch->ch) && (&dbinit_ch != unw_ch->ch)) +/* Should never unwind a condition handler established with ESTABLISH_NOUNWIND. Currently t_ch and dbinit_ch are the only ones. + * Use function pointer (t_ch_fnptr global variable) instead of &tch (and likewise for dbinit_ch) as it will otherwise bloat + * executables that don't need to pull in t_ch/dbinit_ch (e.g. ftok/gtcm_shmclean/dbcertify). + */ +#define UNWINDABLE(unw_ch) ((t_ch_fnptr != unw_ch->ch) && (dbinit_ch_fnptr != unw_ch->ch)) /* Note, since we are not initially changing the assembler ESTABLISH version to also include deferring/enabling of interrupts, * we cannot leave the interrupt block in effect during the longjmp(). But once that support is in place, we can do away with * re-enabling interrupts and let the longjmp() return from setjmp() take care of it. @@ -419,6 +422,8 @@ MBSTART { \ GBLREF boolean_t ok_to_UNWIND_in_exit_handling; \ GBLREF volatile boolean_t in_wcs_recover; \ GBLREF uint4 dollar_tlevel; \ + GBLREF ch_ret_type (*t_ch_fnptr)(); /* Function pointer to t_ch */ \ + GBLREF ch_ret_type (*dbinit_ch_fnptr)();/* Function pointer to dbinit_ch */\ \ intrpt_state_t prev_intrpt_state; \ \ @@ -536,7 +541,7 @@ error_def(ERR_OUTOFSPACE); #define DUMPABLE ((SEVERITY == SEVERE) && IS_GTM_ERROR(SIGNAL) \ && (SIGNAL != (int)ERR_OUTOFSPACE) \ DEBUG_ONLY(&& (WBTEST_ENABLED(WBTEST_SKIP_CORE_FOR_MEMORY_ERROR) \ - ? (!process_exiting || (SIGNAL != (int)ERR_MEMORY)) : TRUE))) + ? (SIGNAL != (int)ERR_MEMORY) : TRUE))) unsigned char *set_zstatus(mstr *src, int arg, unsigned char **ctxtp, boolean_t need_rtsloc); diff --git a/sr_unix/ftok_sems.c b/sr_unix/ftok_sems.c index f1cea1e..9204fee 100644 --- a/sr_unix/ftok_sems.c +++ b/sr_unix/ftok_sems.c @@ -420,6 +420,9 @@ boolean_t ftok_sem_lock(gd_region *reg, boolean_t immediate) || (jgbl.mur_rollback && !jgbl.mur_options_forward) || !holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); udi = FILE_INFO(reg); csa = &udi->s_addrs; + /* Requests for the ftok lock on a db should always comes before requests for crit on the same db. + * This is needed to avoid deadlocks. So we should never hold crit on this db while requesting the ftok lock. Assert that. + */ assert(!csa->now_crit); /* The following two asserts are to ensure we never hold more than one FTOK semaphore at any point in time. The only * exception is if we were MUPIP STOPped (or kill -3ed) while having ftok_sem lock on one region and we came to rundown code diff --git a/sr_unix/gds_rundown.c b/sr_unix/gds_rundown.c index 7c1f1b4..5f029c9 100644 --- a/sr_unix/gds_rundown.c +++ b/sr_unix/gds_rundown.c @@ -46,9 +46,7 @@ #include "send_msg.h" #include "change_reg.h" #include "compswap.h" -#ifdef UNIX #include "mutex.h" -#endif #include "gds_rundown.h" #include "gvusr.h" #include "do_semop.h" @@ -80,6 +78,11 @@ #include "aio_shim.h" #include "gvcst_protos.h" #include "targ_alloc.h" +#include "gdskill.h" /* needed for tp.h */ +#include "gdscc.h" /* needed for tp.h */ +#include "buddy_list.h" /* needed for tp.h */ +#include "hashtab_int4.h" /* needed for tp.h */ +#include "tp.h" GBLREF VSIG_ATOMIC_T forced_exit; GBLREF boolean_t mupip_jnl_recover; @@ -125,7 +128,7 @@ error_def(ERR_STACKOFLOW); error_def(ERR_TEXT); error_def(ERR_WCBLOCKED); -int4 gds_rundown(void) +int4 gds_rundown(boolean_t cleanup_udi) { boolean_t canceled_dbsync_timer, do_jnlwait, ok_to_write_pfin, wrote_pfin; boolean_t have_standalone_access, ipc_deleted, err_caught, aiocancel_timedout; @@ -134,6 +137,7 @@ int4 gds_rundown(void) boolean_t db_needs_flushing; char time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */ gd_region *reg, *statsDBreg; + gd_segment *seg; int save_errno, status, rc; int4 semval, ftok_semval, sopcnt, ftok_sopcnt; short crash_count; @@ -160,6 +164,7 @@ int4 gds_rundown(void) gd_region *baseDBreg; sgmnt_addrs *baseDBcsa; node_local_ptr_t baseDBnl; + sgm_info *si; jnl_status = 0; reg = gv_cur_region; /* Local copy */ @@ -172,7 +177,8 @@ int4 gds_rundown(void) * macro. This would also avoid the assert problem * and should be done eventually. */ - if (dba_cm == reg->dyn.addr->acc_meth) + seg = reg->dyn.addr; + if (dba_cm == seg->acc_meth) return EXIT_NRM; udi = FILE_INFO(reg); csa = &udi->s_addrs; @@ -189,32 +195,43 @@ int4 gds_rundown(void) */ is_statsDB = IS_STATSDB_REG(reg); if (!is_statsDB) - { - if (!(RDBF_NOSTATS & reg->reservedDBFlags)) + { /* Note that even if the baseDB has RDBF_NOSTATS set, we could have opened the statsDB region + * (for example, if statsDB has read-only permissions, we would have opened it and found it is + * read-only when we tried to add the ^%YGS node and would have disabled stats in the baseDB + * all the while leaving the statsDB open. So we need to check if it is open and if so run it down + * without checking the RDBF_NOSTATS bit in the baseDB. + */ + BASEDBREG_TO_STATSDBREG(reg, statsDBreg); + if (statsDBreg->open) { - BASEDBREG_TO_STATSDBREG(reg, statsDBreg); - if (statsDBreg->open) - { - gv_cur_region = statsDBreg; /* Switch "gv_cur_region" to do rundown of statsDB */ - tp_change_reg(); - gds_rundown(); /* Ignore errors in statsdb rundown. Continue with baseDB rundown. */ - gv_cur_region = reg; /* Restore "gv_cur_region" back to continue rundown of baseDB */ - tp_change_reg(); - /* Now that statsdb has been rundown, reset basedb stats back to private memory in case it was - * pointing to statsdb shared/mapped memory. Note that the following reset of the stats - * pointer back to the internal stats buffer located is sgmnt_data is normally taken care - * of by the statsdb unlink processing in gvcst_remove_statsDB_linkage() but we keep this - * reset here also to be sure it gets done in case of a statsDB rundown issue. - */ - csa->gvstats_rec_p = &csa->gvstats_rec; - } + gv_cur_region = statsDBreg; /* Switch "gv_cur_region" to do rundown of statsDB */ + tp_change_reg(); + gds_rundown(cleanup_udi); /* Ignore errors in statsdb rundown. Continue with baseDB rundown. */ + gv_cur_region = reg; /* Restore "gv_cur_region" back to continue rundown of baseDB */ + tp_change_reg(); + /* Now that statsdb has been rundown, reset basedb stats back to private memory in case it was + * pointing to statsdb shared/mapped memory. Note that the following reset of the stats + * pointer back to the internal stats buffer located is sgmnt_data is normally taken care + * of by the statsdb unlink processing in gvcst_remove_statsDB_linkage() but we keep this + * reset here also to be sure it gets done in case of a statsDB rundown issue. + */ + csa->gvstats_rec_p = &csa->gvstats_rec; } - } else + } + csa->regcnt--; + if (csa->regcnt) + { /* There is at least one more region pointing to the same db file as this region. + * Defer rundown of this "csa" until the last region corresponding to this csa is called for rundown. + */ + reg->open = FALSE; + return EXIT_NRM; + } + if (is_statsDB) { /* This is a statsdb. Fix reg->read_only & csa->read_write based on csa->orig_read_write. * This is so it reflects real permissions this process has on the statsdb. */ reg->read_only = !csa->orig_read_write; - csa->read_write = csa->orig_read_write; /* Maintain read_only/read_write in parallel */ + csa->read_write = csa->orig_read_write; /* Maintain read_only/read_write in parallel */ } /* If the process has standalone access, it has udi->grabbed_access_sem set to TRUE at this point. Note that down in a local * variable as the udi->grabbed_access_sem is set to TRUE even for non-standalone access below and hence we can't rely on @@ -240,9 +257,10 @@ int4 gds_rundown(void) assert(!csa->hold_onto_crit || (csa->now_crit && jgbl.onlnrlbk)); /* If we are online rollback, we should already be holding crit and should release it only at the end of this module. This * is usually done by noting down csa->now_crit in a local variable (was_crit) and using it whenever we are about to - * grab_crit. But, there are instances (like mupip_set_journal.c) where we grab_crit but invoke gds_rundown without any - * preceeding rel_crit. Such code relies on the fact that gds_rundown does rel_crit unconditionally (to get locks to a known - * state). So, augment csa->now_crit with jgbl.onlnrlbk to track if we can rel_crit unconditionally or not in gds_rundown. + * grab_crit. But, there are instances (like mupip_set_journal.c) where we grab_crit but invoke "gds_rundown" without any + * preceeding rel_crit. Such code relies on the fact that "gds_rundown" does rel_crit unconditionally (to get locks to a + * known state). So, augment csa->now_crit with jgbl.onlnrlbk to track if we can rel_crit unconditionally or not in + * "gds_rundown". */ was_crit = (csa->now_crit && jgbl.onlnrlbk); /* Cancel any pending flush timer for this region by this process */ @@ -257,8 +275,8 @@ int4 gds_rundown(void) rel_crit(reg); /* get locks to known state */ mutex_cleanup(reg); } - /* The only process that can invoke gds_rundown while holding access control semaphore is RECOVER/ROLLBACK. All the others - * (like MUPIP SET -FILE/MUPIP EXTEND would have invoked db_ipcs_reset() before invoking gds_rundown (from + /* The only process that can invoke "gds_rundown" while holding access control semaphore is RECOVER/ROLLBACK. All the + * others (like MUPIP SET -FILE/MUPIP EXTEND would have invoked db_ipcs_reset() before invoking "gds_rundown" (from * mupip_exit_handler). The only exception is when these processes encounter a terminate signal and they reach * mupip_exit_handler while holding access control semaphore. Assert accordingly. */ @@ -386,7 +404,7 @@ int4 gds_rundown(void) safe_mode = !ok_to_write_pfin || ftok_counter_halted || access_counter_halted || FROZEN_CHILLED(csd); /* At this point we are guaranteed no one else is doing a db_init/rundown as we hold the access control semaphore */ assert(csa->ref_cnt); /* decrement private ref_cnt before shared ref_cnt decrement. */ - csa->ref_cnt--; /* Currently journaling logic in gds_rundown() in VMS relies on this order to detect last writer */ + csa->ref_cnt--; assert(!csa->ref_cnt); /* Note that the below value is normally incremented/decremented under control of the init/rundown semaphore in * "db_init" and "gds_rundown" but if QDBRUNDOWN is turned ON it could be manipulated without the semaphore in @@ -455,8 +473,8 @@ int4 gds_rundown(void) */ if (csa->wbuf_dqd && !is_mm) { /* If we had an orphaned block and were interrupted, mupip_exit_handler will invoke secshr_db_clnup which - * will clear this field and so we should never come to gds_rundown with a non-zero wbuf_dqd. The only - * exception is if we are recover/rollback in which case gds_rundown (from mur_close_files) is invoked + * will clear this field and so we should never come to "gds_rundown" with a non-zero wbuf_dqd. The only + * exception is if we are recover/rollback in which case "gds_rundown" (from mur_close_files) is invoked * BEFORE secshr_db_clnup in mur_close_files. * Note: It is NOT possible for online rollback to reach here with wbuf_dqd being non-zero. This is because * the moment we apply the first PBLK, we stop all interrupts and hence can never be interrupted in @@ -475,14 +493,8 @@ int4 gds_rundown(void) if (!was_crit) rel_crit(reg); } - jpc = csa->jnl; - if (JNL_ENABLED(csd)) - { - jbp = jpc->jnl_buff; - if (IS_GTCM_GNP_SERVER_IMAGE) - originator_prc_vec = NULL; - } else - jbp = NULL; + if (JNL_ENABLED(csd) && IS_GTCM_GNP_SERVER_IMAGE) + originator_prc_vec = NULL; /* If we are the last writing user, then everything must be flushed */ if (we_are_last_writer) { /* Time to flush out all of our buffers */ @@ -525,7 +537,7 @@ int4 gds_rundown(void) assert(0 == memcmp(csd->label, GDS_LABEL, GDS_LABEL_SZ - 1)); } else if (((csa->canceled_flush_timer && (0 > cnl->wcs_timers)) || canceled_dbsync_timer) && !inst_is_frozen) - { /* If we canceled a pending dbsync timer in gds_rundown OR canceled a db flush timer in gds_rundown + { /* If we canceled a pending dbsync timer in "gds_rundown" OR canceled a db flush timer in "gds_rundown" * or sometime in the past (e.g. because we found a JNL_FILE_SWITCHED situation in wcs_stale etc.) * AND there are no other active pending flush timers, it is possible we have unflushed buffers in * the db/jnl so call wcs_flu to flush EPOCH to disk in a timely fashion. @@ -542,6 +554,8 @@ int4 gds_rundown(void) /* Do rundown journal processing after buffer flushes since they require jnl to be open */ if (JNL_ENABLED(csd)) { + jpc = csa->jnl; + jbp = jpc->jnl_buff; if (jbp->fsync_in_prog_latch.u.parts.latch_pid == process_id) { assert(FALSE); @@ -686,9 +700,9 @@ int4 gds_rundown(void) db_ipcs.shmid = INVALID_SHMID; db_ipcs.gt_sem_ctime = 0; db_ipcs.gt_shm_ctime = 0; - db_ipcs.fn_len = reg->dyn.addr->fname_len; - memcpy(db_ipcs.fn, reg->dyn.addr->fname, reg->dyn.addr->fname_len); - db_ipcs.fn[reg->dyn.addr->fname_len] = 0; + db_ipcs.fn_len = seg->fname_len; + memcpy(db_ipcs.fn, seg->fname, seg->fname_len); + db_ipcs.fn[seg->fname_len] = 0; /* request gtmsecshr to flush. read_only cannot flush itself */ WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa); if (!csa->read_only_fs) @@ -713,7 +727,7 @@ int4 gds_rundown(void) * be rundown. This is necessary, however, because we need to cancel all in-progress IOs before the below * CLOSEFILE_RESET(). * - * IOs canceled for subsequent regions will be reissued when we go to gds_rundown() next and the + * IOs canceled for subsequent regions will be reissued when we go to "gds_rundown" next and the * wcs_flu()/wcs_wtstart()/aio_shim_write() happens, which will reopen the kernel context and multiplexing thread * as necessary. */ @@ -781,6 +795,7 @@ int4 gds_rundown(void) GTM_WHITE_BOX_TEST(WBTEST_HOLD_SEM_BYPASS, cnl->wbox_test_seq_num, 0); status = SHMDT((caddr_t)cnl); csa->nl = NULL; /* dereferencing nl after detach is not right, so we set it to NULL so that we can test before dereference*/ + csa->hdr = NULL; /* dereferencing hdr after detach also is not right so set it to NULL */ /* Note that although csa->nl is NULL, we use CSA_ARG(csa) below (not CSA_ARG(NULL)) to be consistent with similar * usages before csa->nl became NULL. The "is_anticipatory_freeze_needed" function (which is in turn called by the * CHECK_IF_FREEZE_ON_ERROR_NEEDED macro) does a check of csa->nl before dereferencing shared memory contents so @@ -791,24 +806,7 @@ int4 gds_rundown(void) LEN_AND_LIT("Error during shmdt"), errno); REMOVE_CSA_FROM_CSADDRSLIST(csa); /* remove "csa" from list of open regions (cs_addrs_list) */ reg->open = FALSE; - if (is_statsDB && !process_exiting) - { /* This is a statsDB, clear a few other pertinent flags in case it gets re-opened */ - reg->statsDB_setup_started = FALSE; - reg->statsDB_setup_completed = FALSE; - csa->hdr = NULL; - csa->db_addrs[0] = NULL; - csa->lock_addrs[0] = NULL; - /* Locate all the gv_targets that map to the region we are abandoning and clear their clues */ - for (currgvt = gv_target_list; currgvt; currgvt = currgvt->next_gvnh) - { - if (csa != currgvt->gd_csa) - continue; - currgvt->clue.end = 0; - if (currgvt != csa->dir_tree) - /* Only clear root for non-directory gv_target */ - currgvt->root = 0; - } - } + assert(!is_statsDB || process_exiting || IS_GTCM_GNP_SERVER_IMAGE); /* If file is still not in good shape, die here and now before we get rid of our storage */ assertpro(0 == csa->wbuf_dqd); ipc_deleted = FALSE; @@ -915,5 +913,58 @@ int4 gds_rundown(void) } } REVERT; + /* Now that "gds_rundown" is done, free up the memory associated with the region as long as the caller is okay with it */ + if (cleanup_udi) + { + if (NULL != csa->dir_tree) + FREE_CSA_DIR_TREE(csa); + if (csa->sgm_info_ptr) + { + si = csa->sgm_info_ptr; + /* It is possible we got interrupted before initializing all fields of "si" + * completely so account for NULL values while freeing/releasing those fields. + */ + assert((si->tp_csa == csa) || (NULL == si->tp_csa)); + if (si->jnl_tail) + { + PROBE_FREEUP_BUDDY_LIST(si->format_buff_list); + PROBE_FREEUP_BUDDY_LIST(si->jnl_list); + } + PROBE_FREEUP_BUDDY_LIST(si->recompute_list); + PROBE_FREEUP_BUDDY_LIST(si->new_buff_list); + PROBE_FREEUP_BUDDY_LIST(si->tlvl_info_list); + PROBE_FREEUP_BUDDY_LIST(si->tlvl_cw_set_list); + PROBE_FREEUP_BUDDY_LIST(si->cw_set_list); + if (NULL != si->blks_in_use) + { + free_hashtab_int4(si->blks_in_use); + free(si->blks_in_use); + si->blks_in_use = NULL; + } + if (si->cr_array_size) + { + assert(NULL != si->cr_array); + if (NULL != si->cr_array) + free(si->cr_array); + } + if (NULL != si->first_tp_hist) + free(si->first_tp_hist); + free(si); + } + if (csa->jnl) + { + assert(&FILE_INFO(csa->jnl->region)->s_addrs == csa); + if (csa->jnl->jnllsb) + { + assert(FALSE); + free(csa->jnl->jnllsb); + } + free(csa->jnl); + } + assert(seg->file_cntl->file_info); + free(seg->file_cntl->file_info); + free(seg->file_cntl); + seg->file_cntl = NULL; + } return EXIT_NRM; } diff --git a/sr_unix/gtm_startup.c b/sr_unix/gtm_startup.c index 72f07e1..050ec2b 100644 --- a/sr_unix/gtm_startup.c +++ b/sr_unix/gtm_startup.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -86,11 +86,10 @@ #include "gtmimagename.h" #include "mprof.h" #include "gt_timers_add_safe_hndlrs.h" -#include "jnl_file_close_timer.h" #include "continue_handler.h" -#include "fake_enospc.h" #include "jobsp.h" /* For gcall.h */ #include "gcall.h" /* For ojchildparms() */ +#include "common_startup_init.h" #ifdef UNICODE_SUPPORTED #include "utfcgr.h" #endif @@ -131,9 +130,6 @@ GBLREF ch_ret_type (*jbxm_dump_ch)(); /* Function pointer to jobexam_dump_ch * GBLREF ch_ret_type (*stpgc_ch)(); /* Function pointer to stp_gcol_ch */ GBLREF enum gtmImageTypes image_type; GBLREF int init_xfer_table(void); -GBLREF void (*jnl_file_close_timer_ptr)(void); -GBLREF void (*fake_enospc_ptr)(void); -GBLREF void (*simple_timeout_timer_ptr)(TID tid, int4 hd_len, boolean_t **timedout); OS_PAGE_SIZE_DECLARE @@ -159,11 +155,9 @@ void gtm_startup(struct startup_vector *svec) IA64_ONLY(init_xfer_table()); get_page_size(); cache_table_relobjs = &cache_table_rebuild; + INIT_FNPTR_GLOBAL_VARIABLES; ht_rhash_ch = &hashtab_rehash_ch; jbxm_dump_ch = &jobexam_dump_ch; - jnl_file_close_timer_ptr = &jnl_file_close_timer; - fake_enospc_ptr = &fake_enospc; - simple_timeout_timer_ptr = &simple_timeout_timer; stpgc_ch = &stp_gcol_ch; rtn_fst_table = rtn_names = (rtn_tabent *)svec->rtn_start; rtn_names_end = rtn_names_top = (rtn_tabent *)svec->rtn_end; diff --git a/sr_unix/gtmrecv_poll_actions.c b/sr_unix/gtmrecv_poll_actions.c index 751f599..72319e4 100644 --- a/sr_unix/gtmrecv_poll_actions.c +++ b/sr_unix/gtmrecv_poll_actions.c @@ -586,7 +586,10 @@ int gtmrecv_poll_actions1(int *pending_data_len, int *buff_unprocessed, unsigned } /* NOTE: update process and receiver each ignore any setting specific to the other (REPLIC_CHANGE_UPD_LOGINTERVAL, * REPLIC_CHANGE_LOGINTERVAL) */ - upd_proc_local->changelog = gtmrecv_local->changelog; /* Pass changelog request to the update process */ + if (REPLIC_CHANGE_LOGINTERVAL == gtmrecv_local->changelog) + upd_proc_local->changelog = 0; + else + upd_proc_local->changelog = gtmrecv_local->changelog; /* Pass changelog request to the update process */ gtmrecv_local->changelog = 0; } if (0 == *pending_data_len && !gtmrecv_logstats && gtmrecv_local->statslog) diff --git a/sr_unix/gvcst_spr_data.c b/sr_unix/gvcst_spr_data.c index baee82e..406c199 100644 --- a/sr_unix/gvcst_spr_data.c +++ b/sr_unix/gvcst_spr_data.c @@ -112,7 +112,7 @@ mint gvcst_spr_data(void) assert(gvnh_reg == TREF(gd_targ_gvnh_reg)); for ( ; map <= end_map; map++) { - OPEN_BASEREG_IF_STATSREG(map); + ASSERT_BASEREG_OPEN_IF_STATSREG(map); /* "gv_srch_map_linear" call above should have ensured that */ reg = map->reg.addr; GET_REG_INDEX(addr, gd_reg_start, reg, reg_index); /* sets "reg_index" */ assert((map != start_map) || (tn_array[reg_index] != gd_targ_tn)); diff --git a/sr_unix/gvcst_spr_kill.c b/sr_unix/gvcst_spr_kill.c index 425f152..1356393 100644 --- a/sr_unix/gvcst_spr_kill.c +++ b/sr_unix/gvcst_spr_kill.c @@ -117,7 +117,7 @@ void gvcst_spr_kill(void) assert(gvnh_reg == TREF(gd_targ_gvnh_reg)); for ( ; map <= end_map; map++) { - OPEN_BASEREG_IF_STATSREG(map); + ASSERT_BASEREG_OPEN_IF_STATSREG(map); /* "gv_srch_map_linear" call above should have ensured that */ reg = map->reg.addr; GET_REG_INDEX(addr, gd_reg_start, reg, reg_index); /* sets "reg_index" */ assert((map != start_map) || (tn_array[reg_index] != gd_targ_tn)); diff --git a/sr_unix/gvcst_spr_order.c b/sr_unix/gvcst_spr_order.c index cf10b17..3fc7333 100644 --- a/sr_unix/gvcst_spr_order.c +++ b/sr_unix/gvcst_spr_order.c @@ -145,7 +145,7 @@ boolean_t gvcst_spr_order(void) * Note down the smallest key found across the scanned regions until we find a key that belongs to the * same map (in the gld) as the currently scanned "map". At which point, the region-spanning order is done. */ - OPEN_BASEREG_IF_STATSREG(map); + ASSERT_BASEREG_OPEN_IF_STATSREG(map); /* "gv_srch_map_linear" call above should have ensured that */ reg = map->reg.addr; GET_REG_INDEX(addr, gd_reg_start, reg, reg_index); /* sets "reg_index" */ assert((map != first_map) || (tn_array[reg_index] != gd_targ_tn)); diff --git a/sr_unix/gvcst_spr_query.c b/sr_unix/gvcst_spr_query.c index 45ebc72..66a4063 100644 --- a/sr_unix/gvcst_spr_query.c +++ b/sr_unix/gvcst_spr_query.c @@ -53,7 +53,7 @@ boolean_t gvcst_spr_query(void) boolean_t est_first_pass; boolean_t found, cumul_found; int reg_index; - gd_binding *start_map, *end_map, *map, *prev_end_map; + gd_binding *start_map, *end_map, *map, *prev_end_map, *stop_map; gd_region *reg, *gd_reg_start; gd_addr *addr; gv_namehead *start_map_gvt; @@ -78,8 +78,15 @@ boolean_t gvcst_spr_query(void) assert(NULL != gvnh_reg); assert(NULL != gvnh_reg->gvspan); /* Now that we know the keyrange maps to more than one region, go through each of them and do the $query - * Since multiple regions are potentially involved, need a TP fence. + * Since multiple regions are potentially involved, need a TP fence. But before that, open any statsDBs pointed + * to by map entries from "start_map" to "stop_map" (as their open will be deferred once we go into TP). Not + * opening them before the TP can produce incomplete results from the $query operation. */ + assert(0 < gvnh_reg->gvspan->end_map_index); + assert(gvnh_reg->gvspan->end_map_index < addr->n_maps); + stop_map = &addr->maps[gvnh_reg->gvspan->end_map_index]; + for (map = start_map; map <= stop_map; map++) + OPEN_BASEREG_IF_STATSREG(map); DEBUG_ONLY(save_dollar_tlevel = dollar_tlevel); if (!dollar_tlevel) { @@ -97,9 +104,7 @@ boolean_t gvcst_spr_query(void) cumul_key_len = 0; DEBUG_ONLY(cumul_key[cumul_key_len] = KEY_DELIMITER;) INCREMENT_GD_TARG_TN(gd_targ_tn); /* takes a copy of incremented "TREF(gd_targ_tn)" into local variable "gd_targ_tn" */ - assert(0 < gvnh_reg->gvspan->end_map_index); - assert(gvnh_reg->gvspan->end_map_index < addr->n_maps); - end_map = &addr->maps[gvnh_reg->gvspan->end_map_index]; + end_map = stop_map; /* Verify that initializations that happened before op_tstart are still unchanged */ assert(addr == TREF(gd_targ_addr)); assert(tn_array == TREF(gd_targ_reg_array)); @@ -109,7 +114,7 @@ boolean_t gvcst_spr_query(void) * Note down the smallest key found across the scanned regions until we find a key that belongs to the * same map (in the gld) as the currently scanned "map". At which point, the region-spanning query is done. */ - OPEN_BASEREG_IF_STATSREG(map); + ASSERT_BASEREG_OPEN_IF_STATSREG(map); /* "OPEN_BASEREG_IF_STATSREG" call above should have ensured that */ reg = map->reg.addr; GET_REG_INDEX(addr, gd_reg_start, reg, reg_index); /* sets "reg_index" */ assert((map != start_map) || (tn_array[reg_index] != gd_targ_tn)); diff --git a/sr_unix/gvcst_spr_queryget.c b/sr_unix/gvcst_spr_queryget.c index f933315..b0f16cb 100644 --- a/sr_unix/gvcst_spr_queryget.c +++ b/sr_unix/gvcst_spr_queryget.c @@ -51,7 +51,7 @@ boolean_t gvcst_spr_queryget(mval *cumul_val) boolean_t spr_tpwrapped; boolean_t est_first_pass; int reg_index; - gd_binding *start_map, *end_map, *map, *prev_end_map; + gd_binding *start_map, *end_map, *map, *prev_end_map, *stop_map; gd_region *reg, *gd_reg_start; gd_addr *addr; gv_namehead *start_map_gvt; @@ -69,10 +69,7 @@ boolean_t gvcst_spr_queryget(mval *cumul_val) SETUP_THREADGBL_ACCESS; start_map = TREF(gd_targ_map); /* set up by op_gvname/op_gvnaked/op_gvextnam done just before invoking op_gvqueryget */ start_map_gvt = gv_target; /* save gv_target corresponding to start_map so we can restore at end */ - /* Now that we know the keyrange maps to more than one region, go through each of them and do the $queryget - * Since multiple regions are potentially involved, need a TP fence. - */ - DEBUG_ONLY(save_dollar_tlevel = dollar_tlevel); + /* Do any initialization that is independent of retries BEFORE the op_tstart */ PUSH_MV_STENT(MVST_MVAL); /* Need to protect value returned by gvcst_queryget from stpgcol */ /* "val" protection might not be necessary specifically for the non-spanning-node gvcst_queryget version. * And most likely not needed for the spanning-node gvcst_queryget version. But it is not easy to be sure and @@ -87,6 +84,17 @@ boolean_t gvcst_spr_queryget(mval *cumul_val) gvnh_reg = TREF(gd_targ_gvnh_reg); assert(NULL != gvnh_reg); assert(NULL != gvnh_reg->gvspan); + /* Now that we know the keyrange maps to more than one region, go through each of them and do the $queryget + * Since multiple regions are potentially involved, need a TP fence. But before that, open any statsDBs pointed + * to by map entries from "start_map" to "stop_map" (as their open will be deferred once we go into TP). Not + * opening them before the TP can produce incomplete results from the $query operation. + */ + assert(0 < gvnh_reg->gvspan->end_map_index); + assert(gvnh_reg->gvspan->end_map_index < addr->n_maps); + stop_map = &addr->maps[gvnh_reg->gvspan->end_map_index]; + for (map = start_map; map <= stop_map; map++) + OPEN_BASEREG_IF_STATSREG(map); + DEBUG_ONLY(save_dollar_tlevel = dollar_tlevel); if (!dollar_tlevel) { spr_tpwrapped = TRUE; @@ -103,9 +111,7 @@ boolean_t gvcst_spr_queryget(mval *cumul_val) cumul_key_len = 0; DEBUG_ONLY(cumul_key[cumul_key_len] = KEY_DELIMITER;) INCREMENT_GD_TARG_TN(gd_targ_tn); /* takes a copy of incremented "TREF(gd_targ_tn)" into local variable "gd_targ_tn" */ - assert(0 < gvnh_reg->gvspan->end_map_index); - assert(gvnh_reg->gvspan->end_map_index < addr->n_maps); - end_map = &addr->maps[gvnh_reg->gvspan->end_map_index]; + end_map = stop_map; /* Verify that initializations that happened before op_tstart are still unchanged */ assert(addr == TREF(gd_targ_addr)); assert(tn_array == TREF(gd_targ_reg_array)); @@ -115,7 +121,7 @@ boolean_t gvcst_spr_queryget(mval *cumul_val) * Note down the smallest key found across the scanned regions until we find a key that belongs to the * same map (in the gld) as the currently scanned "map". At which point, the region-spanning queryget is done. */ - OPEN_BASEREG_IF_STATSREG(map); + ASSERT_BASEREG_OPEN_IF_STATSREG(map); /* "OPEN_BASEREG_IF_STATSREG" call above should have ensured that */ reg = map->reg.addr; GET_REG_INDEX(addr, gd_reg_start, reg, reg_index); /* sets "reg_index" */ assert((map != start_map) || (tn_array[reg_index] != gd_targ_tn)); diff --git a/sr_unix/gvcst_spr_zprevious.c b/sr_unix/gvcst_spr_zprevious.c index 7b30f83..17fcdd5 100644 --- a/sr_unix/gvcst_spr_zprevious.c +++ b/sr_unix/gvcst_spr_zprevious.c @@ -148,7 +148,9 @@ boolean_t gvcst_spr_zprevious(void) * Note down the largest key found across the scanned regions until we find a key that belongs to the * same map (in the gld) as the currently scanned "map". At which point, the region-spanning zprevious is done. */ - OPEN_BASEREG_IF_STATSREG(map); + ASSERT_BASEREG_OPEN_IF_STATSREG(map); /* "gv_srch_map_linear" and "gv_srch_map_linear_backward" call above + * should have ensured that. + */ reg = map->reg.addr; GET_REG_INDEX(addr, gd_reg_start, reg, reg_index); /* sets "reg_index" */ assert((map != first_map) || (tn_array[reg_index] != gd_targ_tn)); diff --git a/sr_unix/jnl_file_open.c b/sr_unix/jnl_file_open.c index afc3aef..096a2ab 100644 --- a/sr_unix/jnl_file_open.c +++ b/sr_unix/jnl_file_open.c @@ -65,7 +65,7 @@ error_def(ERR_JNLMOVED); error_def(ERR_JNLOPNERR); error_def(ERR_JNLRDERR); -uint4 jnl_file_open(gd_region *reg, bool init, void *dummy) /* third argument for compatibility with VMS version */ +uint4 jnl_file_open(gd_region *reg, boolean_t init) { sgmnt_addrs *csa; sgmnt_data_ptr_t csd; @@ -98,14 +98,14 @@ uint4 jnl_file_open(gd_region *reg, bool init, void *dummy) /* third argument fo assert(256 == JNL_NAME_SIZE); nameptr[csd->jnl_file_len] = 0; cre_jnl_file_intrpt_rename(csa); - /* although jnl_file_close() would have reset jnl_file.u.inode and device to 0 and incremented cycle, it + /* although "jnl_file_close" would have reset jnl_file.u.inode and device to 0 and incremented cycle, it * might have got shot in the middle of executing those instructions. we redo it here just to be safe. */ csa->nl->jnl_file.u.inode = 0; csa->nl->jnl_file.u.device = 0; jb->cycle++; /* Source Server only reads journal files so must never try to create and switch to a new journal file. */ - switch_and_retry = (!is_src_server) ? TRUE : FALSE; + switch_and_retry = (!is_src_server); for (;;) { /* D9E04-002445 MUPIP RECOVER always open journal file without O_SYNC, ignoring jnl_sync_io */ @@ -142,11 +142,11 @@ uint4 jnl_file_open(gd_region *reg, bool init, void *dummy) /* third argument fo } else sts = jnl_file_open_common(reg, (off_jnl_t) stat_buf.st_size, buff); } - DEBUG_ONLY( - /* Will fail if Source Server would need to switch journal files. */ - assert((gtm_white_box_test_case_enabled && (WBTEST_JNL_SWITCH_EXPECTED == - gtm_white_box_test_case_number)) || (0 == sts) || switch_and_retry); - ) +# ifdef DEBUG + /* Will fail if Source Server would need to switch journal files. */ + assert((gtm_white_box_test_case_enabled && (WBTEST_JNL_SWITCH_EXPECTED == gtm_white_box_test_case_number)) + || (0 == sts) || (!is_src_server)); +# endif if ((0 != sts) && switch_and_retry) { /* Switch to a new journal file and retry, but only once */ sts = jnl_file_open_switch(reg, sts); diff --git a/sr_unix/jnlsp.h b/sr_unix/jnlsp.h index 02079a1..4bffc68 100644 --- a/sr_unix/jnlsp.h +++ b/sr_unix/jnlsp.h @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -65,6 +65,6 @@ typedef unix_file_info fi_type; #define DEF_DB_EXT_NAME "dat" #define DEF_JNL_EXT_NAME ".mjl" -uint4 jnl_file_open(gd_region *reg, bool init, void *dummy); +uint4 jnl_file_open(gd_region *reg, boolean_t init); #endif /* JNLSP_H_INCLUDED */ diff --git a/sr_unix/mu_cre_file.c b/sr_unix/mu_cre_file.c index b7fab3f..06479ed 100644 --- a/sr_unix/mu_cre_file.c +++ b/sr_unix/mu_cre_file.c @@ -359,7 +359,6 @@ unsigned char mu_cre_file(void) { STATSDBREG_TO_BASEDBREG(gv_cur_region, baseDBreg); assert(baseDBreg->open); - assert(!baseDBreg->was_open); baseDBcsa = &FILE_INFO(baseDBreg)->s_addrs; STAT_FILE((char *)baseDBcsa->nl->fname, &stat_buf, retcode); if (0 > retcode) diff --git a/sr_unix/mu_rndwn_file.c b/sr_unix/mu_rndwn_file.c index a36ff54..e7dc5a1 100644 --- a/sr_unix/mu_rndwn_file.c +++ b/sr_unix/mu_rndwn_file.c @@ -1400,6 +1400,7 @@ boolean_t mu_rndwn_file(gd_region *reg, boolean_t standalone) return FALSE; } csa->nl = cnl = NULL; + csa->hdr = NULL; /* Remove the shared memory only if it is a GT.M created one. */ if (is_gtm_shm) { diff --git a/sr_unix/mupip.c b/sr_unix/mupip.c index 1c4ee2e..b680d5a 100644 --- a/sr_unix/mupip.c +++ b/sr_unix/mupip.c @@ -100,6 +100,7 @@ int main (int argc, char **argv) licensed = TRUE; in_backup = FALSE; op_open_ptr = mu_op_open; + INIT_FNPTR_GLOBAL_VARIABLES; mu_get_term_characterstics(); gtm_chk_dist(argv[0]); cli_lex_setup(argc,argv); diff --git a/sr_unix/mupip_cvtgbl.c b/sr_unix/mupip_cvtgbl.c index 1f68437..04d4608 100644 --- a/sr_unix/mupip_cvtgbl.c +++ b/sr_unix/mupip_cvtgbl.c @@ -83,14 +83,17 @@ void mupip_cvtgbl(void) fn_len = SIZEOF(fn); if (cli_present("STDIN")) { + /* Check if both file name and -STDIN specified. */ + if (cli_get_str("FILE", fn, &fn_len)) + { + util_out_print("STDIN and FILE (!AD) cannot be specified at the same time", TRUE, fn_len, fn); + mupip_exit(ERR_MUPCLIERR); + } /* User wants to load from standard input */ assert(SIZEOF(fn) > sys_input.len); memcpy(fn, sys_input.addr, sys_input.len); fn_len = sys_input.len; assert(-1 != fcntl(fileno(stdin), F_GETFD)); - /* Check if both file name and -STDIN specified. */ - if (cli_get_str("FILE", fn, &fn_len)) - mupip_exit(ERR_MUPCLIERR); } else if (!cli_get_str("FILE", fn, &fn_len)) /* User wants to read from a file. */ mupip_exit(ERR_MUPCLIERR); /* Neither -STDIN nor file name specified. */ file_input_init(fn, fn_len, IOP_EOL); diff --git a/sr_unix/mupip_set_file.c b/sr_unix/mupip_set_file.c index 54949ce..167cde8 100644 --- a/sr_unix/mupip_set_file.c +++ b/sr_unix/mupip_set_file.c @@ -642,7 +642,7 @@ int4 mupip_set_file(int db_fn_len, char *db_fn) { gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DBRDONLY, 2, DB_LEN_STR(gv_cur_region)); exit_stat |= EXIT_ERR; - gds_rundown(); + gds_rundown(CLEANUP_UDI_TRUE); mu_gv_cur_reg_free(); continue; } @@ -657,7 +657,7 @@ int4 mupip_set_file(int db_fn_len, char *db_fn) gtm_putmsg_csa(CSA_ARG(cs_addrs) VARLSTCNT(4) ERR_OFRZACTIVE, 2, DB_LEN_STR(gv_cur_region)); exit_stat |= EXIT_WRN; - exit_stat |= gds_rundown(); + exit_stat |= gds_rundown(CLEANUP_UDI_TRUE); mu_gv_cur_reg_free(); continue; } @@ -844,7 +844,7 @@ int4 mupip_set_file(int db_fn_len, char *db_fn) } else { rel_crit(gv_cur_region); - exit_stat |= gds_rundown(); + exit_stat |= gds_rundown(CLEANUP_UDI_TRUE); } mu_gv_cur_reg_free(); } diff --git a/sr_unix/mur_cre_file_extfmt.c b/sr_unix/mur_cre_file_extfmt.c index 4f40249..13d68f8 100644 --- a/sr_unix/mur_cre_file_extfmt.c +++ b/sr_unix/mur_cre_file_extfmt.c @@ -223,6 +223,7 @@ int4 mur_cre_file_extfmt(jnl_ctl_list *jctl, int recstat) tmplen += SPRINTF(ptr, "%d", rctl - &mur_ctl[0]); file_info->fn_len = tmplen; } + rename_fn_len = ARRAYSIZE(rename_fn); if (RENAME_FAILED == rename_file_if_exists(file_info->fn, file_info->fn_len, rename_fn, &rename_fn_len, &status)) return status; op_pars.mvtype = MV_STR; diff --git a/sr_unix/op_fnzpeek.c b/sr_unix/op_fnzpeek.c index cb96f17..d641306 100644 --- a/sr_unix/op_fnzpeek.c +++ b/sr_unix/op_fnzpeek.c @@ -496,7 +496,6 @@ void op_fnzpeek(mval *structid, int offset, int len, mval *format, mval *ret) */ assert(arglen); pass = (ISLOWER_ASCII(argptr[0]) ? PASS1 : PASS2); - r_ptr = NULL; for ( ; ; ) { if (PASS1 != pass) @@ -508,22 +507,8 @@ void op_fnzpeek(mval *structid, int offset, int len, mval *format, mval *ret) if ((arglen == TREF(zpeek_regname_len)) && (0 == memcmp(argptr, TADR(zpeek_regname), arglen))) { /* Fast path - no lookup necessary */ r_ptr = TREF(zpeek_reg_ptr); - if (!r_ptr->open) - { /* Region was open when we cached it as part of the previous $zpeek but it - * is no longer open. Only possibility is a VIEW "NOSTATSHARE" was done in - * between and that this is a statsdb region. Assert accordingly. - */ - assert(IS_STATSDB_REGNAME(r_ptr)); - assert(PASS1 == pass); - TREF(zpeek_regname_len) = 0; - r_ptr = NULL; - pass = PASS1; - continue; - } break; } - if (NULL != r_ptr) - break; /* Region now defined - make sure it is open */ if (!gd_header) /* If gd_header is NULL, open gbldir */ gvinit(); @@ -552,14 +537,22 @@ void op_fnzpeek(mval *structid, int offset, int len, mval *format, mval *ret) pass = PASS2; continue; } - if (!r_ptr->open) - gv_init_reg(r_ptr); - /* r_ptr now points to (open) region */ - assert(r_ptr->open); /* Make sure truly open */ /* Cache new region access for followup references */ memcpy(TADR(zpeek_regname), argptr, arglen); TREF(zpeek_regname_len) = arglen; TREF(zpeek_reg_ptr) = r_ptr; + break; + } + /* PO_GDRREG opcode examines only the region's fields so does not need the region to be open. + * All the rest need it to be open. If there are any errors in the open (e.g. statsdb specified + * and gtm_statsdir env var is too long etc.) then handle it by issuing an error. + */ + if ((PO_GDRREG != mnemonic_opcode) && !r_ptr->open) + { + gv_init_reg(r_ptr); + if (!r_ptr->open) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, + RTS_ERROR_LITERAL("mnemonic argument (region name could not be opened)")); } break; case PO_GLFREPL: /* These types have an array index argument */ diff --git a/sr_unix/repl_inst_create.c b/sr_unix/repl_inst_create.c index e93304c..88cdcd1 100644 --- a/sr_unix/repl_inst_create.c +++ b/sr_unix/repl_inst_create.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2006-2016 Fidelity National Information * + * Copyright (c) 2006-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -72,7 +72,7 @@ void repl_inst_create(void) unsigned int inst_fn_len; unsigned short inst_name_len; int rename_fn_len; - char rename_fn[MAX_FN_LEN]; + char rename_fn[MAX_FN_LEN + 1]; char inst_fn[MAX_FN_LEN + 1], inst_name[MAX_FN_LEN + 1]; char machine_name[MAX_MCNAMELEN], buff_unaligned[REPL_INST_HDR_SIZE + GTMSRC_LCL_SIZE + 8]; char *buff_8byte_aligned; @@ -137,6 +137,7 @@ void repl_inst_create(void) assert(FALSE); } JNL_SHORT_TIME(now); + rename_fn_len = ARRAYSIZE(rename_fn); if (SS_NORMAL != (status = prepare_unique_name((char *)inst_fn, inst_fn_len, "", "", rename_fn, &rename_fn_len, now, &status2))) { diff --git a/sr_unix/repl_instance.c b/sr_unix/repl_instance.c index 3d64496..47b2ccb 100644 --- a/sr_unix/repl_instance.c +++ b/sr_unix/repl_instance.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -1322,13 +1322,13 @@ int4 repl_inst_reset_zqgblmod_seqno_and_tn(void) for (reg = gd_header->regions, reg_top = reg + gd_header->n_regions; reg < reg_top; reg++) { /* Rundown all databases that we opened as we dont need them anymore. This is not done in the previous * loop as it has to wait until the ftok semaphore of the instance file has been released as otherwise - * an assert in gds_rundown will fail as it tries to get the ftok semaphore of the database while holding + * an assert in "gds_rundown" will fail as it tries to get the ftok semaphore of the database while holding * another ftok semaphore already. */ assert(reg->open); TP_CHANGE_REG(reg); assert(!cs_addrs->now_crit); - UNIX_ONLY(ret |=) gds_rundown(); + ret |= gds_rundown(CLEANUP_UDI_TRUE); } assert(!repl_csa->now_crit); return ret; diff --git a/sr_unix/set_jnl_file_close.c b/sr_unix/set_jnl_file_close.c index bc840d7..fadb0a9 100644 --- a/sr_unix/set_jnl_file_close.c +++ b/sr_unix/set_jnl_file_close.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2016 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -26,7 +26,7 @@ GBLREF gd_region *gv_cur_region; GBLREF sgmnt_addrs *cs_addrs; -uint4 set_jnl_file_close(set_jnl_file_close_opcode_t set_jnl_file_close_opcode) +uint4 set_jnl_file_close(void) { uint4 jnl_status = 0; diff --git a/sr_unix/trigger_upgrade.c b/sr_unix/trigger_upgrade.c index 96bdc20..1c99c97 100644 --- a/sr_unix/trigger_upgrade.c +++ b/sr_unix/trigger_upgrade.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2014-2015 Fidelity National Information * + * Copyright (c) 2014-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -62,7 +62,8 @@ error_def(ERR_TRIGUPBADLABEL); #define LITERAL_TRIGJNLREC "; ^#t physical upgrade from #LABEL 2,3 to #LABEL 4 (no logical change)" #define LITERAL_TRIGJNLREC_LEN STR_LIT_LEN(LITERAL_TRIGJNLREC) -LITDEF mval literal_trigjnlrec = DEFINE_MVAL_LITERAL(MV_STR | MV_NUM_APPROX, 0, 0, LITERAL_TRIGJNLREC_LEN, (char *)LITERAL_TRIGJNLREC, 0, 0); /* BYPASSOK */ +LITDEF mval literal_trigjnlrec = DEFINE_MVAL_LITERAL(MV_STR | MV_NUM_APPROX, 0, 0, LITERAL_TRIGJNLREC_LEN, + (char *)LITERAL_TRIGJNLREC, 0, 0); LITREF mval literal_batch; LITREF mval literal_curlabel; @@ -559,7 +560,7 @@ void trigger_upgrade(gd_region *reg) /* Switch to new journal file and cut previous link if we did ^#t upgrade on a journaled region */ if (do_upgrade && JNL_WRITE_LOGICAL_RECS(csa)) { - sts = set_jnl_file_close(0); + sts = set_jnl_file_close(); assert(SS_NORMAL == sts); /* because we should have done jnl_ensure_open already * in which case set_jnl_file_close has no way of erroring out. */ diff --git a/sr_unix/ygblstat.mpt b/sr_unix/ygblstat.mpt index 747d4d0..980a3f8 100644 --- a/sr_unix/ygblstat.mpt +++ b/sr_unix/ygblstat.mpt @@ -50,7 +50,6 @@ help ; Usage: mumps -run %YGBLSTAT [--help] [--pid pidlist] [--reg reglist] [ ; Note: this program uses external calls, which must be installed. ; Main Program - ; set x=$get(^x) ; workaround till bug in code under development is fixed if $stack do PROMPTGO quit ; if invoked from another program, prompt for inputs, do work, and exit use $principal:(ctrap=$char(3):nocenable:exception="halt") ; terminate on Ctrl-C if invoked from shell set $etrap="set $etrap=""use $principal write $zstatus,! zhalt 1""" diff --git a/sr_unix_gnp/gtcm_open_cmerrlog.c b/sr_unix_gnp/gtcm_open_cmerrlog.c index 388bce1..b8dc11f 100644 --- a/sr_unix_gnp/gtcm_open_cmerrlog.c +++ b/sr_unix_gnp/gtcm_open_cmerrlog.c @@ -1,6 +1,6 @@ /**************************************************************** * * - * Copyright (c) 2001-2015 Fidelity National Information * + * Copyright (c) 2001-2017 Fidelity National Information * * Services, Inc. and/or its subsidiaries. All rights reserved. * * * * This source code contains the intellectual property * @@ -65,6 +65,7 @@ void gtcm_open_cmerrlog(void) if (rval == SS_NORMAL || rval == SS_NOLOGNAM) { lfn_path[lfn2.len] = 0; + new_len = ARRAYSIZE(new_lfn_path); rename_file_if_exists(lfn_path, lfn2.len, new_lfn_path, &new_len, &ustatus); #ifdef __MVS__ if (-1 == gtm_zos_create_tagged_file(lfn_path, TAG_EBCDIC)) diff --git a/sr_x86_64/GDEINITSZ.m b/sr_x86_64/GDEINITSZ.m index 93e7a4b..109130c 100644 --- a/sr_x86_64/GDEINITSZ.m +++ b/sr_x86_64/GDEINITSZ.m @@ -2,14 +2,14 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; -; Generated by scantypedefs.m at 15:28:49 on 2017-03-08 +; Generated by scantypedefs.m at 10:50:05 on 2017-03-30 ; Build done with GT.M version: GT.M V6.3-000A Linux x86_64 ; ; Environment variables during run: ; $gtm_dist: /usr/library/V63000A/dbg -; $gtm_exe: /usr/library/V63001/dbg -; $gtm_src: /usr/library/V63001/src -; $gtm_inc: /usr/library/V63001/inc +; $gtm_exe: /usr/library/V63001A/dbg +; $gtm_src: /usr/library/V63001A/src +; $gtm_inc: /usr/library/V63001A/inc ; ; Note this file should not be manually invoked ; diff --git a/sr_x86_64/GTMDefinedTypesInitDebug.m b/sr_x86_64/GTMDefinedTypesInitDebug.m index 984f9ab..36ae27b 100644 --- a/sr_x86_64/GTMDefinedTypesInitDebug.m +++ b/sr_x86_64/GTMDefinedTypesInitDebug.m @@ -11,14 +11,14 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; -; Generated by scantypedefs.m at 15:28:49 on 2017-03-08 +; Generated by scantypedefs.m at 10:50:05 on 2017-03-30 ; Build done with GT.M version: GT.M V6.3-000A Linux x86_64 ; ; Environment variables during run: ; $gtm_dist: /usr/library/V63000A/dbg -; $gtm_exe: /usr/library/V63001/dbg -; $gtm_src: /usr/library/V63001/src -; $gtm_inc: /usr/library/V63001/inc +; $gtm_exe: /usr/library/V63001A/dbg +; $gtm_src: /usr/library/V63001A/src +; $gtm_inc: /usr/library/V63001A/inc ; ; Note this file should not be manually invoked ; @@ -10460,7 +10460,7 @@ Init Set gtmtypfldindx("jnl_fence_control","strm_seqno")=4 ; Set gtmtypes("jnl_file_header")="struct" - Set gtmtypes("jnl_file_header",0)=66 + Set gtmtypes("jnl_file_header",0)=67 Set gtmtypes("jnl_file_header","len")=2048 Set gtmtypes("jnl_file_header",1,"name")="jnl_file_header.label" Set gtmtypes("jnl_file_header",1,"off")=0 @@ -10789,11 +10789,16 @@ Init Set gtmtypes("jnl_file_header",65,"len")=4 Set gtmtypes("jnl_file_header",65,"type")="boolean_t" Set gtmtypfldindx("jnl_file_header","last_eof_written")=65 - Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.is_not_latest_jnl" Set gtmtypes("jnl_file_header",66,"off")=1612 - Set gtmtypes("jnl_file_header",66,"len")=436 - Set gtmtypes("jnl_file_header",66,"type")="char" - Set gtmtypfldindx("jnl_file_header","filler")=66 + Set gtmtypes("jnl_file_header",66,"len")=4 + Set gtmtypes("jnl_file_header",66,"type")="boolean_t" + Set gtmtypfldindx("jnl_file_header","is_not_latest_jnl")=66 + Set gtmtypes("jnl_file_header",67,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",67,"off")=1616 + Set gtmtypes("jnl_file_header",67,"len")=432 + Set gtmtypes("jnl_file_header",67,"type")="char" + Set gtmtypfldindx("jnl_file_header","filler")=67 ; Set gtmtypes("jnl_format_buffer")="struct" Set gtmtypes("jnl_format_buffer",0)=14 @@ -26463,8 +26468,8 @@ Init Set gtmtypfldindx("sgmm_addrs","filler")=1 ; Set gtmtypes("sgmnt_addrs")="struct" - Set gtmtypes("sgmnt_addrs",0)=151 - Set gtmtypes("sgmnt_addrs","len")=984 + Set gtmtypes("sgmnt_addrs",0)=152 + Set gtmtypes("sgmnt_addrs","len")=992 Set gtmtypes("sgmnt_addrs",1,"name")="sgmnt_addrs.hdr" Set gtmtypes("sgmnt_addrs",1,"off")=0 Set gtmtypes("sgmnt_addrs",1,"len")=8 @@ -27222,6 +27227,11 @@ Init Set gtmtypes("sgmnt_addrs",151,"len")=4 Set gtmtypes("sgmnt_addrs",151,"type")="int" Set gtmtypfldindx("sgmnt_addrs","tp_hint")=151 + Set gtmtypes("sgmnt_addrs",152,"name")="sgmnt_addrs.statsDB_setup_completed" + Set gtmtypes("sgmnt_addrs",152,"off")=984 + Set gtmtypes("sgmnt_addrs",152,"len")=4 + Set gtmtypes("sgmnt_addrs",152,"type")="boolean_t" + Set gtmtypfldindx("sgmnt_addrs","statsDB_setup_completed")=152 ; Set gtmtypes("sgmnt_data")="struct" Set gtmtypes("sgmnt_data",0)=586 @@ -40405,11 +40415,11 @@ Init Set gtmtypfldindx("unique_file_id","file_id")=5 ; Set gtmtypes("unix_db_info")="struct" - Set gtmtypes("unix_db_info",0)=167 - Set gtmtypes("unix_db_info","len")=1088 + Set gtmtypes("unix_db_info",0)=168 + Set gtmtypes("unix_db_info","len")=1096 Set gtmtypes("unix_db_info",1,"name")="unix_db_info.s_addrs" Set gtmtypes("unix_db_info",1,"off")=0 - Set gtmtypes("unix_db_info",1,"len")=984 + Set gtmtypes("unix_db_info",1,"len")=992 Set gtmtypes("unix_db_info",1,"type")="sgmnt_addrs" Set gtmtypfldindx("unix_db_info","s_addrs")=1 Set gtmtypes("unix_db_info",2,"name")="unix_db_info.s_addrs.hdr" @@ -41169,81 +41179,86 @@ Init Set gtmtypes("unix_db_info",152,"len")=4 Set gtmtypes("unix_db_info",152,"type")="int" Set gtmtypfldindx("unix_db_info","s_addrs.tp_hint")=152 - Set gtmtypes("unix_db_info",153,"name")="unix_db_info.fn" + Set gtmtypes("unix_db_info",153,"name")="unix_db_info.s_addrs.statsDB_setup_completed" Set gtmtypes("unix_db_info",153,"off")=984 - Set gtmtypes("unix_db_info",153,"len")=8 - Set gtmtypes("unix_db_info",153,"type")="addr" - Set gtmtypfldindx("unix_db_info","fn")=153 - Set gtmtypes("unix_db_info",154,"name")="unix_db_info.fd" + Set gtmtypes("unix_db_info",153,"len")=4 + Set gtmtypes("unix_db_info",153,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","s_addrs.statsDB_setup_completed")=153 + Set gtmtypes("unix_db_info",154,"name")="unix_db_info.fn" Set gtmtypes("unix_db_info",154,"off")=992 - Set gtmtypes("unix_db_info",154,"len")=4 - Set gtmtypes("unix_db_info",154,"type")="int" - Set gtmtypfldindx("unix_db_info","fd")=154 - Set gtmtypes("unix_db_info",155,"name")="unix_db_info.owning_gd" + Set gtmtypes("unix_db_info",154,"len")=8 + Set gtmtypes("unix_db_info",154,"type")="addr" + Set gtmtypfldindx("unix_db_info","fn")=154 + Set gtmtypes("unix_db_info",155,"name")="unix_db_info.fd" Set gtmtypes("unix_db_info",155,"off")=1000 - Set gtmtypes("unix_db_info",155,"len")=8 - Set gtmtypes("unix_db_info",155,"type")="addr" - Set gtmtypfldindx("unix_db_info","owning_gd")=155 - Set gtmtypes("unix_db_info",156,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",155,"len")=4 + Set gtmtypes("unix_db_info",155,"type")="int" + Set gtmtypfldindx("unix_db_info","fd")=155 + Set gtmtypes("unix_db_info",156,"name")="unix_db_info.owning_gd" Set gtmtypes("unix_db_info",156,"off")=1008 - Set gtmtypes("unix_db_info",156,"len")=24 - Set gtmtypes("unix_db_info",156,"type")="unix_file_id" - Set gtmtypfldindx("unix_db_info","fileid")=156 - Set gtmtypes("unix_db_info",157,"name")="unix_db_info.fileid.inode" - Set gtmtypes("unix_db_info",157,"off")=1008 - Set gtmtypes("unix_db_info",157,"len")=8 - Set gtmtypes("unix_db_info",157,"type")="ino_t" - Set gtmtypfldindx("unix_db_info","fileid.inode")=157 - Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid.device" + Set gtmtypes("unix_db_info",156,"len")=8 + Set gtmtypes("unix_db_info",156,"type")="addr" + Set gtmtypfldindx("unix_db_info","owning_gd")=156 + Set gtmtypes("unix_db_info",157,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",157,"off")=1016 + Set gtmtypes("unix_db_info",157,"len")=24 + Set gtmtypes("unix_db_info",157,"type")="unix_file_id" + Set gtmtypfldindx("unix_db_info","fileid")=157 + Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid.inode" Set gtmtypes("unix_db_info",158,"off")=1016 Set gtmtypes("unix_db_info",158,"len")=8 - Set gtmtypes("unix_db_info",158,"type")="dev_t" - Set gtmtypfldindx("unix_db_info","fileid.device")=158 - Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.st_gen" + Set gtmtypes("unix_db_info",158,"type")="ino_t" + Set gtmtypfldindx("unix_db_info","fileid.inode")=158 + Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.device" Set gtmtypes("unix_db_info",159,"off")=1024 - Set gtmtypes("unix_db_info",159,"len")=4 - Set gtmtypes("unix_db_info",159,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","fileid.st_gen")=159 - Set gtmtypes("unix_db_info",160,"name")="unix_db_info.semid" + Set gtmtypes("unix_db_info",159,"len")=8 + Set gtmtypes("unix_db_info",159,"type")="dev_t" + Set gtmtypfldindx("unix_db_info","fileid.device")=159 + Set gtmtypes("unix_db_info",160,"name")="unix_db_info.fileid.st_gen" Set gtmtypes("unix_db_info",160,"off")=1032 Set gtmtypes("unix_db_info",160,"len")=4 - Set gtmtypes("unix_db_info",160,"type")="int" - Set gtmtypfldindx("unix_db_info","semid")=160 - Set gtmtypes("unix_db_info",161,"name")="unix_db_info.gt_sem_ctime" + Set gtmtypes("unix_db_info",160,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","fileid.st_gen")=160 + Set gtmtypes("unix_db_info",161,"name")="unix_db_info.semid" Set gtmtypes("unix_db_info",161,"off")=1040 - Set gtmtypes("unix_db_info",161,"len")=8 - Set gtmtypes("unix_db_info",161,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=161 - Set gtmtypes("unix_db_info",162,"name")="unix_db_info.shmid" + Set gtmtypes("unix_db_info",161,"len")=4 + Set gtmtypes("unix_db_info",161,"type")="int" + Set gtmtypfldindx("unix_db_info","semid")=161 + Set gtmtypes("unix_db_info",162,"name")="unix_db_info.gt_sem_ctime" Set gtmtypes("unix_db_info",162,"off")=1048 - Set gtmtypes("unix_db_info",162,"len")=4 - Set gtmtypes("unix_db_info",162,"type")="int" - Set gtmtypfldindx("unix_db_info","shmid")=162 - Set gtmtypes("unix_db_info",163,"name")="unix_db_info.gt_shm_ctime" + Set gtmtypes("unix_db_info",162,"len")=8 + Set gtmtypes("unix_db_info",162,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=162 + Set gtmtypes("unix_db_info",163,"name")="unix_db_info.shmid" Set gtmtypes("unix_db_info",163,"off")=1056 - Set gtmtypes("unix_db_info",163,"len")=8 - Set gtmtypes("unix_db_info",163,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=163 - Set gtmtypes("unix_db_info",164,"name")="unix_db_info.ftok_semid" + Set gtmtypes("unix_db_info",163,"len")=4 + Set gtmtypes("unix_db_info",163,"type")="int" + Set gtmtypfldindx("unix_db_info","shmid")=163 + Set gtmtypes("unix_db_info",164,"name")="unix_db_info.gt_shm_ctime" Set gtmtypes("unix_db_info",164,"off")=1064 - Set gtmtypes("unix_db_info",164,"len")=4 - Set gtmtypes("unix_db_info",164,"type")="int" - Set gtmtypfldindx("unix_db_info","ftok_semid")=164 - Set gtmtypes("unix_db_info",165,"name")="unix_db_info.key" - Set gtmtypes("unix_db_info",165,"off")=1068 + Set gtmtypes("unix_db_info",164,"len")=8 + Set gtmtypes("unix_db_info",164,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=164 + Set gtmtypes("unix_db_info",165,"name")="unix_db_info.ftok_semid" + Set gtmtypes("unix_db_info",165,"off")=1072 Set gtmtypes("unix_db_info",165,"len")=4 - Set gtmtypes("unix_db_info",165,"type")="key_t" - Set gtmtypfldindx("unix_db_info","key")=165 - Set gtmtypes("unix_db_info",166,"name")="unix_db_info.raw" - Set gtmtypes("unix_db_info",166,"off")=1072 + Set gtmtypes("unix_db_info",165,"type")="int" + Set gtmtypfldindx("unix_db_info","ftok_semid")=165 + Set gtmtypes("unix_db_info",166,"name")="unix_db_info.key" + Set gtmtypes("unix_db_info",166,"off")=1076 Set gtmtypes("unix_db_info",166,"len")=4 - Set gtmtypes("unix_db_info",166,"type")="boolean_t" - Set gtmtypfldindx("unix_db_info","raw")=166 - Set gtmtypes("unix_db_info",167,"name")="unix_db_info.db_fs_block_size" - Set gtmtypes("unix_db_info",167,"off")=1076 + Set gtmtypes("unix_db_info",166,"type")="key_t" + Set gtmtypfldindx("unix_db_info","key")=166 + Set gtmtypes("unix_db_info",167,"name")="unix_db_info.raw" + Set gtmtypes("unix_db_info",167,"off")=1080 Set gtmtypes("unix_db_info",167,"len")=4 - Set gtmtypes("unix_db_info",167,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","db_fs_block_size")=167 + Set gtmtypes("unix_db_info",167,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","raw")=167 + Set gtmtypes("unix_db_info",168,"name")="unix_db_info.db_fs_block_size" + Set gtmtypes("unix_db_info",168,"off")=1084 + Set gtmtypes("unix_db_info",168,"len")=4 + Set gtmtypes("unix_db_info",168,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","db_fs_block_size")=168 ; Set gtmtypes("unix_file_id")="struct" Set gtmtypes("unix_file_id",0)=3 diff --git a/sr_x86_64/GTMDefinedTypesInitRelease.m b/sr_x86_64/GTMDefinedTypesInitRelease.m index 23fefcb..8a87a51 100644 --- a/sr_x86_64/GTMDefinedTypesInitRelease.m +++ b/sr_x86_64/GTMDefinedTypesInitRelease.m @@ -11,14 +11,14 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; -; Generated by scantypedefs.m at 15:25:42 on 2017-03-08 +; Generated by scantypedefs.m at 10:47:25 on 2017-03-30 ; Build done with GT.M version: GT.M V6.3-000A Linux x86_64 ; ; Environment variables during run: ; $gtm_dist: /usr/library/V63000A/pro -; $gtm_exe: /usr/library/V63001/pro -; $gtm_src: /usr/library/V63001/src -; $gtm_inc: /usr/library/V63001/inc +; $gtm_exe: /usr/library/V63001A/pro +; $gtm_src: /usr/library/V63001A/src +; $gtm_inc: /usr/library/V63001A/inc ; ; Note this file should not be manually invoked ; @@ -10440,7 +10440,7 @@ Init Set gtmtypfldindx("jnl_fence_control","strm_seqno")=4 ; Set gtmtypes("jnl_file_header")="struct" - Set gtmtypes("jnl_file_header",0)=66 + Set gtmtypes("jnl_file_header",0)=67 Set gtmtypes("jnl_file_header","len")=2048 Set gtmtypes("jnl_file_header",1,"name")="jnl_file_header.label" Set gtmtypes("jnl_file_header",1,"off")=0 @@ -10769,11 +10769,16 @@ Init Set gtmtypes("jnl_file_header",65,"len")=4 Set gtmtypes("jnl_file_header",65,"type")="boolean_t" Set gtmtypfldindx("jnl_file_header","last_eof_written")=65 - Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",66,"name")="jnl_file_header.is_not_latest_jnl" Set gtmtypes("jnl_file_header",66,"off")=1612 - Set gtmtypes("jnl_file_header",66,"len")=436 - Set gtmtypes("jnl_file_header",66,"type")="char" - Set gtmtypfldindx("jnl_file_header","filler")=66 + Set gtmtypes("jnl_file_header",66,"len")=4 + Set gtmtypes("jnl_file_header",66,"type")="boolean_t" + Set gtmtypfldindx("jnl_file_header","is_not_latest_jnl")=66 + Set gtmtypes("jnl_file_header",67,"name")="jnl_file_header.filler" + Set gtmtypes("jnl_file_header",67,"off")=1616 + Set gtmtypes("jnl_file_header",67,"len")=432 + Set gtmtypes("jnl_file_header",67,"type")="char" + Set gtmtypfldindx("jnl_file_header","filler")=67 ; Set gtmtypes("jnl_format_buffer")="struct" Set gtmtypes("jnl_format_buffer",0)=14 @@ -26258,8 +26263,8 @@ Init Set gtmtypfldindx("sgmm_addrs","filler")=1 ; Set gtmtypes("sgmnt_addrs")="struct" - Set gtmtypes("sgmnt_addrs",0)=151 - Set gtmtypes("sgmnt_addrs","len")=984 + Set gtmtypes("sgmnt_addrs",0)=152 + Set gtmtypes("sgmnt_addrs","len")=992 Set gtmtypes("sgmnt_addrs",1,"name")="sgmnt_addrs.hdr" Set gtmtypes("sgmnt_addrs",1,"off")=0 Set gtmtypes("sgmnt_addrs",1,"len")=8 @@ -27017,6 +27022,11 @@ Init Set gtmtypes("sgmnt_addrs",151,"len")=4 Set gtmtypes("sgmnt_addrs",151,"type")="int" Set gtmtypfldindx("sgmnt_addrs","tp_hint")=151 + Set gtmtypes("sgmnt_addrs",152,"name")="sgmnt_addrs.statsDB_setup_completed" + Set gtmtypes("sgmnt_addrs",152,"off")=984 + Set gtmtypes("sgmnt_addrs",152,"len")=4 + Set gtmtypes("sgmnt_addrs",152,"type")="boolean_t" + Set gtmtypfldindx("sgmnt_addrs","statsDB_setup_completed")=152 ; Set gtmtypes("sgmnt_data")="struct" Set gtmtypes("sgmnt_data",0)=586 @@ -40141,11 +40151,11 @@ Init Set gtmtypfldindx("unique_file_id","file_id")=5 ; Set gtmtypes("unix_db_info")="struct" - Set gtmtypes("unix_db_info",0)=167 - Set gtmtypes("unix_db_info","len")=1088 + Set gtmtypes("unix_db_info",0)=168 + Set gtmtypes("unix_db_info","len")=1096 Set gtmtypes("unix_db_info",1,"name")="unix_db_info.s_addrs" Set gtmtypes("unix_db_info",1,"off")=0 - Set gtmtypes("unix_db_info",1,"len")=984 + Set gtmtypes("unix_db_info",1,"len")=992 Set gtmtypes("unix_db_info",1,"type")="sgmnt_addrs" Set gtmtypfldindx("unix_db_info","s_addrs")=1 Set gtmtypes("unix_db_info",2,"name")="unix_db_info.s_addrs.hdr" @@ -40905,81 +40915,86 @@ Init Set gtmtypes("unix_db_info",152,"len")=4 Set gtmtypes("unix_db_info",152,"type")="int" Set gtmtypfldindx("unix_db_info","s_addrs.tp_hint")=152 - Set gtmtypes("unix_db_info",153,"name")="unix_db_info.fn" + Set gtmtypes("unix_db_info",153,"name")="unix_db_info.s_addrs.statsDB_setup_completed" Set gtmtypes("unix_db_info",153,"off")=984 - Set gtmtypes("unix_db_info",153,"len")=8 - Set gtmtypes("unix_db_info",153,"type")="addr" - Set gtmtypfldindx("unix_db_info","fn")=153 - Set gtmtypes("unix_db_info",154,"name")="unix_db_info.fd" + Set gtmtypes("unix_db_info",153,"len")=4 + Set gtmtypes("unix_db_info",153,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","s_addrs.statsDB_setup_completed")=153 + Set gtmtypes("unix_db_info",154,"name")="unix_db_info.fn" Set gtmtypes("unix_db_info",154,"off")=992 - Set gtmtypes("unix_db_info",154,"len")=4 - Set gtmtypes("unix_db_info",154,"type")="int" - Set gtmtypfldindx("unix_db_info","fd")=154 - Set gtmtypes("unix_db_info",155,"name")="unix_db_info.owning_gd" + Set gtmtypes("unix_db_info",154,"len")=8 + Set gtmtypes("unix_db_info",154,"type")="addr" + Set gtmtypfldindx("unix_db_info","fn")=154 + Set gtmtypes("unix_db_info",155,"name")="unix_db_info.fd" Set gtmtypes("unix_db_info",155,"off")=1000 - Set gtmtypes("unix_db_info",155,"len")=8 - Set gtmtypes("unix_db_info",155,"type")="addr" - Set gtmtypfldindx("unix_db_info","owning_gd")=155 - Set gtmtypes("unix_db_info",156,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",155,"len")=4 + Set gtmtypes("unix_db_info",155,"type")="int" + Set gtmtypfldindx("unix_db_info","fd")=155 + Set gtmtypes("unix_db_info",156,"name")="unix_db_info.owning_gd" Set gtmtypes("unix_db_info",156,"off")=1008 - Set gtmtypes("unix_db_info",156,"len")=24 - Set gtmtypes("unix_db_info",156,"type")="unix_file_id" - Set gtmtypfldindx("unix_db_info","fileid")=156 - Set gtmtypes("unix_db_info",157,"name")="unix_db_info.fileid.inode" - Set gtmtypes("unix_db_info",157,"off")=1008 - Set gtmtypes("unix_db_info",157,"len")=8 - Set gtmtypes("unix_db_info",157,"type")="ino_t" - Set gtmtypfldindx("unix_db_info","fileid.inode")=157 - Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid.device" + Set gtmtypes("unix_db_info",156,"len")=8 + Set gtmtypes("unix_db_info",156,"type")="addr" + Set gtmtypfldindx("unix_db_info","owning_gd")=156 + Set gtmtypes("unix_db_info",157,"name")="unix_db_info.fileid" + Set gtmtypes("unix_db_info",157,"off")=1016 + Set gtmtypes("unix_db_info",157,"len")=24 + Set gtmtypes("unix_db_info",157,"type")="unix_file_id" + Set gtmtypfldindx("unix_db_info","fileid")=157 + Set gtmtypes("unix_db_info",158,"name")="unix_db_info.fileid.inode" Set gtmtypes("unix_db_info",158,"off")=1016 Set gtmtypes("unix_db_info",158,"len")=8 - Set gtmtypes("unix_db_info",158,"type")="dev_t" - Set gtmtypfldindx("unix_db_info","fileid.device")=158 - Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.st_gen" + Set gtmtypes("unix_db_info",158,"type")="ino_t" + Set gtmtypfldindx("unix_db_info","fileid.inode")=158 + Set gtmtypes("unix_db_info",159,"name")="unix_db_info.fileid.device" Set gtmtypes("unix_db_info",159,"off")=1024 - Set gtmtypes("unix_db_info",159,"len")=4 - Set gtmtypes("unix_db_info",159,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","fileid.st_gen")=159 - Set gtmtypes("unix_db_info",160,"name")="unix_db_info.semid" + Set gtmtypes("unix_db_info",159,"len")=8 + Set gtmtypes("unix_db_info",159,"type")="dev_t" + Set gtmtypfldindx("unix_db_info","fileid.device")=159 + Set gtmtypes("unix_db_info",160,"name")="unix_db_info.fileid.st_gen" Set gtmtypes("unix_db_info",160,"off")=1032 Set gtmtypes("unix_db_info",160,"len")=4 - Set gtmtypes("unix_db_info",160,"type")="int" - Set gtmtypfldindx("unix_db_info","semid")=160 - Set gtmtypes("unix_db_info",161,"name")="unix_db_info.gt_sem_ctime" + Set gtmtypes("unix_db_info",160,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","fileid.st_gen")=160 + Set gtmtypes("unix_db_info",161,"name")="unix_db_info.semid" Set gtmtypes("unix_db_info",161,"off")=1040 - Set gtmtypes("unix_db_info",161,"len")=8 - Set gtmtypes("unix_db_info",161,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=161 - Set gtmtypes("unix_db_info",162,"name")="unix_db_info.shmid" + Set gtmtypes("unix_db_info",161,"len")=4 + Set gtmtypes("unix_db_info",161,"type")="int" + Set gtmtypfldindx("unix_db_info","semid")=161 + Set gtmtypes("unix_db_info",162,"name")="unix_db_info.gt_sem_ctime" Set gtmtypes("unix_db_info",162,"off")=1048 - Set gtmtypes("unix_db_info",162,"len")=4 - Set gtmtypes("unix_db_info",162,"type")="int" - Set gtmtypfldindx("unix_db_info","shmid")=162 - Set gtmtypes("unix_db_info",163,"name")="unix_db_info.gt_shm_ctime" + Set gtmtypes("unix_db_info",162,"len")=8 + Set gtmtypes("unix_db_info",162,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_sem_ctime")=162 + Set gtmtypes("unix_db_info",163,"name")="unix_db_info.shmid" Set gtmtypes("unix_db_info",163,"off")=1056 - Set gtmtypes("unix_db_info",163,"len")=8 - Set gtmtypes("unix_db_info",163,"type")="time_t" - Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=163 - Set gtmtypes("unix_db_info",164,"name")="unix_db_info.ftok_semid" + Set gtmtypes("unix_db_info",163,"len")=4 + Set gtmtypes("unix_db_info",163,"type")="int" + Set gtmtypfldindx("unix_db_info","shmid")=163 + Set gtmtypes("unix_db_info",164,"name")="unix_db_info.gt_shm_ctime" Set gtmtypes("unix_db_info",164,"off")=1064 - Set gtmtypes("unix_db_info",164,"len")=4 - Set gtmtypes("unix_db_info",164,"type")="int" - Set gtmtypfldindx("unix_db_info","ftok_semid")=164 - Set gtmtypes("unix_db_info",165,"name")="unix_db_info.key" - Set gtmtypes("unix_db_info",165,"off")=1068 + Set gtmtypes("unix_db_info",164,"len")=8 + Set gtmtypes("unix_db_info",164,"type")="time_t" + Set gtmtypfldindx("unix_db_info","gt_shm_ctime")=164 + Set gtmtypes("unix_db_info",165,"name")="unix_db_info.ftok_semid" + Set gtmtypes("unix_db_info",165,"off")=1072 Set gtmtypes("unix_db_info",165,"len")=4 - Set gtmtypes("unix_db_info",165,"type")="key_t" - Set gtmtypfldindx("unix_db_info","key")=165 - Set gtmtypes("unix_db_info",166,"name")="unix_db_info.raw" - Set gtmtypes("unix_db_info",166,"off")=1072 + Set gtmtypes("unix_db_info",165,"type")="int" + Set gtmtypfldindx("unix_db_info","ftok_semid")=165 + Set gtmtypes("unix_db_info",166,"name")="unix_db_info.key" + Set gtmtypes("unix_db_info",166,"off")=1076 Set gtmtypes("unix_db_info",166,"len")=4 - Set gtmtypes("unix_db_info",166,"type")="boolean_t" - Set gtmtypfldindx("unix_db_info","raw")=166 - Set gtmtypes("unix_db_info",167,"name")="unix_db_info.db_fs_block_size" - Set gtmtypes("unix_db_info",167,"off")=1076 + Set gtmtypes("unix_db_info",166,"type")="key_t" + Set gtmtypfldindx("unix_db_info","key")=166 + Set gtmtypes("unix_db_info",167,"name")="unix_db_info.raw" + Set gtmtypes("unix_db_info",167,"off")=1080 Set gtmtypes("unix_db_info",167,"len")=4 - Set gtmtypes("unix_db_info",167,"type")="unsigned-int" - Set gtmtypfldindx("unix_db_info","db_fs_block_size")=167 + Set gtmtypes("unix_db_info",167,"type")="boolean_t" + Set gtmtypfldindx("unix_db_info","raw")=167 + Set gtmtypes("unix_db_info",168,"name")="unix_db_info.db_fs_block_size" + Set gtmtypes("unix_db_info",168,"off")=1084 + Set gtmtypes("unix_db_info",168,"len")=4 + Set gtmtypes("unix_db_info",168,"type")="unsigned-int" + Set gtmtypfldindx("unix_db_info","db_fs_block_size")=168 ; Set gtmtypes("unix_file_id")="struct" Set gtmtypes("unix_file_id",0)=3 diff --git a/sr_x86_64/merrors_ansi.h b/sr_x86_64/merrors_ansi.h index e8ce24f..ddf134a 100644 --- a/sr_x86_64/merrors_ansi.h +++ b/sr_x86_64/merrors_ansi.h @@ -1488,4 +1488,7 @@ const static readonly int error_ansi[] = { 0, /* STATSDBERR */ 0, /* STATSDBINUSE */ 0, /* STATSDBFNERR */ + 0, /* JNLSWITCHRETRY */ + 0, /* JNLSWITCHFAIL */ + 0, /* CLISTRTOOLONG */ }; diff --git a/sr_x86_64/merrors_ctl.c b/sr_x86_64/merrors_ctl.c index ab55fe4..47f0528 100644 --- a/sr_x86_64/merrors_ctl.c +++ b/sr_x86_64/merrors_ctl.c @@ -1490,6 +1490,9 @@ LITDEF err_msg merrors[] = { { "STATSDBERR", "Error in/at !AD attempting to use a statistics database: !AD", 4 }, { "STATSDBINUSE", "Statistics database !AD is in use with database !AD so cannot also be used with database !AD", 6 }, { "STATSDBFNERR", "This database has no accessible statistics database due to the following error: !AD", 2 }, + { "JNLSWITCHRETRY", "Retrying previously abandoned switch of journal file !AD for database !AD", 4 }, + { "JNLSWITCHFAIL", "Failed to switch journal file !AD for database file !AD", 4 }, + { "CLISTRTOOLONG", "!AZ specified is !UL bytes long which is greater than the allowed maximum of !UL bytes", 3 }, }; LITDEF int ERR_ACK = 150372361; @@ -2969,9 +2972,12 @@ LITDEF int ERR_INVSTATSDB = 150384146; LITDEF int ERR_STATSDBERR = 150384154; LITDEF int ERR_STATSDBINUSE = 150384162; LITDEF int ERR_STATSDBFNERR = 150384170; +LITDEF int ERR_JNLSWITCHRETRY = 150384179; +LITDEF int ERR_JNLSWITCHFAIL = 150384186; +LITDEF int ERR_CLISTRTOOLONG = 150384194; GBLDEF err_ctl merrors_ctl = { 246, "GTM", &merrors[0], - 1477}; + 1480};