update missed file
This commit is contained in:
parent
5dfa4084d6
commit
833892caf7
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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) {};
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_ */
|
|
@ -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()
|
|
@ -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 */
|
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)_"(...)"
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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++;
|
||||||
|
}
|
|
@ -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 */
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
}
|
|
@ -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)
|
|
@ -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 */
|
||||||
|
}
|
|
@ -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})
|
||||||
|
|
|
@ -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
|
|
@ -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));
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
*/
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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, ®_max_rec, ®_max_key, ®_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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue