update missed file

This commit is contained in:
YuCheng Hu 2024-07-19 11:44:10 -04:00
parent 5dfa4084d6
commit 833892caf7
107 changed files with 13822 additions and 0 deletions

398
.gitignore vendored Normal file
View File

@ -0,0 +1,398 @@
### Gradle ###
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
### Gradle Patch ###
**/build/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### Intellij+iml ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
modules.xml
.idea/misc.xml
*.ipr
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
.flattened-pom.xml
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
### Node Patch ###
# Serverless Webpack directories
.webpack/
# Optional stylelint cache
# SvelteKit build / generate output
.svelte-kit
### yarn ###
.yarn/*
!.yarn/releases
!.yarn/patches
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
# if you are NOT using Zero-installs, then:
# comment the following lines
!.yarn/cache
# and uncomment the following lines
# .pnp.*
### CVS ###
/CVS/*
**/CVS/*
.cvsignore
*/.cvsignore

133
sr_alpha/axp.h Normal file
View File

@ -0,0 +1,133 @@
/****************************************************************
* *
* Copyright 2001, 2002 Sanchez Computer Associates, 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. *
* *
****************************************************************/
/* axp.h - AXP machine instruction information.
*
* Requires "axp_registers.h" and "axp_gtm_registers.h".
*
*/
/* Machine instruction templates. */
#define ALPHA_INS_ADDL ((unsigned)0x10 << ALPHA_SHIFT_OP)
#define ALPHA_INS_BEQ ((unsigned)0x39 << ALPHA_SHIFT_OP)
#define ALPHA_INS_BGE ((unsigned)0x3e << ALPHA_SHIFT_OP)
#define ALPHA_INS_BGT ((unsigned)0x3f << ALPHA_SHIFT_OP)
#define ALPHA_INS_BIS ((unsigned)0x11 << ALPHA_SHIFT_OP | 0x20 << ALPHA_SHIFT_FUNC)
#define ALPHA_INS_BLE ((unsigned)0x3b << ALPHA_SHIFT_OP)
#define ALPHA_INS_BLT ((unsigned)0x3a << ALPHA_SHIFT_OP)
#define ALPHA_INS_BLBC ((unsigned)0x38 << ALPHA_SHIFT_OP)
#define ALPHA_INS_BLBS ((unsigned)0x3c << ALPHA_SHIFT_OP)
#define ALPHA_INS_BNE ((unsigned)0x3d << ALPHA_SHIFT_OP)
#define ALPHA_INS_BSR ((unsigned)0x34 << ALPHA_SHIFT_OP)
#define ALPHA_INS_BR ((unsigned)0x30 << ALPHA_SHIFT_OP)
#define ALPHA_INS_JMP ((unsigned)0x1a << ALPHA_SHIFT_OP)
#define ALPHA_INS_JSR ((unsigned)0x1a << ALPHA_SHIFT_OP | 1 << ALPHA_SHIFT_BRANCH_FUNC)
#define ALPHA_INS_LDA ((unsigned)0x08 << ALPHA_SHIFT_OP)
#define ALPHA_INS_LDAH ((unsigned)0x09 << ALPHA_SHIFT_OP)
#define ALPHA_INS_LDL ((unsigned)0x28 << ALPHA_SHIFT_OP)
#define ALPHA_INS_LDQ ((unsigned)0x29 << ALPHA_SHIFT_OP)
#define ALPHA_INS_RET ((unsigned)0x1a << ALPHA_SHIFT_OP | 2 << ALPHA_SHIFT_BRANCH_FUNC)
#define ALPHA_INS_STL ((unsigned)0x2c << ALPHA_SHIFT_OP)
#define ALPHA_INS_STQ ((unsigned)0x2d << ALPHA_SHIFT_OP)
#define ALPHA_INS_SUBL ((unsigned)0x10 << ALPHA_SHIFT_OP | 0x9 << ALPHA_SHIFT_FUNC)
#define ALPHA_INS_SUBQ ((unsigned)0x10 << ALPHA_SHIFT_OP | 0x29 << ALPHA_SHIFT_FUNC)
/* Bit offsets to instruction fields. */
#define ALPHA_SHIFT_OP 26
#define ALPHA_SHIFT_BRANCH_FUNC 14
#define ALPHA_SHIFT_FUNC 5
#define ALPHA_SHIFT_LITERAL 13
#define ALPHA_SHIFT_RA 21
#define ALPHA_SHIFT_RB 16
#define ALPHA_SHIFT_RC 0
#define ALPHA_SHIFT_BRANCH_DISP 0
#define ALPHA_SHIFT_DISP 0
/* Bit masks for instruction fields. */
#define ALPHA_BIT_LITERAL (1 << 12)
#define ALPHA_MASK_BRANCH_DISP 0x1fffff
#define ALPHA_MASK_BRANCH_FUNC 0xc00000
#define ALPHA_MASK_DISP 0xffff
#define ALPHA_MASK_FUNC 0x7f
#define ALPHA_MASK_LITERAL 0xff
#define ALPHA_MASK_OP 0x3f
#define ALPHA_MASK_REG 0x1f
/* Alternative assembler mnemonics for machine instruction. */
#define ALPHA_INS_CLRQ (ALPHA_INS_BIS \
| (ALPHA_REG_ZERO << ALPHA_SHIFT_RA) \
| (ALPHA_REG_ZERO << ALPHA_SHIFT_RB))
#define ALPHA_INS_LPC (ALPHA_INS_BR \
| (GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RA))
#define ALPHA_INS_MOVE (ALPHA_INS_BIS \
| ALPHA_REG_ZERO << ALPHA_SHIFT_RB)
#define ALPHA_INS_NOP (ALPHA_INS_BIS \
| (ALPHA_REG_ZERO << ALPHA_SHIFT_RA) \
| (ALPHA_REG_ZERO << ALPHA_SHIFT_RB) \
| (ALPHA_REG_ZERO << ALPHA_SHIFT_RC))
/* Construction forms. */
#define ALPHA_BRA(op,ra,disp) ((op) | ((ra) << ALPHA_SHIFT_RA) | (disp)&ALPHA_MASK_BRANCH_DISP)
#define ALPHA_JMP(op,ra,rb) ((op) | ((ra) << ALPHA_SHIFT_RA) | ((rb) << ALPHA_SHIFT_RB))
#define ALPHA_LIT(op,ra,lit,rc) ((op) | ((ra) << ALPHA_SHIFT_RA) \
| (((lit)&ALPHA_MASK_LITERAL) << ALPHA_SHIFT_LITERAL) \
| ALPHA_BIT_LITERAL \
| ((rc) << ALPHA_SHIFT_RC))
#define ALPHA_MEM(op,ra,rb,disp)((op) | ((ra) << ALPHA_SHIFT_RA) | ((rb) << ALPHA_SHIFT_RB) | (disp)&ALPHA_MASK_DISP)
#define ALPHA_OPR(op,ra,rb,rc) ((op) | ((ra) << ALPHA_SHIFT_RA) | ((rb) << ALPHA_SHIFT_RB) | ((rc) << ALPHA_SHIFT_RC))
#ifdef DEBUG
#define GET_OPCODE(ains) ((ains >> ALPHA_SHIFT_OP) & ALPHA_MASK_OP)
#define GET_RA(ains) ((ains >> ALPHA_SHIFT_RA) & ALPHA_MASK_REG)
#define GET_RB(ains) ((ains >> ALPHA_SHIFT_RB) & ALPHA_MASK_REG)
#define GET_RC(ains) ((ains >> ALPHA_SHIFT_RC) & ALPHA_MASK_REG)
#define GET_MEMDISP(ains) ((ains >> ALPHA_SHIFT_DISP) & ALPHA_MASK_DISP)
#define GET_BRDISP(ains) ((ains >> ALPHA_SHIFT_BRANCH_DISP) & ALPHA_MASK_BRANCH_DISP)
#define GET_FUNC(ains) ((ains >> ALPHA_SHIFT_FUNC) & ALPHA_MASK_FUNC)
#define ADDL_INST "addl"
#define SUBL_INST "subl"
#define SUBQ_INST "subq"
#define BIS_INST "bis"
#define JSR_INST "jsr"
#define RET_INST "ret"
#define JMP_INST "jmp"
#define LDA_INST "lda"
#define LDAH_INST "ldah"
#define LDL_INST "ldl"
#define LDQ_INST "ldq"
#define STL_INST "stl"
#define STQ_INST "stq"
#define BR_INST "br"
#define BSR_INST "bsr"
#define BLBC_INST "blbc"
#define BEQ_INST "beq"
#define BLT_INST "blt"
#define BLE_INST "ble"
#define BLBS_INST "blbs"
#define BNE_INST "bne"
#define BGE_INST "bge"
#define BGT_INST "bgt"
#define CONSTANT "Constant 0x"
/* Space for op_code to be in */
#define OPSPC 7
#endif

27
sr_alpha/cacheflush.m64 Normal file
View File

@ -0,0 +1,27 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title cacheflush - flush data and instruction caches
; cacheflush
;
; entry:
; a0 (r16) address of start of region to flush
; a1 (r17) length (in bytes) of region to flush
; a2 (r18) flag indicating which region to flush (not used on AXP)
$routine name=cacheflush, entry=cacheflush_ca, kind=null
imb
ret r26
$end_routine name=cacheflush

158
sr_alpha/double2s.c Normal file
View File

@ -0,0 +1,158 @@
/****************************************************************
* *
* Copyright 2001, 2009 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 "stringpool.h"
#define MAX_NUM_SIZE 64
GBLREF spdesc stringpool;
static char pot_index [256] =
{
-78, 78, -77, 77, 77, 77, -76, 76, 76, -75, 75, 75, -74, 74, 74, 74,
-73, 73, 73, -72, 72, 72, -71, 71, 71, 71, -70, 70, 70, -69, 69, 69,
-68, 68, 68, -67, 67, 67, 67, -66, 66, 66, -65, 65, 65, -64, 64, 64,
64, -63, 63, 63, -62, 62, 62, -61, 61, 61, 61, -60, 60, 60, -59, 59,
59, -58, 58, 58, 58, -57, 57, 57, -56, 56, 56, -55, 55, 55, 55, -54,
54, 54, -53, 53, 53, -52, 52, 52, 52, -51, 51, 51, -50, 50, 50, -49,
49, 49, 49, -48, 48, 48, -47, 47, 47, -46, 46, 46, 46, -45, 45, 45,
-44, 44, 44, -43, 43, 43, 43, -42, 42, 42, -41, 41, 41, -40, 40, 40,
40, -39, 39, 39, -38, 38, 38, -37, 37, 37, -36, 36, 36, 36, -35, 35,
35, -34, 34, 34, -33, 33, 33, 33, -32, 32, 32, -31, 31, 31, -30, 30,
30, 30, -29, 29, 29, -28, 28, 28, -27, 27, 27, 27, -26, 26, 26, -25,
25, 25, -24, 24, 24, 24, -23, 23, 23, -22, 22, 22, -21, 21, 21, 21,
-20, 20, 20, -19, 19, 19, -18, 18, 18, 18, -17, 17, 17, -16, 16, 16,
-15, 15, 15, 15, -14, 14, 14, -13, 13, 13, -12, 12, 12, 12, -11, 11,
11, -10, 10, 10, -9, 9, 9, -8, 8, 8, 8, -7, 7, 7, -6, 6,
6, -5, 5, 5, 5, -4, 4, 4, -3, 3, 3, -2, 2, 2, 2, -1
};
static double pot [79] =
{
1.701411834604692e+38 + 2.83e+22,
1e+38, 1e+37, 1e+36, 1e+35, 1e+34, 1e+33, 1e+32,
1e+31, 1e+30, 1e+29, 1e+28, 1e+27, 1e+26, 1e+25, 1e+24,
1e+23, 1e+22, 1e+21, 1e+20, 1e+19, 1e+18, 1e+17, 1e+16,
1e+15, 1e+14, 1e+13, 1e+12, 1e+11, 1e+10, 1e+9, 1e+8,
1e+7, 1e+6, 1e+5, 1e+4, 1e+3, 1e+2, 1e+1, 1.0,
1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16,
1e-17, 1e-18, 1e-19, 1e-20, 1e-21, 1e-22, 1e-23, 1e-24,
1e-25, 1e-26, 1e-27, 1e-28, 1e-29, 1e-30, 1e-31, 1e-32,
1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 0
};
#define POT_UNITY 39 /* Subscript of pot: pot[POT_UNITY] == 1.0 */
struct D_float /* Format of D-floating point datum */
{
unsigned int : 7; /* fraction, bits 0:6 */
unsigned int exp : 8; /* exponent, bits 7:14 */
unsigned int sign : 1; /* sign, bit 15 */
unsigned int : 16; /* fraction, bits 16:31 */
unsigned int : 32; /* fraction, bits 32:63 */
};
void double2s (double *dp, mval *v)
{
double d = *dp;
char *p, *q;
int i, j, k;
ENSURE_STP_FREE_SPACE(MAX_NUM_SIZE);
assert (stringpool.free >= stringpool.base);
v->mvtype = MV_STR;
p = v->str.addr
= (char *)stringpool.free;
if (d == 0.0)
*p++ = '0';
else
{
if (d < 0.0)
{
*p++ = '-'; /* plug in a minus sign */
d = -d; /* but make d positive */
}
i = pot_index[((struct D_float *)dp)->exp];
if (i < 0)
{
i = -i;
if (d < pot[i])
++i;
}
i = POT_UNITY + 1 - i;
/* "Normalize" the number; i.e. adjust it to be between 0.0 and 1.0 */
d *= pot[i + POT_UNITY];
if (d < 5e-16)
/* Call it zero */
*p++ = '0';
else
{
/* Round the sixteenth digit */
d += 5e-16;
if (d >= 1.0)
{
/* Readjust it to be between 0.0 and 1.0 */
d /= 10.0;
++i;
}
q = p; /* q will point to the last non-zero byte */
j = i;
if (i <= 0)
{
*p++ = '.';
for (; i < 0; ++i)
*p++ = '0';
}
for (i = 15; i > 0; --i)
{
/* Multiply the value by ten, put the integer portion
of the result into k (0 <= k <= 9), and replace the
value with the fractional portion of the result */
k = d *= 10.0;
d -= k;
*p++ = '0' + k;
if (k > 0)
q = p;
if (--j == 0)
{
q = p;
*p++ = '.';
}
}
if (j > 0)
do
*p++ = '0';
while (--j > 0);
else
p = q;
}
}
v->str.len = p - (char *)stringpool.free;
stringpool.free = (unsigned char *)p;
assert(stringpool.free <= stringpool.top);
return;
}

278
sr_alpha/emit_code_sp.c Normal file
View File

@ -0,0 +1,278 @@
/****************************************************************
* *
* Copyright 2001, 2009 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 "gtm_string.h"
#include "cgp.h"
#include "compiler.h"
#include <rtnhdr.h>
#include "list_file.h"
#include <emit_code.h>
GBLREF uint4 code_buf[]; /* Instruction buffer */
GBLREF int code_idx; /* Index into code_buf */
GBLREF char cg_phase; /* Current compiler phase */
GBLREF int4 curr_addr;
#ifdef DEBUG
GBLREF unsigned char *obpt; /* output buffer index */
GBLREF unsigned char outbuf[]; /* assembly language output buffer */
static unsigned int ains; /* assembler instruction (binary) */
#endif
/* Used by emit_base_offset to extract offset parts */
int alpha_adjusted_upper(int offset)
{
int upper;
upper = (offset >> 16) & 0xFFFF;
if (offset & 0x8000)
upper = (upper + 1) & 0xFFFF;
return upper;
}
void emit_base_offset(int base, int offset)
{
/* NOTE: emit_base_offset does not advance past its last
generated instruction because that instruction is
incomplete; it contains only a base and offset -- the
rt and opcode field are left empty for use by the caller. */
int upper, low, source;
switch (cg_phase)
{
#ifdef DEBUG
case CGP_ASSEMBLY:
#endif
case CGP_ADDR_OPT:
case CGP_APPROX_ADDR:
case CGP_MACHINE:
assert(base >= 0 && base <= 31);
source = base;
upper = alpha_adjusted_upper(offset);
if (0 != upper)
{
code_buf[code_idx++] = ALPHA_INS_LDAH
| (GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RA)
| (source << ALPHA_SHIFT_RB)
| (upper & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP;
source = GTM_REG_CODEGEN_TEMP;
}
low = offset & 0xFFFF;
code_buf[code_idx] = source << ALPHA_SHIFT_RB
| (low & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP;
break;
default:
GTMASSERT;
}
}
#ifdef DEBUG
void fmt_ra()
{
*obpt++ = 'r';
obpt = i2asc(obpt, GET_RA(ains));
}
void fmt_ra_rb()
{
fmt_ra();
*obpt++ = ',';
*obpt++;
*obpt++ = 'r';
obpt = i2asc(obpt, GET_RB(ains));
}
void fmt_ra_rb_rc()
{
fmt_ra_rb();
*obpt++ = ',';
*obpt++;
*obpt++ = 'r';
obpt = i2asc(obpt, GET_RC(ains));
}
void fmt_ra_mem()
{
fmt_ra();
*obpt++ = ',';
obpt++;
*obpt++ = '0';
*obpt++ = 'x';
obpt += i2hex_nofill(GET_MEMDISP(ains), obpt, 6);
*obpt++ = '(';
*obpt++ = 'r';
obpt = i2asc(obpt, GET_RB(ains));
*obpt++ = ')';
}
void fmt_ra_brdisp()
{
fmt_ra();
*obpt++ = ',';
obpt++;
*obpt++ = '0';
*obpt++ = 'x';
obpt += i2hex_nofill(GET_BRDISP(ains) * 4, obpt, 6);
}
void format_machine_inst(void)
{
int instindx;
for (instindx = 0; instindx < code_idx; instindx++)
{
list_chkpage();
obpt = &outbuf[0];
memset(obpt, SP, ASM_OUT_BUFF);
obpt += 10;
i2hex((curr_addr - SIZEOF(rhdtyp)), (uchar_ptr_t)obpt, 8);
curr_addr += 4;
obpt += 10;
i2hex(code_buf[instindx], (uchar_ptr_t)obpt, 8);
obpt += 10;
ains = code_buf[instindx];
switch(GET_OPCODE(ains))
{
case 0x8:
memcpy(obpt, LDA_INST, SIZEOF(LDA_INST) - 1);
obpt += OPSPC;
fmt_ra_mem();
break;
case 0x9:
memcpy(obpt, LDAH_INST, SIZEOF(LDAH_INST) - 1);
obpt += OPSPC;
fmt_ra_mem();
break;
case 0x10:
/* Note opcodes 0x10, 0x11, have overlapping functions but none that we generate
so we can combine their disassembly.
*/
case 0x11:
switch(GET_FUNC(ains))
{
case 0x0: /* main opcode 0x10 */
memcpy(obpt, ADDL_INST, SIZEOF(ADDL_INST) - 1);
break;
case 0x9: /* main opcode 0x10 */
memcpy(obpt, SUBL_INST, SIZEOF(SUBL_INST) - 1);
break;
case 0x29: /* main opcode 0x10 */
memcpy(obpt, SUBQ_INST, SIZEOF(SUBQ_INST) - 1);
break;
case 0x20: /* main opcode 0x11 */
memcpy(obpt, BIS_INST, SIZEOF(BIS_INST) - 1);
break;
default:
GTMASSERT;
}
obpt += OPSPC;
fmt_ra_rb_rc();
break;
case 0x1a:
switch(GET_MEMDISP(ains) & 0x3)
{
case 0x0:
memcpy(obpt, JMP_INST, SIZEOF(JMP_INST) - 1);
break;
case 0x1:
memcpy(obpt, JSR_INST, SIZEOF(JSR_INST) - 1);
break;
case 0x2:
memcpy(obpt, RET_INST, SIZEOF(RET_INST) - 1);
break;
default:
GTMASSERT;
}
obpt += OPSPC;
fmt_ra_rb();
break;
case 0x28:
memcpy(obpt, LDL_INST, SIZEOF(LDL_INST) - 1);
obpt += OPSPC;
fmt_ra_mem();
break;
case 0x29:
memcpy(obpt, LDQ_INST, SIZEOF(LDQ_INST) - 1);
obpt += OPSPC;
fmt_ra_mem();
break;
case 0x2c:
memcpy(obpt, STL_INST, SIZEOF(STL_INST) - 1);
obpt += OPSPC;
fmt_ra_mem();
break;
case 0x2d:
memcpy(obpt, STQ_INST, SIZEOF(STQ_INST) - 1);
obpt += OPSPC;
fmt_ra_mem();
break;
case 0x30:
memcpy(obpt, BR_INST, SIZEOF(BR_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x34:
memcpy(obpt, BSR_INST, SIZEOF(BSR_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x38:
memcpy(obpt, BLBC_INST, SIZEOF(BLBC_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x39:
memcpy(obpt, BEQ_INST, SIZEOF(BEQ_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x3a:
memcpy(obpt, BLT_INST, SIZEOF(BLT_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x3b:
memcpy(obpt, BLE_INST, SIZEOF(BLE_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x3c:
memcpy(obpt, BLBS_INST, SIZEOF(BLBS_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x3d:
memcpy(obpt, BNE_INST, SIZEOF(BNE_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x3e:
memcpy(obpt, BGE_INST, SIZEOF(BGE_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
case 0x3f:
memcpy(obpt, BGT_INST, SIZEOF(BGT_INST) - 1);
obpt += OPSPC;
fmt_ra_brdisp();
break;
default: /* Not an instruction but a constant */
memcpy(obpt, CONSTANT, SIZEOF(CONSTANT) - 1);
obpt += SIZEOF(CONSTANT) - 1;
i2hex(ains, obpt, 8);
obpt += 8;
}
emit_eoi();
}
}
#endif

206
sr_alpha/emit_code_sp.h Normal file
View File

@ -0,0 +1,206 @@
/****************************************************************
* *
* Copyright 2003, 2009 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. *
* *
****************************************************************/
#ifndef EMIT_CODE_SP_INCLUDED
#define EMIT_CODE_SP_INCLUDED
#include "axp_registers.h"
#include "axp_gtm_registers.h"
#include "axp.h"
void emit_base_offset(int base, int offset);
int alpha_adjusted_upper(int offset);
#ifdef DEBUG
void format_machine_inst(void);
void fmt_ra(void);
void fmt_ra_rb(void);
void fmt_ra_rb_rc(void);
void fmt_ra_mem(void);
void fmt_ra_brdisp(void);
#endif
#define INST_SIZE (int)SIZEOF(uint4)
#define BRANCH_OFFSET_FROM_IDX(idx_start, idx_end) (idx_end - (idx_start + 1))
#define LONG_JUMP_OFFSET (0x4ffffffc) /* should be large enough to force the long jump instruction sequence */
#define MAX_BRANCH_CODEGEN_SIZE 32 /* The length in bytes, of the longest form of branch instruction sequence */
#define MAX_OFFSET 0x3fff
#define STACK_ARG_OFFSET(indx) (8 * (indx)) /* All arguments on Alpha platforms are 8 bytes wide on stack */
#define MACHINE_FIRST_ARG_REG ALPHA_REG_A0
/* Register usage in some of the code generation expansions */
#define CALLS_TINT_TEMP_REG ALPHA_REG_R1
#define CLRL_REG ALPHA_REG_ZERO
#define CMPL_TEMP_REG ALPHA_REG_T1
#define GET_ARG_REG(indx) (ALPHA_REG_A0 + (indx))
#define MOVC3_SRC_REG ALPHA_REG_R0
#define MOVC3_TRG_REG ALPHA_REG_R1
#define MOVL_RETVAL_REG ALPHA_REG_V0
#define MOVL_REG_R1 ALPHA_REG_R1
/* Macros to define the opcodes for use in emit_jmp() and emit_tip() args */
#define GENERIC_OPCODE_BEQ ((uint4)ALPHA_INS_BEQ)
#define GENERIC_OPCODE_BGE ((uint4)ALPHA_INS_BGE)
#define GENERIC_OPCODE_BGT ((uint4)ALPHA_INS_BGT)
#define GENERIC_OPCODE_BLE ((uint4)ALPHA_INS_BLE)
#define GENERIC_OPCODE_BLT ((uint4)ALPHA_INS_BLT)
#define GENERIC_OPCODE_BNE ((uint4)ALPHA_INS_BNE)
#define GENERIC_OPCODE_BLBC ((uint4)ALPHA_INS_BLBC)
#define GENERIC_OPCODE_BLBS ((uint4)ALPHA_INS_BLBS)
#define GENERIC_OPCODE_BR ((uint4)ALPHA_INS_BR)
#define GENERIC_OPCODE_LDA ((uint4)ALPHA_INS_LDA)
#define GENERIC_OPCODE_LOAD ((uint4)ALPHA_INS_LDL)
#define GENERIC_OPCODE_STORE ((uint4)ALPHA_INS_STL)
#define GENERIC_OPCODE_NOP ((uint4)ALPHA_INS_NOP)
/* Macro to extract parts of generic opcodes */
#define GENXCT_LOAD_SRCREG(inst) ((inst >> ALPHA_SHIFT_RB) & ALPHA_MASK_REG)
/* Macros to create specific generated code sequences */
/* Note that the GEN_CLEAR/SET_TRUTH macros are only used on VMS (TRUTH_IN_REG) */
#define GEN_CLEAR_TRUTH code_buf[code_idx++] = (ALPHA_INS_STL | ALPHA_REG_ZERO << ALPHA_SHIFT_RA \
| GTM_REG_DOLLAR_TRUTH << ALPHA_SHIFT_RB \
| 0 << ALPHA_SHIFT_DISP)
#define GEN_SET_TRUTH { \
code_buf[code_idx++] = (ALPHA_INS_BIS | ALPHA_REG_ZERO << ALPHA_SHIFT_RA \
| 1 << ALPHA_SHIFT_LITERAL | ALPHA_BIT_LITERAL \
| GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RC); \
code_buf[code_idx++] = (ALPHA_INS_STL | GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RA \
| GTM_REG_DOLLAR_TRUTH << ALPHA_SHIFT_RB \
| 0 << ALPHA_SHIFT_DISP); \
}
#define GEN_LOAD_ADDR(reg, breg, disp) code_buf[code_idx++] = (ALPHA_INS_LDA | reg << ALPHA_SHIFT_RA \
| breg << ALPHA_SHIFT_RB \
| (disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP)
#define GEN_LOAD_WORD(reg, breg, disp) code_buf[code_idx++] = (ALPHA_INS_LDL | reg << ALPHA_SHIFT_RA \
| breg << ALPHA_SHIFT_RB \
| (disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP)
#define GEN_STORE_WORD(reg, breg, disp) code_buf[code_idx++] = (ALPHA_INS_STL | reg << ALPHA_SHIFT_RA \
| breg << ALPHA_SHIFT_RB \
| (disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP)
#define GEN_LOAD_IMMED(reg, disp) GEN_LOAD_ADDR(reg, ALPHA_REG_ZERO, disp)
#define GEN_CLEAR_WORD_EMIT(reg) emit_trip(*(fst_opr + *inst++), TRUE, ALPHA_INS_STL, reg)
#define GEN_LOAD_WORD_EMIT(reg) emit_trip(*(fst_opr + *inst++), TRUE, ALPHA_INS_LDL, reg)
#define GEN_SUBTRACT_REGS(src1, src2, trgt) \
code_buf[code_idx++] = (ALPHA_INS_SUBL \
| src1 << ALPHA_SHIFT_RA \
| src2 << ALPHA_SHIFT_RB \
| trgt << ALPHA_SHIFT_RC)
#define GEN_ADD_IMMED(reg, imval) code_buf[code_idx++] = (ALPHA_INS_ADDL \
| reg << ALPHA_SHIFT_RA \
| imval << ALPHA_SHIFT_LITERAL | ALPHA_BIT_LITERAL \
| reg << ALPHA_SHIFT_RC)
#define GEN_JUMP_REG(reg) code_buf[code_idx++] = (ALPHA_INS_JMP | ALPHA_REG_ZERO << ALPHA_SHIFT_RA \
| reg << ALPHA_SHIFT_RB)
#define GEN_STORE_ARG(reg, offset) code_buf[code_idx++] = (ALPHA_INS_STQ | reg << ALPHA_SHIFT_RA \
| ALPHA_REG_SP << ALPHA_SHIFT_RB \
| (offset & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP)
#define GEN_PCREL code_buf[code_idx++] = (ALPHA_INS_LPC)
#define GEN_MOVE_REG(trg, src) code_buf[code_idx++] = (ALPHA_INS_MOVE | src << ALPHA_SHIFT_RA | trg << ALPHA_SHIFT_RC)
#if defined(__vms)
/* CALL_INST_SIZE is the byte length of the minimum-length instruction sequence to implement a transfer
* table call. In the case of OpenVMS AXP, this is the sequence:
*
* ldl r27, xfer(r11) ; get address of procedure descriptor from transfer table
* ldq r26, 8(r27) ; get code address of procedure from procedure descriptor
* jmp r26, (r26) ; call it
*
* This value is used to determine how to adjust the offset value for a relative call and may not
* be appropriate for the Alpha because VAX relative calls are emulated on the Alpha differently.
*/
# define CALL_INST_SIZE (3 * INST_SIZE)
# define GEN_XFER_TBL_CALL(xfer) \
{ \
emit_base_offset(GTM_REG_XFER_TABLE, xfer); \
code_buf[code_idx++] |= ALPHA_INS_LDL | ALPHA_REG_PV << ALPHA_SHIFT_RA; \
emit_base_offset(ALPHA_REG_PV, 8); \
code_buf[code_idx++] |= ALPHA_INS_LDQ | ALPHA_REG_RA << ALPHA_SHIFT_RA; \
code_buf[code_idx++] = ALPHA_INS_JSR | ALPHA_REG_RA << ALPHA_SHIFT_RA | ALPHA_REG_RA << ALPHA_SHIFT_RB; \
}
#elif defined(__osf__)
/* CALL_INST_SIZE is the byte length of the minimum-length instruction sequence to implement a transfer
* table call. In the case of OSF/1 (Digital Unix) AXP, this is the sequence:
*
* ldl r27, offset(r12) # get address of entry point from transfer table
* jmp r26, (r27) # call it
*
* This value is used to determine how to adjust the offset value for a relative call and may not
* be appropriate for the Alpha because VAX relative calls are emulated on the Alpha differently.
*/
# define CALL_INST_SIZE (2 * INST_SIZE)
# define GEN_XFER_TBL_CALL(xfer) \
{ \
emit_base_offset(GTM_REG_XFER_TABLE, xfer); \
code_buf[code_idx++] |= ALPHA_INS_LDL | ALPHA_REG_PV << ALPHA_SHIFT_RA; \
code_buf[code_idx++] = ALPHA_INS_JSR | ALPHA_REG_RA << ALPHA_SHIFT_RA | ALPHA_REG_PV << ALPHA_SHIFT_RB; \
}
#else
# error "Unsupported platform"
#endif
/* Macros to return an instruction value. This is typcically used to modify an instruction
that is already in the instruction buffer such as the last instruction that was created
by emit_pcrel().
*/
#define IGEN_COND_BRANCH_REG_OFFSET(opcode, reg, disp) (opcode | ((reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA) \
| ((disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_BRANCH_DISP))
#define IGEN_UCOND_BRANCH_REG_OFFSET(opcode, reg, disp) IGEN_COND_BRANCH_REG_OFFSET(opcode, reg, disp)
#define IGEN_LOAD_ADDR_REG(reg) (ALPHA_INS_LDA | (reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA)
#define IGEN_LOAD_WORD_REG(reg) (ALPHA_INS_LDL | (reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA)
#define IGEN_LOAD_NATIVE_REG(reg) IGEN_LOAD_WORD_REG(reg)
#define IGEN_COND_BRANCH_OFFSET(disp) ((disp & ALPHA_MASK_BRANCH_DISP) << ALPHA_SHIFT_BRANCH_DISP)
#define IGEN_UCOND_BRANCH_OFFSET(disp) IGEN_COND_BRANCH_OFFSET(disp)
#define IGEN_LOAD_LINKAGE(reg) (ALPHA_INS_LDQ | (reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA)
#define IGEN_GENERIC_REG(opcode, reg) (opcode | ((reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA))
/* Some macros that are used in certain routines in emit_code.c. The names of these
macros start with the routine name they are used in.
*/
/* Branch has origin of +1 instructions. However, if the branch was nullified in an earlier shrink_trips,
* the origin is the current instruction itself */
#define EMIT_JMP_ADJUST_BRANCH_OFFSET branch_offset = ((branch_offset != 0) ? branch_offset - 1 : 0)
/* Can jump be done within range of immediate operand */
#define EMIT_JMP_SHORT_CODE_CHECK (branch_offset >= (-(ALPHA_MASK_BRANCH_DISP/2) - 1) \
&& branch_offset <= (ALPHA_MASK_BRANCH_DISP/2))
/* Emit the short jump */
#define EMIT_JMP_SHORT_CODE_GEN \
{ \
code_buf[code_idx++] = (branchop | (reg << ALPHA_SHIFT_RA) \
| ((branch_offset & ALPHA_MASK_BRANCH_DISP) << ALPHA_SHIFT_BRANCH_DISP)); \
branch_offset--; \
}
/* Is this a conditional branch? */
#define EMIT_JMP_OPPOSITE_BR_CHECK (branchop != ALPHA_INS_BR && (branchop != ALPHA_INS_BEQ || reg != ALPHA_REG_ZERO))
#define EMIT_JMP_GEN_COMPARE /* No compare necessary */
#define EMIT_JMP_LONG_CODE_CHECK FALSE
/* Is the offset field in this instruction zero? */
#define EMIT_JMP_ZERO_DISP_COND (0 == ((code_buf[code_idx] >> ALPHA_SHIFT_DISP) & ALPHA_MASK_DISP))
/* Emit code to load a given numeric literal */
#define EMIT_TRIP_ILIT_GEN { /* Emit liternal number */ \
emit_base_offset(ALPHA_REG_ZERO, immediate); \
code_buf[code_idx++] |= (ALPHA_INS_LDA | \
(trg_reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA); \
}
/*
* GT.M on AIX and SPARC is 64bit
* By default the loads/stores use ldd/std(load double),
* but if the value being dealt with is a word,the
* opcode in generic_inst is changed to ldw/stw
*/
#define REVERT_GENERICINST_TO_WORD(inst)
#endif

32
sr_alpha/follow.m64 Normal file
View File

@ -0,0 +1,32 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title FOLLOW "Allows run-time modules to call OP_FOLLOW"
; FOLLOW simply passes its two arguments, which are pointers to
; mval's, to OP_FOLLOW, which expects them in registers r0 and r1.
; OP_FOLLOW returns 1, 0, or -1; FOLLOW returns a boolean result:
; 1 (true) if OP_FOLLOW returned 1, otherwise 0 (false).
$routine FOLLOW, entry=FOLLOW_CA, kind=stack
.base r27, $ls
sextl r16, r0
sextl r17, r1
$call OP_FOLLOW, set_arg_info=false
sextl r0, r0
cmovlt r0, 0, r0
$return
$end_routine
.end

17
sr_alpha/gtm_dump.c Normal file
View File

@ -0,0 +1,17 @@
/****************************************************************
* *
* Copyright 2001 Sanchez Computer Associates, 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. *
* *
****************************************************************/
/*** STUB FILE ***/
#include "mdef.h"
#include "error.h"
void gtm_dump(void) {};

24
sr_alpha/inst_flush.m64 Normal file
View File

@ -0,0 +1,24 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title inst_flush flush instruction cache
; inst_flush is a C-callable routine that makes the instruction cache coherent with memory.
$routine name=inst_flush,entry=inst_flush_ca,kind=null
imb
ret r26
$end_routine name=inst_flush
.end

51
sr_alpha/mint2mval.m64 Normal file
View File

@ -0,0 +1,51 @@
.title mint2mval "Convert integer to mval"
; ###############################################################
; # #
; # Copyright 2001, 2004 Sanchez Computer Associates, 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. #
; # #
; ###############################################################
; On input, r1 = integer value, r0 -> mval
mval$def
$linkage_section
int_hi_val:
.quad INT_HI
$routine MINT2MVAL, entry=MINT2MVAL_CA, kind=null
lda sp, -24(sp)
stq r26, (sp)
stq r13, 8(sp)
mov r27, r13
.base r13, $ls
ldq r22, int_hi_val
cmplt r1, r22, r28
beq r28, 11$ ; int >= INT_HI
negq r22, r22
cmple r1, r22, r28
bne r28, 11$ ; int <= -INT_HI
mv_i2mval r1, r0
12$: ldq r26, (sp)
ldq r13, 8(sp)
lda sp, 24(sp)
ret r26
11$: mov r0, r16
mov r1, r17
$call I2MVAL, args=<r16, r17>, set_arg_info=false, nonstandard=true
br 12$
$end_routine
.end

21
sr_alpha/movq.m64 Normal file
View File

@ -0,0 +1,21 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title movq move quadword
$routine name=movq,entry=movq_ca,kind=null
ldq r28, (r16)
stq r28, (r17)
ret r26
$end_routine name=movq

39
sr_alpha/mval2bool.m64 Normal file
View File

@ -0,0 +1,39 @@
; ################################################################
; # #
; # Copyright 2000, 2008 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. #
; # #
; ################################################################
.title mval2bool "Sets condition code from mval"
; On entry, r1 -> mval.
; On exit, r24 = numeric value of mval
mval$def
$routine MVAL2BOOL, entry=MVAL2BOOL_CA, kind=null
lda sp, -24(sp)
stq r26, (sp)
stq r13, 8(sp)
mov r27, r13
.base r13, $ls
mv_force_defined r1
stq r1, 16(sp)
mv_force_num (r1)
ldq r1, 16(sp)
ldl r24, mval$l_m1(r1)
ldq r26, (sp)
ldq r13, 8(sp)
lda sp, 24(sp)
ret r26
$end_routine
.end

39
sr_alpha/mval2mint.m64 Normal file
View File

@ -0,0 +1,39 @@
; ################################################################
; # #
; # Copyright 2000, 2008 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. #
; # #
; ################################################################
.title mval2mint "Converts an mval to integer"
; On entry, r1 -> mval
; On exit, r0 = integer value
mval$def
$routine MVAL2MINT, entry=MVAL2MINT_CA, kind=null
lda sp, -24(sp)
stq r26, (sp)
stq r13, 8(sp)
mov r27, r13
.base r13, $ls
mv_force_defined r1
stq r1, 16(sp)
mv_force_num (r1)
ldq r16, 16(sp)
$call MVAL2I, args=<r16>, set_arg_info=false, nonstandard=true
ldq r26, (sp)
ldq r13, 8(sp)
lda sp, 24(sp)
ret r26
$end_routine
.end

457
sr_alpha/objlangdefs.h Normal file
View File

@ -0,0 +1,457 @@
/****************************************************************
* *
* Copyright 2001 Sanchez Computer Associates, 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. *
* *
****************************************************************/
/* Object record types: */
#define EOBJ$C_EMH 8
#define EOBJ$C_EEOM 9
#define EOBJ$C_EGSD 10
#define EOBJ$C_ETIR 11
#define EOBJ$C_EDBG 12
#define EOBJ$C_ETBT 13
#define EOBJ$C_MAXRECTYP 13
/* Byte offsets into object record and related constants: */
#define EOBJ$K_SUBTYP 4
#define EOBJ$C_SUBTYP 4
#define EOBJ$C_MAXRECSIZ 8192
#define EOBJ$C_STRLVL 2
#define EOBJ$C_SYMSIZ 31
#define EOBJ$C_STOREPLIM -1
#define EOBJ$C_PSCALILIM 16
#define EOBJ$S_EOBJRECDEF 10
#define EOBJ$W_RECTYP 0
#define EOBJ$W_SIZE 2
#define EOBJ$W_SUBTYP 4
#define EOBJ$B_MHD_STRLV 6
#define EOBJ$B_MHD_HOLD 7
#define EOBJ$W_MHD_RECSZ 8
#define EOBJ$T_MHD_NAME 10
/* Object header record (EOBJ$C_EMH) subtypes: */
#define EMH$C_MHD 0
#define EMH$C_LNM 1
#define EMH$C_SRC 2
#define EMH$C_TTL 3
#define EMH$C_CPR 4
#define EMH$C_MTC 5
#define EMH$C_GTX 6
#define EMH$C_MAXHDRTYP 6
/* Byte offsets of fields in object header record (EOBJ$C_EMH): */
#define EMH$S_EMHDEF 52
#define EMH$W_RECTYP 0
#define EMH$W_SIZE 2
#define EMH$W_HDRTYP 4
#define EMH$B_STRLVL 6
#define EMH$B_TEMP 7
#define EMH$L_ARCH1 8
#define EMH$L_ARCH2 12
#define EMH$L_RECSIZ 16
#define EMH$B_NAMLNG 20
#define EMH$S_NAME 31
#define EMH$T_NAME 21
#define EEOM$C_SUCCESS 0
#define EEOM$C_WARNING 1
#define EEOM$C_ERROR 2
#define EEOM$C_ABORT 3
#define EEOM$K_EOMMIN 10
#define EEOM$C_EOMMIN 10
#define EEOM$K_EOMMX1 10
#define EEOM$C_EOMMX1 10
#define EEOM$M_WKTFR 0X1
#define EEOM$K_EOMMAX 24
#define EEOM$C_EOMMAX 24
#define EEOM$S_EEOMDEF 24
#define EEOM$W_RECTYP 0
#define EEOM$W_SIZE 2
#define EEOM$L_TOTAL_LPS 4
#define EEOM$W_COMCOD 8
#define EEOM$B_TFRFLG 10
#define EEOM$V_WKTFR 0
#define EEOM$B_TEMP 11
#define EEOM$L_PSINDX 12
#define EEOM$S_TFRADR 8
#define EEOM$Q_TFRADR 16
#define EEOM$L_TFRADR 16
#define EGSD$K_ENTRIES 2
#define EGSD$C_ENTRIES 2
#define EGSD$C_PSC 0
#define EGSD$C_SYM 1
#define EGSD$C_IDC 2
#define EGSD$C_ENV 3
#define EGSD$C_LSY 4
#define EGSD$C_SPSC 5
#define EGSD$C_SYMV 6
#define EGSD$C_SYMM 7
#define EGSD$C_SYMG 8
#define EGSD$C_MAXRECTYP 8
#define EGSD$S_EGSDEF 12
#define EGSD$W_RECTYP 0
#define EGSD$W_RECSIZ 2
#define EGSD$L_ALIGNLW 4
#define EGSD$W_GSDTYP 8
#define EGSD$W_GSDSIZ 10
#define EGPS$M_PIC 0X1
#define EGPS$M_LIB 0X2
#define EGPS$M_OVR 0X4
#define EGPS$M_REL 0X8
#define EGPS$M_GBL 0X10
#define EGPS$M_SHR 0X20
#define EGPS$M_EXE 0X40
#define EGPS$M_RD 0X80
#define EGPS$M_WRT 0X100
#define EGPS$M_VEC 0X200
#define EGPS$M_NOMOD 0X400
#define EGPS$M_COM 0X800
#define EGPS$K_NAME 12
#define EGPS$C_NAME 12
#define EGPS$S_EGPSDEF 44
#define EGPS$W_GSDTYP 0
#define EGPS$T_START 0
#define EGPS$W_SIZE 2
#define EGPS$B_ALIGN 4
#define EGPS$B_TEMP 5
#define EGPS$W_FLAGS 6
#define EGPS$V_PIC 0
#define EGPS$V_LIB 1
#define EGPS$V_OVR 2
#define EGPS$V_REL 3
#define EGPS$V_GBL 4
#define EGPS$V_SHR 5
#define EGPS$V_EXE 6
#define EGPS$V_RD 7
#define EGPS$V_WRT 8
#define EGPS$V_VEC 9
#define EGPS$V_NOMOD 10
#define EGPS$V_COM 11
#define EGPS$L_ALLOC 8
#define EGPS$B_NAMLNG 12
#define EGPS$S_NAME 31
#define EGPS$T_NAME 13
#define ESGPS$M_PIC 0X1
#define ESGPS$M_LIB 0X2
#define ESGPS$M_OVR 0X4
#define ESGPS$M_REL 0X8
#define ESGPS$M_GBL 0X10
#define ESGPS$M_SHR 0X20
#define ESGPS$M_EXE 0X40
#define ESGPS$M_RD 0X80
#define ESGPS$M_WRT 0X100
#define ESGPS$M_VEC 0X200
#define ESGPS$M_NOMOD 0X400
#define ESGPS$M_COM 0X800
#define ESGPS$K_NAME 25
#define ESGPS$C_NAME 25
#define ESGPS$S_ESGPSDEF 56
#define ESGPS$W_GSDTYP 0
#define ESGPS$T_START 0
#define ESGPS$W_SIZE 2
#define ESGPS$B_ALIGN 4
#define ESGPS$B_TEMP 5
#define ESGPS$W_FLAGS 6
#define ESGPS$V_PIC 0
#define ESGPS$V_LIB 1
#define ESGPS$V_OVR 2
#define ESGPS$V_REL 3
#define ESGPS$V_GBL 4
#define ESGPS$V_SHR 5
#define ESGPS$V_EXE 6
#define ESGPS$V_RD 7
#define ESGPS$V_WRT 8
#define ESGPS$V_VEC 9
#define ESGPS$V_NOMOD 10
#define ESGPS$V_COM 11
#define ESGPS$L_ALLOC 8
#define ESGPS$L_BASE 12
#define ESGPS$S_VALUE 8
#define ESGPS$Q_VALUE 16
#define ESGPS$L_VALUE 16
#define ESGPS$B_NAMLNG 24
#define ESGPS$S_NAME 31
#define ESGPS$T_NAME 25
#define EGSY$M_WEAK 0X1
#define EGSY$M_DEF 0X2
#define EGSY$M_UNI 0X4
#define EGSY$M_REL 0X8
#define EGSY$M_COMM 0X10
#define EGSY$M_VECEP 0X20
#define EGSY$M_NORM 0X40
#define EGSY$S_EGSYDEF 8
#define EGSY$W_GSDTYP 0
#define EGSY$T_START 0
#define EGSY$W_SIZE 2
#define EGSY$B_DATYP 4
#define EGSY$B_TEMP 5
#define EGSY$W_FLAGS 6
#define EGSY$V_WEAK 0
#define EGSY$V_DEF 1
#define EGSY$V_UNI 2
#define EGSY$V_REL 3
#define EGSY$V_COMM 4
#define EGSY$V_VECEP 5
#define EGSY$V_NORM 6
#define EGST$K_NAME 37
#define EGST$C_NAME 37
#define EGST$S_EGSTDEF 68
#define EGST$W_GSDTYP 0
#define EGST$T_START 0
#define EGST$W_SIZE 2
#define EGST$B_DATYP 4
#define EGST$B_TEMP 5
#define EGST$W_FLAGS 6
#define EGST$S_VALUE 8
#define EGST$Q_VALUE 8
#define EGST$L_VALUE 8
#define EGST$S_LP_1 8
#define EGST$Q_LP_1 16
#define EGST$L_LP_1 16
#define EGST$S_LP_2 8
#define EGST$Q_LP_2 24
#define EGST$L_LP_2 24
#define EGST$L_PSINDX 32
#define EGST$B_NAMLNG 36
#define EGST$S_NAME 31
#define EGST$T_NAME 37
#define ESDF$K_NAME 33
#define ESDF$C_NAME 33
#define ESDF$S_ESDFDEF 64
#define ESDF$W_GSDTYP 0
#define ESDF$T_START 0
#define ESDF$W_SIZE 2
#define ESDF$B_DATYP 4
#define ESDF$B_TEMP 5
#define ESDF$W_FLAGS 6
#define ESDF$S_VALUE 8
#define ESDF$Q_VALUE 8
#define ESDF$L_VALUE 8
#define ESDF$S_CODE_ADDRESS 8
#define ESDF$Q_CODE_ADDRESS 16
#define ESDF$L_CODE_ADDRESS 16
#define ESDF$L_CA_PSINDX 24
#define ESDF$L_PSINDX 28
#define ESDF$B_NAMLNG 32
#define ESDF$S_NAME 31
#define ESDF$T_NAME 33
#define ESDFV$K_NAME 25
#define ESDFV$C_NAME 25
#define ESDFV$S_ESDFVDEF 56
#define ESDFV$W_GSDTYP 0
#define ESDFV$T_START 0
#define ESDFV$W_SIZE 2
#define ESDFV$B_DATYP 4
#define ESDFV$B_TEMP 5
#define ESDFV$W_FLAGS 6
#define ESDFV$S_VALUE 8
#define ESDFV$Q_VALUE 8
#define ESDFV$L_VALUE 8
#define ESDFV$L_PSINDX 16
#define ESDFV$L_VECTOR 20
#define ESDFV$B_NAMLNG 24
#define ESDFV$S_NAME 31
#define ESDFV$T_NAME 25
#define ESDFM$K_NAME 25
#define ESDFM$C_NAME 25
#define ESDFM$S_ESDFMDEF 56
#define ESDFM$W_GSDTYP 0
#define ESDFM$T_START 0
#define ESDFM$W_SIZE 2
#define ESDFM$B_DATYP 4
#define ESDFM$B_TEMP 5
#define ESDFM$W_FLAGS 6
#define ESDFM$S_VALUE 8
#define ESDFM$Q_VALUE 8
#define ESDFM$L_VALUE 8
#define ESDFM$L_PSINDX 16
#define ESDFM$L_VERSION_MASK 20
#define ESDFM$B_NAMLNG 24
#define ESDFM$S_NAME 31
#define ESDFM$T_NAME 25
#define ESRF$K_NAME 9
#define ESRF$C_NAME 9
#define ESRF$S_ESRFDEF 40
#define ESRF$W_GSDTYP 0
#define ESRF$T_START 0
#define ESRF$W_SIZE 2
#define ESRF$B_DATYP 4
#define ESRF$B_TEMP 5
#define ESRF$W_FLAGS 6
#define ESRF$B_NAMLNG 8
#define ESRF$S_NAME 31
#define ESRF$T_NAME 9
#define EIDC$C_LEQ 0
#define EIDC$C_EQUAL 1
#define EIDC$S_EIDCDEF 7
#define EIDC$W_GSDTYP 0
#define EIDC$W_SIZE 2
#define EIDC$B_NAMLNG 4
#define EIDC$T_NAME 5
#define EIDC$W_FLAGS 5
#define EIDC$V_BINIDENT 0
#define EIDC$S_IDMATCH 2
#define EIDC$V_IDMATCH 1
#define EIDC$S_ERRSEV 3
#define EIDC$V_ERRSEV 3
#define EENV$M_DEF 0X1
#define EENV$M_NESTED 0X2
#define EENV$S_EENVDEF 40
#define EENV$W_GSDTYP 0
#define EENV$W_SIZE 2
#define EENV$W_FLAGS 4
#define EENV$V_DEF 0
#define EENV$V_NESTED 1
#define EENV$W_ENVINDX 6
#define EENV$B_NAMLNG 8
#define EENV$S_NAME 31
#define EENV$T_NAME 9
#define ELSY$M_WEAK 0X1
#define ELSY$M_DEF 0X2
#define ELSY$M_UNI 0X4
#define ELSY$M_REL 0X8
#define ELSY$S_ELSYDEF 14
#define ELSY$W_GSDTYP 0
#define ELSY$T_START 0
#define ELSY$W_SIZE 2
#define ELSY$B_DATYP 4
#define ELSY$B_TEMP1 5
#define ELSY$W_FLAGS 6
#define ELSY$V_WEAK 0
#define ELSY$V_DEF 1
#define ELSY$V_UNI 2
#define ELSY$V_REL 3
#define ELSY$L_PSINDX 8
#define ELSY$W_ENVINDX 12
#define ELSRF$K_NAME 17
#define ELSRF$C_NAME 17
#define ELSRF$S_ELSRFDEF 48
#define ELSRF$W_GSDTYP 0
#define ELSRF$T_START 0
#define ELSRF$W_SIZE 2
#define ELSRF$B_DATYP 4
#define ELSRF$B_TEMP1 5
#define ELSRF$W_FLAGS 6
#define ELSRF$L_PSINDX 8
#define ELSRF$W_ENVINDX 12
#define ELSRF$W_TEMP2 14
#define ELSRF$B_NAMLNG 16
#define ELSRF$S_NAME 31
#define ELSRF$T_NAME 17
#define ELSDF$K_NAME 25
#define ELSDF$C_NAME 25
#define ELSDF$S_ELSDFDEF 56
#define ELSDF$W_GSDTYP 0
#define ELSDF$T_START 0
#define ELSDF$W_SIZE 2
#define ELSDF$B_DATYP 4
#define ELSDF$B_TEMP1 5
#define ELSDF$W_FLAGS 6
#define ELSDF$S_VALUE 8
#define ELSDF$Q_VALUE 8
#define ELSDF$L_VALUE 8
#define ELSDF$L_PSINDX 16
#define ELSDF$W_ENVINDX 20
#define ELSDF$W_TEMP2 22
#define ELSDF$B_NAMLNG 24
#define ELSDF$S_NAME 31
#define ELSDF$T_NAME 25
/* ETIR command types: */
/* ETIR stack commands: */
#define ETIR$C_MINSTACOD 0
#define ETIR$C_STA_GBL 0
#define ETIR$C_STA_LW 1
#define ETIR$C_STA_QW 2
#define ETIR$C_STA_PQ 3
#define ETIR$C_STA_LI 4
#define ETIR$C_STA_MOD 5
#define ETIR$C_STA_CKARG 6
#define ETIR$C_MAXSTACOD 6
#define ETIR$C_MINSTOCOD 50
#define ETIR$C_STO_B 50
#define ETIR$C_STO_W 51
#define ETIR$C_STO_LW 52
#define ETIR$C_STO_QW 53
#define ETIR$C_STO_IMMR 54
#define ETIR$C_STO_GBL 55
#define ETIR$C_STO_CA 56
#define ETIR$C_STO_RB 57
#define ETIR$C_STO_AB 58
#define ETIR$C_STO_OFF 59
#define ETIR$C_STO_IMM 61
#define ETIR$C_STO_GBL_LW 62
#define ETIR$C_STO_HINT_GBL 64
#define ETIR$C_STO_HINT_PS 65
#define ETIR$C_MAXSTOCOD 65
#define ETIR$C_MINOPRCOD 100
#define ETIR$C_OPR_NOP 100
#define ETIR$C_OPR_ADD 101
#define ETIR$C_OPR_SUB 102
#define ETIR$C_OPR_MUL 103
#define ETIR$C_OPR_DIV 104
#define ETIR$C_OPR_AND 105
#define ETIR$C_OPR_IOR 106
#define ETIR$C_OPR_EOR 107
#define ETIR$C_OPR_NEG 108
#define ETIR$C_OPR_COM 109
#define ETIR$C_OPR_INSV 110
#define ETIR$C_OPR_ASH 111
#define ETIR$C_OPR_USH 112
#define ETIR$C_OPR_ROT 113
#define ETIR$C_OPR_SEL 114
#define ETIR$C_OPR_REDEF 115
#define ETIR$C_OPR_DFLIT 116
#define ETIR$C_MAXOPRCOD 116
#define ETIR$C_MINCTLCOD 150
#define ETIR$C_CTL_SETRB 150
#define ETIR$C_CTL_AUGRB 151
#define ETIR$C_CTL_DFLOC 152
#define ETIR$C_CTL_STLOC 153
#define ETIR$C_CTL_STKDL 154
#define ETIR$C_MAXCTLCOD 154
#define ETIR$C_MINSTCCOD 200
#define ETIR$C_STC_LP 200
#define ETIR$C_STC_LP_PSB 201
#define ETIR$C_STC_GBL 202
#define ETIR$C_STC_GCA 203
#define ETIR$C_STC_PS 204
#define ETIR$C_STC_NOP_GBL 205
#define ETIR$C_STC_NOP_PS 206
#define ETIR$C_STC_BSR_GBL 207
#define ETIR$C_STC_BSR_PS 208
#define ETIR$C_STC_LDA_GBL 209
#define ETIR$C_STC_LDA_PS 210
#define ETIR$C_STC_BOH_GBL 211
#define ETIR$C_STC_BOH_PS 212
#define ETIR$C_STC_NBH_GBL 213
#define ETIR$C_STC_NBH_PS 214
#define ETIR$C_MAXSTCCOD 214
#define ETIR$S_ETIRDEF 4
#define ETIR$W_RECTYP 0
#define ETIR$W_SIZE 2

51
sr_alpha/op_call.m64 Normal file
View File

@ -0,0 +1,51 @@
.title OP_CALL
; ###############################################################
; # #
; # Copyright 2001, 2003 Sanchez Computer Associates, 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. #
; # #
; ###############################################################
G_MSF
$linkage_section
a_frame_pointer:
.address frame_pointer
$code_section
$routine OP_CALLB, entry=OP_CALL_CA, aliases=<OP_CALLW, OP_CALLL>, kind=null
lda sp, -16(sp)
stq r13, 8(sp)
stq r26, (sp)
mov r27, r13
.base r13, $ls
ldq r1, a_frame_pointer
ldl r1, (r1)
; Bump the return PC past the branch sequence following the jsr that got us here:
addl r26, r16, r26 ; length of branch sequence
stl r26, msf$mpc_off(r1) ; and store it in the Mumps stack frame
$call COPY_STACK_FRAME, set_arg_info=false, nonstandard=true
ldq r12, a_frame_pointer
ldl r12, (r12)
ldq r26, (sp)
ldq r13, 8(sp)
lda sp, 16(sp)
ret r26
$end_routine
.end

61
sr_alpha/op_equnul.m64 Normal file
View File

@ -0,0 +1,61 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title OP_EQUNUL "Compare mval to null string"
mval$def
$linkage_section
a_undef_inhibit:
.address undef_inhibit
$code_section
$routine OP_EQUNUL, entry=OP_EQUNUL_CA, kind=null
.base r27, $ls
mv_if_notdefined (r0), 30$
mv_if_notstring (r0), 20$
ldl r28, mval$l_strlen(r0)
bne r28, 20$
; Mval is a null string
10$: mov 1, r24
ret r26
; Mval is not a null string
20$: clr r24
ret r26
; If undef_inhibit is set, then all undefined values are equal to the null string:
30$: ldq r28, a_undef_inhibit
ldq_u r24, (r28)
extbl r24, r28, r24
bne r24, 10$ ; it's set; treat mval as a null string
; It's not set, so issue a message:
lda sp, -8(sp) ; but first,
stq r26, (sp) ; save the return address
mov r0, r16
$call UNDERR, args=<r16>, set_arg_info=false, nonstandard=true
ldq r26, (sp) ; restore our return address
lda sp, 8(sp)
ret r26
$end_routine
.end

51
sr_alpha/op_forlcldo.m64 Normal file
View File

@ -0,0 +1,51 @@
.title OP_FORLCLDO
; ###############################################################
; # #
; # Copyright 2001, 2003 Sanchez Computer Associates, 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. #
; # #
; ###############################################################
G_MSF
$linkage_section
a_frame_pointer:
.address frame_pointer
$code_section
$routine OP_FORLCLDOB, entry=OP_FORLCLDO_CA, aliases=<OP_FORLCLDOW,OP_FORLCLDOL>, kind=null
lda sp, -16(sp)
stq r13, 8(sp)
stq r26, (sp)
mov r27, r13
.base r13, $ls
ldq r1, a_frame_pointer
ldl r1, (r1)
; Bump the return PC past the branch instruction following the jsr that got us here:
addl r26, r16, r26 ; length of branch sequence
stl r26, msf$mpc_off(r1) ; and store it in the Mumps stack frame
$call EXFUN_FRAME, set_arg_info=false, nonstandard=true
ldq r12, a_frame_pointer
ldl r12, (r12)
ldl r9, msf$temps_ptr_off(r12)
ldq r26, (sp)
ldq r13, 8(sp)
lda sp, 16(sp)
ret r26
$end_routine
.end

24
sr_alpha/op_linestart.m64 Normal file
View File

@ -0,0 +1,24 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title op_linestart
G_MSF
; op_linestart - establish start of line in GT.M MUMPS stack frame
$routine name=op_linestart,entry=op_linestart_ca,kind=null
stl r26, msf$mpc_off(r12)
stl r13, msf$ctxt_off(r12)
ret r26
$end_routine name=op_linestart

51
sr_alpha/op_pattern.m64 Normal file
View File

@ -0,0 +1,51 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title OP_PATTERN
mval$def
$routine OP_PATTERN, entry=OP_PATTERN_CA, kind=null
lda sp, -16(sp)
stq r13, 8(sp)
stq r26, (sp)
mov r27, r13
.base r13, $ls
mov r0, r16
mov r1, r17
;
; This is an array of unaligned ints. If the first word is zero, then call do_pattern
; instead of do_patfixed. Only the low order byte is significant and so it is the only
; one we need to test. We would do this in assembly because (1) we need the assmembly
; routine anyway to save the return value into $TEST and (2) it saves an extra level of
; call linkage at the C level to do the decision here.
;
ldl r28, mval$a_straddr(r1)
ldq_u r24, (r28)
extbl r24, r28, r24
beq r24, 20$
10$: $call DO_PATFIXED, args=<r16, r17>, set_arg_info=false, nonstandard=true
15$: mov r0, r24
ldq r26, (sp)
ldq r13, 8(sp)
lda sp, 16(sp)
ret r26
20$: $call DO_PATTERN, args=<r16, r17>, set_arg_info=false, nonstandard=true
br 15$
$end_routine
.end

View File

@ -0,0 +1,41 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title OP_SORTS_AFTER
; On entry:
; r0 -> mval for left hand side
; r1 -> mval for right hand side
;
; On exit:
; r24 < 0 : lhs ']] rhs (lhs ]] rhs is false)
; r24 = 0 : lhs = rhs (lhs ]] rhs is false)
; r24 > 0 : lhs ]] rhs (lhs ]] rhs is true)
$routine OP_SORTS_AFTER, entry=OP_SORTS_AFTER_CA, kind=null
lda sp, -8(sp)
stq r26, (sp)
.base r27, $ls
mov r0, r16
mov r1, r17
$call SORTS_AFTER, args=<r16, r17>, set_arg_info=false, nonstandard=true
mov r0, r24
ldq r26, (sp)
lda sp, 8(sp)
ret r26
$end_routine
.end

37
sr_alpha/pseudo_ret.m64 Normal file
View File

@ -0,0 +1,37 @@
; ################################################################
; # #
; # Copyright 2001, 2008 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. #
; # #
; ################################################################
.title PSEUDO_RET
; PSEUDO_RET calls opp_ret (which doesn't return). It executes in a
; GT.M MUMPS stack frame and is, in fact, normally entered via a
; getframe/ret instruction sequence.
;
; entry:
; r13 - address of PSEUDO_RET's procedure descriptor (not r27)
;
; WARNING: because PSEUDO_RET is designed to be invoked from a GT.M
; MUMPS stack frame, it does not conform to the Alpha calling
; standard and cannot be invoked from any high-level language. The
; invoker should load the address of PSEUDO_RET's procedure descriptor
; into r13, not r27.
$code_section
$routine PSEUDO_RET, entry=PSEUDO_RET_CA, kind=null
.base r13, $ls
$call opp_ret, set_arg_info=false, nonstandard=true
$end_routine
.end

28
sr_alpha/zbreaksp.h Normal file
View File

@ -0,0 +1,28 @@
/****************************************************************
* *
* Copyright 2001, 2009 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. *
* *
****************************************************************/
typedef unsigned short zb_code;
#define ZB_CODE_MASK 0xffff
#define INST_TYPE zb_code
/* The ZBreak command operates by finding the generated code for the op_linestart or op_linefetch for the source
* line in question and changing the offset in the transfer table load address instruction from the op_linestart or
* op_linefetch offset to the appropriate zbreak functionality opcode offset.
* In some platforms(IA64 and ZOS) since the INSTRUCTION LAYOUT is complex we need following
* macros for instruction manipulation.
* EXTRACT_OFFSET_TO_M_OPCODE
* FIX_OFFSET_WITH_ZBREAK_OFFSET
* EXTRACT_AND_UPDATE_INST
* These macros are called only when COMPLEX_INSTRUCTION_UPDATE is defined
* If COMPLEX_INSTRUCTION_UPDATE is not defined portable code in the caller of these macros
* is invoked.
*/
#undef COMPLEX_INSTRUCTION_UPDATE

1364
sr_i386/merrors_ansi.h Normal file

File diff suppressed because it is too large Load Diff

39
sr_i386/opp_indsavglvn.s Normal file
View File

@ -0,0 +1,39 @@
#################################################################
# #
# Copyright 2012 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. #
# #
#################################################################
# PAGE ,132
.title opp_indsavglvn.s
# .386
# .MODEL FLAT, C
.include "linkage.si"
.INCLUDE "g_msf.si"
.sbttl opp_indsavglvn
# PAGE +
.DATA
.extern frame_pointer # /* :DWORD */
.text
.extern op_indsavglvn
# PUBLIC opp_indsavglvn
ENTRY opp_indsavglvn # /* PROC */
putframe
addl $4,%esp # /* burn return pc */
call op_indsavglvn
addl $12,%esp # /* burn three passed-in args */
getframe
ret
# opp_indsavglvn ENDP
# END

39
sr_i386/opp_indsavlvn.s Normal file
View File

@ -0,0 +1,39 @@
#################################################################
# #
# Copyright 2012 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. #
# #
#################################################################
# PAGE ,132
.title opp_indsavlvn.s
# .386
# .MODEL FLAT, C
.include "linkage.si"
.INCLUDE "g_msf.si"
.sbttl opp_indsavlvn
# PAGE +
.DATA
.extern frame_pointer # /* :DWORD */
.text
.extern op_indsavlvn
# PUBLIC opp_indsavlvn
ENTRY opp_indsavlvn # /* PROC */
putframe
addl $4,%esp # /* burn return pc */
call op_indsavlvn
addl $8,%esp # /* burn two passed-in args */
getframe
ret
# opp_indsavlvn ENDP
# END

View File

@ -0,0 +1,112 @@
/****************************************************************
* *
* Copyright 2012, 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. *
* *
****************************************************************/
/*
* This file contains functions related to Linux HugeTLB support. Its functions rely
* on libhugetlbfs which allocates memory in Huge Pages.
* This library is Linux only and works only on (currently) x86, AMD64 and PowerPC
* Supported Huge Page functionality requires the following prerequisites:
* Linux kernel support of Huge Pages
* x86_64 or i386 architecture
* libhugetlbfs.so being installed
* Availability of Huge Pages through setting value to /proc/sys/vm/nr_hugepages or hugepages=<n> kernel parameter or
* /proc/sys/vm/nr_overcommit_hugepages
* In order to use shmget with Huge Pages, either the process gid should be in /proc/sys/vm/hugetlb_shm_group or the
* process should have CAP_IPC_LOCK
* In order to remap .text/.data/.bss sections, a file system of type hugetlbfs should be mounted
* Appropriate environmental variables should be set (refer to libhugetlbfs documentation) to enable/disable Huge Pages
*/
#include "mdef.h"
#include <dlfcn.h>
#include "gtm_string.h"
#include "get_page_size.h"
#include "hugetlbfs_overrides.h"
#undef shmget
#include "send_msg.h"
#include "wbox_test_init.h"
#ifdef DEBUG
# define WBTEST_HUGETLB_DLSYM_ERROR "WBTEST_HUGETLB_DLSYM error"
#endif
GBLDEF long gtm_os_hugepage_size = -1; /* Default Huge Page size of OS. If huge pages are not supported or the
* value doesn't fit into a *long* it will be equal to the OS page size
*/
OS_PAGE_SIZE_DECLARE
/* ptr to libhugetlbfs's overriden shmget. It uses Linux Huge Pages to back the shared segment if possible */
STATICDEF int (*p_shmget) (key_t, size_t, int) = NULL;
/* returns default huge page size of the OS or -1 in case huge pages are not supported or their sizes doesn't
* fit into a long. Refer to libhugetlbfs for further info. */
STATICDEF long (*p_gethugepagesize) (void) = NULL;
STATICDEF boolean_t hugetlb_is_attempted = FALSE;
/* all shmget declarations have already been MACROed to gtm_shmget in mdefsp.h so we need to declare the real
* one here */
extern int shmget (key_t __key, size_t __size, int __shmflg);
error_def(ERR_DLLNORTN);
error_def(ERR_TEXT);
/* A MACRO in mdefsp.h (LINUX_ONLY) replaces all shmget with this function */
int gtm_shmget (key_t key, size_t size, int shmflg)
{
assert(hugetlb_is_attempted); /* libhugetlbfs_init must be called prior to this function */
return p_shmget(key, size, shmflg);
}
/*
* This function initializes libhugetlbfs if it's available. Upon dlopen() the initializing function of libhugetlbfs
* is called. If libhugetlbfs is available gtm_shmget uses its shmget. Otherwise it falls back to the native shmget.
* For malloc to use hugepages, it calls __morecore() hook if it needs more memory. In case libhugetlbfs is available
* and other Huge Page conditions are met, the libhugetlbfs assigns __morecore() to a version which backs them with
* hugepages during its initialization
* Consult libhugetlbfs documentation for a list of HugeTLB configuration environment variables.
*/
void libhugetlbfs_init(void)
{
char *error = NULL;
void *handle;
assert(!hugetlb_is_attempted);
handle = dlopen("libhugetlbfs.so", RTLD_NOW);
GTM_WHITE_BOX_TEST(WBTEST_HUGETLB_DLOPEN, handle, NULL);
if (NULL != handle)
{
/* C99 standard leaves casting from "void *" to a function pointer undefined. The assignment used
* below is the POSIX.1-2003 (Technical Corrigendum 1) workaround; */
*(void **) (&p_shmget) = dlsym(handle, "shmget");
GTM_WHITE_BOX_TEST(WBTEST_HUGETLB_DLSYM, p_shmget, NULL);
if (NULL != p_shmget) /* NULL value for shmget() necessarily means it was not found */
{
*(void **) (&p_gethugepagesize) = dlsym(handle, "gethugepagesize");
if (NULL != p_gethugepagesize)
gtm_os_hugepage_size = p_gethugepagesize();
else
error = dlerror();
} else
error = dlerror();
GTM_WHITE_BOX_TEST(WBTEST_HUGETLB_DLSYM, error, WBTEST_HUGETLB_DLSYM_ERROR);
if (error)
{
p_shmget = NULL;
send_msg(VARLSTCNT(8) ERR_DLLNORTN, 2, LEN_AND_LIT("shmget from libhugetlbfs.so"), ERR_TEXT, 2,
LEN_AND_STR(error));
}
}
if (NULL == p_shmget)
p_shmget = &shmget; /* Fall back to using the native shmget */
get_page_size();
if (-1 == gtm_os_hugepage_size)
gtm_os_hugepage_size = OS_PAGE_SIZE;
assert(0 == (gtm_os_hugepage_size % OS_PAGE_SIZE)); /* huge pages sizes are multiples of page sizes */
hugetlb_is_attempted = TRUE;
}

View File

@ -0,0 +1,25 @@
/****************************************************************
* *
* Copyright 2012, 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. *
* *
****************************************************************/
#ifndef HUGETLBFS_OVERRIDES_H_
#define HUGETLBFS_OVERRIDES_H_
#if defined(__linux__) && ( defined(__i386__) || defined(__x86_64__) )
# define HUGETLB_SUPPORTED 1
#endif
GBLREF long gtm_os_hugepage_size;
#define OS_HUGEPAGE_SIZE gtm_os_hugepage_size
extern int gtm_shmget(key_t __key, size_t __size, int __shmflg);
void libhugetlbfs_init(void);
#endif /* HUGETLBFS_OVERRIDES_H_ */

59
sr_linux/platform.cmake Normal file
View File

@ -0,0 +1,59 @@
#################################################################
# #
# Copyright 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. #
# #
#################################################################
if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
set(arch "x86")
set(bits 32)
set(FIND_LIBRARY_USE_LIB64_PATHS FALSE)
else()
set(arch "x86_64")
set(bits 64)
endif()
# Platform directories
list(APPEND gt_src_list sr_linux)
if(${bits} EQUAL 32)
list(APPEND gt_src_list sr_i386 sr_x86_regs sr_unix_nsb)
else()
list(APPEND gt_src_list sr_x86_64 sr_x86_regs)
set(gen_xfer_desc 1)
endif()
# Assembler
set(CMAKE_INCLUDE_FLAG_ASM "-Wa,-I") # gcc -I does not make it to "as"
# Compiler
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -ansi -fsigned-char -fPIC -Wmissing-prototypes -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS_RELEASE
"${CMAKE_C_FLAGS_RELEASE} -fno-defer-pop -fno-strict-aliasing -ffloat-store")
add_definitions(
#-DNOLIBGTMSHR #gt_cc_option_DBTABLD=-DNOLIBGTMSHR
-D_GNU_SOURCE
-D_FILE_OFFSET_BITS=64
-D_XOPEN_SOURCE=600
-D_LARGEFILE64_SOURCE
)
# Linker
set(gtm_link "-Wl,-u,gtm_filename_to_id -Wl,-u,gtm_zstatus -Wl,--version-script,\"${GTM_BINARY_DIR}/gtmexe_symbols.export\"")
set(gtm_dep "${GTM_BINARY_DIR}/gtmexe_symbols.export")
set(libgtmshr_link "-Wl,-u,gtm_ci -Wl,-u,gtm_filename_to_id -Wl,--version-script,\"${GTM_BINARY_DIR}/gtmshr_symbols.export\"")
set(libgtmshr_dep "${GTM_BINARY_DIR}/gtmexe_symbols.export")
if(${bits} EQUAL 32)
set(libmumpslibs "-lncurses -lm -ldl -lc -lpthread -lrt")
else()
set(libmumpslibs "-lelf -lncurses -lm -ldl -lc -lpthread -lrt")
endif()

View File

@ -0,0 +1,344 @@
/****************************************************************
* *
* Copyright 2012, 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. *
* *
****************************************************************/
#ifndef _ANTICIPATORY_FREEZE_H
#define _ANTICIPATORY_FREEZE_H
#ifdef UNIX
#include "gtm_time.h" /* needed for GET_CUR_TIME */
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsblk.h"
#include "gdsfhead.h"
#include "repl_msg.h" /* needed for gtmsource.h */
#include "gtmsource.h" /* needed for jnlpool_addrs typedef */
#include "sleep_cnt.h" /* needed for SLEEP_INSTFREEZEWAIT macro */
#include "wait_for_disk_space.h" /* needed by DB_LSEEKWRITE macro for prototype */
#include "gtmimagename.h" /* needed for IS_GTM_IMAGE */
boolean_t is_anticipatory_freeze_needed(sgmnt_addrs *csa, int msg_id);
void set_anticipatory_freeze(sgmnt_addrs *csa, int msg_id);
boolean_t init_anticipatory_freeze_errors(void);
/* Define function pointers to certain functions to avoid executables like gtmsecshr from unnecessarily
* linking with these functions (which causes the database/replication stuff to be pulled in).
*/
typedef boolean_t (*is_anticipatory_freeze_needed_t)(sgmnt_addrs *csa, int msgid);
typedef void (*set_anticipatory_freeze_t)(sgmnt_addrs *csa, int msg_id);
GBLREF is_anticipatory_freeze_needed_t is_anticipatory_freeze_needed_fnptr;
GBLREF set_anticipatory_freeze_t set_anticipatory_freeze_fnptr;
GBLREF boolean_t pool_init;
GBLREF boolean_t mupip_jnl_recover;
#ifdef DEBUG
GBLREF uint4 lseekwrite_target;
#endif
error_def(ERR_MUINSTFROZEN);
error_def(ERR_MUINSTUNFROZEN);
error_def(ERR_MUNOACTION);
error_def(ERR_REPLINSTFREEZECOMMENT);
error_def(ERR_REPLINSTFROZEN);
error_def(ERR_REPLINSTUNFROZEN);
error_def(ERR_TEXT);
#define ENABLE_FREEZE_ON_ERROR \
{ \
if (ANTICIPATORY_FREEZE_AVAILABLE) \
{ /* Set anticipatory freeze function pointers to be used later (in send_msg and rts_error) */ \
is_anticipatory_freeze_needed_fnptr = &is_anticipatory_freeze_needed; \
set_anticipatory_freeze_fnptr = &set_anticipatory_freeze; \
} \
}
#define CHECK_IF_FREEZE_ON_ERROR_NEEDED(CSA, MSG_ID, FREEZE_NEEDED, FREEZE_MSG_ID) \
{ \
GBLREF jnlpool_addrs jnlpool; \
DCL_THREADGBL_ACCESS; \
\
SETUP_THREADGBL_ACCESS; \
if (!FREEZE_NEEDED && ANTICIPATORY_FREEZE_AVAILABLE && (NULL != is_anticipatory_freeze_needed_fnptr)) \
{ /* NOT gtmsecshr */ \
if (IS_REPL_INST_UNFROZEN && (*is_anticipatory_freeze_needed_fnptr)((sgmnt_addrs *)CSA, MSG_ID)) \
{ \
FREEZE_NEEDED = TRUE; \
FREEZE_MSG_ID = MSG_ID; \
} \
} \
}
#define FREEZE_INSTANCE_IF_NEEDED(CSA, FREEZE_NEEDED, FREEZE_MSG_ID) \
{ \
GBLREF jnlpool_addrs jnlpool; \
\
if (FREEZE_NEEDED) \
{ \
assert(NULL != set_anticipatory_freeze_fnptr); \
(*set_anticipatory_freeze_fnptr)((sgmnt_addrs *)CSA, FREEZE_MSG_ID); \
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLINSTFROZEN, 1, \
jnlpool.repl_inst_filehdr->inst_info.this_instname); \
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLINSTFREEZECOMMENT, 1, jnlpool.jnlpool_ctl->freeze_comment); \
} \
}
#define CLEAR_ANTICIPATORY_FREEZE(FREEZE_CLEARED) \
{ \
GBLREF jnlpool_addrs jnlpool; \
\
if (IS_REPL_INST_FROZEN) \
{ \
jnlpool.jnlpool_ctl->freeze = 0; \
FREEZE_CLEARED = TRUE; \
} \
}
#define REPORT_INSTANCE_UNFROZEN(FREEZE_CLEARED) \
{ \
GBLREF jnlpool_addrs jnlpool; \
\
if (FREEZE_CLEARED) \
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLINSTUNFROZEN, 1, \
jnlpool.repl_inst_filehdr->inst_info.this_instname); \
}
#define AFREEZE_MASK 0x01
#define ANTICIPATORY_FREEZE_AVAILABLE (0 != (TREF(gtm_custom_errors)).len)
#define INSTANCE_FREEZE_HONORED(CSA) (DBG_ASSERT(NULL != CSA) \
((NULL != jnlpool.jnlpool_ctl) \
&& ((REPL_ALLOWED(((sgmnt_addrs *)CSA)->hdr)) \
|| mupip_jnl_recover /* recover or rollback */ \
|| ((sgmnt_addrs *)CSA)->nl->onln_rlbk_pid )))
#define ANTICIPATORY_FREEZE_ENABLED(CSA) (INSTANCE_FREEZE_HONORED(CSA) \
&& ANTICIPATORY_FREEZE_AVAILABLE \
&& (((sgmnt_addrs *)CSA)->hdr->freeze_on_fail))
#define IS_REPL_INST_FROZEN ((NULL != jnlpool.jnlpool_ctl) && jnlpool.jnlpool_ctl->freeze)
#define IS_REPL_INST_UNFROZEN ((NULL != jnlpool.jnlpool_ctl) && !jnlpool.jnlpool_ctl->freeze)
#define INST_FROZEN_COMMENT "PID %d encountered %s; Instance frozen"
#define MSGID_TO_ERRMSG(MSG_ID, ERRMSG) \
{ \
const err_ctl *ctl; \
\
ctl = err_check(MSG_ID); \
assert(NULL != ctl); \
GET_MSG_INFO(MSG_ID, ctl, ERRMSG); \
}
#define GENERATE_INST_FROZEN_COMMENT(BUF, BUF_LEN, MSG_ID) \
{ \
GBLREF uint4 process_id; \
const err_msg *msginfo; \
\
MSGID_TO_ERRMSG(MSG_ID, msginfo); \
SNPRINTF(BUF, BUF_LEN, INST_FROZEN_COMMENT, process_id, msginfo->tag); \
}
/* This is a version of the macro which waits for the instance freeze to be lifted off assuming the process has
* already attached to the journal pool. We need to wait for the freeze only if the input database cares about
* anticipatory freeze. Examples of those databases that dont care are non-replicated databases, databases with
* "freeze_on_fail" field set to FALSE in the file header etc. Hence the use of ANTICIPATORY_FREEZE_ENABLED below.
* Note: Do not use "hiber_start" as that uses timers and if we are already in a timer handler now, nested timers
* wont work. Since SHORT_SLEEP allows a max of 1000, we use 500 (half a second) for now.
*/
#define WAIT_FOR_REPL_INST_UNFREEZE(CSA) \
{ \
gd_region *reg; \
char *time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */ \
now_t now; \
DCL_THREADGBL_ACCESS; \
\
SETUP_THREADGBL_ACCESS; \
assert(NULL != CSA); \
if (INSTANCE_FREEZE_HONORED(CSA)) \
{ \
reg = ((sgmnt_addrs *)CSA)->region; \
if (!IS_GTM_IMAGE) \
{ \
GET_CUR_TIME; \
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_MUINSTFROZEN, 5, CTIME_BEFORE_NL, time_ptr, \
jnlpool.repl_inst_filehdr->inst_info.this_instname, DB_LEN_STR(reg)); \
} \
WAIT_FOR_REPL_INST_UNFREEZE_NOCSA; \
if (!IS_GTM_IMAGE) \
{ \
GET_CUR_TIME; \
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_MUINSTUNFROZEN, 5, CTIME_BEFORE_NL, time_ptr, \
jnlpool.repl_inst_filehdr->inst_info.this_instname, DB_LEN_STR(reg)); \
} \
} \
}
/* This is a safer version of the WAIT_FOR_REPL_INST_UNFREEZE macro, which waits for the instance freeze
* to be lifted off but is not sure if the process has access to the journal pool yet.
* If it does not, then it assumes the instance is not frozen.
*/
#define WAIT_FOR_REPL_INST_UNFREEZE_SAFE(CSA) \
{ \
GBLREF jnlpool_addrs jnlpool; \
\
assert(NULL != CSA); \
if (IS_REPL_INST_FROZEN) \
WAIT_FOR_REPL_INST_UNFREEZE(CSA); \
}
/* Below are similar macros like the above but with no CSA to specifically check for */
#define WAIT_FOR_REPL_INST_UNFREEZE_NOCSA \
{ \
GBLREF jnlpool_addrs jnlpool; \
GBLREF volatile int4 exit_state; \
GBLREF int4 exi_condition; \
GBLREF int4 forced_exit_err; \
\
assert(NULL != jnlpool.jnlpool_ctl); \
/* If this region is not replicated, do not care for instance freezes */ \
while (jnlpool.jnlpool_ctl->freeze) \
{ \
if (exit_state != 0) \
{ \
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err); \
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err); \
exit(-exi_condition); \
} \
SHORT_SLEEP(SLEEP_INSTFREEZEWAIT); \
DEBUG_ONLY(CLEAR_FAKE_ENOSPC_IF_MASTER_DEAD); \
} \
}
#define WAIT_FOR_REPL_INST_UNFREEZE_NOCSA_SAFE \
{ \
GBLREF jnlpool_addrs jnlpool; \
\
if (IS_REPL_INST_FROZEN) \
WAIT_FOR_REPL_INST_UNFREEZE_NOCSA; \
}
/* GTM_DB_FSYNC/GTM_JNL_FSYNC are similar to GTM_FSYNC except that we dont do the fsync
* (but instead hang) if we detect the instance is frozen. We proceed with the fsync once the freeze clears.
* CSA is a parameter indicating which database it is that we want to fsync.
* GTM_REPL_INST_FSYNC is different in that we currently dont care about instance freeze for replication
* instance file writes.
*/
#define GTM_DB_FSYNC(CSA, FD, RC) \
{ \
GBLREF jnlpool_addrs jnlpool; \
node_local_ptr_t cnl; \
\
assert((NULL != CSA) || (NULL == jnlpool.jnlpool_ctl)); \
if (NULL != CSA) \
{ \
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(CSA); \
cnl = (CSA)->nl; \
if (NULL != cnl) \
INCR_GVSTATS_COUNTER((CSA), cnl, n_db_fsync, 1); \
} \
GTM_FSYNC(FD, RC); \
}
#define GTM_JNL_FSYNC(CSA, FD, RC) \
{ \
GBLREF jnlpool_addrs jnlpool; \
node_local_ptr_t cnl; \
\
assert((NULL != CSA) || (NULL == jnlpool.jnlpool_ctl)); \
if (NULL != CSA) \
{ \
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(CSA); \
cnl = (CSA)->nl; \
if (NULL != cnl) \
INCR_GVSTATS_COUNTER((CSA), cnl, n_jnl_fsync, 1); \
} \
GTM_FSYNC(FD, RC); \
}
#define GTM_REPL_INST_FSYNC(FD, RC) GTM_FSYNC(FD, RC)
#define LSEEKWRITE_IS_TO_NONE 0
#define LSEEKWRITE_IS_TO_DB 1
#define LSEEKWRITE_IS_TO_JNL 2
#ifdef DEBUG
#define FAKE_ENOSPC(CSA, FAKE_WHICH_ENOSPC, LSEEKWRITE_TARGET, LCL_STATUS) \
{ \
GBLREF jnlpool_addrs jnlpool; \
if (NULL != CSA) \
{ \
if (WBTEST_ENABLED(WBTEST_RECOVER_ENOSPC)) \
{ /* This test case is only used by mupip */ \
gtm_wbox_input_test_case_count++; \
if ((0 != gtm_white_box_test_case_count) \
&& (gtm_white_box_test_case_count <= gtm_wbox_input_test_case_count)) \
{ \
LCL_STATUS = ENOSPC; \
if (gtm_white_box_test_case_count == gtm_wbox_input_test_case_count) \
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2, \
LEN_AND_LIT("Turning on fake ENOSPC for exit status test")); \
} \
} else if (!IS_DSE_IMAGE /*DSE does not freeze so let it work as normal */ \
&& ((NULL != jnlpool.jnlpool_ctl) && (NULL != ((sgmnt_addrs *)CSA)->nl)) \
&& ((sgmnt_addrs *)CSA)->nl->FAKE_WHICH_ENOSPC) \
{ \
LCL_STATUS = ENOSPC; \
lseekwrite_target = LSEEKWRITE_TARGET; \
} \
} \
}
void clear_fake_enospc_if_master_dead(void);
#define CLEAR_FAKE_ENOSPC_IF_MASTER_DEAD clear_fake_enospc_if_master_dead()
#else
#define FAKE_ENOSPC(CSA, FAKE_ENOSPC, LSEEKWRITE_TARGET, LCL_STATUS) {}
#endif
#define DB_LSEEKWRITE(csa, db_fn, fd, new_eof, buff, size, status) \
DO_LSEEKWRITE(csa, db_fn, fd, new_eof, buff, size, status, fake_db_enospc, LSEEKWRITE_IS_TO_DB)
#define JNL_LSEEKWRITE(csa, jnl_fn, fd, new_eof, buff, size, status) \
DO_LSEEKWRITE(csa, jnl_fn, fd, new_eof, buff, size, status, fake_jnl_enospc, LSEEKWRITE_IS_TO_JNL)
#define DO_LSEEKWRITE(csa, fnptr, fd, new_eof, buff, size, status, FAKE_WHICH_ENOSPC, LSEEKWRITE_TARGET) \
{ \
int lcl_status; \
\
if (NULL != csa) \
WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa); \
LSEEKWRITE(fd, new_eof, buff, size, lcl_status); \
FAKE_ENOSPC(csa, FAKE_WHICH_ENOSPC, LSEEKWRITE_TARGET, lcl_status); \
if (ENOSPC == lcl_status) \
{ \
wait_for_disk_space(csa, (char *)fnptr, fd, (off_t)new_eof, (char *)buff, (size_t)size, &lcl_status); \
assert((NULL == csa) || (NULL == ((sgmnt_addrs *)csa)->nl) || !((sgmnt_addrs *)csa)->nl->FAKE_WHICH_ENOSPC \
|| (ENOSPC != lcl_status)); \
} \
status = lcl_status; \
}
/* Currently, writes to replication instance files do NOT trigger instance freeze behavior.
* Neither does a pre-existing instance freeze affect replication instance file writes.
* Hence this is defined as simple LSEEKWRITE.
*/
#define REPL_INST_LSEEKWRITE LSEEKWRITE
#define REPL_INST_AVAILABLE (repl_inst_get_name((char *)replpool_id.instfilename, &full_len, SIZEOF(replpool_id.instfilename), \
return_on_error))
#else /* #ifdef UNIX */
# define ANTICIPATORY_FREEZE_AVAILABLE FALSE
# define ANTICIPATORY_FREEZE_ENABLED(CSA) FALSE
# define REPL_INST_AVAILABLE FALSE
# define WAIT_FOR_REPL_INST_UNFREEZE
# define WAIT_FOR_REPL_INST_UNFREEZE_SAFE
#endif /* #ifdef UNIX */
#endif /* #ifndef _ANTICIPATORY_FREEZE_H */

View File

@ -0,0 +1,125 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "gtm_ctype.h"
#include "compiler.h"
#include "mdq.h"
#include "opcode.h"
#include "indir_enum.h"
#include "nametabtyp.h"
#include "toktyp.h"
#include "funsvn.h"
#include "mmemory.h"
#include "advancewindow.h"
#include "namelook.h"
#include "cmd.h"
#include "svnames.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "alias.h"
#include "glvn_pool.h"
#ifdef UNICODE_SUPPORTED
#include "gtm_utf8.h"
#endif
/* This function adds triples to the execution chain to store the values of subscripts (in glvns in compound SETs)
* in temporaries (using OC_STOTEMP opcode). This function is only invoked when
* a) The SET is a compound SET (i.e. there are multiple targets specified on the left side of the SET command).
* b) Subscripts are specified in glvns which are targets of the SET.
* e.g. set a=0,(a,array(a))=1
* The expected result of the above command as per the M-standard is that array(0) (not array(1)) gets set to 1.
* That is, the value of the subscript "a" should be evaluated at the start of the compound SET before any sets happen
* and should be used in any subscripts that refer to the name "a".
* In the above example, since it is a compound SET and "a" is used in a subscript, we need to store the value of "a"
* before the start of the compound SET (i.e.a=0) in a temporary and use that as the subscript for "array".
* If in the above example the compound set was instead specified as set a=1,array(a)=1, the value of 1 gets substituted
* when used in "array(a)".
* This is where the compound set acts differently from a sequence of multiple sets. This is per the M-standard.
* In the above example, the subscript used was also a target within the compound SET. It is possible that the
* subscript is not also an individual target within the same compound SET. Even in that case, this function
* will be called to store the subscript in temporaries (as we dont know at compile time if a particular
* subscript is also used as a target within a compound SET).
*/
void create_temporaries(triple *sub, opctype put_oc)
{
oprtype *sb1;
triple *s0, *s1;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
assert(TREF(temp_subs));
assert(NULL != sub);
sb1 = &sub->operand[1];
if ((OC_GVNAME == put_oc) || (OC_PUTINDX == put_oc) || (OC_SRCHINDX == put_oc))
{
sub = sb1->oprval.tref; /* global name */
assert(OC_PARAMETER == sub->opcode);
sb1 = &sub->operand[1];
} else if (OC_GVEXTNAM == put_oc)
{
sub = sb1->oprval.tref; /* first env */
assert(OC_PARAMETER == sub->opcode);
sb1 = &sub->operand[0];
assert(TRIP_REF == sb1->oprclass);
s0 = sb1->oprval.tref;
if ((OC_GETINDX == s0->opcode) || (OC_VAR == s0->opcode))
{
s1 = maketriple(OC_STOTEMP);
s1->operand[0] = *sb1;
*sb1 = put_tref(s1);
s0 = s0->exorder.fl;
dqins(s0->exorder.bl, exorder, s1);
}
sb1 = &sub->operand[1];
sub = sb1->oprval.tref; /* second env */
assert(OC_PARAMETER == sub->opcode);
sb1 = &sub->operand[0];
assert(TRIP_REF == sb1->oprclass);
s0 = sb1->oprval.tref;
if ((OC_GETINDX == s0->opcode) || (OC_VAR == s0->opcode))
{
s1 = maketriple(OC_STOTEMP);
s1->operand[0] = *sb1;
*sb1 = put_tref(s1);
s0 = s0->exorder.fl;
dqins(s0->exorder.bl, exorder, s1);
}
sb1 = &sub->operand[1];
sub = sb1->oprval.tref; /* global name */
assert(OC_PARAMETER == sub->opcode);
sb1 = &sub->operand[1];
}
while (sb1->oprclass)
{
assert(TRIP_REF == sb1->oprclass);
sub = sb1->oprval.tref;
assert(OC_PARAMETER == sub->opcode);
sb1 = &sub->operand[0];
assert(TRIP_REF == sb1->oprclass);
s0 = sb1->oprval.tref;
if ((OC_GETINDX == s0->opcode) || (OC_VAR == s0->opcode))
{
s1 = maketriple(OC_STOTEMP);
s1->operand[0] = *sb1;
*sb1 = put_tref(s1);
s0 = s0->exorder.fl;
dqins(s0->exorder.bl, exorder, s1);
}
sb1 = &sub->operand[1];
}
}

249
sr_port/dsewrap.mpt Normal file
View File

@ -0,0 +1,249 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Copyright 2012, 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. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%DSEWRAP
%dsewrap
; Wrappers for DSE to avoid inadvertently making database changes
set $ETRAP="do errtrap^%DSEWRAP"
set $ecode=",U255," ; must call an entryref
quit:$quit 255 quit ; in case error trap does not end the call
DUMP(r,o,w,d) ; upper case wrapper for dump
new tmp
set tmp=$$dump(r,.o,w,d)
quit:$quit tmp quit
dump(reglist,output,what,detail) ; dump information
; reglist - comma separated list of regions, "*" (default) for all regions
; output - required variable passed by reference where output is returned
; what - optional information to dump - "fileheader" (default) is only option for now
; detail - optional default is basic information, "all" is full fileheader dump
; install an error handler if non exists
if 0=$length($ETRAP) new $ETRAP set $ETRAP="do errtrap^%DSEWRAP"
new cmd,dse,debug,error,gtmdist,i,io,isVMS,line,mod,nopipe,region,ver
; save previous $IO to restore once the routine has completed
set io=$io
if $data(%DSEWRAP("debug")) do
. set debug=$increment(%DSEWRAP("debug"))
. set debug(debug,"input","reglist")=$get(reglist)
. set debug(debug,"input","what")=$get(what)
. set debug(debug,"input","detail")=$get(detail)
;
; Determine if we can use PIPES or not AND where to find DSE
set ver=$tr($piece($zversion," ",2),"V-.",""),ver=$select(ver<1000:ver*10,1:$extract(ver,1,5))
set isVMS=$zversion["VMS"
set nopipe=((ver<53003)&($get(%DSEWRAP("forcenopipe"),0)))!isVMS,mod=$select(isVMS:"/",1:"-")
set gtmdist=$select(isVMS:"gtm$dist",1:"gtm_dist")
;
; Applicable regions list
set reglist=$$reglist($$FUNC^%UCASE($get(reglist,"*")),isVMS)
; What operation? for now, should be just "dump -fileheader [-all]"
if (0=$length($get(what)))!("fileheader"=$$FUNC^%LCASE($get(what))) set what=mod_"fileheader"
else set $ecode=",U254," quit:$quit 254 quit
if 0=$length($get(detail)) set detail=""
else if "all"=$$FUNC^%LCASE(detail) set detail=mod_"all"
else if $length(detail," ")>1 do
. set detail=$$^%MPIECE(detail," "," ")
. for i=1:1:$length(detail," ") if $piece(detail," ",i)'?1(1"/",1"-").A set $piece(detail," ",i)=mod_$piece(detail," ",i)
set cmd="dump "_what_" "_detail
; Use alternate GT.M version - only supported with pipes
if nopipe&$data(%DSEWRAP("alternate")) set $ecode=",U252," quit:$quit 252 quit
; DSE command to use
set dse=$get(%DSEWRAP("alternate"),$ztrnlnm(gtmdist)_"/dse")
if $data(debug) merge debug(debug,"outputreg")=reglist
if reglist="" set $ecode=",U251," quit:$quit 251 quit
; Drive DSE
if 0=nopipe set error=$$dsepipecmd(.output,reglist,dse,cmd)
else set error=$$dsefilecmd(.output,reglist,cmd,isVMS)
use io
if $data(%DSEWRAP("debug")) merge %DSEWRAP("debug")=debug
quit:$quit error quit
; drive DSE through a PIPE device
dsepipecmd(output,regionlist,dse,cmd)
new error,curreg
open "dseproc":(shell="/bin/sh":command=dse)::"pipe"
use "dseproc"
for curreg=2:1:$length(regionlist,",") do
. set region=$piece(regionlist,",",curreg)
. if ($length(region)=0)&($data(debug)) set debug(debug,"reg",curreg)="first"_$c(10)
. if $length(region)>0 do ; should be 0 only when curreg=2
. . write region,! if $data(debug) set debug(debug,"reg",curreg)=region_$c(10)
. . set error=$$parsefhead(.output,1)
. write cmd,! if $data(debug) set debug(debug,"reg",curreg)=$get(debug(debug,"reg",curreg))_cmd
. set error=$$parsefhead(.output,1)
write "exit",!
write /eof
set error=$$parsefhead(.output,1)
close "dseproc"
quit error
; when PIPE devices are not supported drive DSE via a HEREDOC in a script
dsefilecmd(output,regionlist,cmd,isVMS)
new scriptfile,dsecmd,dumpfile,error,i,hdr,ftr,line,ts
set ts="_"_$tr($horolog,",","_")
set scriptfile=$select(isVMS:"dsedump"_ts_".com",1:"dsedump"_ts_".sh")
set dsecmd=$select(isVMS:"@",1:"chmod 755 "_scriptfile_"; ./")_scriptfile
set dumpfile="dsedump.txt"
open scriptfile:newversion use scriptfile
; print the header
set hdr=$select(isVMS:"dsecomhdr",1:"dseshhdr")
for i=1:1 set line=$text(@hdr+i) quit:line["quit" write $piece(line,";",2),!
; print the dump commands per region
for curreg=2:1:$length(regionlist,",") do
. set region=$piece(regionlist,",",curreg)
. if $length(region)>0 write region,! ; should be 0 only when curreg=2
. write cmd,!
; print the footer
set ftr=$select(isVMS:"dsecomftr",1:"dseshftr")
for i=1:1 set line=$text(@ftr+i) quit:line["quit" write $piece(line,";",2),!
; close and execute the script file
close scriptfile
zsystem dsecmd
; read script output and rename the file
open dumpfile:readonly use dumpfile set error=$$parsefhead(.output)
close dumpfile:(rename=dumpfile_ts)
; if no error occurred and debug is UNDEF, delete the script file
if (0=error)&(0=$data(debug)) open scriptfile:readonly close scriptfile:delete
quit error
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; generate the applicable region list
; the output string is a comma separated list of "FIND -REGION=<REGNAME>" and
; not a list of regions. The first piece is always null as a null string
; indicates that the script could find no applicable regions. The second piece
; could be null. If so, that piece represents the first region in which DSE
; starts up
reglist(reglist,isVMS)
; reglist - comma separated list of regions
; isVMS - use '/' (vms) or '-' (unix) for the modifier
; determine GT.CM regions, '::' (vms) vs ':' (unix)
new reg,regavail,i,mod,gtcmKey,regpath
set mod=$select(isVMS:"/",1:"-")
set gtcmKey=$select(isVMS:"::",1:":")
; determine the applicable regions - reglist vs actual available regions
set reglist=$select($get(reglist)="":"*",reglist="ALL":"*",1:reglist)
set regavail=""
if "*"'=reglist for i=1:1:$length(reglist,",") do
. set reg=$piece(reglist,",",i) set regavail(reg)=1 ; define the region
kill reg
for i=1:1 set reg=$view("gvnext",$get(reg)) quit:reg="" do
. set regpath=$VIEW("GVFILE",reg)
. quit:(1<$length(regpath,gtcmKey))
. if ("*"=reglist)!($data(regavail(reg))) do
. . set $piece(regavail,",",$length(regavail,",")+1)=$select(i>1:"find "_mod_"region="_reg,1:"")
quit regavail
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
parsefhead(output,active)
new error,debug,fcnt,field,file,i,line,parsed,region,value
set error=0
if $data(%DSEWRAP("debug")) set debug=$increment(%DSEWRAP("debug"))
if $length($etrap)=0 set $etrap="use $p zshow ""*"" halt"
;
for i=1:1 read line(i):5 quit:error quit:$zeof quit:$select($data(active)=0:0,line(i)["DSE>":1,1:0) do
. if ($test=0)&($length(line(i))=0) write !
. set line=$tr($$FUNC^%TRIM(line(i)),$c(10,13),"")
. quit:($length(line)=0)
. if line["%GTM-E-" set error=1 if $data(%DSEWRAP("debug")) set debug(debug,"error")=line
. if line?1"DSE>".E kill region,file quit ; DSE prompt means reset header information
. quit:line["Error: already in region: " ; ignore already in region error
. if line?1"File"1." ".E set fcnt=$length(line," "),file=$piece(line," ",fcnt) quit
. if line?1"Region"1." ".E do quit
. . set fcnt=$length(line," "),region=$piece(line," ",fcnt)
. . if $data(parsed(region,"File")) kill parsed(region) ; DUPLICATE, throw it away
. . set parsed(region,"File")=file
. quit:$data(region)=0
. if line?1"Date/Time".E set parsed(region,"Date/Time")=$$FUNC^%TRIM($extract(line,10,$length(line))) quit
. ;;; Match stats like output "DRD : #"
. else if line?3(1U,1N)1" : #".E do
. . set field=$$FUNC^%TRIM($piece(line,"0x",1)),value="0x"_$piece(line,"0x",2)
. . do addfield(.parsed,region,field,value)
. ;;; Match lines with " : (0x[0-9A0Z]*| (TRUE|FALSE))" in them
. else if $length(line," : ")>1 do
. . set field=$$FUNC^%TRIM($piece(line," : ",1)),value=$tr($piece(line," : ",2)," ","")
. . do addfield(.parsed,region,field,value)
. ;;; Match all column oriented data
. else do
. . ;;;; Adjust for the varying column width - the order matters
. . if $extract(line,44,45)=" " set $extract(line,44,45)="|" ; dump -all : Snapshot information
. . else if $extract(line,35,42)=" " set $extract(line,35,42)="|" ; dump -all : all after "Full Block Write.*"
. . else if $extract(line,42,43)=" " set $extract(line,42,43)="|" ; dump
. . new columns,col,data,lastfield,lastpiece
. . set columns=$length(line,"|")
. . ;;;; Handle the column data
. . for col=1:1:columns do
. . . set data=$$FUNC^%TRIM($piece(line,"|",col)) ; trim because of "Snapshot in progress"
. . . set lastpiece=$length(data," ")
. . . ;;;;;; Special case - value is a compound statement like "[WAS_ON] OFF"
. . . if (data["State")&(data["[") set lastpiece=$length(data," ")-1
. . . ; value is separated by the last space
. . . set value=$piece(data," ",lastpiece,$length(data," "))
. . . ; take everything but the value and trim off extra spaces
. . . set field=$$FUNC^%TRIM($extract(data,1,($length(data)-$length(value))))
. . . ;;;;;; Special case - fields where value may not exist
. . . if (data?1"Snapshot file name")!(data?1(1"Journal",1"Temp")1" File:") set value="",field=data
. . . ;;;;;; Special case - paired records like those with "Transaction ="
. . . if field="Transaction =" set field=lastfield_" TN" ; handle paired records
. . . if $data(%DSEWRAP("debug")) set debug(debug,i,field)=value
. . . do addfield(.parsed,region,field,value)
. . . set lastfield=field
merge output=parsed
if $data(%DSEWRAP("debug")) do
. merge %DSEWRAP("debug",debug,"line")=line
. set debug(debug,"pipe0ZOEF")=$zeof,debug(debug,"pipe0DEVICE")=$device,debug(debug,"pipe0ZA")=$ZA
. merge %DSEWRAP("debug")=debug
quit:$quit error quit
addfield(var,region,field,value)
if $data(var(region,field))\10 set var(region,field,$increment(var(region,field)))=value
else if $data(var(region,field)) do
. set var(region,field,1)=var(region,field),var(region,field)=2,var(region,field,2)=value
else set var(region,field)=value
quit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
errtrap
use $p
set $etrap="use $principal write $zstatus,! zhalt 1"
set userecode=$piece($ecode,",",2)
set errtext=$select(userecode?1"U"3N:$text(@userecode),1:"")
if $length(errtext) write $text(+0),@$piece(errtext,";",2),!
else write $zstatus,!
if $zlevel<5 zhalt +$extract(userecode,2,$length(userecode))
quit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Scripts to drive DSE via ZSystem
dsecomhdr
;$ define sys$output dsedump.txt
;$ define sys$error dsedump.txt
;$ purge /nolog dsedump.txt
;$ $gtm$dist:dse.exe
quit
dsecomftr
;$ deassign sys$output
;$ deassign sys$error
quit
dseshhdr
;#!/bin/sh
;$gtm_dist/dse > dsedump.txt 2>&1 << EOF
quit
dseshftr
;EOF
quit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error message texts
U251 ;"-F-NOREGIONS none of the target regions exist"
U252 ;"-F-NOPIPENOALTERNATE GT.M "_$zversion_" does not support pipes and cannot drive a different version of GT.M"
U253 ;"-F-ILLEGALDETAIL """_detail_""" is not a valid specification of details to dump"
U254 ;"-F-ILLEGALSELECTION """_what_""" is not a valid selection of what to dump"
U255 ;"-F-BADINVOCATION Must invoke as DO DUMP^"_$text(+0)_"(...)"

70
sr_port/f_get1.c Normal file
View File

@ -0,0 +1,70 @@
/****************************************************************
* *
* Copyright 2012 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 "compiler.h"
#include "toktyp.h"
#include "opcode.h"
#include "indir_enum.h"
#include "mdq.h"
#include "op.h"
#include "fullbool.h"
error_def(ERR_VAREXPECTED);
int f_get1(oprtype *a, opctype op)
{
triple *oldchain, *r;
save_se save_state;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
r = maketriple(OC_NOOP); /* We'll fill in the opcode later, when we figure out what it is */
switch (TREF(window_token))
{
case TK_IDENT:
r->opcode = OC_FNGET1;
if (!lvn(&r->operand[0], OC_SRCHINDX, 0))
return FALSE;
break;
case TK_CIRCUMFLEX:
r->opcode = OC_FNGVGET1;
if (!gvn())
return FALSE;
break;
case TK_ATSIGN:
r->opcode = OC_INDFUN;
r->operand[1] = put_ilit((mint)indir_get);
if (SHIFT_SIDE_EFFECTS)
{ /* with short-circuited booleans move indirect processing to expr_start */
START_GVBIND_CHAIN(&save_state, oldchain);
if (!indirection(&r->operand[0]))
{
setcurtchain(oldchain);
return FALSE;
}
ins_triple(r);
PLACE_GVBIND_CHAIN(&save_state, oldchain);
*a = put_tref(r);
return TRUE;
}
if (!indirection(&(r->operand[0])))
return FALSE;
break;
default:
stx_error(ERR_VAREXPECTED);
return FALSE;
}
ins_triple(r);
*a = put_tref(r);
return TRUE;
}

78
sr_port/f_zpeek.c Normal file
View File

@ -0,0 +1,78 @@
/****************************************************************
* *
* Copyright 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 "compiler.h"
#include "opcode.h"
#include "toktyp.h"
#include "advancewindow.h"
error_def(ERR_COMMA);
#ifdef UNIX
/* Compile 4 parameter $ZPEEK(baseadr,offset,length<,format>) function where:
*
* structid - A string containing a set of mnemonics that identify the structure to fetch from (see op_fnzpeek.c)
* offset - Offset into the block (error if negative).
* length - Length to return (error if negative or > MAX_STRLEN).
* format - Option parm contains single char formatting code (see op_fnzpeek.c)
*/
int f_zpeek(oprtype *a, opctype op)
{
oprtype x;
triple *offset, *length, *format, *r;
mval mv;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
r = maketriple(op);
if (EXPR_FAIL == expr(&(r->operand[0]), MUMPS_STR)) /* Structure identifier string */
return FALSE;
if (TK_COMMA != TREF(window_token))
{
stx_error(ERR_COMMA);
return FALSE;
}
advancewindow();
offset = newtriple(OC_PARAMETER);
r->operand[1] = put_tref(offset);
if (EXPR_FAIL == expr(&(offset->operand[0]), MUMPS_INT))
return FALSE;
if (TK_COMMA != TREF(window_token))
{
stx_error(ERR_COMMA);
return FALSE;
}
advancewindow();
length = newtriple(OC_PARAMETER);
offset->operand[1] = put_tref(length);
if (EXPR_FAIL == expr(&(length->operand[0]), MUMPS_INT))
return FALSE;
format = newtriple(OC_PARAMETER);
length->operand[1] = put_tref(format);
if (TK_COMMA != TREF(window_token))
format->operand[0] = put_str("C", 1); /* Default format if none specified */
else
{
advancewindow();
if (EXPR_FAIL == expr(&(format->operand[0]), MUMPS_STR))
return FALSE;
}
ins_triple(r);
*a = put_tref(r);
return TRUE;
}
#else /* VMS - function not supported here */
int f_zpeek(oprtype *a, opctype op)
{
GTMASSERT;
}
#endif

60
sr_port/f_zwrite.c Normal file
View File

@ -0,0 +1,60 @@
/****************************************************************
* *
* Copyright 2012 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 "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "toktyp.h"
#include "mdq.h"
#include "fullbool.h"
/* $ZWRITE(): Single parameter - string expression */
int f_zwrite(oprtype *a, opctype op)
{
triple *oldchain, *r;
save_se save_state;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
if (TK_ATSIGN != TREF(window_token))
{
r = maketriple(op);
if (EXPR_FAIL == expr(&(r->operand[0]), MUMPS_STR))
return FALSE;
ins_triple(r);
} else
{
r = maketriple(OC_INDFUN);
if (SHIFT_SIDE_EFFECTS)
{
START_GVBIND_CHAIN(&save_state, oldchain);
if (!indirection(&(r->operand[0])))
{
setcurtchain(oldchain);
return FALSE;
}
r->operand[1] = put_ilit((mint)indir_fnzwrite);
ins_triple(r);
PLACE_GVBIND_CHAIN(&save_state, oldchain);
} else
{
if (!indirection(&(r->operand[0])))
return FALSE;
r->operand[1] = put_ilit((mint)indir_fnzwrite);
ins_triple(r);
}
}
*a = put_tref(r);
return TRUE;
}

99
sr_port/glvn_pool.c Normal file
View File

@ -0,0 +1,99 @@
/****************************************************************
* *
* Copyright 2012 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 <stdarg.h>
#include "gtm_stdio.h"
#include "min_max.h"
#include "lv_val.h"
#include <rtnhdr.h>
#include "mv_stent.h"
#include "compiler.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "opcode.h"
#include "glvn_pool.h"
#include "parm_pool.h" /* for CAPACITY_ROUND_UP2 macro */
void glvn_pool_init(void)
{
glvn_pool *pool;
uint4 capacity, mval_capacity, slotoff;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
capacity = INIT_GLVN_POOL_CAPACITY;
mval_capacity = INIT_GLVN_POOL_MVAL_CAPACITY;
slotoff = (uint4)OFFSETOF(glvn_pool, slot[0]);
pool = (glvn_pool *)malloc(ROUND_UP(slotoff, (capacity + 1) * SIZEOF(glvn_pool_entry)));
pool->mval_stack = (mval *)malloc(mval_capacity * SIZEOF(mval));
pool->capacity = capacity;
pool->top = 0;
pool->mval_capacity = mval_capacity;
pool->mval_top = 0;
memset(pool->for_slot, (int)GLVN_POOL_EMPTY, (MAX_FOR_STACK + 1) * SIZEOF(uint4));
TREF(glvn_pool_ptr) = pool;
}
void glvn_pool_expand_slots(void)
{
glvn_pool *pool, *old_pool;
uint4 capacity, slotoff;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
old_pool = TREF(glvn_pool_ptr);
capacity = 2 * old_pool->capacity;
assert(capacity <= MAX_EXPECTED_CAPACITY); /* Don't expect more than this in the test system */
slotoff = (uint4)OFFSETOF(glvn_pool, slot[0]);
pool = (glvn_pool *)malloc(ROUND_UP(slotoff, (capacity + 1) * SIZEOF(glvn_pool_entry)));
memcpy(pool, old_pool, slotoff + old_pool->top * SIZEOF(glvn_pool_entry));
pool->capacity = capacity;
TREF(glvn_pool_ptr) = pool;
free(old_pool);
}
void glvn_pool_expand_mvals(void)
{
glvn_pool *pool;
glvn_pool_entry *slot, *top;
int i, n;
mval *mval_stack, *old_mval_stack;
uint4 mval_capacity;
INTPTR_T shift;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
pool = TREF(glvn_pool_ptr);
mval_capacity = 2 * pool->mval_capacity;
assert(mval_capacity <= MAX_EXPECTED_MVAL_CAPACITY); /* Don't expect more than this in the test system */
old_mval_stack = pool->mval_stack;
mval_stack = (mval *)malloc(mval_capacity * SIZEOF(mval));
memcpy(mval_stack, old_mval_stack, pool->mval_top * SIZEOF(mval));
shift = (INTPTR_T)mval_stack - (INTPTR_T)old_mval_stack;
for (slot = pool->slot, top = slot + pool->top - 1; slot < top; slot++)
{ /* Touch up glvn_info pointers, but leave lvn start alone */
n = slot->glvn_info.n;
assert(n <= MAX_ACTUALS);
if (FIRST_SAVED_ARG(slot))
slot->lvname = (mval *)(shift + (char *)slot->lvname);
for (i = FIRST_SAVED_ARG(slot); i < n; i++)
slot->glvn_info.arg[i] = (void *)(shift + (char *)slot->glvn_info.arg[i]);
}
pool->mval_stack = mval_stack;
pool->mval_capacity = mval_capacity;
free(old_mval_stack);
}

139
sr_port/glvn_pool.h Normal file
View File

@ -0,0 +1,139 @@
/****************************************************************
* *
* Copyright 2012 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. *
* *
****************************************************************/
#ifndef GLVN_POOL_H_INCLUDED
#define GLVN_POOL_H_INCLUDED
#include "callg.h"
#include "compiler.h"
#include "lv_val.h"
/* Here we provide tools for saving identifying information of local or global variables. For local variables this includes
* the variable name itself, as well as copies of each subscript. For global variables we save each argument that needs to
* be later passed into op_gvname/op_gvnaked/op_gvextnam. Note that deferring the op_gvnaked call allows us to achieve
* correct naked indicator flow. For example, in the command SET @"^(subs)"=rhs, the ^() needs to be evaluated relative to
* the expression on the right hand side, and the right hand side needs to happen AFTER the subscripts have been evaluated.
* The structure involved - the "glvn pool" - consists of a stack of entries, each corresponding to a single glvn, and
* a parallel stack of mvals, each corresponding to some parent entry. Both stacks are expandable, doubling in size whenever
* they run out of space. The glvn pool entries can be popped in three different ways. For SET, it's convenient to save the
* glvn pool state, i.e. the top of the array of still-relevant entries. After completion of the set, the pool is restored to
* this state and younger entries popped. With FOR, it's more convenient defer popping until another FOR loop at the same
* nesting level starts. At that time the previously used FOR slot is recycled and everything younger than it is popped.
* Finally, when a non-indirect frame is unwound, all younger pool entries are popped.
*/
#define ANY_SLOT 0
#define FIRST_SAVED_ARG(SLOT) ((OC_SAVLVN == (SLOT)->sav_opcode) ? 1 : 0)
/* To avoid breaking gtmpcat, we retain the 'for_ctrl_stack' field of the frame_pointer struct instead of replacing it
* with a uint4 'glvn_indx' field. The macros manipulate this field. Also for the convenience of gtmpcat: we declare the
* glvn_pool and glvn_pool_entry structs in compiler.h instead of here. This is because gtmpcat does not know to include
* glvn_pool.h when going through gtm_threadgbl_defs.h.
* When gtmpcat is changed to accommodate a new name, these macros and the stack frame struct need to be changed,
* and the glvn_pool structs in compiler.h should probably be moved into this file.
*/
#define GLVN_INDX(FP) ((uint4)(UINTPTR_T)((FP)->for_ctrl_stack))
#define GLVN_POOL_EMPTY ((uint4)-1) /* this must be an "impossible" value for a real pool */
#define GLVN_POOL_SLOTS_AVAILABLE ((TREF(glvn_pool_ptr))->capacity - (TREF(glvn_pool_ptr))->top)
#define GLVN_POOL_MVALS_AVAILABLE ((TREF(glvn_pool_ptr))->mval_capacity - (TREF(glvn_pool_ptr))->mval_top)
#define INIT_GLVN_POOL_CAPACITY 8
#define INIT_GLVN_POOL_MVAL_CAPACITY 64
#define GLVN_POOL_UNTOUCHED 0
#define MAX_EXPECTED_CAPACITY 2048
#define MAX_EXPECTED_MVAL_CAPACITY 2048
#define SLOT_NEEDS_REWIND(INDX) (((TREF(glvn_pool_ptr))->top <= (INDX)) && (GLVN_POOL_EMPTY != (INDX)))
#define SLOT_OPCODE(INDX) ((TREF(glvn_pool_ptr))->slot[INDX].sav_opcode)
#define SET_GLVN_INDX(FP, VALUE) \
{ \
(FP)->for_ctrl_stack = (unsigned char *)(UINTPTR_T)(VALUE); \
}
#define GLVN_POOL_EXPAND_IF_NEEDED \
{ \
if (!TREF(glvn_pool_ptr)) \
glvn_pool_init(); \
else if (!GLVN_POOL_SLOTS_AVAILABLE) \
glvn_pool_expand_slots(); \
}
#define ENSURE_GLVN_POOL_SPACE(SPC) \
{ \
if (GLVN_POOL_MVALS_AVAILABLE < (uint4)(SPC)) \
{ \
glvn_pool_expand_mvals(); \
assert(GLVN_POOL_MVALS_AVAILABLE >= (uint4)(SPC)); \
} \
}
#define GET_GLVN_POOL_STATE(SLOT, M) \
{ /* Find current available SLOT and mval. */ \
uint4 INDX, MVAL_INDX; \
\
INDX = (TREF(glvn_pool_ptr))->share_slot; \
SLOT = &(TREF(glvn_pool_ptr))->slot[INDX]; \
MVAL_INDX = SLOT->mval_top; \
M = &(TREF(glvn_pool_ptr))->mval_stack[MVAL_INDX]; \
}
#define DRAIN_GLVN_POOL_IF_NEEDED \
{ \
int I; \
uint4 INDX, FINDX; \
glvn_pool_entry *SLOT; \
\
if ((GLVN_POOL_UNTOUCHED != GLVN_INDX(frame_pointer)) && !(frame_pointer->flags & SFF_INDCE)) \
{ /* Someone used an ugly FOR control variable or did an indirect set. */ \
INDX = (GLVN_POOL_EMPTY != GLVN_INDX(frame_pointer)) ? GLVN_INDX(frame_pointer) : 0; \
op_glvnpop(INDX); \
for (I = 1; I <= MAX_FOR_STACK; I++) \
{ /* rewind the for_slot array */ \
FINDX = (TREF(glvn_pool_ptr))->for_slot[I]; \
if (SLOT_NEEDS_REWIND(FINDX)) \
{ /* reset to precursor */ \
SLOT = &(TREF(glvn_pool_ptr))->slot[FINDX]; \
assert(!SLOT_NEEDS_REWIND(SLOT->precursor)); \
(TREF(glvn_pool_ptr))->for_slot[I] = SLOT->precursor; \
} else /* no higher FOR levels were used by current frame */ \
break; \
} \
} \
}
#define INSERT_INDSAVGLVN(CTRL, V, RECYCLE, DO_REF) \
{ \
triple *PUSH, *SAV, *PAR; \
\
PUSH = newtriple(OC_GLVNSLOT); \
PUSH->operand[0] = put_ilit((mint)(RECYCLE)); \
CTRL = put_tref(PUSH); \
SAV = newtriple(OC_INDSAVGLVN); \
SAV->operand[0] = V; \
PAR = newtriple(OC_PARAMETER); \
SAV->operand[1] = put_tref(PAR); \
PAR->operand[0] = CTRL; \
PAR->operand[1] = put_ilit((mint)(DO_REF)); /* flag to suppress global reference here */ \
}
void glvn_pool_init(void); /* invoked via GLVN_POOL_EXPAND_IF_NEEDED macro */
void glvn_pool_expand_slots(void); /* invoked via GLVN_POOL_EXPAND_IF_NEEDED macro */
void glvn_pool_expand_mvals(void); /* invoked via ENSURE_GLVN_POOL_SPACE macro */
void op_glvnpop(uint4 indx); /* Used by [SET and $ORDER()] */
uint4 op_glvnslot(uint4 recycle); /* Used by [FOR, SET and $ORDER()] */
void op_indsavglvn(mval *target, uint4 slot, uint4 do_ref); /* Used by [SET and $ORDER()] */
void op_indsavlvn(mval *target, uint4 slot); /* Used by [FOR] */
void op_rfrshgvn(uint4 indx, opctype oc); /* Used by [SET and $ORDER()] */
lv_val *op_rfrshlvn(uint4 indx, opctype oc); /* Used by [FOR, SET and $ORDER()] */
void op_savgvn(UNIX_ONLY_COMMA(int argcnt) mval *val_arg, ...); /* Used by [SET and $ORDER()] */
void op_savlvn(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...); /* Used by [FOR, SET and $ORDER()] */
void op_shareslot(uint4 indx, opctype opcode); /* Used by [FOR, SET and $ORDER()] */
void op_stoglvn(uint4 indx, mval *value); /* Used by [SET] */
#endif /* GLVN_POOL_H_INCLUDED */

146
sr_port/gtm_common_defs.h Normal file
View File

@ -0,0 +1,146 @@
/****************************************************************
* *
* Copyright 2012, 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. *
* *
****************************************************************/
#ifndef GTM_COMMON_DEFS_H
#define GTM_COMMON_DEFS_H
#if defined(__ia64) || defined(__x86_64__) || defined(__sparc) || defined(__s390__) || defined (_AIX)
# define GTM64
#endif
#ifdef GTM64
# define GTM64_ONLY(X) X
# define NON_GTM64_ONLY(X)
#else
# define GTM64_ONLY(X)
# define NON_GTM64_ONLY(X) X
#endif
#ifndef __vms
# define readonly
# define GBLDEF
# define GBLREF extern
# define LITDEF const
# define LITREF extern const
# define error_def(x) LITREF int x
#else
# ifdef __cplusplus
# define GBLDEF
# define GBLREF extern
# define LITDEF const
# define LITREF extern const
# else
# define GBLDEF globaldef
# define GBLREF globalref
# define LITDEF const globaldef
# define LITREF const globalref
# endif
#endif
/* Use GBLDEF to define STATICDEF for variables and STATICFNDEF, STATICFNDCL for functions. Define STATICDEF to "GBLDEF". This way
* we know such usages are intended to be "static" but yet can effectively debug these variables since they are externally
* visible. For functions, do not use the "static" keyword to make them externally visible. Note that a STATICREF for variables
* does not make sense since statics are supposed to be used only within one module.
*/
#define STATICDEF GBLDEF
#define STATICFNDCL extern
#define STATICFNDEF
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#ifndef NULL
# define NULL ((void *) 0)
#endif
#if defined(__ia64) || defined(__MVS__)
# define INTCAST(X) ((int)(X))
# define UINTCAST(X) ((uint4)(X))
# define STRLEN(X) ((int)(strlen(X)))
# define USTRLEN(X) ((unsigned int)(strlen(X)))
# define OFFSETOF(X,Y) ((int)(offsetof(X,Y)))
#else
# define INTCAST(X) X
# define UINTCAST(X) X
# define STRLEN(X) strlen(X)
# define USTRLEN(X) strlen(X)
# define OFFSETOF(X,Y) offsetof(X,Y)
#endif
#ifndef __vms
# define DIR_SEPARATOR '/'
#endif
/* the LITERAL version of the macro should be used over STRING whenever possible for efficiency reasons */
#define STR_LIT_LEN(LITERAL) (SIZEOF(LITERAL) - 1)
#define LITERAL_AND_LENGTH(LITERAL) (LITERAL), (SIZEOF(LITERAL) - 1)
#define LENGTH_AND_LITERAL(LITERAL) (SIZEOF(LITERAL) - 1), (LITERAL)
#define STRING_AND_LENGTH(STRING) (STRING), (STRLEN((char *)(STRING)))
#define LENGTH_AND_STRING(STRING) (strlen((char *)(STRING))), (STRING)
#define LEN_AND_LIT(LITERAL) LENGTH_AND_LITERAL(LITERAL)
#define LIT_AND_LEN(LITERAL) LITERAL_AND_LENGTH(LITERAL)
#define STR_AND_LEN(STRING) STRING_AND_LENGTH(STRING)
#define LEN_AND_STR(STRING) LENGTH_AND_STRING(STRING)
#define ARRAYSIZE(arr) SIZEOF(arr)/SIZEOF(arr[0]) /* # of elements defined in the array */
#define ARRAYTOP(arr) (&arr[0] + ARRAYSIZE(arr)) /* address of the TOP of the array (first byte AFTER
* array limits).Use &arr[0] + size instead of
* &arr[size] to avoid compiler warning.
*/
#define MEMCMP_LIT(SOURCE, LITERAL) memcmp(SOURCE, LITERAL, SIZEOF(LITERAL) - 1)
#define MEMCPY_LIT(TARGET, LITERAL) memcpy(TARGET, LITERAL, SIZEOF(LITERAL) - 1)
#define DIVIDE_ROUND_UP(VALUE, MODULUS) (((VALUE) + ((MODULUS) - 1)) / (MODULUS))
#define DIVIDE_ROUND_DOWN(VALUE, MODULUS) ((VALUE) / (MODULUS))
#define ROUND_UP(VALUE, MODULUS) (DIVIDE_ROUND_UP(VALUE, MODULUS) * (MODULUS))
#define ROUND_DOWN(VALUE, MODULUS) (DIVIDE_ROUND_DOWN(VALUE, MODULUS) * (MODULUS))
/* Macro to copy a source string to a malloced area that is set to the destination pointer.
* Since it is possible that DST might have multiple pointer dereferences in its usage, we
* use a local pointer variable and finally assign it to DST thereby avoiding duplication of
* those pointer dereferences (one for the malloc and one for the strcpy).
* There are two macros depending on whether a string or literal is passed.
*/
#define MALLOC_CPY_STR(DST, SRC) \
{ \
char *mcs_ptr; \
int mcs_len; \
\
mcs_len = STRLEN(SRC) + 1; \
mcs_ptr = malloc(mcs_len); \
memcpy(mcs_ptr, SRC, mcs_len); \
DST = mcs_ptr; \
}
#define MALLOC_CPY_LIT(DST, SRC) \
{ \
char *mcs_ptr; \
int mcs_len; \
\
mcs_len = SIZEOF(SRC); \
mcs_ptr = malloc(mcs_len); \
memcpy(mcs_ptr, SRC, mcs_len); \
DST = mcs_ptr; \
}
#define MALLOC_INIT(DST, SIZ) \
{ \
void *lcl_ptr; \
\
lcl_ptr = malloc(SIZ); \
memset(lcl_ptr, 0, SIZ); \
DST = lcl_ptr; \
}
#endif /* GTM_COMMON_DEFS_H */

134
sr_port/gtm_ipv6.h Normal file
View File

@ -0,0 +1,134 @@
/****************************************************************
* *
* Copyright 2001, 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. *
* *
****************************************************************/
/* gtm_ipv6.h - interlude to <sys/socket.h> system header file. */
#ifndef GTM_IPV6H
#define GTM_IPV6H
#include <gtm_netdb.h> /* Make sure we have AI_V4MAPPED/AI_NUMERICSERV defined if available */
GBLREF boolean_t ipv4_only; /* If TRUE, only use AF_INET. */
/* ai_canonname must be set NULL for AIX. Otherwise, freeaddrinfo() freeing the ai_canonname will hit SIG-11
* other field which were not initialized as 0 will also causes getaddrinfo()to fail
* Setting AI_PASSIVE will give you a wildcard address if addr is NULL, i.e. INADDR_ANY or IN6ADDR_ANY
* AI_NUMERICSERV is to pass the numeric port to address, it is to inhibit the name resolution to improve efficience
* AI_ADDRCONFIG: IPv4 addresses are returned only if the local system has at least one IPv4 address
configured; IPv6 addresses are only returned if the local system has at least one IPv6
address configured. For now we only use IPv6 address. So not use this flag here.
* AI_V4MAPPED: IPv4 mapped addresses are acceptable
* (Note: for snail, AI_V4MAPPED is defined but AI_NUMERICSERV is not defined)
*/
#if (defined(__hppa) || defined(__vms) || defined(__osf__))
#define GTM_IPV6_SUPPORTED FALSE
#else
#define GTM_IPV6_SUPPORTED TRUE
#endif
#if !GTM_IPV6_SUPPORTED
#define SERVER_HINTS(hints, af) \
{ \
assert(AF_INET6 != af); \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = AF_INET; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = AI_PASSIVE; \
}
#define CLIENT_HINTS(hints) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = AF_INET; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = 0; \
}
#define CLIENT_HINTS_AF(hints, af) \
{ \
assert(AF_INET == af); \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = AF_INET; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = 0; \
}
#elif (defined(AI_V4MAPPED) && defined(AI_NUMERICSERV))
#define SERVER_HINTS(hints, af) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = af; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = AI_V4MAPPED | AI_PASSIVE | AI_NUMERICSERV; \
}
#define CLIENT_HINTS(hints) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = (ipv4_only ? AF_INET : AF_UNSPEC); \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; \
}
#define CLIENT_HINTS_AF(hints, af) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = af; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = AI_V4MAPPED; \
}
#else
#error "Ok, so we do have non-AI_V4MAPPED/AI_NUMERICSERV machines with IPv6 support"
#define SERVER_HINTS(hints, af) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = af; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = AI_PASSIVE; \
}
#define CLIENT_HINTS(hints) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = (ipv4_only ? AF_INET : AF_UNSPEC); \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = AI_ADDRCONFIG; \
}
#define CLIENT_HINTS_AF(hints, af) \
{ \
memset(&hints, 0, SIZEOF(struct addrinfo)); \
hints.ai_family = AF_INET; \
hints.ai_socktype = SOCK_STREAM; \
hints.ai_protocol = IPPROTO_TCP; \
hints.ai_flags = 0; \
}
#endif
#define FREEADDRINFO(ai_ptr) \
{ \
if(ai_ptr) \
freeaddrinfo(ai_ptr); \
}
union gtm_sockaddr_in46
{
struct sockaddr_in ipv4;
# if GTM_IPV6_SUPPORTED
struct sockaddr_in6 ipv6;
# endif
};
#endif

View File

@ -0,0 +1,51 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_stdio.h"
#include "gtm_unistd.h"
#include "gtm_socket.h"
#include "io.h"
#include "iotcpdef.h"
#include "iotcproutine.h"
#include "iosocketdef.h"
#include "gtmio.h"
GBLREF io_log_name *io_root_log_name;
void iosocket_destroy (io_desc *ciod)
{
io_log_name **lpp, *lp; /* logical name pointers */
d_socket_struct *dsocketptr;
assertpro(ciod->type == gtmsocket);
assertpro(ciod->state == dev_closed);
dsocketptr = (d_socket_struct *) ciod->dev_sp;
assertpro(dsocketptr != NULL);
for (lpp = &io_root_log_name, lp = *lpp; lp; lp = *lpp)
{
if (lp->iod->pair.in == ciod)
{
/* The only device that may be "split" is the principal device. Since it is permanently open,
* it will never get here.
*/
assert(lp->iod == ciod);
assert(lp->iod->pair.out == ciod);
*lpp = (*lpp)->next;
free(lp);
}
else
lpp = &lp->next;
}
free(dsocketptr);
free(ciod);
}

View File

@ -0,0 +1,35 @@
/****************************************************************
* *
* Copyright 2012 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 "error.h"
#include "mlkdef.h"
#include "lock_str_to_buff.h"
#include "gtm_string.h"
#include "zshow.h"
/* Takes a lock as input and outputs lock name to string to buff (terminated with NULL). This is called from op_lock2.
* This function consolidates "output" variable initialization and name string formatting into one function.
*/
void lock_str_to_buff(mlk_pvtblk *pvt_ptr, char *outbuff, int outbuff_len)
{
mval v;
zshow_out output;
memset(&output, 0, SIZEOF(output));
output.type = ZSHOW_BUFF_ONLY; /* This setting only changes out->ptr the other fileds are ignored */
output.buff = &outbuff[0];
output.size = outbuff_len;
output.ptr = output.buff;
zshow_format_lock(&output,pvt_ptr);
*output.ptr = '\0';
return;
}

View File

@ -0,0 +1,17 @@
/****************************************************************
* *
* Copyright 2012 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. *
* *
****************************************************************/
#ifndef LOCK_STR_TO_BUFF_H
#define LOCK_STR_TO_BUFF_H
void lock_str_to_buff(mlk_pvtblk *pvt_ptr1, char *outbuff, int outbuff_len);
#endif

38
sr_port/mpiece.mpt Normal file
View File

@ -0,0 +1,38 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Copyright 2012 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. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%MPIECE(str,delim,newdelim)
; Replace one or more consecutive occurrences of input parameter
; 'delim' with one 'newdelim' in parameter 'str' so that you can
; use $piece on the result.
; This lets us use $piece like AWK does
new dlen,i,lastch,len,next,output,substr
; convert tabs to spaces when delim is not specified
if $length($get(delim))=0 set str=$translate(str,$char(9),$char(32))
set newdelim=$get(newdelim,$char(32)) ; default to space
set delim=$get(delim,$char(32)) ; default to space
set len=$zlength(str),lastch=1,dlen=$zlength(delim)
; $zfind to the first occurrence of delim after lastch
for i=1:1 quit:lastch>len set next=$zfind(str,delim,lastch) quit:'next do
. ; append non-null extract of str from lastch to next
. set substr=$zextract(str,lastch,next-(1+dlen))
. if $zlength(substr) set output=$get(output)_substr_newdelim
. ; advance until the next non-delim character
. for lastch=next:1:(len+1) quit:($zextract(str,lastch)'=delim)
; append the remainder of str
if lastch<(len+1) set output=$get(output)_$zextract(str,lastch,len)
quit $get(output)
; split a string into an array like AWK split does
SPLIT(str,delim)
new outstr,i
set outstr=$$^%MPIECE(str,$get(delim,$char(32)),$char(0))
for i=1:1:$zlength(outstr,$char(0)) set fields(i)=$zpiece(outstr,$char(0),i)
if $data(fields)<10 set $ECODE=",U117,"
quit *fields

16
sr_port/mtables.h Normal file
View File

@ -0,0 +1,16 @@
/****************************************************************
* *
* Copyright 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. *
* *
****************************************************************/
#ifndef MTABLE_H_DEFINED
#define MTABLE_H_DEFINED
void mtables_chk(void); /* Routine invoked in debug builds to check some mtable assertions */
#endif

View File

@ -0,0 +1,36 @@
/****************************************************************
* *
* Copyright 2012 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 "op.h"
#include "mupip_put_gvn_fragment.h"
#include "mv_stent.h"
void mupip_put_gvn_fragment(char *cp,int len, int val_off1, int val_len1)
{
mval *u, v;
mv_stent *mv_stacktop;
PUSH_MV_STENT(MVST_MVAL); /* protect mval value from stp_gcol */
mv_stacktop = mv_chain;
u = &mv_chain->mv_st_cont.mvs_mval;
u->str.len = 0;
u->mvtype = 0;
op_fngvget1(u);
v.mvtype = MV_STR;
v.str.addr = cp;
v.str.len = len;
op_setzextract(u, &v, val_off1+1, (val_off1 + val_len1), u);
op_gvput(u);
assertpro(mv_stacktop == mv_chain);
POP_MV_STENT();
return;
}

View File

@ -0,0 +1,17 @@
/****************************************************************
* *
* Copyright 2012 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. *
* *
****************************************************************/
#ifndef MUPIP_PUT_GVN_FRAGMENT_INCLUDED
#define MUPIP_PUT_GVN_FRAGMENT_INCLUDED
void mupip_put_gvn_fragment(char *cp, int len, int val_off1, int val_len1);
#endif /* MUPIP_PUT_GVN_FRAGMENT_INCLUDED */

28
sr_port/op_fnget1.c Normal file
View File

@ -0,0 +1,28 @@
/****************************************************************
* *
* Copyright 2012 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 "op.h"
/* This code is similar in function to opp_fnget (assembler) except, if src is undefined, this returns an undefined value to signal
* op_fnget2, which, in turn, returns a specified "default" value; this slight of hand deals with order of evaluation issues.
*/
void op_fnget1(mval *src, mval *dst)
{
if (src && MV_DEFINED(src))
{
*dst = *src;
dst->mvtype &= ~MV_ALIASCONT; /* Make sure alias container property does not pass */
}
else
dst->mvtype = 0;
return;
}

44
sr_port/op_fnzwrite.c Normal file
View File

@ -0,0 +1,44 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "stringpool.h"
#include "op.h"
#include "zshow.h"
error_def(ERR_MAXSTRLEN);
/* Routine to return a string in zwrite format */
void op_fnzwrite(mval* src, mval* dst)
{
int dst_len, str_len;
MV_FORCE_STR(src);
MV_FORCE_NUM(src);
if MV_IS_CANONICAL(src)
*dst = *src;
else
{
str_len = ZWR_EXP_RATIO(src->str.len);
ENSURE_STP_FREE_SPACE((int)str_len);
DBG_MARK_STRINGPOOL_UNEXPANDABLE;
format2zwr((sm_uc_ptr_t)src->str.addr, src->str.len, (uchar_ptr_t)stringpool.free, &dst_len);
DBG_MARK_STRINGPOOL_EXPANDABLE;
if (MAX_STRLEN < dst_len)
rts_error(VARLSTCNT(1) ERR_MAXSTRLEN);
dst->str.addr = (char *)stringpool.free; /* deferred in case dst == str */
dst->str.len = dst_len;
dst->mvtype = MV_STR;
assert((unsigned char *)(dst->str.addr + dst_len) <= stringpool.top);
stringpool.free = (unsigned char *)(dst->str.addr + dst_len);
}
}

43
sr_port/op_glvnpop.c Normal file
View File

@ -0,0 +1,43 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
void op_glvnpop(uint4 indx)
{
glvn_pool_entry *slot;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
slot = &(TREF(glvn_pool_ptr))->slot[indx];
(TREF(glvn_pool_ptr))->top = indx;
(TREF(glvn_pool_ptr))->mval_top = slot->mval_top;
}

68
sr_port/op_glvnslot.c Normal file
View File

@ -0,0 +1,68 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
GBLREF stack_frame *frame_pointer;
/* Finds a slot in the glvn pool for saving a variable name. Used by SET and FOR */
uint4 op_glvnslot(uint4 recycle)
{
glvn_pool_entry *slot;
uint4 indx, findx;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
GLVN_POOL_EXPAND_IF_NEEDED;
indx = (TREF(glvn_pool_ptr))->top;
if (GLVN_POOL_UNTOUCHED == GLVN_INDX(frame_pointer))
/* low water mark - drain back to here when frame is unwound */
SET_GLVN_INDX(frame_pointer, (indx) ? indx : GLVN_POOL_EMPTY);
slot = &(TREF(glvn_pool_ptr))->slot[indx];
slot->sav_opcode = OC_NOOP; /* flag the slot as not filled out in case something goes wrong */
if (ANY_SLOT != recycle)
{ /* attempt to reuse slot (for FOR control) */
assert((0 < recycle) && (recycle <= MAX_FOR_STACK));
findx = (TREF(glvn_pool_ptr))->for_slot[recycle];
if (((GLVN_INDX(frame_pointer) <= findx) || (GLVN_POOL_EMPTY == GLVN_INDX(frame_pointer))) && (findx < indx))
{ /* reuse and pop anything beyond it */
slot = &(TREF(glvn_pool_ptr))->slot[findx];
(TREF(glvn_pool_ptr))->top = findx + 1;
(TREF(glvn_pool_ptr))->mval_top = slot->mval_top;
return findx;
}
/* point new slot's precursor field at indx, which corresponds an earlier frame */
(TREF(glvn_pool_ptr))->for_slot[recycle] = indx;
slot->precursor = (findx < indx) ? findx : GLVN_POOL_EMPTY;
}
slot->mval_top = (TREF(glvn_pool_ptr))->mval_top;
return (TREF(glvn_pool_ptr))->top++;
}

21
sr_port/op_igetdst.c Normal file
View File

@ -0,0 +1,21 @@
/****************************************************************
* *
* Copyright 2012 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 "op.h"
mval *op_igetdst(void)
{
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
return TREF(ind_result); /* see comment in comp_init.c */
}

62
sr_port/op_indfnname2.c Normal file
View File

@ -0,0 +1,62 @@
/****************************************************************
* *
* Copyright 2012 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 "mvalconv.h"
#include "op.h"
#include "is_canonic_name.h"
error_def(ERR_FNNAMENEG);
error_def(ERR_NOCANONICNAME);
/*
* Removes extra subscripts from result of op_indfnname. Similar to $QLENGTH and $QSUBSCRIPT.
* E.g. $name(@"x(6,7,8)",2):
* 1. Do op_indfnname and find ALL subscripts --> "x(6,7,8)"
* 2. Evaluate second argument --> 2
* 3. Using the results of the previous two steps, do op_indfnname2 to remove extra subscripts --> "x(6,7)"
*/
void op_indfnname2(mval *finaldst, mval *depthval, mval *prechomp)
{
int depth, dummy, start, subscripts;
char *c;
MV_FORCE_STR(prechomp);
depth = MV_FORCE_INT(depthval);
if (depth < 0)
rts_error(VARLSTCNT(1) ERR_FNNAMENEG);
subscripts = depth + 1;
*finaldst = *prechomp;
if (subscripts > MAX_LVSUBSCRIPTS)
return;
if (!is_canonic_name(prechomp, &subscripts, &start, &dummy))
{ /* op_indfnname should have passed us a valid name */
assert(FALSE);
rts_error(VARLSTCNT(4) ERR_NOCANONICNAME, 2, prechomp->str.len, prechomp->str.addr);
}
if (start)
{ /* indeed have subscripts to remove */
c = finaldst->str.addr + start - 1;
if ('"' == *c)
{
c--;
start--;
}
assert(('(' == *c) || (',' == *c));
if ('(' == *c)
start--;
else
*c = ')';
finaldst->str.len = start;
}
return;
}

54
sr_port/op_indget1.c Normal file
View File

@ -0,0 +1,54 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
LITREF mval literal_null;
/* [Used by SET] Get the value of a saved local or global variable. Return literal_null by default. */
void op_indget1(uint4 indx, mval *dst)
{
lv_val *lv;
opctype oc;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
oc = (TREF(glvn_pool_ptr))->slot[indx].sav_opcode;
if (OC_SAVLVN == oc)
{ /* lvn */
lv = op_rfrshlvn(indx, OC_PUTINDX);
op_fnget2((mval *)lv, (mval *)&literal_null, dst);
} else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */
{ /* gvn */
op_rfrshgvn(indx, oc);
op_fngvget(dst);
}
}

44
sr_port/op_indget2.c Normal file
View File

@ -0,0 +1,44 @@
/****************************************************************
* *
* Copyright 2012 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 "compiler.h"
#include "opcode.h"
#include "op.h"
#include "lv_val.h"
#include "mvalconv.h"
#include "glvn_pool.h"
error_def(ERR_ORDER2);
error_def(ERR_VAREXPECTED);
void op_indget2(mval *dst, uint4 indx)
{
glvn_pool_entry *slot;
lv_val *lv;
opctype oc;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
slot = &((TREF(glvn_pool_ptr))->slot[indx]);
oc = slot->sav_opcode;
if (OC_SAVLVN == oc)
{ /* lvn */
lv = op_rfrshlvn(indx, OC_RFRSHLVN); /* funky opcode prevents UNDEF in rfrlvn */
op_fnget1((mval *)lv, dst);
} else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */
{ /* gvn */
op_rfrshgvn(indx, oc);
op_fngvget1(dst);
}
return;
}

54
sr_port/op_indmerge2.c Normal file
View File

@ -0,0 +1,54 @@
/****************************************************************
* *
* Copyright 2012 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 "gdsroot.h"
#include "gdskill.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "compiler.h"
#include "opcode.h"
#include "op.h"
#include "lv_val.h"
#include "mvalconv.h"
#include "glvn_pool.h"
#include "merge_def.h"
#include "filestruct.h"
#include "gdscc.h"
#include "copy.h"
#include "jnl.h"
#include "buddy_list.h"
#include "hashtab_int4.h" /* needed for tp.h */
#include "tp.h"
#include "gvname_info.h"
#include "op_merge.h"
void op_indmerge2(uint4 indx)
{
lv_val *lv;
opctype oc;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
if (OC_SAVLVN == (oc = SLOT_OPCODE(indx))) /* note assignment */
{ /* lvn */
lv = op_rfrshlvn(indx, OC_PUTINDX);
op_merge_arg(MARG1_LCL, lv);
} else if (OC_NOOP != oc)
{ /* gvn */
op_rfrshgvn(indx, oc);
op_merge_arg(MARG1_GBL, NULL);
}
return;
}

121
sr_port/op_indsavglvn.c Normal file
View File

@ -0,0 +1,121 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
error_def(ERR_VAREXPECTED);
/* [Used by SET] Saves an indirect variable in the glvn pool and returns its index. Maintain in parallel with op_indsavlvn. */
void op_indsavglvn(mval *target, uint4 slot, uint4 do_ref)
{
icode_str indir_src;
int rval;
mstr *obj, object;
oprtype v, getdst;
opctype put_oc;
triple *s, *s1, *sub, *share;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
MV_FORCE_STR(target);
indir_src.str = target->str;
indir_src.code = do_ref ? indir_savglvn1 : indir_savglvn0; /* must differenitate the 2 code variants */
if (NULL == (obj = cache_get(&indir_src)))
{
obj = &object;
comp_init(&target->str, &getdst);
share = maketriple(OC_SHARESLOT);
share->operand[0] = getdst;
switch (TREF(window_token))
{
case TK_IDENT:
if (EXPR_FAIL != (rval = lvn(&v, OC_SAVLVN, NULL))) /* NOTE assignment */
{
s = v.oprval.tref;
if (OC_SAVLVN != s->opcode)
{ /* No subscripts. Still, let's do savindx */
s = newtriple(OC_SAVLVN);
s->operand[0] = put_ilit(1);
s->operand[1] = v;
}
share->operand[1] = put_ilit(OC_SAVLVN);
dqins(s->exorder.bl, exorder, share);
}
break;
case TK_CIRCUMFLEX:
s1 = (TREF(curtchain))->exorder.bl;
if (EXPR_FAIL != (rval = gvn())) /* NOTE assignment */
{
for (sub = (TREF(curtchain))->exorder.bl; sub != s1; sub = sub->exorder.bl)
{
put_oc = sub->opcode;
if ((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc) || (OC_GVEXTNAM == put_oc))
break;
}
assert((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc) || (OC_GVEXTNAM == put_oc));
if (!do_ref)
sub->opcode = OC_SAVGVN; /* steal gv bind action to suppress global reference */
else
{ /* or replicate it to cause bind to update $R before save */
s = maketriple(OC_SAVGVN);
s->operand[0] = sub->operand[0];
s->operand[1] = sub->operand[1];
dqins(sub, exorder, s);
}
share->operand[1] = put_ilit(put_oc);
dqins(sub->exorder.bl, exorder, share);
}
break;
case TK_ATSIGN:
if (EXPR_FAIL != (rval = indirection(&v))) /* NOTE assignment */
{
s = newtriple(OC_INDSAVGLVN);
s->operand[0] = v;
s1 = newtriple(OC_PARAMETER);
s->operand[1] = put_tref(s1);
s1->operand[0] = getdst;
s1->operand[1] = put_ilit(do_ref); /* pass along flag to control global reference */
}
break;
default:
stx_error(ERR_VAREXPECTED);
rval = EXPR_FAIL;
break;
}
if (EXPR_FAIL == comp_fini(rval, obj, OC_RET, NULL, NULL, target->str.len))
return;
indir_src.str.addr = target->str.addr;
cache_put(&indir_src, obj);
assert(NULL != cache_get(&indir_src));
}
TREF(ind_result) = (mval *)(UINTPTR_T)slot;
comp_indr(obj);
}

93
sr_port/op_indsavlvn.c Normal file
View File

@ -0,0 +1,93 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
error_def(ERR_VAREXPECTED);
/* [Used by FOR] Same as op_indsavglvn, but only allows local variables. Compare with op_indlvadr. */
void op_indsavlvn(mval *target, uint4 slot)
{
icode_str indir_src;
int rval;
mstr *obj, object;
oprtype v, getdst;
triple *s, *share;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
MV_FORCE_STR(target);
indir_src.str = target->str;
indir_src.code = indir_savlvn;
if (NULL == (obj = cache_get(&indir_src)))
{
obj = &object;
comp_init(&target->str, &getdst);
share = maketriple(OC_SHARESLOT);
share->operand[0] = getdst;
switch (TREF(window_token))
{
case TK_IDENT:
if (EXPR_FAIL != (rval = lvn(&v, OC_SAVLVN, NULL))) /* NOTE assignment */
{
s = v.oprval.tref;
if (OC_SAVLVN != s->opcode)
{ /* No subscripts. Still, let's do savindx */
s = newtriple(OC_SAVLVN);
s->operand[0] = put_ilit(1);
s->operand[1] = v;
}
share->operand[1] = put_ilit(OC_SAVLVN);
dqins(s->exorder.bl, exorder, share);
}
break;
case TK_ATSIGN:
if (EXPR_FAIL != (rval = indirection(&v))) /* NOTE assignment */
{
s = newtriple(OC_INDSAVLVN);
s->operand[0] = v;
s->operand[1] = getdst;
}
break;
default:
stx_error(ERR_VAREXPECTED);
rval = EXPR_FAIL;
break;
}
if (EXPR_FAIL == comp_fini(rval, obj, OC_RET, NULL, NULL, target->str.len))
return;
indir_src.str.addr = target->str.addr;
cache_put(&indir_src, obj);
assert(NULL != cache_get(&indir_src));
}
TREF(ind_result) = (mval *)(UINTPTR_T)slot;
comp_indr(obj);
}

34
sr_port/op_litc.c Normal file
View File

@ -0,0 +1,34 @@
/****************************************************************
* *
* Copyright 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 "cmd_qlf.h"
#include "op.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "stringpool.h"
GBLREF stack_frame *frame_pointer;
void op_litc(mval *dst, mval *src)
{
# ifdef USHBIN_SUPPORTED
assert(DYNAMIC_LITERALS_ENABLED(frame_pointer->rvector));
assert((char *)frame_pointer->literal_ptr == (char *)frame_pointer->rvector->literal_adr);
assert(MVAL_IN_RANGE(src, frame_pointer->literal_ptr, frame_pointer->rvector->literal_len)); /* src is a literal mval */
assert(!MVAL_IN_RANGE(dst, frame_pointer->literal_ptr, frame_pointer->rvector->literal_len)); /* dst is NOT a literal */
*dst = *src;
dst->str.addr += (INTPTR_T)(frame_pointer->rvector->literal_text_adr);
# else
assert(FALSE);
# endif
return;
}

47
sr_port/op_rfrshgvn.c Normal file
View File

@ -0,0 +1,47 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "compiler.h"
#include "opcode.h"
#include "op.h"
#include "gtm_string.h"
#include "callg.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "glvn_pool.h"
/* [Used by SET] */
void op_rfrshgvn(uint4 indx, opctype oc)
{
glvn_pool_entry *slot;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
slot = &(TREF(glvn_pool_ptr))->slot[indx];
assert(MAX_ACTUALS >= slot->glvn_info.n);
switch (oc)
{
case OC_GVNAME:
callg((callgfnptr)op_gvname, (gparam_list *)&slot->glvn_info);
break;
case OC_GVNAKED:
callg((callgfnptr)op_gvnaked, (gparam_list *)&slot->glvn_info);
break;
case OC_GVEXTNAM:
callg((callgfnptr)op_gvextnam, (gparam_list *)&slot->glvn_info);
break;
default:
GTMASSERT;
}
}

86
sr_port/op_rfrshlvn.c Normal file
View File

@ -0,0 +1,86 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
GBLREF bool undef_inhibit;
GBLREF symval *curr_symval;
error_def(ERR_UNDEF);
/* [Used by FOR, SET and $ORDER()] Looks up a saved local variable. */
lv_val *op_rfrshlvn(uint4 indx, opctype oc)
{
glvn_pool_entry *slot;
ht_ent_mname *tabent;
mname_entry targ_key;
lv_val *lv;
lvname_info *lvn_info;
unsigned char buff[512], *end;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
slot = &(TREF(glvn_pool_ptr))->slot[indx];
assert(OC_SAVLVN == slot->sav_opcode);
targ_key.var_name = slot->lvname->str;
COMPUTE_HASH_MNAME(&targ_key);
targ_key.marked = FALSE;
if (add_hashtab_mname_symval(&curr_symval->h_symtab, &targ_key, NULL, &tabent))
lv_newname(tabent, curr_symval);
lvn_info = (lvname_info *)&slot->glvn_info;
lvn_info->start_lvp = (lv_val *)tabent->value;
switch (oc)
{
case OC_RFRSHLVN: /* no UNDEF for $ORDER()/$GET() from srchindx nor bogus opcode, so borrow "impossible" opcode */
return (lv_val *)callg((callgfnptr)op_srchindx, (gparam_list *)lvn_info);
break;
case OC_PUTINDX:
lv = (lv_val *)callg((callgfnptr)op_putindx, (gparam_list *)lvn_info);
break;
case OC_SRCHINDX:
lv = (lv_val *)callg((callgfnptr)op_srchindx, (gparam_list *)lvn_info);
if (NULL == lv)
{ /* This path is currently only used by FOR. Issue UNDEF error even if NOUNDEF is enabled. */
end = format_key_mvals(buff, SIZEOF(buff), lvn_info);
rts_error(VARLSTCNT(4) ERR_UNDEF, 2, end - buff, buff);
assert(FALSE);
}
break;
case OC_M_SRCHINDX:
/* not currently used */
lv = (lv_val *)callg((callgfnptr)op_m_srchindx, (gparam_list *)lvn_info);
break;
default:
GTMASSERT;
}
assert(lv);
return lv;
}

68
sr_port/op_savgvn.c Normal file
View File

@ -0,0 +1,68 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
GBLREF spdesc stringpool;
/* [Used by SET] Saves a global in the glvn pool and returns its index. */
void op_savgvn(UNIX_ONLY_COMMA(int argcnt) mval *val_arg, ...)
{
va_list var;
mval *m, *key;
glvn_pool_entry *slot;
gparam_list *gvn_info;
int i;
VMS_ONLY(int argcnt;)
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
VAR_START(var, val_arg);
VMS_ONLY(va_count(argcnt));
ENSURE_GLVN_POOL_SPACE(argcnt);
GET_GLVN_POOL_STATE(slot, m);
gvn_info = (gparam_list *)&slot->glvn_info;
gvn_info->n = argcnt;
key = val_arg;
for (i = 0; ; )
{
*m = *key;
gvn_info->arg[i] = m;
(TREF(glvn_pool_ptr))->mval_top++;
if (MV_IS_STRING(m) && !IS_IN_STRINGPOOL(m->str.addr, m->str.len))
s2pool(&m->str);
m++;
if (++i < argcnt)
key = va_arg(var, mval *);
else
break;
}
}

79
sr_port/op_savlvn.c Normal file
View File

@ -0,0 +1,79 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
GBLREF spdesc stringpool;
/* [Used by FOR, SET and $ORDER()] Saves a local in the glvn pool and returns its index. */
void op_savlvn(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...)
{
glvn_pool_entry *slot;
int i;
VMS_ONLY(int argcnt;)
lvname_info *lvn_info;
mident *lvent;
mname_entry *targ_key;
mval *m, *key;
unsigned char *c, *ptr;
va_list var;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
VAR_START(var, start);
VMS_ONLY(va_count(argcnt));
ENSURE_GLVN_POOL_SPACE(argcnt);
/* Get variable name and store it in the stringpool. */
GET_GLVN_POOL_STATE(slot, m);
assert(OC_SAVLVN == slot->sav_opcode);
ENSURE_STP_FREE_SPACE(SIZEOF(mident_fixed));
slot->lvname = m;
m->mvtype = MV_STR; /* needs to be protected if garbage collection happens during s2pool below */
lvent = &slot->lvname->str;
ptr = stringpool.free;
c = format_lvname(start, ptr, SIZEOF(mident_fixed));
lvent->addr = (char *)ptr;
lvent->len = (char *)c - (char *)ptr;
stringpool.free = c;
m++;
(TREF(glvn_pool_ptr))->mval_top++;
lvn_info = (lvname_info *)&slot->glvn_info;
lvn_info->total_lv_subs = argcnt--;
for (i = 0; i < argcnt; i++, m++)
{ /* now all the pieces of the key */
key = va_arg(var, mval *);
*m = *key;
lvn_info->lv_subs[i] = m;
(TREF(glvn_pool_ptr))->mval_top++;
if (MV_IS_STRING(m) && !IS_IN_STRINGPOOL(m->str.addr, m->str.len))
s2pool(&m->str);
}
}

43
sr_port/op_shareslot.c Normal file
View File

@ -0,0 +1,43 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
void op_shareslot(uint4 indx, opctype opcode)
{
glvn_pool_entry *slot;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
(TREF(glvn_pool_ptr))->share_slot = indx;
slot = &(TREF(glvn_pool_ptr))->slot[indx];
slot->sav_opcode = opcode;
}

52
sr_port/op_stoglvn.c Normal file
View File

@ -0,0 +1,52 @@
/****************************************************************
* *
* Copyright 2012 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 "lv_val.h"
#include "toktyp.h"
#include "compiler.h"
#include "opcode.h"
#include "indir_enum.h"
#include "cache.h"
#include "op.h"
#include <rtnhdr.h>
#include "valid_mname.h"
#include "gtm_string.h"
#include "cachectl.h"
#include "gtm_text_alloc.h"
#include "callg.h"
#include "mdq.h"
#include "stack_frame.h"
#include "stringpool.h"
#include "mv_stent.h"
#include "min_max.h"
#include "glvn_pool.h"
/* [Used by SET] Store a value in a saved local or global variable. */
void op_stoglvn(uint4 indx, mval *value)
{
lv_val *lv;
opctype oc;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
oc = (TREF(glvn_pool_ptr))->slot[indx].sav_opcode;
if (OC_SAVLVN == oc)
{ /* lvn */
lv = op_rfrshlvn(indx, OC_PUTINDX);
lv->v = *value;
} else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */
{ /* gvn */
op_rfrshgvn(indx, oc);
op_gvput(value);
}
}

32
sr_port/op_stolitc.c Normal file
View File

@ -0,0 +1,32 @@
/****************************************************************
* *
* Copyright 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 "cmd_qlf.h"
#include "op.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "stringpool.h"
GBLREF stack_frame *frame_pointer;
void op_stolitc(mval *val)
{
# ifdef USHBIN_SUPPORTED
assert(DYNAMIC_LITERALS_ENABLED(frame_pointer->rvector));
assert((char *)frame_pointer->literal_ptr == (char *)frame_pointer->rvector->literal_adr);
assert(!MVAL_IN_RANGE(val, frame_pointer->literal_ptr, frame_pointer->rvector->literal_len)); /* val is NOT a literal */
val->str.addr += (INTPTR_T)(frame_pointer->rvector->literal_text_adr);
# else
assert(FALSE);
# endif
return;
}

View File

@ -0,0 +1,145 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h" /* for the RESET_GV_TARGET macro which in turn uses "memcmp" */
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "probe.h"
#include "gdsfhead.h"
#include "error.h"
#include "gdskill.h"
#include "filestruct.h"
#include "jnl.h"
#include "buddy_list.h" /* needed for tp.h */
#include "gdscc.h"
#include "hashtab_int4.h" /* needed for tp.h */
#include "tp.h"
#include "interlock.h"
#include "preemptive_db_clnup.h"
#include "add_inter.h"
#include "gtmimagename.h"
#include "t_abort.h"
#include "dpgbldir.h"
GBLREF gv_namehead *reset_gv_target;
GBLREF gv_namehead *gv_target;
GBLREF sgmnt_addrs *kip_csa;
GBLREF uint4 dollar_tlevel;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF sgm_info *first_sgm_info;
GBLREF boolean_t need_kip_incr;
GBLREF uint4 update_trans;
/* container for all the common chores that need to be performed on error conditions */
#define CLEAR_CSE(GVNH) \
{ \
gv_namehead *gvnh; \
srch_blk_status *s; \
\
gvnh = GVNH; \
if (NULL != gvnh) \
{ \
for (s = &gvnh->hist.h[0]; s->blk_num; s++) \
s->cse = NULL; \
} \
}
void preemptive_db_clnup(int preemptive_severe)
{
sgmnt_addrs *csa;
sgm_info *si;
gd_region *r_top, *reg;
gd_addr *addr_ptr;
if (!dollar_tlevel && update_trans)
{ /* It's possible we hit an error in the middle of an update, at which point we have
* a valid clue and non-NULL cse. However, this causes problems for subsequent
* transactions (see comment in t_begin). In particular we could end up pinning buffers
* unnecessarily. So clear the cse of any histories that may have been active during the update.
*/
CLEAR_CSE(gv_target);
if ((NULL != gv_target) && (NULL != gv_target->gd_csa))
{
CLEAR_CSE(gv_target->gd_csa->dir_tree);
GTMTRIG_ONLY(CLEAR_CSE(gv_target->gd_csa->hasht_tree));
}
}
if (INVALID_GV_TARGET != reset_gv_target)
{
if (SUCCESS != preemptive_severe && INFO != preemptive_severe)
{
/* We know of a few cases in Unix where gv_target and gv_currkey could be out of sync at this point.
* a) If we are inside trigger code which in turn does an update that does
* reads of ^#t global and ends up in a restart. This restart would
* in turn do a rts_error(TPRETRY) which would invoke mdb_condition_handler
* that would in turn invoke preemptive_db_clnup which invokes this macro.
* In this tp restart case though, it is ok for gv_target and gv_currkey
* to be out of sync because they are going to be reset by tp_clean_up anyways.
* So skip the dbg-only in-sync check.
* b) If we are in gvtr_init reading the ^#t global and detect an error (e.g. TRIGINVCHSET)
* gv_target after the reset would be pointing to a regular global whereas gv_currkey
* would be pointing to ^#t. It is ok to be out-of-sync since in this case, we expect
* mdb_condition_handler to be calling us. That has code to reset gv_currkey (and
* cs_addrs/cs_data etc.) to reflect gv_target (i.e. get them back in sync).
* Therefore in Unix we pass SKIP_GVT_GVKEY_CHECK to skip the gvtarget/gvcurrkey out-of-sync check
* in RESET_GV_TARGET. In VMS we pass DO_GVT_GVKEY_CHECK as we dont yet know of an out-of-sync situation.
*/
RESET_GV_TARGET(UNIX_ONLY(SKIP_GVT_GVKEY_CHECK) VMS_ONLY(DO_GVT_GVKEY_CHECK));
}
}
need_kip_incr = FALSE; /* in case we got an error in t_end (e.g. GBLOFLOW), dont want this global variable to get
* carried over to the next non-TP transaction that this process does (e.g. inside an error trap).
*/
if (dollar_tlevel)
{
for (si = first_sgm_info; si != NULL; si = si->next_sgm_info)
{
if (NULL != si->kip_csa)
{
csa = si->tp_csa;
assert(si->tp_csa == si->kip_csa);
CAREFUL_DECR_KIP(csa->hdr, csa, si->kip_csa);
}
}
} else if (NULL != kip_csa && (NULL != kip_csa->hdr) && (NULL != kip_csa->nl))
CAREFUL_DECR_KIP(kip_csa->hdr, kip_csa, kip_csa);
if (IS_DSE_IMAGE)
{ /* Release crit on any region that was obtained for the current erroring DSE operation.
* Take care NOT to release crits obtained by a previous CRIT -SEIZE command.
*/
for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
{
for (reg = addr_ptr->regions, r_top = reg + addr_ptr->n_regions; reg < r_top; reg++)
{
if (reg->open && !reg->was_open)
{
csa = &FILE_INFO(reg)->s_addrs;
assert(csa->hold_onto_crit || !csa->dse_crit_seize_done);
assert(!csa->hold_onto_crit || csa->now_crit);
if (csa->now_crit && (!csa->hold_onto_crit || !csa->dse_crit_seize_done))
{
rel_crit(reg);
csa->hold_onto_crit = FALSE;
t_abort(reg, csa); /* cancel mini-transaction if any in progress */
}
}
}
}
}
}

View File

@ -0,0 +1,17 @@
/****************************************************************
* *
* Copyright 2012 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. *
* *
****************************************************************/
#ifndef PREEMPTIVE_DB_CLNUP_INCLUDED
#define PREEMPTIVE_DB_CLNUP_INCLUDED
void preemptive_db_clnup(int preemptive_severe);
#endif /* PREEMPTIVE_DB_CLNUP_INCLUDED */

184
sr_port/reorg_funcs.c Normal file
View File

@ -0,0 +1,184 @@
/****************************************************************
* *
* Copyright 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 "gtm_string.h"
#include "cdb_sc.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
#include "copy.h"
#include "mu_reorg.h"
#include "util.h"
#include "min_max.h"
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF unsigned int t_tries;
#ifdef DEBUG
# define DBG_VERIFY_ACCESS(PTR) \
{ /* Ensure accessible pointer (no SIG-11) */ \
unsigned char c; \
\
c = *(unsigned char *)(PTR); \
}
#else
# define DBG_VERIFY_ACCESS(PTR)
#endif
/*
* Get length of the global variable name contained in the key starting at KEY_BASE.
* NOTE: If keys reside outside a GDS block (e.g. in cs_data), allocated buffer should have capacity at least MAX_KEY_SZ.
* Input:
* BLK_BASE := if non-NULL, base of current block
* if NULL, it means we're dealing with a key that is not within a database block
* KEY_BASE := starting address of key
* Output:
* GBLNAME_LEN := length of global variable name
*/
int get_gblname_len(sm_uc_ptr_t blk_base, sm_uc_ptr_t key_base)
{
sm_uc_ptr_t rPtr1, blk_end;
blk_end = (NULL != blk_base) ? (blk_base + cs_data->blk_size) : (key_base + MAX_KEY_SZ);
DBG_VERIFY_ACCESS(blk_end - 1);
for (rPtr1 = key_base; ; )
{
if (blk_end <= rPtr1)
break;
if (KEY_DELIMITER == *rPtr1++)
break;
}
return (int)(rPtr1 - key_base);
}
/*
* Get length of the key starting at KEY_BASE.
* NOTE: If keys reside outside a GDS block (e.g. in cs_data), allocated buffer should have capacity at least MAX_KEY_SZ.
* Currently, all get_key_len() calls take a key in shared memory; the only "allocated buffer" is csd->reorg_restart_key.
* Input:
* BLK_BASE := if non-NULL, base of current block
* if NULL, it means we're dealing with a key that is not within a database block
* KEY_BASE := starting address of key
* Output:
* KEY_LEN := length of key, including 2 null bytes at the end
*/
int get_key_len(sm_uc_ptr_t blk_base, sm_uc_ptr_t key_base)
{
sm_uc_ptr_t rPtr1, blk_end;
blk_end = (NULL != blk_base) ? (blk_base + cs_data->blk_size) : (key_base + MAX_KEY_SZ);
DBG_VERIFY_ACCESS(blk_end - 1);
for (rPtr1 = key_base; ; )
{
if (blk_end <= rPtr1 + 1)
break;
if ((KEY_DELIMITER == *rPtr1++) && (KEY_DELIMITER == *rPtr1))
break;
}
return (int)(rPtr1 + 1 - key_base);
}
/*
* Get compression count of SECOND_KEY with respect to FIRST_KEY.
* NOTE: Each key should reside in a private buffer with capacity at least MAX_KEY_SZ.
*/
int get_cmpc(sm_uc_ptr_t first_key, sm_uc_ptr_t second_key)
{
sm_uc_ptr_t rPtr1, rPtr2;
int cmpc;
DBG_VERIFY_ACCESS(first_key + MAX_KEY_SZ - 1);
DBG_VERIFY_ACCESS(second_key + MAX_KEY_SZ - 1);
/* We don't expect the inputs to be equal, hence the assert. It shouldn't matter, though. If the keys' contents are equal,
* we return an indeterminate value between the key length and MAX_KEY_SZ. The value depends on the garbage bytes past the
* terminating null bytes. But we don't care because we don't compress a key off an identical key in the final retry.
*/
assert(first_key != second_key);
for (rPtr1 = first_key, rPtr2 = second_key, cmpc = 0; cmpc < MAX_KEY_SZ; cmpc++)
{
if (*rPtr1++ != *rPtr2++)
break;
}
return cmpc;
}
/*
* Copy record info (record size and key) out of a block.
* Input:
* LEVEL := level of current block
* BLK_BASE := base of current block
* REC_BASE := starting address of record in current block
* KEY := previous key; first KEY_CMPC bytes are retained in output KEY
* Output:
* STATUS := status of read
* REC_SIZE := record size
* KEY_CMPC := key compression count
* KEY_LEN := key length
* KEY := local copy of key copied out of record
*/
enum cdb_sc read_record(int *rec_size_ptr, int *key_cmpc_ptr, int *key_len_ptr, sm_uc_ptr_t key,
int level, sm_uc_ptr_t blk_base, sm_uc_ptr_t rec_base)
{
sm_uc_ptr_t rPtr1, rPtr2, blk_end, rPtr1_end, rPtr2_end;
unsigned short temp_ushort;
int key_cmpc, rec_size, key_len;
boolean_t invalid;
blk_end = blk_base + cs_data->blk_size;
DBG_VERIFY_ACCESS(blk_end - 1);
if (blk_end <= (rec_base + SIZEOF(rec_hdr)))
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_blkmod;
}
GET_USHORT(temp_ushort, &(((rec_hdr_ptr_t)rec_base)->rsiz));
rec_size = temp_ushort;
key_cmpc = EVAL_CMPC((rec_hdr_ptr_t)rec_base);
if ((0 != level) && (BSTAR_REC_SIZE == rec_size))
{
key_len = 0;
*key_cmpc_ptr = key_cmpc;
*rec_size_ptr = rec_size;
*key_len_ptr = key_len;
return cdb_sc_starrecord;
}
rPtr1_end = key + MAX_KEY_SZ - 1;
DBG_VERIFY_ACCESS(rPtr1_end);
rPtr2_end = MIN(blk_end - 1, rec_base + SIZEOF(rec_hdr) + MAX_KEY_SZ - 1);
for (rPtr1 = key + key_cmpc, rPtr2 = rec_base + SIZEOF(rec_hdr); (rPtr1 < rPtr1_end) && (rPtr2 < rPtr2_end); )
{
if ((KEY_DELIMITER == (*rPtr1++ = *rPtr2++)) && (KEY_DELIMITER == *rPtr2)) /* note assignment */
break;
}
*rPtr1++ = *rPtr2++;
key_len = (int)(rPtr2 - rec_base - SIZEOF(rec_hdr));
invalid = INVALID_RECORD(level, rec_size, key_len, key_cmpc);
if (invalid || ((KEY_DELIMITER != *(rPtr1 - 1)) || (KEY_DELIMITER != *(rPtr1 - 2))))
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_blkmod;
}
*key_cmpc_ptr = key_cmpc;
*rec_size_ptr = rec_size;
*key_len_ptr = key_len;
return cdb_sc_normal;
}

24
sr_port/trim.mpt Normal file
View File

@ -0,0 +1,24 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Copyright 2012 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. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%TRIM ; routine to strip of leading and trailing spaces/tabs
for quit:$zeof read line write !,$$FUNC(line),!
quit
FUNC(s) quit $$L($$R(s))
L(s) new i,l,tmp
set l=$length(s)
for set tmp=$extract(s,$increment(i)) quit:" "'=tmp&($c(9)'=tmp)!'$length(tmp)
quit $extract(s,i,$length(s))
R(s) new i,l,tmp
set i=$length(s)+1 for set tmp=$extract(s,$increment(i,-1)) quit:" "'=tmp&($c(9)'=tmp)!'i
quit $extract(s,1,i)

33
sr_port/underr_strict.c Normal file
View File

@ -0,0 +1,33 @@
/****************************************************************
* *
* Copyright 2012 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 <stdarg.h>
#include "lv_val.h"
#include "undx.h"
error_def(ERR_UNDEF);
mval *underr_strict(mval *start, ...)
{
mident_fixed name;
unsigned char *end;
va_list var;
/* Variation of underr in which we ignore NOUNDEF */
va_start (var, start);
end = format_lvname((lv_val *)start, (uchar_ptr_t)name.c, SIZEOF(name));
va_end(var);
rts_error(VARLSTCNT(4) ERR_UNDEF, 2, ((char *)end - name.c), name.c);
return (mval *)NULL; /* To keep compiler happy */
}

788
sr_unix/CMakeLists.txt Normal file
View File

@ -0,0 +1,788 @@
#################################################################
# #
# Copyright 2012, 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. #
# #
#################################################################
# CMake 2.8.4 introduced LINK_DEPENDS target property
# CMake 2.8.4 introduced generator expressions in custom commands
# CMake 2.8.5 introduced use of C compiler as the assembler
cmake_minimum_required(VERSION 2.8.5)
project(GTM C ASM)
# Max optimization level is -O2
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(lang ${languages})
get_property(flags CACHE CMAKE_${lang}_FLAGS_RELEASE PROPERTY VALUE)
if("${flags}" MATCHES "-O[3-9]")
string(REGEX REPLACE "-O[3-9]" "-O2" flags "${flags}")
set_property(CACHE CMAKE_${lang}_FLAGS_RELEASE PROPERTY VALUE "${flags}")
endif()
endforeach()
# Defaults
set(version GTM_RELEASE_VERSION)
if("${version}" STREQUAL "")
set(version V9.9-0)
endif()
# If CMAKE_BUILD_TYPE is not defined make it a Release build
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
# If it's a debug build make sure GT.M uses all of its debug options
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
set(install_permissions_script
OWNER_READ OWNER_EXECUTE OWNER_WRITE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG)
# Only IA64 and x86_64 architectures use this option
set(gen_xfer_desc 0)
# Platform specific libs
set(gtm_osarch_libs "")
# Define these ahead of establishing platforms
set(gt_src_list)
set(sources_used "")
set(extralibs "")
set(is_encryption_supported 1)
set(libmumpsrestoreregex "")
message("--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}")
# Establish platform
# Except for Solaris, CMAKE_COMPILER_IS_GNUCC is true
if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
include(sr_linux/platform.cmake)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "HP-UX")
include(sr_hpux/platform.cmake)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
include(sr_aix/platform.cmake)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
include(sr_sun/platform.cmake)
else()
message(FATAL_ERROR "--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}")
endif()
# Choose where to get bootstrap sources.
set(GTM_DIST "" CACHE PATH "Existing GT.M Distribution")
if(GTM_DIST)
# Bootstrap using already-installed mumps.
message(STATUS "Using existing gtm_dist=${GTM_DIST} to generate sources.")
set(gen_bootstrap 1)
set(gen_bootstrap_dist "${GTM_DIST}")
set(gen_bootstrap_mumps "${GTM_DIST}/mumps")
set(gen_bootstrap_depend "${gen_bootstrap_mumps}")
else()
# Bootstrap using pre-generated bootstrap sources.
# We generate them again only for comparison.
set(gen_bootstrap 0)
set(gen_bootstrap_dist "${GTM_BINARY_DIR}")
set(gen_bootstrap_mumps "$<TARGET_FILE:mumps>")
set(gen_bootstrap_depend mumps)
endif()
set(GTM_INSTALL_DIR lib/fis-gtm/${version}_${arch} CACHE STRING "Install directory (under CMAKE_PREFIX_PATH if relative)")
if(NOT GTM_INSTALL_DIR)
set(GTM_INSTALL_DIR .)
endif()
#-----------------------------------------------------------------------------
# Source files are organized into subdirectories named by platform.
# Store in 'gt_src_list' a list of directory names selected and
# ordered based on the target platform. A given source file name may
# appear in multiple directories but only the instance found earliest
# in the search path will be used. Later instances of the same source
# file name will be ignored.
list(APPEND gt_src_list
sr_unix_gnp
sr_unix_cm
sr_unix
sr_port_cm
sr_port
)
# Collect the source file names belonging to each directory. Store
# the full path to a directory in 'source_dir_${d}' and the list of
# source file names in the directory in 'sources_${d}'.
foreach(d ${gt_src_list})
set(source_dir_${d} ${GTM_SOURCE_DIR}/${d})
file(GLOB sources_${d} RELATIVE ${source_dir_${d}}
${d}/*.c ${d}/*.s ${d}/*.si)
endforeach()
if(gen_bootstrap)
# Prefer generated sources over all other locations.
set(gt_src_list gen ${gt_src_list})
set(source_dir_gen ${GTM_BINARY_DIR}/gen)
# Hard-code list since we cannot glob files that do not exist.
set(sources_gen cmerrors_ctl.c cmierrors_ctl.c gdeerrors_ctl.c merrors_ctl.c ttt.c)
endif()
# The C preprocessor include search path consists of every source
# directory ordered by 'gt_src_list'.
set(includes)
foreach(d ${gt_src_list})
list(APPEND includes ${source_dir_${d}})
endforeach()
include_directories(${includes})
# We generate some uniquely-named headers in the top of the build tree.
include_directories(${GTM_BINARY_DIR})
# Function to select the first instance of a given source file name
# found in the ordered 'gt_src_list' search path.
function(select_file src_var name)
set(found "")
foreach(d ${gt_src_list})
set(src "${source_dir_${d}}/${name}")
if(EXISTS "${src}")
set(found "${src}")
break()
endif()
endforeach()
if(NOT found)
message(FATAL_ERROR "Cannot find \"${name}\" as ${ARGN}")
endif()
set("${src_var}" "${found}" PARENT_SCOPE)
endfunction()
# Macro to search directories ordered by 'gt_src_list' for a given
# list of source file names, assign them to a target, and exclude the
# source file names from inclusion in libmumps.
macro(set_source_list target)
foreach(name ${ARGN})
set(src "")
foreach(d ${gt_src_list})
if(";${sources_${d}};" MATCHES ";(${name}\\.(c|s|si));")
set(fname ${CMAKE_MATCH_1})
set(src ${d}/${fname})
set("source_used_${fname}" 1)
list(APPEND sources_used ${source_dir_${d}}/${fname})
if(NOT "${libmumpsrestoreregex}" STREQUAL "")
if(";${name};" MATCHES ";(${libmumpsrestoreregex});")
set("source_used_${fname}" 0)
endif()
endif()
break()
endif()
endforeach()
if(src)
list(APPEND ${target}_SOURCES ${src})
else()
message(FATAL_ERROR "No source \"${name}\" available!")
endif()
endforeach()
endmacro()
# Macro like set_source_list but that loads the list of source file
# names from a file.
macro(load_source_list target listfile)
file(STRINGS "${listfile}" names)
set_source_list(${target} ${names})
endmacro()
#-----------------------------------------------------------------------------
# Assign sources to libraries.
load_source_list(libcmisockettcp sr_unix_gnp/libcmisockettcp.list)
load_source_list(libdbcertify sr_unix/libdbcertify.list)
load_source_list(libdse sr_unix/libdse.list)
load_source_list(libgnpclient sr_unix_gnp/libgnpclient.list)
load_source_list(libgnpserver sr_unix_gnp/libgnpserver.list)
load_source_list(libgtcm sr_unix_cm/libgtcm.list)
load_source_list(liblke sr_unix/liblke.list)
load_source_list(libmupip sr_unix/libmupip.list)
load_source_list(libstub sr_unix/libstub.list)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
load_source_list(libgtmrpc sr_sun/libgtmrpc.list)
endif()
# Assign sources to executables.
set_source_list(gtm_threadgbl_deftypes gtm_threadgbl_deftypes)
set_source_list(dbcertify dbcertify dbcertify_cmd)
set_source_list(dse dse dse_cmd)
set_source_list(ftok ftok)
set_source_list(geteuid geteuid)
set_source_list(gtcm_gnp_server gtcm_gnp_server)
set_source_list(gtcm_pkdisp gtcm_pkdisp)
set_source_list(gtcm_play gtcm_play omi_srvc_xct)
set_source_list(gtcm_server gtcm_main omi_srvc_xct)
set_source_list(gtcm_shmclean gtcm_shmclean)
set_source_list(gtmsecshr gtmsecshr_wrapper)
set_source_list(gtmsecshr_real gtmsecshr)
set_source_list(libgtmcrypt gtmcrypt_ref gtmcrypt_pk_ref gtmcrypt_dbk_ref)
set_source_list(libgtmshr gtm_main)
set_source_list(lke lke lke_cmd)
set_source_list(maskpass maskpass)
set_source_list(mumps gtm)
set_source_list(mupip mupip mupip_cmd)
set_source_list(semstat2 semstat2)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
set_source_list(gtm_svc gtm_svc gtm_rpc_init gtm_dal_svc)
endif()
#-----------------------------------------------------------------------------
# libmumps gets leftover sources, so compute the remaining list.
set(source_used_dtgbldir.c 1) # exclude unused source
set(libmumps_SOURCES "")
foreach(d ${gt_src_list})
foreach(s ${sources_${d}})
if(NOT source_used_${s})
list(APPEND libmumps_SOURCES ${d}/${s})
set(source_used_${s} 1)
list(APPEND sources_used ${source_dir_${d}}/${s})
endif()
endforeach()
endforeach()
#-----------------------------------------------------------------------------
# Generate files depending on gtm
# Copy generation routines to a working directory.
foreach(m chk2lev.m chkop.m gendash.m genout.m loadop.m loadvx.m msg.m tttgen.m tttscan.m)
add_custom_command(
OUTPUT gen/${m}
DEPENDS ${GTM_SOURCE_DIR}/sr_port/${m}
COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/sr_port/${m} ${GTM_BINARY_DIR}/gen/${m}
)
endforeach()
foreach(f ttt.txt opcode_def.h vxi.h)
select_file(src ${f})
list(APPEND tttfiles ${src})
endforeach()
set(mumps_ttt_args -run tttgen ${tttfiles})
add_custom_command(
OUTPUT gen/ttt.c
DEPENDS ${tttfiles}
gen/chk2lev.m gen/chkop.m gen/gendash.m gen/genout.m gen/loadop.m
gen/loadvx.m gen/tttgen.m gen/tttscan.m
${GTM_SOURCE_DIR}/sr_unix/mumps.cmake ${gen_bootstrap_depend}
WORKING_DIRECTORY ${GTM_BINARY_DIR}/gen
COMMAND ${CMAKE_COMMAND}
-D gtm_dist=${gen_bootstrap_dist}
-D gtmroutines=.
-D mumps=${gen_bootstrap_mumps}
-D "args=${mumps_ttt_args}"
-D output_file=ttt.log
-P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake
VERBATIM
)
list(APPEND gen_bootstrap_files gen/ttt.c)
set(gen_merrors_extra gen/merrors_ansi.h)
foreach(msg
sr_port/cmerrors.msg
sr_port/gdeerrors.msg
sr_port/merrors.msg
sr_unix_gnp/cmierrors.msg
)
get_filename_component(name ${msg} NAME_WE)
set(mumps_msg_args -run msg ${GTM_SOURCE_DIR}/${msg} unix)
set(outputs gen/${name}_ctl.c ${gen_${name}_extra})
add_custom_command(
OUTPUT ${outputs}
DEPENDS gen/msg.m ${GTM_SOURCE_DIR}/${msg}
${GTM_SOURCE_DIR}/sr_unix/mumps.cmake ${gen_bootstrap_depend}
WORKING_DIRECTORY ${GTM_BINARY_DIR}/gen
COMMAND ${CMAKE_COMMAND}
-D gtm_dist=${gen_bootstrap_dist}
-D gtmroutines=.
-D mumps=${gen_bootstrap_mumps}
-D "args=${mumps_msg_args}"
-P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake
VERBATIM
)
list(APPEND gen_bootstrap_files ${outputs})
endforeach()
add_custom_target(gen_bootstrap ALL DEPENDS ${gen_bootstrap_files})
#-----------------------------------------------------------------------------
if(gen_xfer_desc)
list(SORT sources_used)
set(CMAKE_CONFIGURABLE_FILE_CONTENT "")
foreach(src ${sources_used})
set(CMAKE_CONFIGURABLE_FILE_CONTENT "${CMAKE_CONFIGURABLE_FILE_CONTENT}${src}\n")
endforeach()
configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in ${GTM_BINARY_DIR}/sources.list)
add_custom_command(
OUTPUT xfer_desc.i
WORKING_DIRECTORY ${GTM_BINARY_DIR}
DEPENDS ${GTM_SOURCE_DIR}/sr_unix/gen_xfer_desc.cmake
${GTM_BINARY_DIR}/sources.list
COMMAND ${CMAKE_COMMAND}
-D CMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-D "arch=${arch}"
-D "includes=${includes}"
-P ${GTM_SOURCE_DIR}/sr_unix/gen_xfer_desc.cmake
VERBATIM
)
add_custom_target(gen_xfer_desc DEPENDS xfer_desc.i)
if(gen_bootstrap)
add_dependencies(gen_xfer_desc gen_bootstrap)
endif()
endif()
#-----------------------------------------------------------------------------
add_executable(gtm_threadgbl_deftypes ${gtm_threadgbl_deftypes_SOURCES})
if(gen_xfer_desc)
add_dependencies(gtm_threadgbl_deftypes gen_xfer_desc)
elseif(gen_bootstrap)
add_dependencies(gtm_threadgbl_deftypes gen_bootstrap)
endif()
add_custom_command(
OUTPUT gtm_threadgbl_deftypes.h
DEPENDS gtm_threadgbl_deftypes
COMMAND gtm_threadgbl_deftypes > gtm_threadgbl_deftypes.h.tmp
COMMAND ${CMAKE_COMMAND} -E rename gtm_threadgbl_deftypes.h.tmp gtm_threadgbl_deftypes.h
)
add_custom_target(gen_gtm_threadgbl_deftypes DEPENDS gtm_threadgbl_deftypes.h)
foreach(exp exe shr)
set(out gtm${exp}_symbols.export)
set(in ${GTM_SOURCE_DIR}/sr_unix/gtm${exp}_symbols.exp)
add_custom_command(
OUTPUT ${out}
DEPENDS ${in}
COMMAND tcsh -f ${GTM_SOURCE_DIR}/sr_linux/genexport.csh ${in} ${out}
)
endforeach()
add_custom_target(gen_export DEPENDS gtmexe_symbols.export gtmshr_symbols.export)
foreach(lib
gtcm
cmisockettcp
gnpclient
gnpserver
dbcertify
dse
lke
mupip
stub
mumps
${extralibs}
)
add_library(lib${lib} STATIC ${lib${lib}_SOURCES})
set_property(TARGET lib${lib} PROPERTY OUTPUT_NAME ${lib})
add_dependencies(lib${lib} gen_gtm_threadgbl_deftypes)
endforeach()
# TODO: find_package or find_library for system libs?
include_directories ("/usr/local/include")
target_link_libraries(libmumps ${libmumpslibs})
add_executable(mumps ${mumps_SOURCES})
target_link_libraries(mumps libmumps)
add_executable(dse ${dse_SOURCES})
target_link_libraries(dse libdse libmumps libstub)
list(APPEND with_export dse)
add_executable(dbcertify ${dbcertify_SOURCES})
target_link_libraries(dbcertify libdbcertify libmupip libmumps libstub)
add_executable(geteuid ${geteuid_SOURCES})
add_executable(gtmsecshr ${gtmsecshr_SOURCES})
add_dependencies(gtmsecshr gen_gtm_threadgbl_deftypes)
add_executable(gtmsecshr_real ${gtmsecshr_real_SOURCES})
target_link_libraries(gtmsecshr_real libmumps)
set_target_properties(gtmsecshr_real PROPERTIES
OUTPUT_NAME gtmsecshr
RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/gtmsecshrdir
)
add_dependencies(gtmsecshr_real gen_gtm_threadgbl_deftypes)
add_executable(mupip ${mupip_SOURCES})
target_link_libraries(mupip libmupip libmumps libstub)
list(APPEND with_export mupip)
add_executable(lke ${lke_SOURCES})
target_link_libraries(lke liblke libmumps libgnpclient libmumps libgnpclient libcmisockettcp)
list(APPEND with_export lke)
add_executable(gtcm_server ${gtcm_server_SOURCES})
target_link_libraries(gtcm_server libgtcm libmumps libstub)
list(APPEND with_export gtcm_server)
add_executable(gtcm_gnp_server ${gtcm_gnp_server_SOURCES})
target_link_libraries(gtcm_gnp_server libgnpserver liblke libmumps libcmisockettcp libstub)
list(APPEND with_export gtcm_gnp_server)
add_executable(gtcm_play ${gtcm_play_SOURCES})
target_link_libraries(gtcm_play libgtcm libmumps libstub)
list(APPEND with_export gtcm_play)
add_executable(gtcm_pkdisp ${gtcm_pkdisp_SOURCES})
target_link_libraries(gtcm_pkdisp libgtcm libmumps libstub)
add_executable(gtcm_shmclean ${gtcm_shmclean_SOURCES})
target_link_libraries(gtcm_shmclean libgtcm libmumps libstub)
add_executable(semstat2 ${semstat2_SOURCES})
add_executable(ftok ${ftok_SOURCES})
target_link_libraries(ftok libmumps libstub)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
add_executable(gtm_svc ${gtm_svc_SOURCES})
target_link_libraries(gtm_svc libmumps libgnpclient libcmisockettcp libgtmrpc)
endif()
foreach(t ${with_export})
set_target_properties(${t} PROPERTIES
LINK_FLAGS "${gtm_link}"
LINK_DEPENDS "${gtm_dep}"
)
add_dependencies(${t} gen_export)
endforeach()
add_library(libgtmshr MODULE ${libgtmshr_SOURCES})
set_property(TARGET libgtmshr PROPERTY OUTPUT_NAME gtmshr)
target_link_libraries(libgtmshr libmumps libgnpclient libcmisockettcp)
set_target_properties(libgtmshr PROPERTIES
LINK_FLAGS "${libgtmshr_link}"
LINK_DEPENDS "${libgtmshr_dep}"
)
add_dependencies(libgtmshr gen_export)
add_dependencies(mumps libgtmshr)
if(is_encryption_supported)
# Iterate over the list of GPG related libraries
foreach(gpglib gpg-error gpgme gcrypt)
# For each library, we need a new CMake variable, hence GPGLIB_${gpglib}
find_library(GPGLIB_${gpglib} NAME ${gpglib} PATHS ${CMAKE_LIBRARY_PATH})
# Append the found library to the list
set(GPG_LIBRARIES ${GPG_LIBRARIES} ${GPGLIB_${gpglib}})
endforeach()
add_library(libgtmcrypt MODULE ${libgtmcrypt_SOURCES})
set_target_properties(libgtmcrypt PROPERTIES
OUTPUT_NAME gtmcrypt
COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_AES256CFB"
LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin
)
target_link_libraries(libgtmcrypt ${GPG_LIBRARIES})
install(TARGETS libgtmcrypt DESTINATION ${GTM_INSTALL_DIR}/plugin)
add_executable(maskpass ${maskpass_SOURCES})
target_link_libraries(maskpass ${GPG_LIBRARIES})
set_target_properties(maskpass PROPERTIES
COMPILE_DEFINITIONS USE_GCRYPT
RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin/gtmcrypt
)
install(TARGETS maskpass DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt)
foreach(f
add_db_key.sh
build.sh
encrypt_sign_db_key.sh
gen_keypair.sh
gen_sym_hash.sh
gen_sym_key.sh
gtmcrypt.tab
gtmcrypt_dbk_ref.c
gtmcrypt_dbk_ref.h
gtmcrypt_interface.h
gtmcrypt_pk_ref.c
gtmcrypt_pk_ref.h
gtmcrypt_dbk_ref.c
gtmcrypt_dbk_ref.h
gtmcrypt_ref.c
gtmcrypt_ref.h
gtmcrypt_sym_ref.h
gtmxc_types.h
import_and_sign_key.sh
install.sh
maskpass.c
pinentry-gtm.sh
pinentry.m
pinentry.m
show_install_config.sh
)
set(f_in "${GTM_SOURCE_DIR}/sr_unix/${f}")
set(f_out "${GTM_BINARY_DIR}/plugin/gtmcrypt/${f}")
add_custom_command(
OUTPUT "${f_out}"
DEPENDS "${f_in}"
COMMAND ${CMAKE_COMMAND} -E copy "${f_in}" "${f_out}"
)
if("${f}" MATCHES "\\.sh$")
set(permissions PERMISSIONS ${install_permissions_script})
else()
set(permissions "")
endif()
install(FILES "${f_out}" DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt ${permissions})
list(APPEND files_to_place "${f_out}")
endforeach()
endif()
install(TARGETS
mumps
dse
lke
geteuid
gtcm_server
gtcm_gnp_server
gtcm_pkdisp
gtcm_play
gtcm_shmclean
semstat2
ftok
gtmsecshr
mupip
libgtmshr
DESTINATION ${GTM_INSTALL_DIR}
)
install(TARGETS gtmsecshr_real DESTINATION ${GTM_INSTALL_DIR}/gtmsecshrdir)
# <r>.m -> <R>.m
#file(GLOB m_files_sr_port RELATIVE ${GTM_SOURCE_DIR}/sr_port ${GTM_SOURCE_DIR}/sr_port/*.m)
set(m_files_sr_port
gde.m
gdeadd.m
gdechang.m
gdedelet.m
gdeexit.m
gdehelp.m
gdeinit.m
gdelocks.m
gdelog.m
gdemap.m
gdemsgin.m
gdeparse.m
gdequit.m
gderenam.m
gdescan.m
gdesetgd.m
gdeshow.m
gdespawn.m
gdetempl.m
)
file(GLOB m_files_sr_unix RELATIVE ${GTM_SOURCE_DIR}/sr_unix ${GTM_SOURCE_DIR}/sr_unix/*.m)
file(GLOB mpt_files_sr_port RELATIVE ${GTM_SOURCE_DIR}/sr_port ${GTM_SOURCE_DIR}/sr_port/*.mpt)
file(GLOB mpt_files_sr_unix RELATIVE ${GTM_SOURCE_DIR}/sr_unix ${GTM_SOURCE_DIR}/sr_unix/*.mpt)
set(gtm_chset_dir_ "")
set(gtm_chset_dir_UTF-8 "/utf8")
foreach(d sr_port sr_unix)
foreach(m ${m_files_${d}})
get_filename_component(m_name "${m}" NAME_WE)
string(TOUPPER "${m_name}" m_upper)
if("${m}" MATCHES "^gde")
foreach(gtm_chset "" "UTF-8")
set(m_out "${GTM_BINARY_DIR}${gtm_chset_dir_${gtm_chset}}/${m_upper}.m")
add_custom_command(
OUTPUT "${m_out}"
DEPENDS ${GTM_SOURCE_DIR}/${d}/${m}
COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/${d}/${m} "${m_out}"
)
list(APPEND files_to_place "${m_out}")
list(APPEND gtm_chset_routines_${gtm_chset} "${m_out}")
endforeach()
else()
set(m_out "${GTM_BINARY_DIR}/${m_upper}.m")
add_custom_command(
OUTPUT "${m_out}"
DEPENDS ${GTM_SOURCE_DIR}/${d}/${m}
COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/${d}/${m} "${m_out}"
)
install(FILES "${m_out}" DESTINATION ${GTM_INSTALL_DIR})
list(APPEND files_to_place "${m_out}")
endif()
endforeach()
foreach(m ${mpt_files_${d}})
string(TOUPPER "_${m}" m_upper)
string(REGEX REPLACE "MPT$" "m" m_out "${GTM_BINARY_DIR}/${m_upper}")
add_custom_command(
OUTPUT "${m_out}"
DEPENDS ${GTM_SOURCE_DIR}/${d}/${m}
COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/${d}/${m} "${m_out}"
)
install(FILES "${m_out}" DESTINATION ${GTM_INSTALL_DIR})
list(APPEND files_to_place "${m_out}")
endforeach()
endforeach()
set(files)
foreach(f
gtm_descript.h
gtm_limits.h
gtm_sizeof.h
gtm_stdio.h
gtm_stdlib.h
gtm_string.h
gtm_strings.h
gtmxc_types.h
main_pragma.h
arch.gtc
gtcm_run.gtc
gtcm_slist.gtc
gdedefaults.gtc
gtmcshrc.gtc
gtmprofile.gtc
gtmprofile_preV54000.gtc
gtmstart.gtc
gtmstop.gtc
dse.hlp
gde.hlp
lke.hlp
mumps.hlp
mupip.hlp
custom_errors_sample.txt
)
select_file(src ${f})
list(APPEND files ${src})
endforeach()
install(FILES ${files} DESTINATION ${GTM_INSTALL_DIR})
set(scripts)
foreach(f
gtm.gtc
gtmbase.gtc
)
select_file(src ${f})
list(APPEND scripts ${src})
endforeach()
install(FILES ${scripts}
DESTINATION ${GTM_INSTALL_DIR}
PERMISSIONS ${install_permissions_script}
)
find_program(ICUCONFIG NAMES icu-config)
if(ICUCONFIG)
execute_process(
COMMAND ${ICUCONFIG} --version
OUTPUT_VARIABLE icu_version
RESULT_VARIABLE icu_failed
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(icu_failed)
message(FATAL_ERROR "Command\n ${ICUCONFIG} --version\nfailed (${icu_failed}).")
elseif("x${icu_version}" MATCHES "^x([0-9]+\\.[0-9]+)")
set(gtm_icu_version "${CMAKE_MATCH_1}")
else()
message(FATAL_ERROR "Command\n ${ICUCONFIG} --version\nproduced unrecognized output:\n ${icu_version}")
endif()
else()
message(FATAL_ERROR "Unable to find 'icu-config'. Set ICUCONFIG in CMake cache.")
endif()
if (gtm_icu_version GREATER 10)
message("libicu version ${gtm_icu_version} > 10")
string(REGEX REPLACE "([0-9])([0-9]).*" "\\1.\\2" gtm_icu_version "${gtm_icu_version}")
message("Fixing gtm_icu_version to ${gtm_icu_version}.\nThis had better be the default")
endif()
foreach(gtm_chset "" "UTF-8")
foreach(in ${gtm_chset_routines_${gtm_chset}})
string(REPLACE ".m" ".o" out "${in}")
get_filename_component(out_dir "${out}" PATH)
add_custom_command(
OUTPUT ${out}
DEPENDS ${in} ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake mumps
COMMAND ${CMAKE_COMMAND}
-D gtm_dist=${GTM_BINARY_DIR}
-D gtmroutines=.
-D gtm_chset=${gtm_chset}
-D gtm_icu_version=${gtm_icu_version}
-D mumps=$<TARGET_FILE:mumps>
-D "args=${in}"
-P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake
WORKING_DIRECTORY ${out_dir}
VERBATIM
)
list(APPEND files_to_place ${out})
install(FILES "${out}" DESTINATION ${GTM_INSTALL_DIR}${gtm_chset_dir_${gtm_chset}})
endforeach()
endforeach()
#-----------------------------------------------------------------------------
set(gtm_hlp mumps.hlp)
set(gde_hlp gde.hlp)
set(mupip_hlp mupip.hlp)
set(dse_hlp dse.hlp)
set(lke_hlp lke.hlp)
foreach(help gtm gde mupip dse lke)
set(CMAKE_CONFIGURABLE_FILE_CONTENT
"Change -segment DEFAULT -block=2048 -file=\$gtm_dist/${help}help.dat
Change -region DEFAULT -record=1020 -key=255
exit")
configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in
${GTM_BINARY_DIR}/${help}help.in1)
set(CMAKE_CONFIGURABLE_FILE_CONTENT
"Do ^GTMHLPLD
${GTM_SOURCE_DIR}/sr_port/${${help}_hlp}
Halt")
configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in
${GTM_BINARY_DIR}/${help}help.in2)
set(env
-D gtm_dist=${GTM_BINARY_DIR}
-D gtmroutines=.
-D gtmgbldir=${GTM_BINARY_DIR}/${help}help
)
add_custom_command(
OUTPUT ${help}help.dat ${help}help.gld
DEPENDS ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake mumps mupip
${GTM_BINARY_DIR}/${help}help.in1
${GTM_BINARY_DIR}/${help}help.in2
COMMAND ${CMAKE_COMMAND} -E remove ${help}help.dat ${help}help.gld
COMMAND ${CMAKE_COMMAND} ${env}
-D mumps=$<TARGET_FILE:mumps> -D "args=-run;GDE"
-D input_file=${GTM_BINARY_DIR}/${help}help.in1
-P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake
COMMAND ${CMAKE_COMMAND} ${env}
-D mumps=$<TARGET_FILE:mupip> -D "args=create"
-P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake
COMMAND ${CMAKE_COMMAND} ${env}
-D mumps=$<TARGET_FILE:mumps> -D "args=-direct"
-D input_file=${GTM_BINARY_DIR}/${help}help.in2
-P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake
VERBATIM
)
list(APPEND files_to_place ${help}help.dat)
install(FILES ${GTM_BINARY_DIR}/${help}help.dat DESTINATION ${GTM_INSTALL_DIR})
endforeach()
#-----------------------------------------------------------------------------
set(GTM_TOP "${GTM_BINARY_DIR}")
configure_file(sr_unix/gpgagent.tab.in plugin/gpgagent.tab @ONLY)
set(GTM_TOP "${CMAKE_INSTALL_PREFIX}/${GTM_INSTALL_DIR}")
configure_file(sr_unix/gpgagent.tab.in CMakeFiles/plugin/gpgagent.tab @ONLY)
install(FILES ${GTM_BINARY_DIR}/CMakeFiles/plugin/gpgagent.tab DESTINATION ${GTM_INSTALL_DIR}/plugin)
install(FILES sr_unix/configure.gtc DESTINATION ${GTM_INSTALL_DIR}
PERMISSIONS ${install_permissions_script}
RENAME configure
)
install(FILES sr_unix/gtminstall.sh DESTINATION ${GTM_INSTALL_DIR}
PERMISSIONS ${install_permissions_script}
RENAME gtminstall
)
install(FILES sr_unix/lowerc_cp.sh DESTINATION ${GTM_INSTALL_DIR}
RENAME lowerc_cp
)
install(FILES COPYING DESTINATION ${GTM_INSTALL_DIR})
add_custom_target(place_files ALL DEPENDS ${files_to_place})

View File

@ -0,0 +1,393 @@
/****************************************************************
* *
* Copyright 2012, 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 <errno.h>
#include "gtm_stdio.h"
#include "gtm_ctype.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "error.h"
#include "repl_sem.h"
#include "gtmimagename.h"
#include "hashtab_str.h"
#include "eintr_wrappers.h"
#include "gtmmsg.h"
#include "anticipatory_freeze.h"
#ifdef DEBUG
#include "dpgbldir.h"
#include "is_proc_alive.h"
#endif
#define MAX_TAG_LEN 128 /* Maximum size of an error mnemonic */
#define MAX_READ_SZ 1024 /* Mnemonic + flags shouldn't exceed this limit */
#define COMMENT_DELIMITER ';'
#define NEWLINE 0x0A
#define EOL_REACHED (char *)(-1)
#define EOF_REACHED (char *)(-2)
#define EXHAUST_CURRENT_LINE(BUFF, HANDLE, FGETS_RC) \
{ \
assert(NEWLINE != BUFF[STRLEN(BUFF) - 1]); \
while (TRUE) \
{ \
FGETS_FILE(BUFF, MAX_READ_SZ, HANDLE, FGETS_RC); \
if ((NULL == FGETS_RC) || NEWLINE == BUFF[STRLEN(BUFF) - 1]) \
break; \
} \
}
error_def(ERR_ASSERT);
error_def(ERR_CUSTERRNOTFND);
error_def(ERR_CUSTERRSYNTAX);
error_def(ERR_CUSTOMFILOPERR);
error_def(ERR_DSKSPCAVAILABLE);
error_def(ERR_ENOSPCQIODEFER);
error_def(ERR_REPLINSTFREEZECOMMENT);
error_def(ERR_REPLINSTFROZEN);
error_def(ERR_TEXT);
error_def(ERR_INSTFRZDEFER);
GBLREF jnlpool_addrs jnlpool;
GBLREF jnlpool_ctl_ptr_t jnlpool_ctl;
GBLREF boolean_t is_src_server;
GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS];
#ifdef DEBUG
GBLREF uint4 process_id;
GBLREF volatile boolean_t timer_in_handler;
#endif
/* Typically prototypes are included in the header file. But, in this case the static function - get_mnemonic_offset - has the
* hash_table_str as one of the function parameters which means all the files which includes anticipatory_freeze.h needs to include
* hashtab_str.h and since there are lot of such C files, we chose to define static function prototypes in the C file itself.
*/
STATICFNDCL char *scan_space(FILE *handle, char *buff, char *buffptr, char *buff_top);
STATICFNDCL int get_mnemonic_offset(hash_table_str **err_hashtab, char *mnemonic_buf, int mnemonic_len);
/* Scan through whitespace in the current buffer (read more if required) */
STATICFNDEF char *scan_space(FILE *handle, char *buff, char *buffptr, char *buff_top)
{
char *fgets_rc;
while (TRUE)
{
for (; (buffptr < buff_top) && (ISSPACE_ASCII(*buffptr)); buffptr++)
;
if (buffptr < buff_top)
return buffptr; /* first non-whitespace character */
if (NEWLINE == *(buffptr - 1))
return EOL_REACHED;
/* current buffer is exhausted and we haven't seen a newline; read more */
FGETS_FILE(buff, MAX_READ_SZ, handle, fgets_rc);
if (NULL == fgets_rc)
break;
buffptr = buff;
buff_top = buffptr + STRLEN(buff);
}
return EOF_REACHED;
}
STATICFNDEF int get_mnemonic_offset(hash_table_str **err_hashtab, char *mnemonic_buf, int mnemonic_len)
{
const err_msg *msg_beg, *msg_top;
hash_table_str *tmp_err_hashtab;
ht_ent_str *err_htent;
stringkey key;
err_msg *msg_info;
boolean_t added;
DEBUG_ONLY(int idx;)
msg_beg = merrors_ctl.fst_msg;
msg_top = msg_beg + merrors_ctl.msg_cnt;
assert('\0' == mnemonic_buf[mnemonic_len]);
if (NULL == (tmp_err_hashtab = *err_hashtab))
{ /* create and populate hash-table for future lookups */
tmp_err_hashtab = (hash_table_str *)malloc(SIZEOF(hash_table_str));
DEBUG_ONLY(tmp_err_hashtab->base = NULL);
init_hashtab_str(tmp_err_hashtab, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE);
assert(tmp_err_hashtab->base);
for (msg_info = (err_msg *)msg_beg; msg_info < msg_top; msg_info++)
{
key.str.addr = msg_info->tag;
key.str.len = STRLEN(msg_info->tag);
COMPUTE_HASH_STR(&key);
added = add_hashtab_str(tmp_err_hashtab, &key, msg_info, &err_htent);
assert(added);
assert(err_htent->value);
assert(msg_info->tag == ((err_msg *)(err_htent->value))->tag);
}
*err_hashtab = tmp_err_hashtab;
}
assert(NULL != tmp_err_hashtab);
/* lookup for the mnemonic */
key.str.addr = mnemonic_buf;
key.str.len = mnemonic_len;
COMPUTE_HASH_STR(&key);
if (NULL == (err_htent = lookup_hashtab_str(tmp_err_hashtab, &key)))
return -1;
msg_info = (err_msg *)(err_htent->value);
assert(msg_info >= msg_beg && msg_info < msg_top);
return msg_info - msg_beg;
}
/* Determine whether a given msg_id qualifies for an anticipatory freeze or not */
boolean_t is_anticipatory_freeze_needed(sgmnt_addrs *csa, int msg_id)
{
const err_ctl *ctl;
int idx;
assert(NULL != jnlpool.jnlpool_ctl);
/* Certain error messages should NOT trigger a freeze even if they are so configured in the custom errors file as they might
* result in instance freezes that can be set indefinitely. Currently, we know of at least 3 such messages:
* 1. ENOSPCQIODEFER and INSTFRZDEFER : To ensure we don't set anticipatory freeze if we don't/can't hold crit
* (due to possible deadlock)
* 2. DSKSPCAVAILABLE : To ensure we don't set anticipatory freeze if the disk space becomes available after an initial
* lack of space.
* These messages have csa == NULL so they are guarranteed to not trigger a freeze.
*/
assert(((ERR_ENOSPCQIODEFER != msg_id) && (ERR_DSKSPCAVAILABLE != msg_id) && (ERR_INSTFRZDEFER != msg_id))
|| (NULL == csa));
if (!csa || !csa->nl || !csa->hdr || !csa->hdr->freeze_on_fail)
return FALSE;
ctl = err_check(msg_id);
if (NULL != ctl)
{
GET_MSG_IDX(msg_id, ctl, idx);
assert(idx < ARRAYSIZE(jnlpool_ctl->merrors_array));
if (jnlpool_ctl->merrors_array[idx] & AFREEZE_MASK)
return TRUE;
}
return FALSE;
}
/* set the anticipatory freeze in the journal pool */
void set_anticipatory_freeze(sgmnt_addrs *csa, int msg_id)
{
boolean_t was_crit;
sgmnt_addrs *repl_csa;
const err_msg *msginfo;
# ifdef DEBUG
qw_off_t write_addr;
uint4 write;
# endif
assert(is_anticipatory_freeze_needed(csa, msg_id));
DEBUG_ONLY(
write_addr = jnlpool_ctl->write_addr;
write = jnlpool_ctl->write;
)
assert(write == write_addr % jnlpool_ctl->jnlpool_size);
repl_csa = &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs;
assert(NULL != repl_csa);
was_crit = repl_csa->now_crit;
if (!was_crit)
{
if (csa->now_crit)
grab_lock(jnlpool.jnlpool_dummy_reg, TRUE, GRAB_LOCK_ONLY);
else if (FALSE == grab_lock(jnlpool.jnlpool_dummy_reg, FALSE, GRAB_LOCK_ONLY))
{
MSGID_TO_ERRMSG(msg_id, msginfo);
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_INSTFRZDEFER, 4, LEN_AND_STR(msginfo->tag),
REG_LEN_STR(csa->region));
return;
}
}
/* Now that we hold necessary locks, set the freeze and the comment field */
jnlpool.jnlpool_ctl->freeze = TRUE;
GENERATE_INST_FROZEN_COMMENT(jnlpool.jnlpool_ctl->freeze_comment, SIZEOF(jnlpool.jnlpool_ctl->freeze_comment), msg_id);
/* TODO : Do we need a SHM_WRITE_MEMORY_BARRIER ? */
if (!was_crit)
rel_lock(jnlpool.jnlpool_dummy_reg);
}
/* initialize jnlpool_ctl->merrors_array to set up the list of errors that should trigger anticipatory freeze errors */
boolean_t init_anticipatory_freeze_errors()
{
int idx, save_errno, status, mnemonic_len, offset, line_no;
FILE *handle;
char *fgets_rc;
char buff[MAX_READ_SZ], mnemonic_buf[MAX_TAG_LEN];
char *buffptr, *buff_top, *errptr, *errptr_top;
mstr custom_err_file;
hash_table_str *err_hashtab = NULL;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
/* TODO : Currently, we process errors that belong to merrors[] as those are the ones related to database/journal. Need
* to check if cmerrors/cmierrors also need to be included in this list or not.
*/
assert(IS_MUPIP_IMAGE); /* is_src_server is not initialized at this point */
assert(jnlpool_ctl && !jnlpool_ctl->pool_initialized); /* should be invoked BEFORE the journal pool is fully-initialized */
assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); /* should hold journal pool access control semaphore */
/* Now, read the custom errors file and populate the journal pool */
custom_err_file = TREF(gtm_custom_errors);
handle = Fopen(custom_err_file.addr, "r");
if (NULL == handle)
{
save_errno = errno;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fopen"), custom_err_file.len,
custom_err_file.addr, save_errno);
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fopen"), custom_err_file.len,
custom_err_file.addr, save_errno);
return FALSE;
}
line_no = 0;
/* The code below parses a custom errors file in the following format.
*
* file ::= line*
* line ::= mnemonic SPACE* comment? EOL |
* comment EOL
* mnemonic ::= ALNUM+
* comment ::= COMMENT_DELIMITER ANY*
*
* SPACE ::= any ASCII white space character
* COMMENT_DELIMITER ::= ';'
* ANY ::= any ASCII character except end of line
* EOL ::= ASCII end of line character
* ALNUM ::= any ASCII alphanumeric character
*
* NOTES:
* "*" denotes zero-or-more of the previous item
* "?" denotes zero-or-one of the previous item
* "+" denotes one-or-more of the previous item
* "|" denotes multiple alternatives
* The mnemonic must match an entry in the GT.M error message list.
* Anything between the COMMENT_DELIMITER and EOL is ignored.
* Each iteration of the loop parses one line.
*/
while (TRUE)
{
FGETS_FILE(buff, MAX_READ_SZ, handle, fgets_rc);
line_no++;
if (NULL == fgets_rc)
break;
buffptr = buff;
buff_top = buffptr + STRLEN(buff);
errptr = &mnemonic_buf[0];
errptr_top = errptr + MAX_TAG_LEN;
/* The first character has to be alpha-numeric or a comment */
if (!ISALNUM_ASCII(*buffptr) && (COMMENT_DELIMITER != *buffptr))
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr,
line_no, ERR_TEXT, 2,
LEN_AND_LIT("First character should be comment (;) or alpha numeric"));
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr,
line_no, ERR_TEXT, 2,
LEN_AND_LIT("First character should be comment (;) or alpha numeric"));
return FALSE;
}
while (ISALNUM_ASCII(*buffptr))
{
*errptr++ = *buffptr++;
if (errptr > errptr_top)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len,
custom_err_file.addr, line_no, ERR_TEXT, 2, LEN_AND_LIT("Mnemonic too long"));
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len,
custom_err_file.addr, line_no, ERR_TEXT, 2, LEN_AND_LIT("Mnemonic too long"));
return FALSE;
}
assert(buffptr < buff_top); /* errptr > errptr_top should fail before this */
}
*errptr = '\0';
if (0 < (mnemonic_len = (errptr - &mnemonic_buf[0])))
{ /* Non-empty error mnemonic found; look it up */
if (-1 == (offset = get_mnemonic_offset(&err_hashtab, mnemonic_buf, mnemonic_len)))
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CUSTERRNOTFND, 2, mnemonic_len, mnemonic_buf);
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CUSTERRNOTFND, 2, mnemonic_len, mnemonic_buf);
return FALSE;
}
jnlpool_ctl->merrors_array[offset] |= AFREEZE_MASK; /* duplicate entries are not considered an error */
}
assert(ISSPACE_ASCII(*buffptr) || (COMMENT_DELIMITER == *buffptr));
if (EOL_REACHED == (buffptr = scan_space(handle, buff, buffptr, buff_top)))
continue;
else if (EOF_REACHED == buffptr)
break;
assert(buffptr < buff_top);
if (COMMENT_DELIMITER != *buffptr)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr,
line_no, ERR_TEXT, 2, LEN_AND_LIT("Unexpected character found after mnemonic"));
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr,
line_no, ERR_TEXT, 2, LEN_AND_LIT("Unexpected character found after mnemonic"));
return FALSE;
}
/* Need to ignore the rest of the current buffer and exhaust the current line */
if (NEWLINE != *(buff_top - 1))
EXHAUST_CURRENT_LINE(buff, handle, fgets_rc);
}
if (err_hashtab)
{
free_hashtab_str(err_hashtab);
free(err_hashtab);
}
if (!feof(handle))
{
save_errno = errno;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fgets"), custom_err_file.len,
custom_err_file.addr, save_errno);
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fgets"), custom_err_file.len,
custom_err_file.addr, save_errno);
return FALSE;
}
FCLOSE(handle, status);
if (SS_NORMAL != status)
{
save_errno = errno;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fclose"), custom_err_file.len,
custom_err_file.addr, save_errno);
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fclose"), custom_err_file.len,
custom_err_file.addr, save_errno);
return FALSE;
}
jnlpool_ctl->instfreeze_environ_inited = TRUE;
return TRUE;
}
#ifdef DEBUG
void clear_fake_enospc_if_master_dead(void)
{
gd_addr *addr_ptr;
gd_region *r_top, *r_local;
sgmnt_addrs *csa;
if((jnlpool_ctl->jnlpool_creator_pid != process_id) && !is_proc_alive(jnlpool_ctl->jnlpool_creator_pid, 0))
{
for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr))
{
for (r_local = addr_ptr->regions, r_top = r_local + addr_ptr->n_regions; r_local < r_top; r_local++)
{
if ((dba_bg != r_local->dyn.addr->acc_meth) && (dba_mm != r_local->dyn.addr->acc_meth))
continue;
csa = REG2CSA(r_local);
if ((NULL != csa) && (NULL != csa->nl))
if (csa->nl->fake_db_enospc || csa->nl->fake_jnl_enospc)
{
csa->nl->fake_db_enospc = FALSE;
csa->nl->fake_jnl_enospc = FALSE;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_TEXT, 2, DB_LEN_STR(r_local), ERR_TEXT,
2, LEN_AND_LIT("Resetting fake_db_enospc and fake_jnl_enospc because "
"fake ENOSPC master is dead"));
}
}
}
}
}
#endif

95
sr_unix/condstk_expand.c Normal file
View File

@ -0,0 +1,95 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "gtm_stdio.h"
#include "gtmio.h"
#include "error.h"
#include "mv_stent.h"
GBLREF unsigned char *stackbase;
#ifdef DEBUG_CONDSTK
# define DBGCSTK(x) DBGFPF(x)
#else
# define DBGCSTK(x)
#endif
/* Expands the condition handler stack copying old stack to new expanded stack.
*
* Note, chnd_end is always set 2 entries from the actual true top of the stack. Consider what can happen
* if we go to expand the stack but storage is not available. We will fail but when running things down,
* we ALSO need to install handlers. So once process_exiting is set, we are allowed to use the extra handlers.
*/
void condstk_expand(void)
{
condition_handler *new_chnd, *new_chnd_end, *ctxt_ent;
int new_size, old_len, old_size, cnt;
UINTPTR_T delta;
mv_stent *mvs;
DBGEHND((stderr, "condstk_expand: old: chnd: "lvaddr" chnd_end: "lvaddr" ctxt: "lvaddr" active_ch: "lvaddr
" chnd_incr: %d\n", chnd, chnd_end, ctxt, active_ch, chnd_incr));
/* Make sure we are allowed to expand */
old_len = INTCAST((char *)chnd_end - (char *)chnd);
old_size = old_len / SIZEOF(condition_handler);
new_size = old_size + chnd_incr + CONDSTK_RESERVE; /* New count of entries in cond handlr stack */
/* Nothing known should allow/require stack to get this large */
assertpro(new_size <= CONDSTK_MAX_STACK);
new_chnd = malloc(new_size * SIZEOF(condition_handler)); /* Allocate new condition handler stack */
new_chnd_end = &new_chnd[new_size];
delta = (UINTPTR_T)((char *)new_chnd - (char *)chnd);
memcpy(new_chnd, chnd, old_len); /* Copy occupied part of old stack */
assert(chnd < chnd_end);
/* Modify the address of save_active_ch so points to relevant entry in new condition handler stack. Note first
* entry back pointer remains unmodified (as NULL).
*/
for (cnt = 2, ctxt_ent = new_chnd + 1; cnt <= old_size; cnt++, ctxt_ent++)
{
assert(ctxt_ent >= new_chnd);
assert(ctxt_ent < new_chnd_end);
DBGEHND((stderr, "condstk_expand: cnt: %d, chptr: 0x"lvaddr" save_active_ch from 0x"lvaddr
" to 0x"lvaddr"\n", cnt, ctxt_ent, ctxt_ent->save_active_ch, ((char *)ctxt_ent->save_active_ch + delta)));
ctxt_ent->save_active_ch = (condition_handler *)((char *)ctxt_ent->save_active_ch + delta);
assert((1 == cnt) || (ctxt_ent->save_active_ch >= new_chnd));
assert((1 == cnt) || (ctxt_ent->save_active_ch < new_chnd_end));
}
# ifdef GTM_TRIGGER
/* Trigger type mv_stent (MVST_TRIGR) save/restore the value of ctxt so look through the stack to locate those and
* fix them up too.
*/
for (mvs = mv_chain; mvs < (mv_stent *)stackbase; mvs = (mv_stent *)((char *)mvs + mvs->mv_st_next))
{
if (MVST_TRIGR != mvs->mv_st_type)
continue;
DBGEHND((stderr, "condstk_expand: Trigger saved ctxt modified from 0x"lvaddr" to 0x"lvaddr"\n",
mvs->mv_st_cont.mvs_trigr.ctxt_save, (char *)mvs->mv_st_cont.mvs_trigr.ctxt_save + delta));
/* Have a trigger mv_stent - appropriately modify the saved ctxt value (high water mark for condition handlers */
mvs->mv_st_cont.mvs_trigr.ctxt_save = (condition_handler *)((char *)mvs->mv_st_cont.mvs_trigr.ctxt_save + delta);
}
# endif
/* Condition handler stack now reset - modify globals of record accordingly */
free(chnd); /* Old version no longer needed */
chnd = new_chnd;
chnd_end = new_chnd_end;
if (CONDSTK_MAX_INCR > chnd_incr)
chnd_incr = chnd_incr * 2;
ctxt = (condition_handler *)((char *)ctxt + delta);
active_ch = (condition_handler *)((char *)active_ch + delta);
assert(ctxt >= chnd);
assert(ctxt < chnd_end);
assert(active_ch >= chnd);
assert(active_ch < chnd_end);
DBGEHND((stderr, "condstk_expand: new: chnd: "lvaddr" chnd_end: "lvaddr" ctxt: "lvaddr" active_ch: "lvaddr
" chnd_incr: %d delta: "lvaddr"\n", chnd, chnd_end, ctxt, active_ch, chnd_incr, delta));
}

View File

@ -0,0 +1,33 @@
DBBMLCORRUPT
DBDANGER
DBFSYNCERR
DBIOERR
DSKNOSPCAVAIL
GBLOFLOW
GVDATAFAIL
GVDATAGETFAIL ; This is currently reported as TPFAIL and invisible to the user.
GVGETFAIL
GVINCRFAIL
GVKILLFAIL
GVORDERFAIL
GVPUTFAIL
GVQUERYFAIL
GVQUERYGETFAIL
GVZTRIGFAIL ; This is currently reported as TPFAIL and invisible to the user.
JNLACCESS
JNLCLOSE
JNLCLOSED
JNLCNTRL
JNLEXTEND
JNLFILECLOSERR
JNLFILEXTERR
JNLFILOPN
JNLFLUSH
JNLFSYNCERR
JNLRDERR
JNLREAD
JNLVSIZE
JNLWRERR
JRTNULLFAIL
OUTOFSPACE
TRIGDEFBAD

View File

@ -0,0 +1,79 @@
/****************************************************************
* *
* Copyright 2012 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 <errno.h>
#include "gtm_unistd.h"
#include "gtm_fcntl.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "gtm_stdio.h"
#include "gtm_stdlib.h"
#include "gtm_string.h"
#include "gtmio.h"
#include "iosp.h"
#include "eintr_wrappers.h"
#include "file_head_write.h"
#include "gtmmsg.h"
#ifdef __MVS__
#include "gtm_zos_io.h"
#endif
error_def(ERR_DBFILOPERR);
error_def(ERR_DBNOTGDS);
error_def(ERR_TEXT);
ZOS_ONLY(error_def(ERR_BADTAG);)
/*
* This is a plain way to write file header to database.
* Caller needs to take care of concurrency issue etc.
* Parameters :
* fn : full name of a database file.
* header: Pointer to database file header structure (may not be in shared memory)
* len: length of header to write (should be either SGMNT_HDR_LEN or SIZEOF_FILE_HDR(header))
*/
boolean_t file_head_write_secshr(char *fn, sgmnt_data_ptr_t header, int4 len)
{
int save_errno, fd, header_size;
ZOS_ONLY(int realfiletag;)
header_size = (int)SIZEOF_FILE_HDR(header);
assert(SGMNT_HDR_LEN == len || header_size == len);
OPENFILE(fn, O_RDWR, fd);
if (FD_INVALID == fd)
{
save_errno = errno;
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(fn), save_errno);
return FALSE;
}
#ifdef __MVS__
if (-1 == gtm_zos_tag_to_policy(fd, TAG_BINARY, &realfiletag))
TAG_POLICY_GTM_PUTMSG(fn, errno, realfiletag, TAG_BINARY);
#endif
LSEEKWRITE(fd, 0, header, len, save_errno);
if (0 != save_errno)
{
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(fn), save_errno);
return FALSE;
}
CLOSEFILE_RESET(fd, save_errno); /* resets "fd" to FD_INVALID */
if (0 != save_errno)
{
gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(fn), save_errno);
return FALSE;
}
return TRUE;
}

39
sr_unix/gds_rundown_ch.c Normal file
View File

@ -0,0 +1,39 @@
/****************************************************************
* *
* Copyright 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 "error.h"
GBLREF boolean_t created_core, need_core, dont_want_core;
#ifdef DEBUG
#include "have_crit.h"
GBLREF boolean_t ok_to_UNWIND_in_exit_handling;
#endif
CONDITION_HANDLER(gds_rundown_ch)
{
START_CH;
/* To get as virgin a state as possible in the core, take the core now if we
* would be doing so anyway. This will set created_core so it doesn't happen again.
*/
if (DUMPABLE && !SUPPRESS_DUMP)
{
need_core = TRUE;
gtm_fork_n_core();
}
assert(INTRPT_IN_GDS_RUNDOWN == intrpt_ok_state);
PRN_ERROR;
DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = TRUE);
UNWIND(NULL, NULL);
}

View File

@ -0,0 +1,91 @@
/****************************************************************
* *
* Copyright 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 "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "gds_rundown.h"
#include "jnl.h"
#include "gtm_semutils.h"
#include "do_semop.h"
#include "add_inter.h"
#include "ftok_sems.h"
#include <sys/sem.h>
#include "wcs_clean_dbsync.h"
#include "interlock.h"
#include "wbox_test_init.h"
#include "gds_rundown_err_cleanup.h"
GBLREF gd_region *gv_cur_region;
GBLREF jnl_gbls_t jgbl;
GBLREF uint4 process_id;
error_def(ERR_TEXT);
error_def(ERR_DBRNDWN);
void gds_rundown_err_cleanup(boolean_t have_standalone_access)
{
pid_t sem_pid;
int semop_res;
unix_db_info *udi;
sgmnt_addrs *csa;
boolean_t cancelled_timer, cancelled_dbsync_timer;
udi = FILE_INFO(gv_cur_region);
csa = &udi->s_addrs;
/* We got here on an error and are going to close the region. Cancel any pending flush timer for this region by this task*/
CANCEL_DB_TIMERS(gv_cur_region, csa, cancelled_timer, cancelled_dbsync_timer);
if (csa->now_crit) /* Might hold crit if wcs_flu or other failure */
{
assert(!csa->hold_onto_crit || jgbl.onlnrlbk);
if (NULL != csa->nl)
rel_crit(gv_cur_region); /* also sets csa->now_crit to FALSE */
else
csa->now_crit = FALSE;
}
if (!have_standalone_access)
{
if (udi->grabbed_access_sem)
{ /* release the access control semaphore, if you hold it */
sem_pid = semctl(udi->semid, 0, GETPID);
assert(sem_pid == process_id);
if (0 != (semop_res = do_semop(udi->semid, DB_CONTROL_SEM, -1, SEM_UNDO | IPC_NOWAIT)))
send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(gv_cur_region),
ERR_TEXT, 2, RTS_ERROR_TEXT("Error releasing access semaphore"), semop_res);
udi->grabbed_access_sem = FALSE;
}
if (udi->counter_acc_incremented)
{
if (0 != (semop_res = do_semop(udi->semid, DB_COUNTER_SEM, -1, SEM_UNDO | IPC_NOWAIT)))
send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(gv_cur_region),
ERR_TEXT, 2, RTS_ERROR_TEXT("Error decreasing access semaphore counter"), semop_res);
udi->counter_acc_incremented = FALSE;
}
}
if (udi->grabbed_ftok_sem)
{ /* Decrease counter and release ftok */
assert(!have_standalone_access);
ftok_sem_release(gv_cur_region, !have_standalone_access, TRUE);
} else if (udi->counter_ftok_incremented) /* Just decrease ftok counter */
{
if (0 != (semop_res = do_semop(udi->ftok_semid, DB_COUNTER_SEM, -1, SEM_UNDO | IPC_NOWAIT)))
send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(gv_cur_region),
ERR_TEXT, 2, RTS_ERROR_TEXT("Error decreasing ftok semaphore counter"), semop_res);
udi->counter_ftok_incremented = FALSE;
}
gv_cur_region->open = FALSE;
csa->nl = NULL;
REMOVE_CSA_FROM_CSADDRSLIST(csa); /* remove "csa" from list of open regions (cs_addrs_list) */
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DBRNDWN, 2, REG_LEN_STR(gv_cur_region));
}

View File

@ -0,0 +1,16 @@
/****************************************************************
* *
* Copyright 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. *
* *
****************************************************************/
#ifndef GDS_RUNDOWN_ERR_CLEANUP_INCLUDED
#define GDS_RUNDOWN_ERR_CLEANUP_INCLUDED
void gds_rundown_err_cleanup(boolean_t have_standalone_access);
#endif

View File

@ -0,0 +1,108 @@
/****************************************************************
* *
* Copyright 2001, 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 <signal.h> /* for VSIG_ATOMIC_T type */
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "gdsbgtr.h"
#include "filestruct.h"
#include "send_msg.h"
#include "mutex.h"
#include "deferred_signal_handler.h"
#include "wcs_recover.h"
#include "caller_id.h"
#include "is_proc_alive.h"
#include "gtmimagename.h"
#include "error.h"
GBLREF short crash_count;
GBLREF volatile int4 crit_count;
GBLREF uint4 process_id;
GBLREF node_local_ptr_t locknl;
GBLREF boolean_t mupip_jnl_recover;
error_def(ERR_CRITRESET);
error_def(ERR_DBCCERR);
error_def(ERR_DBFLCORRP);
boolean_t grab_crit_immediate(gd_region *reg)
{
unix_db_info *udi;
sgmnt_addrs *csa;
sgmnt_data_ptr_t csd;
node_local_ptr_t cnl;
enum cdb_sc status;
mutex_spin_parms_ptr_t mutex_spin_parms;
udi = FILE_INFO(reg);
csa = &udi->s_addrs;
csd = csa->hdr;
cnl = csa->nl;
if (!csa->now_crit)
{
assert(0 == crit_count);
crit_count++; /* prevent interrupts */
DEBUG_ONLY(locknl = cnl;) /* for DEBUG_ONLY LOCK_HIST macro */
mutex_spin_parms = (mutex_spin_parms_ptr_t)&csd->mutex_spin_parms;
status = mutex_lockwim(reg, mutex_spin_parms, crash_count);
DEBUG_ONLY(locknl = NULL;) /* restore "locknl" to default value */
if (status != cdb_sc_normal)
{
crit_count = 0;
switch (status)
{
case cdb_sc_nolock:
return(FALSE);
case cdb_sc_critreset:
rts_error(VARLSTCNT(4) ERR_CRITRESET, 2, REG_LEN_STR(reg));
case cdb_sc_dbccerr:
rts_error(VARLSTCNT(4) ERR_DBCCERR, 2, REG_LEN_STR(reg));
default:
GTMASSERT;
}
return(FALSE);
}
/* There is only one case we know of when cnl->in_crit can be non-zero and that is when a process holding
* crit gets kill -9ed and another process ends up invoking "secshr_db_clnup" which in turn clears the
* crit semaphore (making it available for waiters) but does not also clear cnl->in_crit since it does not
* hold crit at that point. But in that case, the pid reported in cnl->in_crit should be dead. Check that.
*/
assert((0 == cnl->in_crit) || (FALSE == is_proc_alive(cnl->in_crit, 0)));
cnl->in_crit = process_id;
CRIT_TRACE(crit_ops_gw); /* see gdsbt.h for comment on placement */
crit_count = 0;
}
else
assert(FALSE);
if (csd->file_corrupt && !mupip_jnl_recover)
{
if (!IS_DSE_IMAGE)
rts_error(VARLSTCNT(4) ERR_DBFLCORRP, 2, DB_LEN_STR(reg));
else
gtm_putmsg(VARLSTCNT(4) MAKE_MSG_WARNING(ERR_DBFLCORRP), 2, DB_LEN_STR(reg));
}
/* Ideally we do not want to do wcs_recover if we are in interrupt code (as opposed to mainline code).
* This is easily accomplished in VMS with a library function lib$ast_in_prog but in Unix there is no way
* to tell mainline code from interrupt code without the caller providing that information. Hence we
* currently do the cache recovery even in case of interrupt code even though it is a heavyweight operation.
* If it is found to cause issues, this logic has to be re-examined.
*/
if (cnl->wc_blocked)
wcs_recover(reg);
return(TRUE);
}

View File

@ -0,0 +1,29 @@
/****************************************************************
* *
* Copyright 2012 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 "gt_timer.h"
#include "gt_timers_add_safe_hndlrs.h"
#include "heartbeat_timer.h"
#include "semwt2long_handler.h"
#include "secshr_client.h"
/* This optional routine adds entries to the safe_handlers[] array. It is separate because while most executables need
* these timers listed, there is one executable (gtmsecshr) that decidedly does not - gtmsecshr. If these routines are
* part of gtmsecshr, they cause large numers of other routines that should definitely not be part of a root privileged
* executable to be pulled in.
*/
void gt_timers_add_safe_hndlrs(void)
{
add_safe_timer_handler(3, semwt2long_handler, client_timer_handler, heartbeat_timer);
}

View File

@ -0,0 +1,17 @@
/****************************************************************
* *
* Copyright 2012 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. *
* *
****************************************************************/
#ifndef GT_TIMERS_ADD_SAFE_HNDLRS_INCLUDED
#define GT_TIMERS_ADD_SAFE_HNDLRS_INCLUDED
void gt_timers_add_safe_hndlrs(void);
#endif

View File

@ -0,0 +1,24 @@
/****************************************************************
* *
* Copyright 2012, 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 "error.h" /* Declares all needed globals */
void gtm_asm_establish(void); /* Only needs to be declared here as is only called from assembler routines */
/* This routine is called from assembler routines (basically dm_start) who need to do an ESTABLISH. We do all of the ESTABLISH
* here except for the actual setjmp() call which needs to be in the assembler macro itself.
*/
void gtm_asm_establish(void)
{
GTM_ASM_ESTABLISH;
}

147
sr_unix/gtm_c_stack_trace.c Normal file
View File

@ -0,0 +1,147 @@
/****************************************************************
* *
* Copyright 2012, 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 <errno.h>
#include <sys/un.h>
#include <signal.h>
#include <sys/wait.h>
#include "gtm_stdio.h" /* For SPRINTF */
#include "gtm_string.h"
#include "send_msg.h"
#include "wbox_test_init.h"
#include "gt_timer.h"
#include "gtm_logicals.h"
#include "trans_log_name.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "gtm_c_stack_trace.h"
#include "jobsp.h" /* for MAX_PIDSTR_LEN */
#include "gtm_limits.h"
error_def(ERR_STUCKACT);
error_def(ERR_SYSCALL);
error_def(ERR_TEXT);
/* This looks up the environment variable gtm_procstuckexec, adds the calling information to it, passes it to a SYSTEM call
* and checks the returns from both the system and the invoked shell command
*/
void gtm_c_stack_trace(char *message, pid_t waiting_pid, pid_t blocking_pid, uint4 count)
{
int4 messagelen, arr_len;
char *command;
char *currpos;
int save_errno;
mstr envvar_logical, trans;
char buf[GTM_PATH_MAX];
int status;
# ifdef _BSD
union wait wait_stat;
# else
int4 wait_stat;
# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
messagelen = STRLEN(message);
assert(SIZEOF(count) <= SIZEOF(pid_t));
arr_len = GTM_MAX_DIR_LEN + messagelen + (3 * MAX_PIDSTR_LEN) + 5; /* 4 spaces and a terminator */
if (!(TREF(gtm_waitstuck_script)).len)
{ /* uninitialized buffer - translate logical and move it to the buffer */
envvar_logical.addr = GTM_PROCSTUCKEXEC;
envvar_logical.len = SIZEOF(GTM_PROCSTUCKEXEC) - 1;
if (SS_NORMAL == (status = TRANS_LOG_NAME(&envvar_logical, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long)))
{ /* the environmental variable is defined */
assert(SIZEOF(buf) > trans.len);
if (0 != trans.len)
{ /* and it has a value - stick the length of the translation in char_len of mstr */
(TREF(gtm_waitstuck_script)).len = trans.len + arr_len;
(TREF(gtm_waitstuck_script)).addr
= (char *)malloc((TREF(gtm_waitstuck_script)).len);
memcpy((TREF(gtm_waitstuck_script)).addr, trans.addr, trans.len);
*(char *)((TREF(gtm_waitstuck_script)).addr + trans.len) = ' ';
trans.len += 1;
(TREF(gtm_waitstuck_script)).char_len = trans.len; /* abuse of mstr to hold second length */
}
}
} else
{ /* already have a pointer to the shell command get its length */
trans.len = (TREF(gtm_waitstuck_script)).char_len;
assert(0 < trans.len);
if ((trans.len + arr_len) > (TREF(gtm_waitstuck_script)).len)
{ /* new message doesn't fit - malloc fresh space and free the old */
(TREF(gtm_waitstuck_script)).len = trans.len + arr_len;
trans.addr = (char *)malloc((TREF(gtm_waitstuck_script)).len);
memcpy(trans.addr, (TREF(gtm_waitstuck_script)).addr, trans.len);
free((TREF(gtm_waitstuck_script)).addr);
(TREF(gtm_waitstuck_script)).addr = trans.addr;
}
}
if (0 != (TREF(gtm_waitstuck_script)).len)
{ /* have a command and a message */
command = (TREF(gtm_waitstuck_script)).addr;
currpos = command + trans.len;
memcpy(currpos, message, messagelen);
currpos += messagelen;
*currpos++ = ' ';
currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)waiting_pid);
*currpos++ = ' ';
currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)blocking_pid);
*currpos++ = ' ';
currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)count);
*currpos++ = 0;
assert(currpos - (TREF(gtm_waitstuck_script)).addr <= (TREF(gtm_waitstuck_script)).len);
status = SYSTEM(((char *)((TREF(gtm_waitstuck_script)).addr)));
if (-1 == status)
{ /* SYSTEM failed */
save_errno = errno;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4, LEN_AND_LIT("FAILURE"), LEN_AND_STR(command));
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("system"), CALLFROM, save_errno);
} else
{ /* check on how the command did */
assert(SIZEOF(wait_stat) == SIZEOF(int4));
# ifdef _BSD
wait_stat.w_status = status;
# else
wait_stat = status;
# endif
if (WIFEXITED(wait_stat))
{
status = WEXITSTATUS(wait_stat);
if (!status)
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4,
LEN_AND_LIT("SUCCESS"), LEN_AND_STR(command));
else
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4,
LEN_AND_LIT("FAILURE"), LEN_AND_STR(command));
if (WIFSIGNALED(wait_stat))
{
status = WTERMSIG(wait_stat);
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
LEN_AND_LIT("PROCSTUCK terminated by signal"), CALLFROM, status);
} else
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
LEN_AND_LIT("PROCSTUCK"), CALLFROM, status);
}
} else
{ /* it's gone rogue' */
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4,
LEN_AND_LIT("FAILURE"), LEN_AND_STR(command));
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
LEN_AND_LIT("PROCSTUCK did not report status"), CALLFROM, status);
assert(FALSE);
}
}
}
}

100
sr_unix/gtm_conv_init.c Normal file
View File

@ -0,0 +1,100 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "gtm_caseconv.h"
#include "gtm_utf8.h"
#include "gtm_conv.h"
GBLREF UConverter *chset_desc[CHSET_MAX_IDX];
GBLREF casemap_t casemaps[MAX_CASE_IDX];
GBLREF u_casemap_t gtm_strToTitle_ptr; /* Function pointer for gtm_strToTitle */
LITREF mstr chset_names[CHSET_MAX_IDX_ALL];
/* Note these routines are separated from gtm_conv.c to avoid pulling into gtmsecshr all the stuff the conversion modules use */
error_def(ERR_ICUERROR);
/* Startup initializations of conversion data */
void gtm_conv_init(void)
{
assert(gtm_utf8_mode);
/* Implicitly created CHSET descriptor for UTF-8 */
get_chset_desc(&chset_names[CHSET_UTF8]);
assert(NULL != chset_desc[CHSET_UTF8]);
/* initialize the case conversion disposal functions */
casemaps[0].u = u_strToUpper;
casemaps[1].u = u_strToLower;
casemaps[2].u = gtm_strToTitle_ptr;
}
UConverter* get_chset_desc(const mstr* chset)
{
int chset_indx;
UErrorCode status;
if ((0 >= (chset_indx = verify_chset(chset))) || (CHSET_MAX_IDX <= chset_indx))
return NULL;
if (NULL == chset_desc[chset_indx])
{
status = U_ZERO_ERROR;
chset_desc[chset_indx] = ucnv_open(chset_names[chset_indx].addr, &status);
if (U_FAILURE(status))
rts_error(VARLSTCNT(3) ERR_ICUERROR, 1, status); /* strange and unexpected ICU unhappiness */
/* Initialize the callback for illegal/invalid characters, so that conversion
* stops at the first illegal character rather than continuing with replacement */
status = U_ZERO_ERROR;
ucnv_setToUCallBack(chset_desc[chset_indx], &callback_stop, NULL, NULL, NULL, &status);
if (U_FAILURE(status))
rts_error(VARLSTCNT(3) ERR_ICUERROR, 1, status); /* strange and unexpected ICU unhappiness */
}
return chset_desc[chset_indx];
}
/* Routine to verify given parameter against supported CHSETs.
* Valid arguments (case-insensitive):
* "M", "UTF-8", "UTF-16", "UTF-16LE" and "UTF-16BE"
* Returns
* -1 (if invalid argument) or
* 0 (if "M") or
* non-zero index to an entry of chset_names[] (if valid)
*/
int verify_chset(const mstr *parm)
{
const mstr *vptr, *vptr_top;
char mode[MAX_CHSET_LEN];
if ((MIN_CHSET_LEN > parm->len) || (MAX_CHSET_LEN < parm->len))
return -1; /* Parameter is smaller or larger than any possible CHSET */
/* Make a translated copy of the parm */
lower_to_upper((unsigned char *)mode, (unsigned char *)parm->addr, parm->len);
/* See if any of our possibilities match */
for (vptr = chset_names, vptr_top = vptr + CHSET_MAX_IDX_ALL; vptr < vptr_top; ++vptr)
{
if (parm->len == vptr->len &&
0 == memcmp(mode, vptr->addr, vptr->len))
return (int)(vptr - chset_names); /* return the index */
}
return -1;
}
void callback_stop(const void* context, UConverterToUnicodeArgs *args, const char *codeUnits,
int32_t length, UConverterCallbackReason reason, UErrorCode *pErrorCode)
{
/* EMPTY BODY:
* By not resetting the pErrorCode, this routine returns to ICU routine directing
* it to stop and return immediately
*/
}

88
sr_unix/gtm_system.c Normal file
View File

@ -0,0 +1,88 @@
/****************************************************************
* *
* Copyright 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 <sys/wait.h>
#include <errno.h>
#include "have_crit.h"
#include "fork_init.h"
#include "gtm_unistd.h"
#include "gtm_stdlib.h"
#include "eintr_wrappers.h"
#define RESTOREMASK \
{ \
sigaction(SIGINT, &old_intrpt, NULL); \
sigaction(SIGQUIT, &old_quit, NULL); \
sigprocmask(SIG_SETMASK, &savemask, NULL); \
}
int gtm_system(const char *cmdline)
{
struct sigaction ignore, old_intrpt, old_quit;
sigset_t mask, savemask;
pid_t pid;
int stat; /* child exit status */
int ret; /* return value from waitpid */
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
DEFER_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM);
sigemptyset(&ignore.sa_mask);
ignore.sa_handler = SIG_IGN;
ignore.sa_flags = 0;
if (sigaction(SIGINT, &ignore, &old_intrpt))
{
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM);
return -1;
}
if (sigaction(SIGQUIT, &ignore, &old_quit))
{
sigaction(SIGINT, &old_intrpt, NULL);
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM);
return -1;
}
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &mask, &savemask))
{
sigaction(SIGINT, &old_intrpt, NULL);
sigaction(SIGQUIT, &old_quit, NULL);
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM);
return -1;
}
/* Below FORK is not used as interrupts are already disabled at the
* beginning of this function
*/
pid = fork(); /* BYPASSOK */
if (0 > pid)
{
RESTOREMASK;
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM);
return -1;
}
else if (0 == pid)
{
RESTOREMASK;
execl("/bin/sh", "sh", "-c", cmdline, (char *)0);
_exit(127);
} else
{
ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM);
WAITPID(pid, &stat, 0, ret);
if ((-1 == ret) && (EINTR != errno))
stat = -1;
RESTOREMASK;
return stat;
}
}

49
sr_unix/gtmdbgflags.h Normal file
View File

@ -0,0 +1,49 @@
/****************************************************************
* *
* Copyright 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. *
* *
****************************************************************/
#ifndef _GTMDBGFLAGS_H
#define _GTMDBGFLAGS_H
#ifdef GTMDBGFLAGS_ENABLED
# define GTMDBGFLAGS_MASK_SET(MASK) (TREF(gtmdbgflags) & MASK)
# define GTMDBGFLAGS_ONLY(MASK, ...) \
{ \
DCL_THREADGBL_ACCESS; \
\
SETUP_THREADGBL_ACCESS; \
if (GTMDBGFLAGS_MASK_SET(MASK)) \
{ \
(TREF(gtmdbgflags_freq_cntr))++; \
if (TREF(gtmdbgflags_freq) == TREF(gtmdbgflags_freq_cntr)) \
{ \
__VA_ARGS__; \
TREF(gtmdbgflags_freq_cntr) = 0; \
} \
} \
}
# define GTMDBGFLAGS_NOFREQ_ONLY(MASK, ...) \
{ \
DCL_THREADGBL_ACCESS; \
\
SETUP_THREADGBL_ACCESS; \
if (GTMDBGFLAGS_MASK_SET(MASK)) \
{ \
__VA_ARGS__; \
} \
}
# define GTMSOURCE_FORCE_READ_FILE_MODE 0x00000001
#else
# define GTMDBGFLAGS_MASK_SET(MASK) FALSE
# define GTMDBGFLAGS_ONLY(MASK, FREQ, ...)
# define GTMDBGFLAGS_NOFREQ_ONLY(MASK, ...)
#endif
#endif

View File

@ -0,0 +1,65 @@
/****************************************************************
* *
* Copyright 2012, 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 "gdsroot.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "repl_sem.h"
#include "repl_shutdcode.h"
#include "filestruct.h"
#include "util.h"
GBLREF jnlpool_addrs jnlpool;
GBLREF gtmsource_options_t gtmsource_options;
GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS];
error_def(ERR_REPLINSTFREEZECOMMENT);
error_def(ERR_REPLINSTFROZEN);
error_def(ERR_REPLINSTUNFROZEN);
int gtmsource_showfreeze(void)
{
boolean_t instance_frozen;
assert(!holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]);
instance_frozen = jnlpool.jnlpool_ctl->freeze;
util_out_print("Instance Freeze: !AZ", TRUE, instance_frozen ? "ON" : "OFF");
if (jnlpool.jnlpool_ctl->freeze)
util_out_print(" Freeze Comment: !AZ", TRUE, jnlpool.jnlpool_ctl->freeze_comment);
return (instance_frozen ? (SRV_ERR + NORMAL_SHUTDOWN) : NORMAL_SHUTDOWN);
}
int gtmsource_setfreeze(void)
{
if (gtmsource_options.freezeval)
{
assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]);
grab_lock(jnlpool.jnlpool_dummy_reg, TRUE, ASSERT_NO_ONLINE_ROLLBACK); /* sets gtmsource_state */
} else
assert(!holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]);
jnlpool.jnlpool_ctl->freeze = gtmsource_options.freezeval;
if (gtmsource_options.setcomment)
STRNCPY_STR(jnlpool.jnlpool_ctl->freeze_comment, gtmsource_options.freeze_comment,
SIZEOF(jnlpool.jnlpool_ctl->freeze_comment));
if (gtmsource_options.freezeval)
{
send_msg(VARLSTCNT(3) ERR_REPLINSTFROZEN, 1, jnlpool.repl_inst_filehdr->inst_info.this_instname);
send_msg(VARLSTCNT(3) ERR_REPLINSTFREEZECOMMENT, 1, jnlpool.jnlpool_ctl->freeze_comment);
rel_lock(jnlpool.jnlpool_dummy_reg);
} else
{
send_msg(VARLSTCNT(3) ERR_REPLINSTUNFROZEN, 1, jnlpool.repl_inst_filehdr->inst_info.this_instname);
}
return (NORMAL_SHUTDOWN);
}

54
sr_unix/iott_iocontrol.c Normal file
View File

@ -0,0 +1,54 @@
/****************************************************************
* *
* Copyright 2001, 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 <sys/types.h>
#include "gtm_inet.h"
#include "gtm_string.h"
#include "io.h"
#include "iotcpdef.h"
GBLREF io_pair io_curr_device;
void iott_iocontrol(mstr *d)
{
return;
}
void iott_dlr_device(mstr *d)
{
io_desc *iod;
int len;
iod = io_curr_device.out;
len = STRLEN(iod->dollar.device);
/* verify internal buffer has enough space for $DEVICE string value */
assert((int)d->len > len);
memcpy(d->addr, iod->dollar.device, len);
d->len = len;
return;
}
void iott_dlr_key(mstr *d)
{
io_desc *iod;
int len;
iod = io_curr_device.out;
len = STRLEN(iod->dollar.key);
/* verify internal buffer has enough space for $KEY string value */
assert((int)d->len > len);
memcpy(d->addr, iod->dollar.key, len);
d->len = len;
return;
}

View File

@ -0,0 +1,186 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_ipc.h"
#include "gtm_unistd.h"
#include "gtm_string.h"
#include "gtm_inet.h"
#include "gtm_fcntl.h"
#include <sys/sem.h>
#include <errno.h>
#include <stddef.h>
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "iosp.h"
#include "gtmrecv.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "gtm_logicals.h"
#include "jnl.h"
#include "repl_sem.h"
#include "repl_shutdcode.h"
#include "io.h"
#include "trans_log_name.h"
#include "repl_instance.h"
#include "gtmmsg.h"
#include "gtm_sem.h"
#include "mu_rndwn_replpool.h"
#include "ftok_sems.h"
#include "anticipatory_freeze.h"
#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \
{ \
gtm_putmsg(VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \
gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \
return -1; \
}
GBLREF jnlpool_addrs jnlpool;
GBLREF recvpool_addrs recvpool;
GBLREF gd_region *gv_cur_region;
GBLREF jnl_gbls_t jgbl;
GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS];
GBLREF boolean_t argumentless_rundown;
error_def(ERR_REPLACCSEM);
int mu_replpool_release_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_type, boolean_t remove_sem)
{
int save_errno, instfilelen, status, sem_id, semval;
uint4 semnum;
char *instfilename;
gd_region *replreg;
# ifdef DEBUG
unix_db_info *udi;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
# endif
assert((NULL != jnlpool.jnlpool_dummy_reg) && (jnlpool.jnlpool_dummy_reg == recvpool.recvpool_dummy_reg));
replreg = jnlpool.jnlpool_dummy_reg;
DEBUG_ONLY(udi = FILE_INFO(jnlpool.jnlpool_dummy_reg));
assert(udi->grabbed_ftok_sem || jgbl.mur_rollback); /* Rollback already holds standalone access so no need for ftok lock */
instfilename = (char *)replreg->dyn.addr->fname;
instfilelen = replreg->dyn.addr->fname_len;
assert((NULL != instfilename) && (0 != instfilelen) && ('\0' == instfilename[instfilelen]));
assert((JNLPOOL_SEGMENT == pool_type) || (RECVPOOL_SEGMENT == pool_type));
if (JNLPOOL_SEGMENT == pool_type)
{
sem_id = repl_inst_filehdr->jnlpool_semid;
semval = semctl(sem_id, SRC_SERV_COUNT_SEM, GETVAL);
/* mu_replpool_grab_sem always increments the counter semaphore. So, it should be 1 at this point. In addition,
* if not ONLINE ROLLBACK or RUNDOWN with Anticipatory Freeze, we wait for the counter to become zero before
* grabbing it. The only exception where semval can be greater than 1 is if we are ONLINE ROLLBACK or RUNDOWN -REG
* with anticipatory freeze scheme in effect.
*/
assert((1 == semval) || ((1 <= semval)
&& (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && ANTICIPATORY_FREEZE_AVAILABLE))));
remove_sem &= (1 == semval); /* we can remove the sem if the caller intends to and the counter semaphore is 1 */
if (0 < semval)
{
status = decr_sem(SOURCE, SRC_SERV_COUNT_SEM);
if (SS_NORMAL != status)
{
save_errno = errno;
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semop()");
}
} else if (-1 == semval)
{
save_errno = errno;
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semctl()");
}
holds_sem[SOURCE][SRC_SERV_COUNT_SEM] = FALSE;
assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]);
assert(1 == semctl(sem_id, JNL_POOL_ACCESS_SEM, GETVAL)); /* we hold the access control semaphore */
status = rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM);
assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */
holds_sem[SOURCE][JNL_POOL_ACCESS_SEM] = FALSE;
/* Now that we have released the access control semaphore, see if we can remove the semaphore altogether from the
* system. For this, we should be holding the FTOK on the replication instance AND the counter semaphore should be
* 0. If we are called from mu_rndwn_repl_instance, we are guaranteed we will be holding the FTOK. But, if we are
* ROLLBACK (online or noonline), we need not hold the FTOK, if somebody else (possibly a source or receiver server
* startup command) is holding it. In that case, we don't remove the semaphore, because any process that is waiting
* on the access control will now get an EIDRM error which is NOT user friendly. So, just release the access
* control and let the waiting process do the clean up.
*/
if (remove_sem)
{
status = remove_sem_set(SOURCE);
if (SS_NORMAL != status)
{
save_errno = errno;
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "sem_rmid()");
}
repl_inst_filehdr->jnlpool_semid = INVALID_SEMID;
repl_inst_filehdr->jnlpool_semid_ctime = 0;
}
} else
{
sem_id = repl_inst_filehdr->recvpool_semid;
for (semnum = RECV_SERV_COUNT_SEM; semnum <= UPD_PROC_COUNT_SEM; semnum++)
{
semval = semctl(sem_id, semnum, GETVAL);
assert((1 == semval) || jgbl.onlnrlbk);
remove_sem &= (1 == semval);
if (0 < semval)
{
status = decr_sem(RECV, semnum);
if (SS_NORMAL != status)
{
save_errno = errno;
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semop()");
}
} else if (-1 == semval)
{
save_errno = errno;
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semctl()");
}
holds_sem[RECV][semnum] = FALSE;
}
assert(holds_sem[RECV][RECV_POOL_ACCESS_SEM] && holds_sem[RECV][RECV_SERV_OPTIONS_SEM]);
assert(1 == semctl(sem_id, RECV_POOL_ACCESS_SEM, GETVAL) && (1 == semctl(sem_id, RECV_SERV_OPTIONS_SEM, GETVAL)));
status = rel_sem_immediate(RECV, RECV_SERV_OPTIONS_SEM);
assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */
status = rel_sem_immediate(RECV, RECV_POOL_ACCESS_SEM);
assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */
holds_sem[RECV][RECV_POOL_ACCESS_SEM] = FALSE;
holds_sem[RECV][RECV_SERV_OPTIONS_SEM] = FALSE;
/* Now that we have released the access control semaphore, see if we can remove the semaphore altogether from the
* system. For this, we should be holding the FTOK on the replication instance AND the counter semaphore should be
* 0. If we are called from mu_rndwn_repl_instance, we are guaranteed we will be holding the FTOK. But, if we are
* ROLLBACK (online or noonline), we need not hold the FTOK, if somebody else (possibly a source or receiver server
* startup command) is holding it. In that case, we don't remove the semaphore, because any process that is waiting
* on the access control will now get an EIDRM error which is NOT user friendly. So, just release the access
* control and let the waiting process do the clean up.
*/
if (remove_sem)
{
status = remove_sem_set(RECV);
if (SS_NORMAL != status)
{
save_errno = errno;
DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "sem_rmid()");
}
repl_inst_filehdr->recvpool_semid = INVALID_SEMID;
repl_inst_filehdr->recvpool_semid_ctime = 0;
}
}
return SS_NORMAL;
}

400
sr_unix/mu_size_arsample.c Normal file
View File

@ -0,0 +1,400 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "cdb_sc.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
#include "copy.h"
#include "interlock.h"
#include "muextr.h"
#include "mu_reorg.h"
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
#include "mupip_size.h"
#include "util.h"
#include "t_begin.h"
#include "op.h"
#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */
#include "gvcst_bmp_mark_free.h"
#include "gvcst_kill_sort.h"
#include "gtmmsg.h"
#include "add_inter.h"
#include "t_abort.h"
#include "sleep_cnt.h"
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "gtm_time.h"
#include "mvalconv.h"
#include "t_qread.h"
#include "longset.h" /* needed for cws_insert.h */
#include "hashtab_int4.h"
#include "cws_insert.h"
#include "min_max.h"
#include <math.h>
error_def(ERR_GBLNOEXIST);
error_def(ERR_MUSIZEFAIL);
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF gv_namehead *gv_target;
GBLREF unsigned int t_tries;
GBLREF int4 process_id;
GBLREF inctn_opcode_t inctn_opcode;
GBLREF unsigned char rdfail_detail;
#define MAX_RECS_PER_BLK 65535
#define MAX_RELIABLE 10000 /* Used to tweak the error estimates */
#define EPS 1e-6
#define APPROX_F_MAX 500 /* Approximate upper bound for the number of records per index block in
* a realistic database.
*/
#define DYNAMIC_F_MAX 10 /* Choice of these two constants relates to choice of APPROX_F_MAX */
#define EXTRA_F_MAX 50
#define SQR(X) ((double)(X) * (double)(X))
#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */
typedef struct
{ /* cumulative running stats */
int n; /* number of previous traversals */
int N[MAX_BT_DEPTH + 1]; /* number of accepted samples at each given level (more are likely for higher levels) */
double M[MAX_BT_DEPTH + 1]; /* M[j] := mean of r[j]'s over previous n traversals
* Note: M_n = M_{n-1} + (r_n - M_{n-1}) / n
*/
double S[MAX_BT_DEPTH + 1]; /* S[j] := sum of (r_i[j] - M[j])^2 over each previous traversal, i=1..n
* Note: S_n = S_{n-1} + (r_n - M_n) * (r_n - M_{n-1})
* Later, S values are divided by number of samples to give a plugin estimate of variance
* and subsequently are divided by the sample size to give the variance of the mean
*/
double f_max[MAX_BT_DEPTH + 1]; /* estimated max fanning factor */
double r_max[MAX_BT_DEPTH + 1]; /* max records found in a block at a given level */
/* Final estimates */
double blktot[MAX_BT_DEPTH + 1]; /* estimated #blocks at each level */
double blkerr[MAX_BT_DEPTH + 1]; /* approximate variance of blktot */
double rectot[MAX_BT_DEPTH + 1]; /* estimated #records at each level */
double B; /* estimated total blocks */
double error; /* approximate error in estimate B */
double R; /* estimated total records */
} stat_t;
STATICFNDCL void finalize_stats_ar(stat_t *stat, boolean_t ar);
STATICFNDCL void accum_stats_ar(stat_t *stat, double *r, boolean_t ar);
#define CLEAR_VECTOR(v) \
{ \
int j; \
\
for (j = 0; j <= MAX_BT_DEPTH; j++) \
v[j] = 0; \
}
#define INIT_STATS(stat) \
{ \
int j; \
\
stat.n = 0; \
for (j = 0; j <= MAX_BT_DEPTH; j++) \
{ \
stat.f_max[j] = APPROX_F_MAX; \
stat.r_max[j] = 1; \
} \
CLEAR_VECTOR(stat.N); \
CLEAR_VECTOR(stat.M); \
CLEAR_VECTOR(stat.S); \
CLEAR_VECTOR(stat.blktot); \
CLEAR_VECTOR(stat.blkerr); \
CLEAR_VECTOR(stat.rectot); \
}
int4 mu_size_arsample(mval *gn, uint4 M, boolean_t ar, int seed)
{
enum cdb_sc status;
trans_num ret_tn;
int k, h;
boolean_t verify_reads;
boolean_t tn_aborted;
unsigned int lcl_t_tries;
double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */
stat_t rstat, ustat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
inctn_opcode = inctn_invalid_op;
op_gvname(VARLSTCNT(1) gn);
if (0 == gv_target->root)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
if (!seed)
seed = (int4)(time(0) * process_id);
srand48(seed);
/* do random traversals until M of them are accepted at level 1 */
INIT_STATS(rstat);
for (k = 1; rstat.N[1] < M; k++)
{
if (mu_ctrlc_occurred || mu_ctrly_occurred)
return EXIT_ERR;
t_begin(ERR_MUSIZEFAIL, 0);
for (;;)
{
CLEAR_VECTOR(r);
if (cdb_sc_normal != (status = rand_traverse(r)))
{
assert(CDB_STAGNATE > t_tries);
t_retry(status);
continue;
}
gv_target->clue.end = 0;
gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */
DEBUG_ONLY(lcl_t_tries = t_tries);
if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED)))
{
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
continue;
}
accum_stats_ar(&rstat, r, ar);
break;
}
}
finalize_stats_ar(&rstat, ar);
/* display rstat data */
/* Showing the error as 2 standard deviations which is a 95% confidence interval for the mean number of blocks at
* each level*/
util_out_print("!/Number of generated samples = !UL", FLUSH, rstat.n);
util_out_print("Number of accepted samples = !UL", FLUSH, rstat.N[1]);
util_out_print("Level Blocks 2 sigma(+/-) % Accepted", FLUSH);
for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--);
for ( ; h > 0; h--)
util_out_print("!5UL !15UL !15UL ~ !3UL% !15UL", FLUSH, h, (int)ROUND(rstat.blktot[h]),
(int)ROUND(sqrt(rstat.blkerr[h])*2),
(int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100),
(int)ROUND(100.0*rstat.N[h]/rstat.n)
);
util_out_print("!5UL !15UL !15UL ~ !3UL% N/A", FLUSH, h, (int)ROUND(rstat.blktot[h]),
(int)ROUND(sqrt(rstat.blkerr[h])*2),
(int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0)
);
util_out_print("Total !15UL !15UL ~ !3UL% N/A", FLUSH, (int)ROUND(rstat.B),
(int)ROUND(sqrt(rstat.error)*2),
(int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0)
);
return EXIT_NRM;
}
void accum_stats_ar(stat_t *stat, double *r, boolean_t ar)
{
int j, depth, n;
double random, M0, accept[MAX_BT_DEPTH + 1];
++stat->n;
for (j = MAX_BT_DEPTH; (j >= 0) && (r[j] < EPS); j--)
accept[j] = 0;
depth = j;
assert(depth >= 0); /* r[0] should remain zero since we don't maintain it */
accept[depth] = 1; /* always accept the root */
for (j = depth - 1; j >= 1; j--)
{
if (!ar)
accept[j] = 1; /* don't reject anything */
else if (j == depth - 1)
accept[j] = accept[j + 1]; /* always accept level beneath root, too */
else
accept[j] = accept[j + 1] * (r[j + 1] / stat->f_max[j + 1]);
}
accept[0] = 0; /* computing #blks (e.g #recs in lvl 1+), not #recs in lvl 0+ */
random = drand48();
for (j = 0; j <= MAX_BT_DEPTH; j++)
{
if (random < accept[j])
{
n = ++stat->N[j];
M0 = stat->M[j];
stat->M[j] += (r[j] - stat->M[j]) / n;
stat->S[j] += (r[j] - stat->M[j]) * (r[j] - M0);
if (n > DYNAMIC_F_MAX)
stat->f_max[j] = stat->r_max[j] + EXTRA_F_MAX;
}
stat->r_max[j] = MAX(stat->r_max[j], r[j]);
}
}
void finalize_stats_ar(stat_t *stat, boolean_t ar)
{
int j;
double factor;
for (j = 0; j <= MAX_BT_DEPTH; j++)
/* Variance of the mean (mean referes to avg number of records per block) is Var(R)/N where N is samples size */
if (stat->N[j] > 0)
{
stat->S[j] /= stat->N[j];
stat->S[j] /= stat->N[j];
}
stat->N[0] = stat->n; /* for arithmetic below */
for (j = MAX_BT_DEPTH; (j >= 0) && (stat->M[j] < EPS); j--);
assert(j >= 0); /* stat->M[0] should remain zero since we don't maintain it */
stat->blktot[j] = 1;
stat->blkerr[j] = 0;
for (j-- ; j >= 0; j--)
{
if (stat->M[j + 1] == 0)
stat->M[j + 1] = EPS; /* remove any chance of division by zero */
stat->blktot[j] = stat->blktot[j + 1] * stat->M[j + 1];
/* Var(XY) assuming X and Y are independent = E[X]^2*Var(Y) + E[Y]^2*Var(X) + Var(X)*Var(Y) */
stat->blkerr[j] = SQR(stat->M[j + 1])*stat->blkerr[j + 1] +
SQR(stat->blktot[j + 1])*stat->S[j + 1] + stat->blkerr[j + 1]*stat->S[j + 1];
}
stat->B = 0;
stat->error = 0;
for (j = 0; j <= MAX_BT_DEPTH; j++)
{
stat->B += stat->blktot[j];
stat->error += stat->blkerr[j];
}
stat->R = 0;
for (j = 0; j <= MAX_BT_DEPTH; j++)
{
stat->rectot[j] = stat->blktot[j] * stat->M[j];
stat->R += stat->rectot[j];
}
}
/*
* Performs a random traversal for the sampling methods
*/
enum cdb_sc rand_traverse(double *r)
{
sm_uc_ptr_t pVal, pTop, pRec, pBlkBase;
register gv_namehead *pTarg;
register srch_blk_status *pCurr;
register srch_hist *pTargHist;
block_id nBlkId;
block_id valBlk[MAX_RECS_PER_BLK]; /* valBlk[j] := value in j-th record of current block */
unsigned char nLevl;
cache_rec_ptr_t cr;
int cycle;
trans_num tn;
sm_uc_ptr_t buffaddr;
unsigned short nRecLen;
uint4 tmp;
boolean_t is_mm;
int4 random;
int4 rCnt; /* number of entries in valBlk */
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
is_mm = (dba_mm == cs_data->acc_meth);
pTarg = gv_target;
pTargHist = &gv_target->hist;
/* The following largely mimics gvcst_search/gvcst_search_blk */
nBlkId = pTarg->root;
tn = cs_addrs->ti->curr_tn;
if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&cycle, &cr)))
return (enum cdb_sc)rdfail_detail;
nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl;
if (MAX_BT_DEPTH < (int)nLevl)
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_maxlvl;
}
if (0 == (int)nLevl)
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_badlvl;
}
pTargHist->depth = (int)nLevl;
pCurr = &pTargHist->h[nLevl];
(pCurr + 1)->blk_num = 0;
pCurr->tn = tn;
pCurr->cycle = cycle;
pCurr->cr = cr;
for (;;)
{
assert(pCurr->level == nLevl);
pCurr->cse = NULL;
pCurr->blk_num = nBlkId;
pCurr->buffaddr = pBlkBase;
for ( rCnt = 0, pRec = pBlkBase + SIZEOF(blk_hdr), pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz;
pRec != pTop && rCnt < MAX_RECS_PER_BLK;
rCnt++, pRec += nRecLen )
{ /* enumerate records in block */
GET_USHORT(nRecLen, &((rec_hdr_ptr_t)pRec)->rsiz);
pVal = pRec + nRecLen - SIZEOF(block_id);
if (nRecLen == 0)
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_badoffset;
}
if (pRec + nRecLen > pTop)
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_blklenerr;
}
GET_LONG(tmp, pVal);
valBlk[rCnt] = tmp;
}
r[nLevl] = rCnt;
/* randomly select next block */
random = (int4)(rCnt * drand48());
random = random & 0x7fffffff; /* to make sure that the sign bit(msb) is off */
nBlkId = valBlk[random];
if (is_mm && (nBlkId > cs_addrs->total_blks))
{
if (cs_addrs->total_blks < cs_addrs->ti->total_blks)
return cdb_sc_helpedout;
else
return cdb_sc_blknumerr;
}
--pCurr; --nLevl;
if (nLevl < 1)
break;
pCurr->tn = cs_addrs->ti->curr_tn;
if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&pCurr->cycle, &pCurr->cr)))
return (enum cdb_sc)rdfail_detail;
if (((blk_hdr_ptr_t)pBlkBase)->levl != nLevl)
{
assert(CDB_STAGNATE > t_tries);
return cdb_sc_badlvl;
}
}
return cdb_sc_normal;
}

281
sr_unix/mu_size_impsample.c Normal file
View File

@ -0,0 +1,281 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "cdb_sc.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
#include "copy.h"
#include "interlock.h"
#include "muextr.h"
#include "mu_reorg.h"
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
#include "mupip_size.h"
#include "util.h"
#include "t_begin.h"
#include "op.h"
#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */
#include "gvcst_bmp_mark_free.h"
#include "gvcst_kill_sort.h"
#include "gtmmsg.h"
#include "add_inter.h"
#include "t_abort.h"
#include "sleep_cnt.h"
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "gtm_time.h"
#include "mvalconv.h"
#include "t_qread.h"
#include "longset.h" /* needed for cws_insert.h */
#include "hashtab_int4.h"
#include "cws_insert.h"
#include <math.h>
error_def(ERR_GBLNOEXIST);
error_def(ERR_MUSIZEFAIL);
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
GBLREF gv_namehead *gv_target;
GBLREF unsigned int t_tries;
GBLREF int4 process_id;
GBLREF inctn_opcode_t inctn_opcode;
#define MAX_RECS_PER_BLK 65535
#define MAX_RELIABLE 10000 /* Used to tweak the error estimates */
#define EPS 1e-6
#define SQR(X) ((double)(X) * (double)(X))
#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */
typedef struct
{ /* cumulative stats */
int4 n; /* number of samples */
double W[MAX_BT_DEPTH + 1]; /* Sum of the importance values of samples for each depth level */
double w_mu[MAX_BT_DEPTH + 1]; /* The mean of importance values. It is used to calculate w_variance */
double w_variance[MAX_BT_DEPTH + 1];/* The variance of importance values. It is used to calculate effective sample size */
double mu[MAX_BT_DEPTH + 1]; /* mu[j] := mean of weighted r[j]'s over previous n traversals.
It is the expected number of records at depth j
* Note: mu_n = mu_{n-1} + w_n/W_n*(r_n - M_{n-1})
*/
double S[MAX_BT_DEPTH + 1]; /* S[j] := sum of w_i*(r_i[j] - M[j])^2 over previous traversals.
* Note: S_n = S_{n-1} + w_n*(r_n - M_n)*(r_n - M_{n-1})
* Later, S values are divided by W values to give plugin estimate of the variance.
* Subsequently they are divided by the effective sample size to give the variance
* of the mean
*/
/* Final estimates */
double blktot[MAX_BT_DEPTH + 1]; /* estimated #blocks at each level */
double blkerr[MAX_BT_DEPTH + 1]; /* approximate variance of blktot */
double rectot[MAX_BT_DEPTH + 1]; /* estimated #records at each level */
double B; /* estimated total blocks */
double error; /* approximate error in estimate B */
double R; /* estimated total records */
} stat_t;
STATICFNDCL void clear_vector_impsmpl(double *v);
STATICFNDCL void init_stats_impsmpl(stat_t *stat);
STATICFNDCL void finalize_stats_impsmpl(stat_t *stat);
STATICFNDCL void accum_stats_impsmpl(stat_t *stat, double *r);
STATICFNDEF void clear_vector_impsmpl(double *v)
{
int j;
for (j = 0; j <= MAX_BT_DEPTH; j++)
v[j] = 0;
}
STATICFNDEF void init_stats_impsmpl(stat_t *stat)
{
stat->n = 0;
clear_vector_impsmpl(stat->W);
clear_vector_impsmpl(stat->w_mu);
clear_vector_impsmpl(stat->w_variance);
clear_vector_impsmpl(stat->mu);
clear_vector_impsmpl(stat->S);
clear_vector_impsmpl(stat->blktot);
clear_vector_impsmpl(stat->blkerr);
clear_vector_impsmpl(stat->rectot);
}
/*
* Importance Sampling
*/
int4 mu_size_impsample(mval *gn, int4 M, int4 seed)
{
enum cdb_sc status;
trans_num ret_tn;
int k, h;
boolean_t verify_reads;
boolean_t tn_aborted;
unsigned int lcl_t_tries;
double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */
stat_t rstat, ustat;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
inctn_opcode = inctn_invalid_op;
op_gvname(VARLSTCNT(1) gn);
if (0 == gv_target->root)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
if (!seed)
seed = (int4)(time(0) * process_id);
srand48(seed);
/* do M random traversals */
init_stats_impsmpl(&rstat);
for (k = 1; k <= M; k++)
{
if (mu_ctrlc_occurred || mu_ctrly_occurred)
return EXIT_ERR;
t_begin(ERR_MUSIZEFAIL, 0);
for (;;)
{
clear_vector_impsmpl(r);
if (cdb_sc_normal != (status = rand_traverse(r)))
{
assert(CDB_STAGNATE > t_tries);
t_retry(status);
continue;
}
gv_target->clue.end = 0;
gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */
DEBUG_ONLY(lcl_t_tries = t_tries);
if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED)))
{
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
continue;
}
accum_stats_impsmpl(&rstat, r);
break;
}
}
finalize_stats_impsmpl(&rstat);
/* display rstat data
* Showing the error as 2 standard deviations which is a 95% confidence interval for the
* mean number of blocks at each level
*/
util_out_print("Number of generated samples = !UL", FLUSH, rstat.n);
util_out_print("Level Blocks 2 sigma(+/-)", FLUSH);
for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--);
for ( ; h > 0; h--)
util_out_print("!5UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]),
(int)ROUND(sqrt(rstat.blkerr[h])*2),
(int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0)
);
util_out_print("!5UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]),
(int)ROUND(sqrt(rstat.blkerr[h])*2),
(int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0)
);
util_out_print("Total !15UL !15UL ~ !3UL%", FLUSH, (int)ROUND(rstat.B),
(int)ROUND(sqrt(rstat.error)*2),
(int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0)
);
return EXIT_NRM;
}
STATICFNDEF void accum_stats_impsmpl(stat_t *stat, double *r)
{
int l, root_level, n;
double mu0, w_mu0, w[MAX_BT_DEPTH + 1] /* importance */;
++stat->n;
for (l = MAX_BT_DEPTH; (l >= 0) && (r[l] < EPS); l--)
w[l] = 0;
root_level = l;
assert(root_level >= 0);
w[root_level] = 1;
for (l = root_level - 1; l >= 1; l--)
w[l] = w[l + 1] * r[l + 1]; /* TODO consider using log to avoid overflow if it becomes an issue */
w[0] = 0; /* computing #blks (e.g #recs in lvl 1+), not #recs in lvl 0+ */
for (l = 1; l <= root_level; l++)
{
stat->W[l] += w[l];
w_mu0 = stat->w_mu[l];
stat->w_mu[l] += (w[l] - stat->w_mu[l])/stat->n;
stat->w_variance[l] += (w[l] - stat->w_mu[l])*(w[l] - w_mu0);
mu0 = stat->mu[l];
stat->mu[l] += w[l]/stat->W[l]*(r[l] - stat->mu[l]);
stat->S[l] += w[l]*(r[l] - stat->mu[l])*(r[l] - mu0);
}
}
STATICFNDEF void finalize_stats_impsmpl(stat_t *stat)
{
int h;
double ess; /* effective sample size */
for (h = 1; h <= MAX_BT_DEPTH; h++)
if (stat->W[h] > 0)
{
/* ess = n / ( 1 + Var( w/mu(w) ) ).
* This comes from effective sample size for importance sampling in the literature*/
ess = stat->n / ( 1 + (stat->w_variance[h]/stat->n)/SQR(stat->w_mu[h]) );
/* Variance of the mean (mean referes to avg number of records per block) is
* Var(R)/N where N is effective sample size */
stat->S[h] /= stat->W[h];
stat->S[h] /= (ess + 1);
}
stat->W[0] = stat->n; /* for arithmetic below */
for (h = MAX_BT_DEPTH; (h >= 0) && (stat->mu[h] < EPS); h--);
assert(h >= 0); /* stat->mu[0] should remain zero */
stat->blktot[h] = 1;
stat->blkerr[h] = 0;
for (h-- ; h >= 0; h--)
{
stat->blktot[h] = stat->blktot[h + 1] * stat->mu[h + 1];
/* Var(XY) assuming X and Y are independent = E[X]^2*Var(Y) + E[Y]^2*Var(X) + Var(X)*Var(Y) */
stat->blkerr[h] = SQR(stat->mu[h + 1])*stat->blkerr[h + 1] + SQR(stat->blktot[h + 1])*stat->S[h + 1]
+ stat->blkerr[h + 1]*stat->S[h + 1];
}
stat->B = 0;
stat->error = 0;
for (h = 0; h <= MAX_BT_DEPTH; h++)
{
stat->B += stat->blktot[h];
stat->error += stat->blkerr[h];
}
stat->R = 0;
for (h = 0; h <= MAX_BT_DEPTH; h++)
{
stat->rectot[h] = stat->blktot[h] * stat->mu[h];
stat->R += stat->rectot[h];
}
}

354
sr_unix/mu_size_scan.c Normal file
View File

@ -0,0 +1,354 @@
/****************************************************************
* *
* Copyright 2012, 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 "gtm_string.h"
#include "cdb_sc.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
#include "copy.h"
#include "interlock.h"
#include "muextr.h"
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
#include "mupip_size.h"
#include "util.h"
#include "t_begin.h"
#include "op.h"
#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */
#include "gvcst_bmp_mark_free.h"
#include "gvcst_kill_sort.h"
#include "gtmmsg.h"
#include "add_inter.h"
#include "t_abort.h"
#include "sleep_cnt.h"
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "gtm_time.h"
#include "mvalconv.h"
#include "t_qread.h"
#include "longset.h" /* needed for cws_insert.h */
#include "hashtab_int4.h"
#include "cws_insert.h"
#include "min_max.h"
#include <math.h>
error_def(ERR_GBLNOEXIST);
error_def(ERR_MUSIZEFAIL);
error_def(ERR_MUSIZEINVARG);
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF gv_namehead *gv_target;
GBLREF unsigned int t_tries;
GBLREF int4 process_id;
GBLREF inctn_opcode_t inctn_opcode;
GBLREF unsigned char rdfail_detail;
GBLDEF uint4 total_recs;
GBLDEF uint4 total_scans;
GBLDEF int targ_levl;
GBLDEF INTPTR_T saveoff[MAX_BT_DEPTH + 1];
#define ANY_ROOT_LEVL (MAX_BT_DEPTH + 5) /* overload invalid level value */
#define MAX_RECS_PER_BLK 65535
#define MAX_SCANS 200000000 /* catch infinite loops */
#define GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop) \
{ \
status = cdb_sc_normal; \
GET_USHORT(nRecLen, &((rec_hdr_ptr_t)pRec)->rsiz); \
if (nRecLen == 0) \
status = cdb_sc_badoffset; \
else if (pRec + nRecLen > pTop) \
status = cdb_sc_blklenerr; \
}
#define GET_AND_CHECK_LEVL(status, nLevl, desired_levl, pBlkBase) \
{ \
status = cdb_sc_normal; \
nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl; \
if (MAX_BT_DEPTH < (int)nLevl) \
status = cdb_sc_maxlvl; \
else if (ANY_ROOT_LEVL == desired_levl) \
{ \
if (0 == (int)nLevl) \
status = cdb_sc_badlvl; \
} else if (desired_levl !=(int)nLevl) \
status = cdb_sc_badlvl; \
}
#define BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen) for (pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz, \
pRec = pBlkBase + SIZEOF(blk_hdr), i = 0; \
i < MAX_RECS_PER_BLK && (pRec != pTop); i++, pRec += nRecLen)
enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs);
enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl);
int4 mu_size_scan(mval *gn, int4 level)
{
enum cdb_sc status;
trans_num ret_tn;
int k, h;
boolean_t verify_reads;
boolean_t tn_aborted;
boolean_t equal;
unsigned int lcl_t_tries;
block_id nBlkId;
int4 nLevl;
sm_uc_ptr_t pBlkBase;
int i;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
inctn_opcode = inctn_invalid_op;
op_gvname(VARLSTCNT(1) gn);
if (0 == gv_target->root)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
gv_target->alt_hist->depth = MAX_BT_DEPTH; /* initialize: don't copy to saveoff if restart before a single success */
total_recs = total_scans = 0;
for (k = 0; k <= MAX_BT_DEPTH; k++)
{
saveoff[k] = 0;
gv_target->hist.h[k].cr = NULL; /* initialize for optimization in read_block which bumps cr refer bits */
}
targ_levl = 0;
/* Read the root block and convert negative levels to positive. Negative levels are defined to be counted from root with
* -1 being children of root */
t_begin(ERR_MUSIZEFAIL, 0);
for(;;)
{ /* retry loop */
status = read_block(gv_target->root, &pBlkBase, &nLevl, ANY_ROOT_LEVL);
if (cdb_sc_normal != status)
{
assert(CDB_STAGNATE > t_tries);
t_retry(status);
continue;
}
memcpy(&gv_target->hist.h[0], &gv_target->hist.h[nLevl], SIZEOF(srch_blk_status));
gv_target->hist.h[1].blk_num = 0;
if ((trans_num)0 == t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED)){
lcl_t_tries = TREF(prev_t_tries);
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
continue;
}
break;
}
if (level < 0)
level += nLevl;
if (level < 0 || nLevl < level)
{
gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.LEVEL"));
return EXIT_ERR;
}
targ_levl = level;
/* Run the dfs down to targ_levl to count records and blocks. Validate every path from root to blocks at targ_levl */
t_begin(ERR_MUSIZEFAIL, 0);
for (;;)
{ /* retry loop. note that multiple successful read transactions can occur within a single iteration */
nBlkId = gv_target->root;
nLevl = ANY_ROOT_LEVL;
status = read_block(nBlkId, &pBlkBase, &nLevl, ANY_ROOT_LEVL);
if (cdb_sc_normal == status)
status = dfs(nLevl, pBlkBase, TRUE, TRUE);
if (cdb_sc_endtree != status)
{
assert(cdb_sc_normal != status); /* should have continued recursive search */
if (cdb_sc_restarted != status)
t_retry(status);
lcl_t_tries = TREF(prev_t_tries);
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
{ /* Global does not exist (online rollback). Not an error. */
gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return EXIT_NRM;
}
/* update saveoff */
if (gv_target->alt_hist->depth < MAX_BT_DEPTH)
{
for (i = targ_levl; i <= gv_target->alt_hist->depth; i++)
saveoff[i] = gv_target->alt_hist->h[i - targ_levl].curr_rec.offset;
}
continue;
}
break;
}
util_out_print("Level Blocks Records", FLUSH);
util_out_print("!5UL !15UL !16UL", FLUSH, level, total_scans, total_recs);
if (mu_ctrlc_occurred || mu_ctrly_occurred)
return EXIT_ERR;
return EXIT_NRM;
}
enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs)
{
int incr_recs = 0, incr_scans = 0;
boolean_t first_iter, last_rec, next_endtree, next_skiprecs;
trans_num ret_tn;
sm_uc_ptr_t pVal, pTop, pRec, child_pBlkBase;
int4 child_nLevl;
unsigned short nRecLen;
int4 i;
enum cdb_sc status;
block_id nBlkId;
int curroff;
cache_rec_ptr_t cr;
srch_hist sibhist;
assert(total_scans < MAX_SCANS);
if (lvl == targ_levl)
{ /* reached the bottom. count records in this block and validate */
BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen)
{
GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop);
if (cdb_sc_normal != status)
{
assert(CDB_STAGNATE > t_tries);
return status;
}
}
incr_recs = i;
incr_scans = 1;
} else if (lvl > targ_levl)
{ /* visit each child */
first_iter = TRUE;
gv_target->hist.h[lvl - targ_levl].curr_rec.offset = saveoff[lvl];
BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen)
{
GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop);
if (cdb_sc_normal != status)
{
assert(CDB_STAGNATE > t_tries);
return status;
}
curroff = (INTPTR_T)(pRec - pBlkBase);
gv_target->hist.h[lvl - targ_levl].curr_rec.offset = curroff;
if (skiprecs && (curroff < saveoff[lvl]))
continue; /* skip these guys, we've already counted over there */
pVal = pRec + nRecLen - SIZEOF(block_id);
GET_LONG(nBlkId, pVal);
status = read_block(nBlkId, &child_pBlkBase, &child_nLevl, lvl - 1);
if (status != cdb_sc_normal)
{
assert(CDB_STAGNATE > t_tries);
return status;
}
last_rec = ((pRec + nRecLen) == pTop);
first_iter = (curroff == saveoff[lvl]);
next_endtree = endtree && last_rec;
next_skiprecs = skiprecs && first_iter;
status = dfs(lvl - 1, child_pBlkBase, next_endtree, next_skiprecs);
if (status != cdb_sc_normal)
return status;
first_iter = FALSE;
}
}
/* make sure we can really move on from this block to the next: validate all blocks down to here */
memcpy(&sibhist.h[0], &gv_target->hist.h[lvl], SIZEOF(srch_blk_status) * (gv_target->hist.depth - lvl + 2));
if ((trans_num)0 == (ret_tn = t_end(&sibhist, NULL, TN_NOT_SPECIFIED)))
return cdb_sc_restarted;
total_recs += incr_recs;
total_scans += incr_scans;
if (endtree || mu_ctrlc_occurred || mu_ctrly_occurred)
return cdb_sc_endtree; /* note: usage slightly different from elsewhere, since we've already done validation */
assert(lvl >= targ_levl);
memcpy(gv_target->alt_hist, &gv_target->hist, SIZEOF(srch_hist)); /* take a copy of most recently validated history */
gv_target->alt_hist->h[lvl - targ_levl + 1].curr_rec.offset++; /* don't recount the previously validated/counted path */
for (i = 0; i <= (lvl - targ_levl); i++)
gv_target->alt_hist->h[i].curr_rec.offset = 0;
/* Free up the cache record for the block we're done with. I.e. mark it available to whoever makes the next pass through
* db_csh_getn.
*/
cr = gv_target->alt_hist->h[lvl - targ_levl].cr;
assert((NULL != cr) || (dba_mm == cs_data->acc_meth));
if (NULL != cr)
cr->refer = FALSE;
gv_target->clue.end = 1; /* to set start_tn to earliest tn in history */
t_begin(ERR_MUSIZEFAIL, 0); /* start a new transaction and continue recursive search */
gv_target->clue.end = 0;
return cdb_sc_normal;
}
enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl)
{
sm_uc_ptr_t pBlkBase;
register srch_blk_status *pCurr;
register srch_hist *pTargHist;
unsigned char nLevl;
cache_rec_ptr_t cr;
int cycle;
trans_num tn;
enum cdb_sc status;
int i;
pTargHist = &gv_target->hist;
tn = cs_addrs->ti->curr_tn;
if ((dba_mm != cs_data->acc_meth) && (ANY_ROOT_LEVL != desired_levl))
{ /* avoid reading into a cache record we're already using in this transaction. prevents self-induced restarts. */
for (i = 0; i <= MAX_BT_DEPTH; i++)
if (pTargHist->h[i].blk_num && (NULL != (cr = pTargHist->h[i].cr))) /* note: assignment */
cr->refer = TRUE;
}
# ifdef DEBUG
/* restart occasionally */
if ((nBlkId % ((process_id % 25) + 25) == 0) && (t_tries == 0))
return cdb_sc_blkmod;
# endif
if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&cycle, &cr)))
return (enum cdb_sc)rdfail_detail;
GET_AND_CHECK_LEVL(status, nLevl, desired_levl, pBlkBase);
if (cdb_sc_normal != status)
{
assert(CDB_STAGNATE > t_tries);
return status;
}
pCurr = &pTargHist->h[nLevl - targ_levl]; /* No blocks to read beneath input level */
if (ANY_ROOT_LEVL == desired_levl)
{
if (nLevl < targ_levl)
pCurr = &pTargHist->h[0];
(pCurr + 1)->blk_num = 0;
pTargHist->depth = (int)nLevl;
}
pCurr->cse = NULL;
pCurr->blk_num = nBlkId;
pCurr->buffaddr = pBlkBase;
pCurr->tn = tn;
pCurr->cycle = cycle;
pCurr->cr = cr;
*nLevl_ptr = nLevl;
*pBlkBase_ptr = pBlkBase;
return cdb_sc_normal;
}

462
sr_unix/mu_swap_root.c Normal file
View File

@ -0,0 +1,462 @@
/****************************************************************
* *
* Copyright 2012, 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 "gtm_string.h"
#include "cdb_sc.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "gdsblkops.h"
#include "gdskill.h"
#include "gdscc.h"
#include "copy.h"
#include "interlock.h"
#include "muextr.h"
#include "mu_reorg.h"
/* Include prototypes */
#include "t_end.h"
#include "t_retry.h"
#include "mupip_reorg.h"
#include "util.h"
#include "t_begin.h"
#include "op.h"
#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */
#include "gvcst_bmp_mark_free.h"
#include "gvcst_kill_sort.h"
#include "gtmmsg.h"
#include "add_inter.h"
#include "t_abort.h"
#include "sleep_cnt.h"
#include "wcs_sleep.h"
#include "memcoherency.h"
#include "gdsbml.h"
#include "jnl_get_checksum.h"
#include "t_qread.h"
#include "t_create.h"
#include "t_write_map.h"
#include "t_write.h"
#ifdef GTM_TRIGGER
#include "hashtab_mname.h"
#include "gv_trigger.h"
#include "gv_trigger_common.h"
#include "targ_alloc.h"
#endif
GTMTRIG_ONLY(LITREF mval literal_hasht;)
GBLREF sgmnt_data_ptr_t cs_data;
GBLREF sgmnt_addrs *cs_addrs;
GBLREF gd_region *gv_cur_region;
GBLREF gv_key *gv_currkey, *gv_altkey;
GBLREF gv_namehead *gv_target;
GBLREF gv_namehead *reorg_gv_target;
GBLREF unsigned char cw_map_depth;
GBLREF unsigned char cw_set_depth;
GBLREF cw_set_element cw_set[];
GBLREF uint4 t_err;
GBLREF unsigned int t_tries;
GBLREF unsigned char rdfail_detail;
GBLREF inctn_opcode_t inctn_opcode;
GBLREF kill_set *kill_set_tail;
GBLREF sgmnt_addrs *kip_csa;
GBLREF boolean_t mu_reorg_process;
GBLREF boolean_t mu_reorg_upgrd_dwngrd_in_prog;
GBLREF boolean_t need_kip_incr;
GBLREF uint4 update_trans;
GBLREF gv_key *gv_altkey;
GBLREF char *update_array, *update_array_ptr;
GBLREF uint4 update_array_size;
GBLREF inctn_opcode_t inctn_opcode;
error_def(ERR_DBRDONLY);
error_def(ERR_GBLNOEXIST);
error_def(ERR_MAXBTLEVEL);
error_def(ERR_MUREORGFAIL);
error_def(ERR_MUTRUNCNOTBG);
#define RETRY_SWAP (0)
#define ABORT_SWAP (1)
boolean_t mu_swap_root(mval *gn, int *root_swap_statistic_ptr)
{
sgmnt_data_ptr_t csd;
sgmnt_addrs *csa;
node_local_ptr_t cnl;
srch_hist *dir_hist_ptr, *gvt_hist_ptr;
gv_namehead *save_targ;
block_id root_blk_id, child_blk_id, free_blk_id;
sm_uc_ptr_t root_blk_ptr, child_blk_ptr;
kill_set kill_set_list;
trans_num curr_tn, ret_tn;
int level, root_blk_lvl;
block_id save_root;
boolean_t tn_aborted;
unsigned int lcl_t_tries;
enum cdb_sc status;
# ifdef GTM_TRIGGER
gv_namehead *hasht_tree;
mname_entry gvent;
# endif
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
assert(mu_reorg_process);
gv_target->root = 0;
gv_target->clue.end = 0;
dir_hist_ptr = gv_target->alt_hist;
gvt_hist_ptr = &(gv_target->hist);
inctn_opcode = inctn_invalid_op;
# ifdef GTM_TRIGGER
if (IS_MNAME_HASHT_GBLNAME(gn->str))
{ /* Initialize ^#t global for this region. */
csa = cs_addrs; /* needed for SETUP_TRIGGER_GLOBAL and INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED macros */
SETUP_TRIGGER_GLOBAL;
INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED;
DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE);
if (0 == gv_target->root)
return TRUE;
} else
# endif /* Initialization for current global */
op_gvname(VARLSTCNT(1) (gn));
csa = cs_addrs;
cnl = csa->nl;
csd = cs_data; /* Be careful to keep csd up to date. With MM, cs_data can change, and
* dereferencing an older copy can result in a SIG-11.
*/
if (0 == gv_target->root)
{ /* Global does not exist (online rollback). No problem. */
gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return TRUE;
}
if (dba_mm == csd->acc_meth)
/* return for now without doing any swapping operation because later mu_truncate
* is going to issue the MUTRUNCNOTBG message.
*/
return TRUE;
SET_GV_ALTKEY_TO_GBLNAME_FROM_GV_CURRKEY; /* set up gv_altkey to be just the gblname */
/* ------------ Swap root block of global variable tree --------- */
t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK);
for (;;)
{
curr_tn = csa->ti->curr_tn;
kill_set_list.used = 0;
save_root = gv_target->root;
gv_target->root = csa->dir_tree->root;
gv_target->clue.end = 0;
if (cdb_sc_normal != (status = gvcst_search(gv_altkey, dir_hist_ptr)))
{ /* Assign directory tree path to dir_hist_ptr */
assert(t_tries < CDB_STAGNATE);
gv_target->root = save_root;
t_retry(status);
continue;
}
gv_target->root = save_root;
gv_target->clue.end = 0;
if (cdb_sc_normal != (gvcst_search(gv_currkey, NULL)))
{ /* Assign global variable tree path to gvt_hist_ptr */
assert(t_tries < CDB_STAGNATE);
t_retry(status);
continue;
}
/* We've already search the directory tree in op_gvname/t_retry and obtained gv_target->root.
* Should restart with gvtrootmod2 if they don't agree. gvcst_root_search is the final arbiter.
* Really need that for debug info and also should assert(gv_currkey is global name).
*/
root_blk_lvl = gvt_hist_ptr->depth;
assert(root_blk_lvl > 0);
root_blk_ptr = gvt_hist_ptr->h[root_blk_lvl].buffaddr;
root_blk_id = gvt_hist_ptr->h[root_blk_lvl].blk_num;
assert((CDB_STAGNATE > t_tries) || (gv_target->root == gvt_hist_ptr->h[root_blk_lvl].blk_num));
free_blk_id = swap_root_or_directory_block(0, root_blk_lvl, dir_hist_ptr, root_blk_id,
root_blk_ptr, &kill_set_list, curr_tn);
if (RETRY_SWAP == free_blk_id)
continue;
else if (ABORT_SWAP == free_blk_id)
break;
update_trans = UPDTRNS_DB_UPDATED_MASK;
inctn_opcode = inctn_mu_reorg;
assert(1 == kill_set_list.used);
need_kip_incr = TRUE;
if (!csa->now_crit)
WAIT_ON_INHIBIT_KILLS(cnl, MAXWAIT2KILL);
DEBUG_ONLY(lcl_t_tries = t_tries);
TREF(in_mu_swap_root_state) = MUSWP_INCR_ROOT_CYCLE;
assert(!TREF(in_gvcst_redo_root_search));
if ((trans_num)0 == (ret_tn = t_end(gvt_hist_ptr, dir_hist_ptr, TN_NOT_SPECIFIED)))
{
TREF(in_mu_swap_root_state) = MUSWP_NONE;
need_kip_incr = FALSE;
assert(NULL == kip_csa);
ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted);
if (tn_aborted)
{ /* It is not an error if the global (that once existed) doesn't exist anymore (due to ROLLBACK) */
gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr);
return TRUE;
}
continue;
}
TREF(in_mu_swap_root_state) = MUSWP_NONE;
/* Note that this particular process's csa->root_search_cycle is now behind cnl->root_search_cycle.
* This forces a cdb_sc_gvtrootmod2 restart in gvcst_bmp_mark_free below.
*/
assert(cnl->root_search_cycle > csa->root_search_cycle);
gvcst_kill_sort(&kill_set_list);
GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg, inctn_opcode, csa);
DECR_KIP(csd, csa, kip_csa);
*root_swap_statistic_ptr += 1;
break;
}
/* ------------ Swap blocks in branch of directory tree --------- */
for (level = 0; level <= MAX_BT_DEPTH; level++)
{
t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK);
for (;;)
{
curr_tn = csa->ti->curr_tn;
kill_set_list.used = 0;
save_root = gv_target->root;
gv_target->root = csa->dir_tree->root;
gv_target->clue.end = 0;
if (cdb_sc_normal != (status = gvcst_search(gv_altkey, dir_hist_ptr)))
{ /* assign branch path of directory tree into dir_hist_ptr */
assert(t_tries < CDB_STAGNATE);
gv_target->root = save_root;
t_retry(status);
continue;
}
gv_target->root = save_root;
gv_target->clue.end = 0;
if (level >= dir_hist_ptr->depth)
{ /* done */
t_abort(gv_cur_region, csa);
return TRUE;
}
child_blk_ptr = dir_hist_ptr->h[level].buffaddr;
child_blk_id = dir_hist_ptr->h[level].blk_num;
assert(csa->dir_tree->root != child_blk_id);
free_blk_id = swap_root_or_directory_block(level + 1, level, dir_hist_ptr, child_blk_id,
child_blk_ptr, &kill_set_list, curr_tn);
if (level == 0)
/* set level as 1 to mark this kill set is for level-0 block in directory tree.
* The kill-set level later will be used in gvcst_bmp_markfree to assign a special value to
* cw_set_element, which will be eventually used by t_end to write the block to snapshot
*/
kill_set_list.blk[kill_set_list.used - 1].level = 1;
if (RETRY_SWAP == free_blk_id)
continue;
else if (ABORT_SWAP == free_blk_id)
break;
update_trans = UPDTRNS_DB_UPDATED_MASK;
inctn_opcode = inctn_mu_reorg;
assert(1 == kill_set_list.used);
need_kip_incr = TRUE;
if (!csa->now_crit)
WAIT_ON_INHIBIT_KILLS(cnl, MAXWAIT2KILL);
DEBUG_ONLY(lcl_t_tries = t_tries);
TREF(in_mu_swap_root_state) = MUSWP_DIRECTORY_SWAP;
if ((trans_num)0 == (ret_tn = t_end(dir_hist_ptr, NULL, TN_NOT_SPECIFIED)))
{
TREF(in_mu_swap_root_state) = MUSWP_NONE;
need_kip_incr = FALSE;
assert(NULL == kip_csa);
continue;
}
TREF(in_mu_swap_root_state) = MUSWP_NONE;
gvcst_kill_sort(&kill_set_list);
TREF(in_mu_swap_root_state) = MUSWP_FREE_BLK;
GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg,
inctn_opcode, csa);
TREF(in_mu_swap_root_state) = MUSWP_NONE;
DECR_KIP(csd, csa, kip_csa);
break;
}
}
return TRUE;
}
/* Finds a free block and adds information to update array and cw_set */
block_id swap_root_or_directory_block(int parent_blk_lvl, int child_blk_lvl, srch_hist *dir_hist_ptr, block_id child_blk_id,
sm_uc_ptr_t child_blk_ptr, kill_set *kill_set_list, trans_num curr_tn)
{
sgmnt_data_ptr_t csd;
sgmnt_addrs *csa;
node_local_ptr_t cnl;
srch_blk_status bmlhist, freeblkhist;
block_id hint_blk_num, free_blk_id, parent_blk_id;
boolean_t free_blk_recycled;
int4 master_bit, num_local_maps, free_bit, hint_bit, maxbitsthismap;
uint4 total_blks;
int blk_seg_cnt, blk_size;
sm_uc_ptr_t parent_blk_ptr, bn_ptr, saved_blk;
blk_segment *bs1, *bs_ptr;
int parent_blk_size, child_blk_size, bsiz;
int rec_size1, curr_offset, bpntr_end, hdr_len;
int tmp_cmpc;
cw_set_element *tmpcse;
jnl_buffer_ptr_t jbbp; /* jbbp is non-NULL only if before-image journaling */
unsigned short temp_ushort;
unsigned long temp_long;
unsigned char save_cw_set_depth;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
csd = cs_data;
csa = cs_addrs;
cnl = csa->nl;
blk_size = csd->blk_size;
/* Find a free/recycled block for new block location. */
hint_blk_num = 0;
total_blks = csa->ti->total_blks;
num_local_maps = DIVIDE_ROUND_UP(total_blks, BLKS_PER_LMAP);
master_bit = bmm_find_free((hint_blk_num / BLKS_PER_LMAP), csa->bmm, num_local_maps);
if ((NO_FREE_SPACE == master_bit))
{
t_abort(gv_cur_region, csa);
return ABORT_SWAP;
}
bmlhist.blk_num = (block_id)master_bit * BLKS_PER_LMAP;
if (NULL == (bmlhist.buffaddr = t_qread(bmlhist.blk_num, (sm_int_ptr_t)&bmlhist.cycle, &bmlhist.cr)))
{
assert(t_tries < CDB_STAGNATE);
t_retry((enum cdb_sc)rdfail_detail);
return RETRY_SWAP;
}
hint_bit = 0;
maxbitsthismap = (master_bit != (num_local_maps - 1)) ? BLKS_PER_LMAP : total_blks - bmlhist.blk_num;
free_bit = bm_find_blk(hint_bit, bmlhist.buffaddr + SIZEOF(blk_hdr), maxbitsthismap, &free_blk_recycled);
free_blk_id = bmlhist.blk_num + free_bit;
if (DIR_ROOT >= free_blk_id)
{ /* Bitmap block 0 and directory tree root block 1 should always be marked busy. */
assert(t_tries < CDB_STAGNATE);
t_retry(cdb_sc_badbitmap);
return RETRY_SWAP;
}
if (child_blk_id <= free_blk_id)
{ /* stop swapping root or DT blocks once the database is truncated well enough. A good heuristic for this is to check
* if the block is to be swapped into a higher block number and if so do not swap
*/
t_abort(gv_cur_region, csa);
return ABORT_SWAP;
}
/* ====== begin update array ======
* Four blocks get changed.
* 1. Free block becomes busy and gains the contents of child (root block/directory tree block)
* 2. Parent block in directory tree remains busy, but points to new root block location.
* 3. Free block's corresponding bitmap reflects above change.
* 4. Child block gets marked recycled in bitmap. (GVCST_BMP_MARK_FREE)
*/
parent_blk_ptr = dir_hist_ptr->h[parent_blk_lvl].buffaddr; /* parent_blk_lvl is 0 iff we're moving a gvt root block */
parent_blk_id = dir_hist_ptr->h[parent_blk_lvl].blk_num;
CHECK_AND_RESET_UPDATE_ARRAY;
if (free_blk_recycled)
{ /* Otherwise, it's a completely free block, in which case no need to read. */
freeblkhist.blk_num = (block_id)free_blk_id;
if (NULL == (freeblkhist.buffaddr = t_qread(free_blk_id, (sm_int_ptr_t)&freeblkhist.cycle, &freeblkhist.cr)))
{
assert(t_tries < CDB_STAGNATE);
t_retry((enum cdb_sc)rdfail_detail);
return RETRY_SWAP;
}
}
child_blk_size = ((blk_hdr_ptr_t)child_blk_ptr)->bsiz;
BLK_INIT(bs_ptr, bs1);
BLK_ADDR(saved_blk, child_blk_size, unsigned char);
memcpy(saved_blk, child_blk_ptr, child_blk_size);
BLK_SEG(bs_ptr, saved_blk + SIZEOF(blk_hdr), child_blk_size - SIZEOF(blk_hdr));
assert(blk_seg_cnt == child_blk_size);
if (!BLK_FINI(bs_ptr, bs1))
{
assert(t_tries < CDB_STAGNATE);
t_retry(cdb_sc_blkmod);
return RETRY_SWAP;
}
tmpcse = &cw_set[cw_set_depth];
(free_blk_recycled) ? BIT_SET_RECYCLED_AND_CLEAR_FREE(tmpcse->blk_prior_state)
: BIT_CLEAR_RECYCLED_AND_SET_FREE(tmpcse->blk_prior_state);
t_create(free_blk_id, (unsigned char *)bs1, 0, 0, child_blk_lvl);
tmpcse->mode = gds_t_acquired;
if (!free_blk_recycled || !cs_data->db_got_to_v5_once)
tmpcse->old_block = NULL;
else
{
tmpcse->old_block = freeblkhist.buffaddr;
tmpcse->cr = freeblkhist.cr;
tmpcse->cycle = freeblkhist.cycle;
jbbp = (JNL_ENABLED(csa) && csa->jnl_before_image) ? csa->jnl->jnl_buff : NULL;
if ((NULL != jbbp) && (((blk_hdr_ptr_t)tmpcse->old_block)->tn < jbbp->epoch_tn))
{
bsiz = ((blk_hdr_ptr_t)(tmpcse->old_block))->bsiz;
if (bsiz > blk_size)
{
assert(CDB_STAGNATE > t_tries);
t_retry(cdb_sc_lostbmlcr);
return RETRY_SWAP;
}
JNL_GET_CHECKSUM_ACQUIRED_BLK(tmpcse, csd, csa, tmpcse->old_block, bsiz);
}
}
/* 2. Parent block in directory tree remains busy, but points to new child block location. */
curr_offset = dir_hist_ptr->h[parent_blk_lvl].curr_rec.offset;
parent_blk_size = ((blk_hdr_ptr_t)parent_blk_ptr)->bsiz;
GET_RSIZ(rec_size1, (parent_blk_ptr + curr_offset));
if ((parent_blk_size < rec_size1 + curr_offset) || (BSTAR_REC_SIZE > rec_size1))
{
assert(t_tries < CDB_STAGNATE);
t_retry(cdb_sc_blkmod);
return RETRY_SWAP;
}
BLK_INIT(bs_ptr, bs1);
if (0 == parent_blk_lvl)
/* There can be collation stuff in the record value after the block pointer. See gvcst_root_search. */
hdr_len = SIZEOF(rec_hdr) + gv_altkey->end + 1 - EVAL_CMPC((rec_hdr_ptr_t)(parent_blk_ptr + curr_offset));
else
hdr_len = rec_size1 - SIZEOF(block_id);
bpntr_end = curr_offset + hdr_len + SIZEOF(block_id);
BLK_SEG(bs_ptr, parent_blk_ptr + SIZEOF(blk_hdr), curr_offset + hdr_len - SIZEOF(blk_hdr));
BLK_ADDR(bn_ptr, SIZEOF(block_id), unsigned char);
PUT_LONG(bn_ptr, free_blk_id);
BLK_SEG(bs_ptr, bn_ptr, SIZEOF(block_id));
BLK_SEG(bs_ptr, parent_blk_ptr + bpntr_end, parent_blk_size - bpntr_end);
assert(blk_seg_cnt == parent_blk_size);
if (!BLK_FINI(bs_ptr, bs1))
{
assert(t_tries < CDB_STAGNATE);
t_retry(cdb_sc_blkmod);
return RETRY_SWAP;
}
t_write(&dir_hist_ptr->h[parent_blk_lvl], (unsigned char *)bs1, 0, 0, parent_blk_lvl, FALSE, TRUE, GDS_WRITE_KILLTN);
/* To indicate later snapshot file writing process during fast_integ not to skip writing the block to snapshot file */
BIT_SET_DIR_TREE(cw_set[cw_set_depth-1].blk_prior_state);
/* 3. Free block's corresponding bitmap reflects above change. */
PUT_LONG(update_array_ptr, free_bit);
save_cw_set_depth = cw_set_depth; /* Bit maps go on end of cw_set (more fake acquired) */
assert(!cw_map_depth);
t_write_map(&bmlhist, (uchar_ptr_t)update_array_ptr, curr_tn, 1);
cw_map_depth = cw_set_depth;
cw_set_depth = save_cw_set_depth;
update_array_ptr += SIZEOF(block_id);
temp_long = 0;
PUT_LONG(update_array_ptr, temp_long);
update_array_ptr += SIZEOF(block_id);
assert(1 == cw_set[cw_map_depth - 1].reference_cnt);
/* 4. Child block gets marked recycled in bitmap. (GVCST_BMP_MARK_FREE) */
kill_set_list->blk[kill_set_list->used].flag = 0;
kill_set_list->blk[kill_set_list->used].level = 0;
kill_set_list->blk[kill_set_list->used++].block = child_blk_id;
return free_blk_id;
}

210
sr_unix/mupip_size.c Normal file
View File

@ -0,0 +1,210 @@
/****************************************************************
* *
* Copyright 2012 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 "gtm_string.h"
#include "stp_parms.h"
#include "gdsroot.h"
#include "gdsblk.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "gdskill.h"
#include "muextr.h"
#include "iosp.h"
#include "cli.h"
#include "mu_reorg.h"
#include "util.h"
#include "filestruct.h"
#include "error.h"
#include "gdscc.h"
#include "jnl.h"
#include "buddy_list.h" /* needed for tp.h */
#include "hashtab_int4.h" /* needed for tp.h */
#include "tp.h"
/* Prototypes */
#include "mupip_size.h"
#include "targ_alloc.h"
#include "mupip_exit.h"
#include "gv_select.h"
#include "mu_outofband_setup.h"
#include "gtmmsg.h"
#include "mu_getlst.h"
error_def(ERR_NOSELECT);
error_def(ERR_MUNOFINISH);
error_def(ERR_MUNOACTION);
error_def(ERR_MUSIZEINVARG);
GBLREF tp_region *grlist;
GBLREF bool error_mupip;
GBLREF bool mu_ctrlc_occurred;
GBLREF bool mu_ctrly_occurred;
typedef struct {
enum {arsample, scan, impsample} heuristic;
int4 samples;
int4 level;
mval *global_name;
int4 seed;
} mupip_size_cfg_t;
STATICFNDCL void mupip_size_check_error(void);
/*
* This function reads command line parameters and forms a configuration for mupip size invocation.
* It later executes mupip size on each global based on the configuration
*
* MUPIP SIZE interface is described in GTM-7292
*/
void mupip_size(void)
{
uint4 status = EXIT_NRM;
glist gl_head, exclude_gl_head, *gl_ptr;
/* configuration default values */
mupip_size_cfg_t mupip_size_cfg = { impsample, 1000, 1, 0, 0 };
char cli_buff[MAX_LINE];
int4 reg_max_rec, reg_max_key, reg_max_blk;
unsigned short n_len;
char buff[MAX_LINE];
unsigned short BUFF_LEN = SIZEOF(buff);
char *p_end; /* used for strtol validation */
boolean_t restrict_reg = FALSE;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
mu_outofband_setup();
error_mupip = FALSE;
/* Region qualifier */
grlist = NULL;
if (CLI_PRESENT == cli_present("REGION"))
{
restrict_reg = TRUE;
gvinit(); /* initialize gd_header (needed by the following call to mu_getlst) */
mu_getlst("REGION", SIZEOF(tp_region)); /* get the parameter corresponding to REGION qualifier */
}
mupip_size_check_error();
/* SELECT qualifier */
memset(cli_buff, 0, SIZEOF(cli_buff));
n_len = SIZEOF(cli_buff);
if (CLI_PRESENT != cli_present("SELECT"))
{
n_len = 1;
cli_buff[0] = '*';
}
else if (FALSE == cli_get_str("SELECT", cli_buff, &n_len))
{
n_len = 1;
cli_buff[0] = '*';
}
/* gv_select will select globals for this clause*/
gv_select(cli_buff, n_len, FALSE, "SELECT", &gl_head, &reg_max_rec, &reg_max_key, &reg_max_blk, restrict_reg);
if (!gl_head.next){
error_mupip = TRUE;
gtm_putmsg(VARLSTCNT(1) ERR_NOSELECT);
}
mupip_size_check_error();
/* HEURISTIC qualifier */
if (cli_present("HEURISTIC.SCAN") == CLI_PRESENT)
{
mupip_size_cfg.heuristic = scan;
if (cli_present("HEURISTIC.LEVEL"))
{
boolean_t valid = TRUE;
if (cli_get_str("HEURISTIC.LEVEL", buff, &BUFF_LEN))
{
mupip_size_cfg.level = strtol(buff, &p_end, 10);
valid = (*p_end == '\0');
}
else
valid = FALSE;
if (!valid || mupip_size_cfg.level <= -MAX_BT_DEPTH || MAX_BT_DEPTH <= mupip_size_cfg.level)
{
error_mupip = TRUE;
gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.LEVEL"));
}
}
/* else level is already initialized with default value */
}
else if (cli_present("HEURISTIC.ARSAMPLE") == CLI_PRESENT || cli_present("HEURISTIC.IMPSAMPLE") == CLI_PRESENT)
{
if (cli_present("HEURISTIC.ARSAMPLE") == CLI_PRESENT)
mupip_size_cfg.heuristic = arsample;
else if (cli_present("HEURISTIC.IMPSAMPLE") == CLI_PRESENT)
mupip_size_cfg.heuristic = impsample;
if (cli_present("HEURISTIC.SAMPLES"))
{
boolean_t valid = cli_get_int("HEURISTIC.SAMPLES", &(mupip_size_cfg.samples));
if (!valid || mupip_size_cfg.samples <= 0){
error_mupip = TRUE;
gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.SAMPLES"));
}
}
/* else samples is already initialized with default value */
/* undocumented SEED parameter used for testing sampling method */
if (cli_present("HEURISTIC.SEED"))
{
boolean_t valid = cli_get_int("HEURISTIC.SEED", &(mupip_size_cfg.seed));
if (!valid){
error_mupip = TRUE;
gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.SEED"));
}
}
/* else seed will be based on the time */
}
mupip_size_check_error();
/* run mupip size on each global */
for (gl_ptr = gl_head.next; gl_ptr; gl_ptr = gl_ptr->next)
{
util_out_print("!/Global: !AD ", FLUSH, gl_ptr->name.str.len, gl_ptr->name.str.addr);
mupip_size_cfg.global_name = &(gl_ptr->name);
switch (mupip_size_cfg.heuristic)
{
case scan:
status |= mu_size_scan(mupip_size_cfg.global_name, mupip_size_cfg.level);
break;
case arsample:
status |= mu_size_arsample(mupip_size_cfg.global_name, mupip_size_cfg.samples, TRUE, mupip_size_cfg.seed);
break;
case impsample:
status |= mu_size_impsample(mupip_size_cfg.global_name, mupip_size_cfg.samples, mupip_size_cfg.seed);
break;
default:
GTMASSERT;
break;
}
if (mu_ctrlc_occurred || mu_ctrly_occurred)
mupip_exit(ERR_MUNOFINISH);
}
mupip_exit(status == EXIT_NRM ? SS_NORMAL : ERR_MUNOFINISH);
}
STATICDEF void mupip_size_check_error(void)
{
if (error_mupip)
{
util_out_print("!/MUPIP SIZE cannot proceed with above errors!/", FLUSH);
mupip_exit(ERR_MUNOACTION);
}
}

23
sr_unix/mupip_size.h Normal file
View File

@ -0,0 +1,23 @@
/****************************************************************
* *
* Copyright 2012 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. *
* *
****************************************************************/
#ifndef __MUPIP_SIZE_H__
#define __MUPIP_SIZE_H__
#include "cdb_sc.h"
void mupip_size(void);
int4 mu_size_arsample(mval *gn, uint M, boolean_t ar, int seed);
int4 mu_size_impsample(mval *gn, int4 M, int4 seed);
int4 mu_size_scan(mval *gn, int4 level);
enum cdb_sc rand_traverse(double *r);
#endif

664
sr_unix/op_fnzpeek.c Normal file
View File

@ -0,0 +1,664 @@
/****************************************************************
* *
* Copyright 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 <sys/types.h>
#include <signal.h>
#include "gtm_unistd.h"
#include "gtm_string.h"
#include "send_msg.h"
#include "error.h"
#include "stringpool.h"
#include "util.h"
#include "op.h"
#include "nametabtyp.h"
#include "namelook.h"
#include "gdsroot.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "repl_msg.h"
#include "gtmsource.h"
#include "gtmrecv.h"
#include "anticipatory_freeze.h"
#include "gtm_caseconv.h"
error_def(ERR_BADZPEEKARG);
error_def(ERR_BADZPEEKFMT);
error_def(ERR_BADZPEEKRANGE);
error_def(ERR_MAXSTRLEN);
error_def(ERR_ZPEEKNORPLINFO);
#define FMTHEXDGT(spfree, digit) *spfree++ = digit + ((digit <= 9) ? '0' : ('A' - 0x0A))
#define ZPEEKDEFFMT "C"
#define ZPEEKDEFFMT_LEN (SIZEOF(ZPEEKDEFFMT) - 1)
#define ARGUMENT_MAX_LEN MAX_MIDENT_LEN
/* Codes for peek operation mnemonics */
#define PO_CSAREG 0 /* Region information - sgmnt_addrs struct - process private structure */
#define PO_FHREG 1 /* Fileheader information from sgmnt_data for specified region */
#define PO_GDRREG 2 /* Region information - gd_region struct - process private structure */
#define PO_NLREG 3 /* Fileheader information from node_local for specified region (transient - non permanent) */
#define PO_NLREPL 4 /* Fileheader information from node_local for replication dummy region */
#define PO_GLFREPL 5 /* Replication information from gtmsrc_lcl_array structure */
#define PO_GSLREPL 6 /* Replication information from gtmsource_local_array structure */
#define PO_JPCREPL 7 /* Replication information from jnlpool_ctl structure */
#define PO_PEEK 8 /* Generalized peek specifying (base) address argument */
#define PO_RIHREPL 9 /* Replication information from repl_inst_hdr structure */
#define PO_RPCREPL 10 /* Replication information from recvpool_ctl_struct */
#define PO_UPLREPL 11 /* Replication information from upd_proc_local_struct */
#define PO_GRLREPL 12 /* Replication information from gtmrecv_local_struct */
#define PO_UHCREPL 13 /* Replication information from upd_helper_ctl */
GBLREF boolean_t created_core;
GBLREF sigset_t blockalrm;
GBLREF gd_addr *gd_header;
GBLREF boolean_t pool_init;
GBLREF boolean_t jnlpool_init_needed;
GBLREF jnlpool_addrs jnlpool;
GBLREF recvpool_addrs recvpool;
DEBUG_ONLY(GBLREF boolean_t ok_to_UNWIND_in_exit_handling;)
LITDEF mval literal_zpeekdeffmt = DEFINE_MVAL_LITERAL(MV_STR, 0, 0, ZPEEKDEFFMT_LEN, (char *)ZPEEKDEFFMT, 0, 0);
LITREF unsigned char lower_to_upper_table[];
STATICFNDCL void op_fnzpeek_signal_handler(int sig, siginfo_t *info, void *context);
STATICFNDCL int op_fnzpeek_stpcopy(char *zpeekadr, int len, mval *ret, char fmtcode);
STATICFNDCL uchar_ptr_t op_fnzpeek_uint64fmt(uchar_ptr_t p, gtm_uint64_t n);
STATICFNDCL uchar_ptr_t op_fnzpeek_hexfmt(uchar_ptr_t p, gtm_uint64_t n, int fmtlen);
STATICFNDEF boolean_t op_fnzpeek_attach_jnlpool(void);
STATICFNDEF boolean_t op_fnzpeek_attach_recvpool(void);
typedef struct
{
int peekop; /* Peek operation mnemonic id */
boolean_t allowargs; /* Number of arguments allowed */
} zpeek_data_typ;
/* Lookup tables for first argument - Note names are limited to NAME_ENTRY_SZ bytes each */
LITDEF nametabent zpeek_names[] =
{ /* Array offsets */
{3, "CSA"}, {6, "CSAREG"} /* 0, 1 */
,{2, "FH"}, {5, "FHREG"} /* 2, 3 */
,{3, "GDR"}, {6, "GDRREG"} /* 4, 5 */
,{3, "GLF"}, {7, "GLFREPL"} /* 6, 7 */
,{3, "GRL"}, {7, "GRLREPL"} /* 8, 9 */
,{3, "GSL"}, {7, "GSLREPL"} /* 10, 11 */
,{3, "JPC"}, {7, "JPCREPL"} /* 12, 13 */
,{2, "NL"}, {5, "NLREG"} /* 14, 15 */
,{6, "NLREPL"} /* 16 */
,{4, "PEEK"} /* 17 */
,{3, "RIH"}, {7, "RIHREPL"} /* 18, 19 */
,{3, "RPC"}, {7, "RPCREPL"} /* 20, 21 */
,{3, "UHC"}, {7, "UHCREPL"} /* 22, 23 */
,{3, "UPL"}, {7, "UPLREPL"} /* 24, 25 */
/* Total length 26 */
};
LITDEF unsigned char zpeek_index[] =
{
0, 0, 0, 2, 2, 2, 4, 12, 12, /* a b c d e f g h i */
12, 14, 14, 14, 14, 17, 17, 18, 18, /* j k l m n o p q r */
22, 22, 22, 26, 26, 26, 26, 26, 26 /* s t u v w x y z ~ */
};
LITDEF zpeek_data_typ zpeek_data[] =
{
{PO_CSAREG, 1}, {PO_CSAREG, 1}
,{PO_FHREG, 1}, {PO_FHREG, 1}
,{PO_GDRREG, 1}, {PO_GDRREG, 1}
,{PO_GLFREPL, 1}, {PO_GLFREPL, 1}
,{PO_GRLREPL, 0}, {PO_GRLREPL, 0}
,{PO_GSLREPL, 1}, {PO_GSLREPL, 1}
,{PO_JPCREPL, 0}, {PO_JPCREPL, 0}
,{PO_NLREG, 1}, {PO_NLREG, 1}
,{PO_NLREPL, 0}
,{PO_PEEK, 1}
,{PO_RIHREPL, 0}, {PO_RIHREPL, 0}
,{PO_RPCREPL, 0}, {PO_RPCREPL, 0}
,{PO_UHCREPL, 0}, {PO_UHCREPL, 0}
,{PO_UPLREPL, 0}, {PO_UPLREPL, 0}
};
/* Condition handler for use during copy of memory range to the stringpool for return. Note this condition handler is itself
* never tripped but serves as an unwind target for the signal handler defined below (see its comments).
*/
CONDITION_HANDLER(op_fnzpeek_ch)
{
START_CH;
NEXTCH; /* In the unlikely event it gets driven, just be a pass-thru */
}
/* $ZPEEK() is processing a process memory range specified by an M routine so is definitely capable of getting
* user inspired address type exceptions. We protect against this by setting up our signal handler to catch any
* such exceptions for the duration of this routine and just unwind them so we can throw a non-fatal error
* message instead.
*/
void op_fnzpeek_signal_handler(int sig, siginfo_t *info, void *context)
{
/* We basically want to do UNWIND(NULL, NULL) logic but the UNWIND macro can only be used in a condition
* handler so next is a block that pretends it is our condition handler and does the needful. Note in order
* for this to work, we need to be wrapped in a condition handler even if that condition handler is never
* actually invoked to serve as the target for the UNWIND().
*/
{ /* Needs new block since START_CH declares a new var used in UNWIND() */
int arg = 0; /* Needed for START_CH macro if debugging enabled */
START_CH;
DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = TRUE);
UNWIND(NULL, NULL);
}
}
/* Routine to convert gtm_uint64_t to ascii value not losing any precision. Routine is based on i2asc() but
* uses gtm_uint64_t as the type.
*/
STATICFNDCL uchar_ptr_t op_fnzpeek_uint64fmt(uchar_ptr_t p, gtm_uint64_t n)
{
unsigned char ar[MAX_DIGITS_IN_INT8], *q;
gtm_uint64_t m;
int len;
q = ar + SIZEOF(ar);
if (!n)
*--q = '0';
else
{
while (n)
{
m = n / 10;
*--q = n - (m * 10) + '0';
n = m;
}
}
assert((uintszofptr_t)q >= (uintszofptr_t)ar);
len = (unsigned int)(ar + SIZEOF(ar) - q);
memcpy(p, q, len);
return p + len;
}
/* Routine to format hex output to given length with format 0xhh<hh<hhhh<hhhhhhhh>>>. Similar to i2asclx().
*
* p - Output buffer (generally stringpool.free)
* n - Hex value to format
* fmtlen - Length in bytes of output value
*/
STATICFNDCL uchar_ptr_t op_fnzpeek_hexfmt(uchar_ptr_t p, gtm_uint64_t n, int fmtlen)
{
unsigned char ar[MAX_HEX_DIGITS_IN_INT8], *q;
int m, digits;
q = ar + SIZEOF(ar);
for (digits = fmtlen; (0 < digits); --digits)
{
m = n & 0xF;
if (m <= 9)
*--q = m + '0';
else
*--q = m - 0xa + 'A';
n = n >> 4;
}
assert(0 == n); /* Verify complete number has been output (no truncated digits) */
memcpy(p, q, fmtlen);
return p + fmtlen;
}
/* Routine to extract and optionally format the requested data leaving it in the stringpool. This routine is protected
* by a signal handler for data access against SIGSEGV or SIGBUS signals. Note the fields that are sub-integer (1 or
* 2 bytes) are pulled into integer forms before processing.
*/
STATICFNDEF int op_fnzpeek_stpcopy(char *zpeekadr, int len, mval *ret, char fmtcode)
{
unsigned int uint;
boolean_t negative;
gtm_uint64_t uint64;
unsigned char *numstrstart, *numstrend;
unsigned char *hexchr, *hexchrend, hexc, hexdgt, *spfree;
ESTABLISH_RET(op_fnzpeek_ch, ERR_BADZPEEKRANGE); /* If get an exception, likely due to bad range */
ret->mvtype = 0; /* Prevent GC of incomplete field */
switch(fmtcode)
{
case 'S': /* Null terminated string processing */
STRNLEN(zpeekadr, len, len); /* Reset len to actual len, fall into "C" processing */
/* warning - fall through */
case 'C': /* Character area (no processing - just copy */
if (len > MAX_STRLEN)
{ /* Requested string return is too large */
REVERT;
return ERR_MAXSTRLEN;
}
ENSURE_STP_FREE_SPACE(len);
memcpy(stringpool.free, zpeekadr, len);
ret->str.addr = (char *)stringpool.free;
ret->str.len = len;
stringpool.free += len;
break;
case 'I': /* Initially, treat signed/unsigned the same */
case 'U':
negative = FALSE;
switch(len)
{
case SIZEOF(gtm_uint64_t):
/* Dealing with 8 byte integer style values is not GT.M's forte since its internal
* number scheme is limited to 20 digits. So use our own routine to do the conversion.
* Note: we could use this routine for all the below cases but on 32 bit platforms
* with no native 8 byte values, they would run far slower so only use this for the
* 8 byte values we deal with.
*/
uint64 = *(gtm_uint64_t *)zpeekadr;
if ('I' == fmtcode)
{ /* If signed, check if need to add minus sign to value and change value to
* positive.
*/
negative = (0 > (gtm_int64_t)uint64);
if (negative)
uint64 = (gtm_uint64_t)(-(gtm_int64_t)uint64);
}
fmtcode = 'u'; /* Change fmtcode to skip negative value check below */
break;
case SIZEOF(unsigned int):
uint = *(unsigned int *)zpeekadr;
break;
case SIZEOF(short):
uint = (unsigned int)*(unsigned short *)zpeekadr;
break;
case SIZEOF(char):
uint = (unsigned int)*(unsigned char *)zpeekadr;
break;
default:
REVERT;
return ERR_BADZPEEKFMT;
}
if ('I' == fmtcode)
{ /* If signed, check if need to add minus sign to value and change value to positive. Note this test
* is bypassed for uint64 types because the check is already made (in a differet/longer value).
*/
negative = (0 > (signed int)uint);
if (negative)
uint = (unsigned int)(-(signed int)uint);
}
ENSURE_STP_FREE_SPACE(MAX_DIGITS_IN_INT + negative); /* Space to hold # */
numstrstart = stringpool.free;
if (negative)
*stringpool.free++ = '-'; /* Value is negative, record in output */
/* Use the correct formmating routine based on size */
numstrend = (SIZEOF(gtm_uint64_t) != len) ? i2asc(stringpool.free, uint)
: op_fnzpeek_uint64fmt(stringpool.free, uint64);
ret->str.addr = (char *)numstrstart;
ret->str.len = INTCAST(numstrend - numstrstart);
stringpool.free = numstrend;
break;
case 'X': /* Hex format for numeric values */
switch(len)
{
case SIZEOF(gtm_uint64_t):
uint64 = *(gtm_uint64_t *)zpeekadr;
break;
case SIZEOF(unsigned int):
uint64 = (gtm_uint64_t)*(unsigned int *)zpeekadr;
break;
case SIZEOF(unsigned short):
uint64 = (gtm_uint64_t)*(unsigned short *)zpeekadr;
break;
case SIZEOF(unsigned char):
uint64 = (gtm_uint64_t)*(unsigned char *)zpeekadr;
break;
default:
REVERT;
return ERR_BADZPEEKFMT;
}
ENSURE_STP_FREE_SPACE((len * 2) + 2);
numstrstart = stringpool.free;
*stringpool.free++ = '0';
*stringpool.free++ = 'x';
numstrend = op_fnzpeek_hexfmt(stringpool.free, uint64, (len * 2));
ret->str.addr = (char *)numstrstart;
ret->str.len = INTCAST(numstrend - numstrstart);
stringpool.free = numstrend;
break;
case 'Z': /* Hex format (no 0x prefix) of storage as it exists */
if ((len * 2) > MAX_STRLEN)
{ /* Requested string return is too large */
REVERT;
return ERR_MAXSTRLEN;
}
ENSURE_STP_FREE_SPACE(len * 2); /* Need enough space for hex string */
spfree = stringpool.free;
ret->str.addr = (char *)spfree;
hexchr = (unsigned char *)zpeekadr;
hexchrend = hexchr + len;
if (hexchr > hexchrend) /* Wrapped address - range error */
{
REVERT;
return ERR_BADZPEEKRANGE;
}
for (; hexchr < hexchrend; ++hexchr)
{ /* Format 2 digits in each character encountered */
hexc = *hexchr;
hexdgt = (hexc & 0xF0) >> 4;
FMTHEXDGT(spfree, hexdgt);
hexdgt = (hexc & 0x0F);
FMTHEXDGT(spfree, hexdgt);
}
stringpool.free = spfree; /* "commit" string to stringpool */
ret->str.len = len * 2;
break;
default:
REVERT;
return ERR_BADZPEEKARG;
}
REVERT;
ret->mvtype = MV_STR;
return 0;
}
/* A condition handler for when we are attaching to either the jnlpool or the gtmrecv pool. We don't
* care why we can't get to them. On the fact that we can't is material for $ZPEEK().
*/
CONDITION_HANDLER(op_fnzpeek_getpool_ch)
{
START_CH;
if (DUMPABLE)
NEXTCH; /* Let next (more robust) handler deal with it */
UNWIND(NULL, NULL);
}
/* Attach to the journal pool. Separate routine so can be wrapped in a condition handler */
STATICFNDEF boolean_t op_fnzpeek_attach_jnlpool(void)
{
ESTABLISH_RET(op_fnzpeek_getpool_ch, FALSE);
jnlpool_init(GTMRELAXED, FALSE, NULL); /* Attach to journal pool */
REVERT;
return pool_init;
}
/* Attach to the receive pool. Separate routine so can be wrapped in a condition handler */
STATICFNDEF boolean_t op_fnzpeek_attach_recvpool(void)
{
ESTABLISH_RET(op_fnzpeek_getpool_ch, FALSE);
recvpool_init(GTMZPEEK, FALSE); /* Attach to receive pool */
REVERT;
return ((NULL != recvpool.recvpool_ctl) && recvpool.recvpool_ctl->initialized);
}
/* Generalized peek facility:
*
* structid - String that describes the structure
* offset - Offset of item within that structure.
* len - Length of the fetch.
* format - Option format character - codes described below
* ret - Return mval
*/
void op_fnzpeek(mval *structid, int offset, int len, mval *format, mval *ret)
{
void *zpeekadr;
UINTPTR_T prmpeekadr;
struct sigaction new_action, prev_action_bus, prev_action_segv;
sigset_t savemask;
int errtoraise, rslt;
char fmtcode;
boolean_t arg_supplied, attach_success;
unsigned char mnemonic[NAME_ENTRY_SZ], *nptr, *cptr, *cptrend, *argptr;
int mnemonic_len, mnemonic_index, mnemonic_opcode, arglen, arryidx;
gd_region *r_top, *r_ptr;
replpool_identifier replpool_id;
unsigned int full_len;
unsigned char argument_uc_buf[ARGUMENT_MAX_LEN];
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
/* Make sure lookup table is setup correctly */
assert(zpeek_index[26] == (SIZEOF(zpeek_names) / SIZEOF(nametabent)));
assert((SIZEOF(zpeek_names) / SIZEOF(nametabent)) == (SIZEOF(zpeek_data) / SIZEOF(zpeek_data_typ)));
/* Initialize */
fmtcode = 'C'; /* If arg is NULL string (noundef default), provide default */
MV_FORCE_STR(structid);
if (MV_DEFINED(format))
{
MV_FORCE_STR(format);
} else format = (mval *)&literal_zpeekdeffmt; /* Cast to avoid compiler warning about dropping readonly type attributes */
/* Parse and lookup the first arg's mnemonic and arg (if supplied) */
for (nptr = mnemonic, cptr = (unsigned char *)structid->str.addr, cptrend = cptr + structid->str.len;
cptr < cptrend; ++cptr)
{
if (':' == *cptr)
break; /* End of mnemonic, start of arg */
*nptr++ = *cptr;
}
arg_supplied = (cptr < cptrend);
mnemonic_len = INTCAST(nptr - mnemonic);
mnemonic_index = namelook(zpeek_index, zpeek_names, (char *)mnemonic, mnemonic_len);
if (0 > mnemonic_index)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic type"));
mnemonic_opcode = zpeek_data[mnemonic_index].peekop;
if ((arg_supplied && !zpeek_data[mnemonic_index].allowargs) || (!arg_supplied && zpeek_data[mnemonic_index].allowargs))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic argument"));
if (arg_supplied)
{ /* Parse supplied argument */
argptr = ++cptr; /* Bump past ":" - if now have end-of-arg then arg is missing */
if (argptr == cptrend)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic argument"));
arglen = INTCAST(cptrend - cptr);
if (ARGUMENT_MAX_LEN < arglen)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic argument"));
switch(mnemonic_opcode)
{
case PO_CSAREG: /* These types have a region name argument */
case PO_FHREG:
case PO_GDRREG:
case PO_NLREG:
/* Uppercase the region name since that is what GDE does when creating them */
lower_to_upper(argument_uc_buf, argptr, arglen);
argptr = argument_uc_buf; /* Reset now to point to upper case version */
/* See if region recently used so can avoid lookup */
if ((arglen == TREF(zpeek_regname_len)) && (0 == memcmp(argptr, TADR(zpeek_regname), arglen)))
{ /* Fast path - no lookup necessary */
r_ptr = TREF(zpeek_reg_ptr);
assert(r_ptr->open && !r_ptr->was_open); /* Make sure truly open */
break;
}
/* Region now defined - make sure it is open */
if (!gd_header) /* If gd_header is NULL, open gbldir */
gvinit();
r_ptr = gd_header->regions;
for (r_top = r_ptr + gd_header->n_regions; ; r_ptr++)
{
if (r_ptr >= r_top)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2,
RTS_ERROR_LITERAL("mnemonic argument (region name)"));
if ((r_ptr->rname_len == arglen) && (0 == memcmp(r_ptr->rname, argptr, arglen)))
break;
}
if (!r_ptr->open)
gv_init_reg(r_ptr);
/* Cache new region access for followup references */
memcpy(TADR(zpeek_regname), argptr, arglen);
TREF(zpeek_regname_len) = arglen;
TREF(zpeek_reg_ptr) = r_ptr;
/* r_ptr now points to (open) region */
assert(r_ptr->open && !r_ptr->was_open); /* Make sure truly open */
break;
case PO_GLFREPL: /* These types have an array index argument */
case PO_GSLREPL:
arryidx = asc2i(argptr, arglen);
if ((0 > arryidx) || (NUM_GTMSRC_LCL < arryidx))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2,
RTS_ERROR_LITERAL("mnemonic argument (array index)"));
break;
case PO_PEEK: /* Argument is address of form 0Xhhhhhhhh[hhhhhhhh] */
if (('0' != *cptr++) || ('x' != *cptr) && ('X' != *cptr))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2,
RTS_ERROR_LITERAL("mnemonic argument (peek base address)"));
cptr++; /* Bump past 'x' or 'X' - rest of arg should be hex value */
prmpeekadr = (UINTPTR_T)GTM64_ONLY(asc_hex2l)NON_GTM64_ONLY(asc_hex2i)(cptr, arglen - 2);
if (-1 == (INTPTR_T)prmpeekadr)
/* Either an error occurred or the user specified the maximum address. So it's
* either an error from the conversion routine or an otherwise useless value.
*/
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2,
RTS_ERROR_LITERAL("mnemonic argument (peek base address)"));
break;
default:
assert(FALSE); /* Only the above types should ever have an argument */
}
}
/* Figure out the address of each block to return */
switch(mnemonic_opcode)
{
case PO_CSAREG: /* r_ptr set from option processing */
zpeekadr = &FILE_INFO(r_ptr)->s_addrs;
break;
case PO_FHREG: /* r_ptr set from option processing */
zpeekadr = (&FILE_INFO(r_ptr)->s_addrs)->hdr;
break;
case PO_GDRREG: /* r_ptr set from option processing */
zpeekadr = r_ptr;
break;
case PO_NLREG: /* r_ptr set from option processing */
zpeekadr = (&FILE_INFO(r_ptr)->s_addrs)->nl;
break;
case PO_GLFREPL: /* This set of opcodes all require the journal pool to be initialized. Verify it */
case PO_GSLREPL:
case PO_JPCREPL:
case PO_NLREPL:
case PO_RIHREPL:
/* Make sure jnlpool_addrs are availble */
if (!REPL_INST_AVAILABLE)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO);
if (!pool_init)
{
attach_success = op_fnzpeek_attach_jnlpool();
if (!attach_success)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO);
}
switch(mnemonic_opcode)
{
case PO_GLFREPL: /* arryidx set by option processing */
zpeekadr = (jnlpool.gtmsrc_lcl_array + arryidx);
break;
case PO_GSLREPL: /* arryidx set by option processing */
zpeekadr = (jnlpool.gtmsource_local_array + arryidx);
break;
case PO_NLREPL:
zpeekadr = (&FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs)->nl;
break;
case PO_JPCREPL:
zpeekadr = jnlpool.jnlpool_ctl;
break;
case PO_RIHREPL:
zpeekadr = jnlpool.repl_inst_filehdr;
break;
default:
assert(FALSE);
}
break;
case PO_RPCREPL: /* This set of opcodes all require the receive pool to be initialized. Verify it */
case PO_GRLREPL:
case PO_UPLREPL:
case PO_UHCREPL:
/* Make sure recvpool_addrs are available */
if (!REPL_INST_AVAILABLE)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO);
if (NULL == recvpool.recvpool_ctl)
{
attach_success = op_fnzpeek_attach_recvpool();
if (!attach_success)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO);
}
switch(mnemonic_opcode)
{
case PO_RPCREPL:
zpeekadr = recvpool.recvpool_ctl;
break;
case PO_GRLREPL:
zpeekadr = recvpool.gtmrecv_local;
break;
case PO_UPLREPL:
zpeekadr = recvpool.upd_proc_local;
break;
case PO_UHCREPL:
zpeekadr = recvpool.upd_helper_ctl;
break;
default:
assert(FALSE);
}
break;
case PO_PEEK: /* prmpeekadr set up in argument processing */
zpeekadr = (void *)prmpeekadr;
break;
default:
assert(FALSE);
}
assert(NULL != zpeekadr);
/* Check the rest of the args */
if (0 > offset)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("offset"));
zpeekadr = (void *)((char *)zpeekadr + offset);
if ((0 > len) || (MAX_STRLEN < len))
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("length"));
if (1 < format->str.len)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("format"));
else if (1 == format->str.len)
{ /* Validate format option */
fmtcode = *format->str.addr;
fmtcode = lower_to_upper_table[fmtcode];
switch(fmtcode)
{
case 'C': /* Character data - returned as is */
case 'I': /* Signed integer format - up to 31 bits */
case 'S': /* String data - Same as 'C' except string is NULL terminated */
case 'U': /* Unsigned integer format - up to 64 bits */
case 'X': /* Humeric hex format: e.g. 0x12AB. Total length is (2 * bytes) + 2 */
case 'Z': /* Hex format - not treated as numeric. Shown as occurs in memory (subject to endian)
* and is returned with no 0x prefix.
*/
break;
default:
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("format"));
}
}
/* Block out timer calls that might trigger processing that could fail. We especially want to prevent
* nesting of signal handlers since the longjump() function used by the UNWIND macro is undefined on
* Tru64 when signal handlers are nested.
*/
sigprocmask(SIG_BLOCK, &blockalrm, &savemask);
/* Setup new signal handler to just drive condition handler which will do the right thing */
memset(&new_action, 0, SIZEOF(new_action));
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = SA_SIGINFO;
# ifdef __sparc
new_action.sa_handler = op_fnzpeek_signal_handler;
# else
new_action.sa_sigaction = op_fnzpeek_signal_handler;
# endif
sigaction(SIGBUS, &new_action, &prev_action_bus);
sigaction(SIGSEGV, &new_action, &prev_action_segv);
/* Attempt to copy return string to stringpool which protected by our handlers. If the copy completes, the return
* mval is updated to point to the return string. Even errors return here so these sigactions can be reversed.
*/
errtoraise = op_fnzpeek_stpcopy(zpeekadr, len, ret, fmtcode);
/* Can restore handlers now that access verified */
sigaction(SIGBUS, &prev_action_bus, NULL);
sigaction(SIGSEGV, &prev_action_segv, NULL);
/* Let the timers pop again.. */
sigprocmask(SIG_SETMASK, &savemask, NULL);
/* If we didn't complete correctly, raise error */
if (0 != errtoraise)
{ /* The only time ERR_BADZPEEKARG is driven is when the format code is not recognized so give that error
* specifically with the additional args. Else just raise the error.
*/
if (ERR_BADZPEEKARG == errtoraise)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) errtoraise, 2, RTS_ERROR_LITERAL("format"));
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errtoraise);
}
return;
}

View File

@ -0,0 +1,80 @@
/****************************************************************
* *
* Copyright 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 <stddef.h>
#include <errno.h>
#include "mdef.h"
#include "gtm_limits.h"
#include "gtm_string.h"
#include "gtm_stdio.h"
#include "gtm_unistd.h"
#include "repl_msg.h"
#include "repl_log.h"
#include "gdsroot.h"
#include "have_crit.h"
#include "min_max.h"
error_def(ERR_FILENAMETOOLONG);
GBLREF uint4 process_id;
uint4 repl_logfileinfo_get(char *logfile, repl_logfile_info_msg_t *msgp, boolean_t cross_endian, FILE *logfp)
{
uint4 status, fullpath_len, msglen;
int save_errno;
char fullpath[GTM_PATH_MAX], *cwdptr;
assert(NULL != msgp);
msgp->type = cross_endian ? GTM_BYTESWAP_32(REPL_LOGFILE_INFO) : REPL_LOGFILE_INFO;
assert(GTM_PATH_MAX >= REPL_LOGFILE_PATH_MAX);
assert(GTM_PATH_MAX >= PATH_MAX);
if (NULL == logfile)
{
GETCWD(fullpath, GTM_PATH_MAX, cwdptr);
assert(NULL != cwdptr);
if (NULL == cwdptr)
{
save_errno = errno;
assert(FALSE);
repl_log(logfp, TRUE, TRUE, "Could not obtain current working directory: %s\n", STRERROR(save_errno));
SNPRINTF(fullpath, GTM_PATH_MAX, "Could not obtain current working directory");
}
fullpath_len = STRLEN(fullpath);
} else if (!get_full_path(STR_AND_LEN(logfile), fullpath, &fullpath_len, GTM_PATH_MAX + 1, &status))
{ /* Either GETCWD failed or buffer not large enough to hold the expanded logfile path. In either case, we don't want
* to error out as this is just a supplementary message. Copy whatever possible.
*/
assert(ERR_FILENAMETOOLONG != status);
SNPRINTF(fullpath, GTM_PATH_MAX, logfile);
fullpath_len = STRLEN(fullpath);
/* Print a warning message for diagnostic purposes */
if (ERR_FILENAMETOOLONG != status)
repl_log(logfp, TRUE, TRUE, "Could not obtain current working directory: %s\n", STRERROR(status));
else
repl_log(logfp, TRUE, TRUE, "Could not obtain full path of log file: Path name exceeds %d characters\n",
GTM_PATH_MAX);
}
assert('\0' == fullpath[fullpath_len]);
fullpath_len = MIN(fullpath_len, REPL_LOGFILE_PATH_MAX);
fullpath[fullpath_len] = '\0'; /* truncate if needed */
fullpath_len++; /* So that, we copy and send null-terminator as well */
memcpy(msgp->fullpath, fullpath, fullpath_len);
msgp->fullpath_len = cross_endian ? GTM_BYTESWAP_32(fullpath_len) : fullpath_len;
assert(fullpath_len <= REPL_LOGFILE_PATH_MAX);
/* Receiver expects 8 byte alignment on data portion of the message. */
fullpath_len = ROUND_UP2(fullpath_len, REPL_MSG_ALIGN);
assert(fullpath_len <= REPL_LOGFILE_PATH_MAX + 1);
msglen = REPL_LOGFILE_INFO_MSGHDR_SZ + fullpath_len;
msgp->len = cross_endian ? GTM_BYTESWAP_32(msglen) : msglen;
msgp->proto_ver = REPL_PROTO_VER_THIS;
msgp->pid = cross_endian ? GTM_BYTESWAP_32(process_id) : process_id;
return msglen;
}

View File

@ -0,0 +1,54 @@
#!/bin/sh
#################################################################
# #
# Copyright 2012 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. #
# #
#################################################################
if [ "x" = x"$gtm_dist" ]; then
echo "Environment variable - gtm_dist not defined."
exit 1
fi
if [ ! -d $gtm_dist/plugin ]; then
echo "Unable to locate $gtm_dist/plugin. Exiting..."
exit 1
fi
platform_name=`uname -s`
ext=".so"
if [ "OS/390" = $platform_name ]; then ext=".dll" ; fi
base_libname="libgtmcrypt"
generic_libname=$base_libname$ext
if [ "x" = x"$gtm_crypt_plugin" ]; then
shared_object="$gtm_dist/plugin/$generic_libname"
txt="symbolic link pointed by $gtm_dist/plugin/$generic_libname"
else
shared_object="$gtm_dist/plugin/$gtm_crypt_plugin"
txt='$gtm_crypt_plugin'
fi
if [ ! -f $shared_object ] ; then
echo "Cannot find $shared_object. Exiting..."
exit 1
fi
# Obtain the symbolic link (if any)
link=`ls -l $shared_object | awk '{print $NF}'`
# Get rid of the prefix (any path associated with the link) and the extension
basepart=`echo $link | awk -F/ '{print $NF}' | sed 's/'"$ext"'$//'`
# Resulting $basepart should be of form -- A_B_C
encryption_lib=`echo $basepart | cut -f2 -d'_'`
algorithm=`echo $basepart | cut -f3 -d'_'`
if [ "$encryption_lib" = "$algorithm" -o "" = "$algorithm" ] ; then
echo "Unable to determine encryption library name or algorithm. Please ensure that $txt has the correct format. Exiting..."
exit 1
fi
echo "ENCRYPTION_LIB = $encryption_lib"
echo "ALGORITHM = $algorithm"
exit 0

63
sr_unix/util_help.c Normal file
View File

@ -0,0 +1,63 @@
/****************************************************************
* *
* Copyright 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 "util_help.h"
#include "gtm_stdio.h" /* for snprintf() */
#include "gtm_string.h" /* for strlen() */
#include "gtm_stdlib.h" /* for SYSTEM() */
#include "gtmimagename.h" /* for struct gtmImageName */
error_def(ERR_TEXT);
#define HELP_CMD_STRING_SIZE 512
#define EXEC_GTMHELP "$gtm_dist/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"$gtm_dist/%shelp.gld\")'",
#define UTIL_HELP_IMAGES 5
/* We need the first two entries for compatibility */
char *utilImageGLDs[UTIL_HELP_IMAGES] =
{
#define IMAGE_TABLE_ENTRY(A,B) B,
IMAGE_TABLE_ENTRY (INVALID_IMAGE, "")
IMAGE_TABLE_ENTRY (GTM_IMAGE, "gtm")
IMAGE_TABLE_ENTRY (MUPIP_IMAGE, "mupip")
IMAGE_TABLE_ENTRY (DSE_IMAGE, "dse")
IMAGE_TABLE_ENTRY (LKE_IMAGE, "lke")
#undef IMAGE_TABLE_ENTRY
};
void util_help(void)
{
int rc;
char *help_option;
char help_cmd_string[HELP_CMD_STRING_SIZE];
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
assert(1 >= TREF(parms_cnt));
assert(GTM_IMAGE < image_type && UTIL_HELP_IMAGES > image_type);
if (0 == TREF(parms_cnt))
help_option = utilImageGLDs[INVALID_IMAGE];
else
{
assert(TAREF1(parm_ary, TREF(parms_cnt) - 1));
assert((char *)-1L != (TAREF1(parm_ary, TREF(parms_cnt) - 1)));
help_option = (TAREF1(parm_ary, TREF(parms_cnt) - 1));
}
SNPRINTF(help_cmd_string, SIZEOF(help_cmd_string),
"$gtm_dist/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"$gtm_dist/%shelp.gld\")'",
help_option, utilImageGLDs[image_type]);
rc = SYSTEM(help_cmd_string);
if (0 != rc)
rts_error_csa(NULL, VARLSTCNT(5) ERR_TEXT, 2, RTS_ERROR_TEXT("HELP command error"), rc);
}

16
sr_unix/util_help.h Normal file
View File

@ -0,0 +1,16 @@
/****************************************************************
* *
* Copyright 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. *
* *
****************************************************************/
#ifndef UTIL_HELP_INCLUDED
#define UTIL_HELP_INCLUDED
void util_help(void);
#endif

View File

@ -0,0 +1,155 @@
/****************************************************************
* *
* Copyright 2012, 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 <errno.h> /* for ENOSPC */
#include "anticipatory_freeze.h"
#include "wait_for_disk_space.h"
#include "gtmio.h"
#include "have_crit.h"
#include "filestruct.h"
#include "jnl.h"
#include "error.h"
#include "gtmmsg.h"
#ifdef DEBUG
GBLDEF uint4 lseekwrite_target;
#endif
GBLREF jnlpool_addrs jnlpool;
GBLREF volatile int4 exit_state;
GBLREF int4 exi_condition;
GBLREF int4 forced_exit_err;
error_def(ERR_DSKNOSPCAVAIL);
error_def(ERR_DSKNOSPCBLOCKED);
error_def(ERR_DSKSPCAVAILABLE);
error_def(ERR_ENOSPCQIODEFER);
/* In case of ENOSPC, if anticipatory freeze scheme is in effect and this process has attached to the
* journal pool, trigger an instance freeze in this case and wait for the disk space to be available
* at which point unfreeze the instance.
*/
void wait_for_disk_space(sgmnt_addrs *csa, char *fn, int fd, off_t offset, char *buf, size_t count, int *save_errno)
{
boolean_t was_crit;
gd_region *reg;
int fn_len, tmp_errno;
boolean_t freeze_cleared;
char wait_comment[MAX_FREEZE_COMMENT_LEN];
sgmnt_addrs *repl_csa;
# ifdef DEBUG
uint4 lcl_lseekwrite_target;
# endif
DCL_THREADGBL_ACCESS; /* needed by ANTICIPATORY_FREEZE_AVAILABLE macro */
SETUP_THREADGBL_ACCESS; /* needed by ANTICIPATORY_FREEZE_AVAILABLE macro */
# ifdef DEBUG
/* Reset global to safe state after noting it down in a local (just in case there are errors in this function) */
lcl_lseekwrite_target = lseekwrite_target; lseekwrite_target = LSEEKWRITE_IS_TO_NONE;
# endif
/* If anticipatory freeze scheme is not in effect, or if this database does not care about it,
* or DSKNOSPCAVAIL is not configured as a custom error, return right away.
*/
if (!ANTICIPATORY_FREEZE_ENABLED(csa) || (NULL == is_anticipatory_freeze_needed_fnptr)
|| !(*is_anticipatory_freeze_needed_fnptr)(csa, ERR_DSKNOSPCAVAIL))
return;
fn_len = STRLEN(fn);
repl_csa = &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs;
was_crit = repl_csa->now_crit;
reg = csa->region;
if (!was_crit)
{ /* Setting the instance freeze requires the journal pool lock (grab_lock). However, we need to be careful
* to avoid a deadlock. A deadlock is possible if we hold the io_in_prog_latch, and meanwhile another
* process has grabbed crit in t_end/tp_tend, grabbed the journal pool lock, and is now waiting on the
* io_in_prog_latch (e.g., via jnl_write). By doing a blocking wait in grab_lock here, we would
* deadlock. Therefore, we must pass is_blocking_wait = FALSE to grab_lock. If grab_lock does not succeed,
* we return right away and do not complete the jnl or db write operation for which we are waiting for disk
* space. Since we do not hold crit, we can safely proceed without its completion.
* On the other hand, this scenario is not possible if we hold crit on the region of interest. In this
* case, a normal grab_lock is fine (is_blocking_wait = TRUE).
*/
if (csa->now_crit)
grab_lock(jnlpool.jnlpool_dummy_reg, TRUE, GRAB_LOCK_ONLY);
else if (FALSE == grab_lock(jnlpool.jnlpool_dummy_reg, FALSE, GRAB_LOCK_ONLY))
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ENOSPCQIODEFER, 2, fn_len, fn);
*save_errno = ERR_ENOSPCQIODEFER;
return;
}
}
/* We either came into this function holding journal pool lock or grab_lock() succeeded */
assert(NULL != jnlpool.jnlpool_ctl);
assert(NULL != fn); /* if "csa" is non-NULL, fn better be non-NULL as well */
/* The "send_msg" of DSKNOSPCAVAIL done below will set instance freeze (the configuration file includes it). After that, we
* will keep retrying the IO waiting for disk space to become available. If yes, we will clear the freeze. Until that is
* done, we should not allow ourselves to be interrupted as otherwise interrupt code can try to write to the db/jnl (as
* part of DB_LSEEKWRITE) and the first step there would be to wait for the freeze to be lifted off. Since we were the ones
* who set the freeze in the first place, the auto-clearing of freeze (on disk space freeup) will no longer work in that
* case. Hence the reason not to allow interrupts.
*/
DEFER_INTERRUPTS(INTRPT_IN_WAIT_FOR_DISK_SPACE);
send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DSKNOSPCAVAIL, 2, fn_len, fn); /* this should set the instance freeze */
/* Make a copy of the freeze comment which would be set by the previous message. */
GENERATE_INST_FROZEN_COMMENT(wait_comment, MAX_FREEZE_COMMENT_LEN, ERR_DSKNOSPCAVAIL);
tmp_errno = *save_errno;
assert(ENOSPC == tmp_errno);
/* Hang/retry waiting for the disk space situation to be cleared. */
for ( ; ENOSPC == tmp_errno; )
{
if (!IS_REPL_INST_FROZEN)
{ /* Some other process cleared the instance freeze. But we still dont have our disk
* space issue resolved so set the freeze flag again until space is available for us.
*/
send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DSKNOSPCAVAIL, 2, fn_len, fn);
} else if (exit_state != 0)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err);
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err);
exit(-exi_condition);
}
/* Sleep for a while before retrying the write. Do not use "hiber_start" as that
* uses timers and if we are already in a timer handler now, nested timers wont work.
*/
SHORT_SLEEP(SLEEP_IORETRYWAIT);
DEBUG_ONLY(CLEAR_FAKE_ENOSPC_IF_MASTER_DEAD);
/* If some other process froze the instance and changed the comment, a retry of the
* LSEEKWRITE may not be appropriate, so just loop waiting for the freeze to be lifted.
*/
if (IS_REPL_INST_FROZEN && (STRCMP(wait_comment, jnlpool.jnlpool_ctl->freeze_comment) != 0))
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DSKNOSPCBLOCKED, 2, fn_len, fn);
WAIT_FOR_REPL_INST_UNFREEZE(csa)
}
LSEEKWRITE(fd, offset, buf, count, tmp_errno);
# ifdef DEBUG
if (LSEEKWRITE_IS_TO_DB == lcl_lseekwrite_target)
FAKE_ENOSPC(csa, fake_db_enospc, lcl_lseekwrite_target, tmp_errno)
else if (LSEEKWRITE_IS_TO_JNL == lcl_lseekwrite_target)
FAKE_ENOSPC(csa, fake_jnl_enospc, lcl_lseekwrite_target, tmp_errno)
# endif
}
/* Report that we were able to continue whether we are still frozen or not. */
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DSKSPCAVAILABLE, 2, fn_len, fn);
/* Only report if we were the process to set the current freeze comment; otherwise someone else reported it. */
if (STRCMP(wait_comment, jnlpool.jnlpool_ctl->freeze_comment) == 0)
{
CLEAR_ANTICIPATORY_FREEZE(freeze_cleared); /* sets freeze_cleared */
REPORT_INSTANCE_UNFROZEN(freeze_cleared);
}
*save_errno = tmp_errno;
ENABLE_INTERRUPTS(INTRPT_IN_WAIT_FOR_DISK_SPACE);
if (!was_crit)
rel_lock(jnlpool.jnlpool_dummy_reg);
return;
}

Some files were not shown because too many files have changed in this diff Show More