Enscribe Programmer’s Guide Programmers

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 191

DownloadEnscribe Programmer’s Guide Programmers
Open PDF In BrowserView PDF
Enscribe Programmer’s Guide

Abstract
This manual describes how to create, access, and load the five types of disk files supported by the Enscribe software.

Part Number: 520369-009R
Published: November 2015
Edition: 2

© Copyright 1999, , 2015 Hewlett Packard Enterprise Development LP
The information contained herein is subject to change without notice. The only warranties for Hewlett Packard Enterprise products and services
are set forth in the express warranty statements accompanying such products and services. Nothing herein should be construed as constituting
an additional warranty. Hewlett Packard Enterprise shall not be liable for technical or editorial errors or omissions contained herein.
Confidential computer software. Valid license from Hewlett Packard Enterprise required for possession, use, or copying. Consistent with FAR
12.211 and 12.212, Commercial Computer Software, Computer Software Documentation, and Technical Data for Commercial Items are licensed
to the U.S. Government under vendor's standard commercial license.
Export of the information contained in this publication may require authorization from the U.S. Department of Commerce.
Links to third-party websites take you outside the Hewlett Packard Enterprise website. Hewlett Packard Enterprise has no control over and is not
responsible for information outside the Hewlett Packard Enterprise website.
Acknowledgments
Intel®, Itanium®, Pentium®, Intel Inside®, and the Intel Inside logo are trademarks of Intel Corporation in the United States and other countries.
Microsoft® and Windows® are trademarks of the Microsoft group of companies.
Adobe® and Acrobat® are trademarks of Adobe Systems Incorporated.
Java and Oracle are registered trademarks of Oracle and/or its affiliates.
UNIX® is a registered trademark of The Open Group.
Motif, OSF/1, UNIX, X/Open, and the "X" device are registered trademarks and IT DialTone and The Open Group are trademarks of The Open
Group in the U.S. and other countries.
Open Software Foundation, OSF, the OSF logo, OSF/1, OSF/Motif, and Motif are trademarks of the Open Software Foundation, Inc
OSF MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THE OSF MATERIAL PROVIDED HEREIN, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
OSF shall not be liable for errors contained herein or for incidental consequential damages in connection with the furnishing, performance, or
use of this material
© 1990, 1991, 1992, 1993 Open Software Foundation, Inc. This documentation and the software to which it relates are derived in part from
materials supplied by the following:
© 1987, 1988, 1989 Carnegie-Mellon University. © 1989, 1990, 1991 Digital Equipment Corporation. © 1985, 1988, 1989, 1990 Encore Computer
Corporation. © 1988 Free Software Foundation, Inc. © 1987, 1988, 1989, 1990, 1991 Hewlett-Packard Company. © 1985, 1987, 1988, 1989,
1990, 1991,
1992 International Business Machines Corporation. © 1988, 1989 Massachusetts Institute of Technology. © 1988, 1989, 1990 Mentat Inc. ©
1988 Microsoft Corporation. © 1987, 1988, 1989, 1990, 1991, 1992 SecureWare, Inc. © 1990, 1991 Siemens Nixdorf Informationssysteme AG.
© 1986, 1989, 1996, 1997 Sun Microsystems, Inc. © 1989, 1990, 1991 Transarc Corporation.
This software and documentation are based in part on the Fourth Berkeley Software Distribution under license from The Regents of the University
of California. OSF acknowledges the following individuals and institutions for their role in its development: Kenneth C.R.C. Arnold, Gregory S.
Couch, Conrad C. Huang, Ed James, Symmetric Computer Systems, Robert Elz. © 1980, 1981, 1982, 1983, 1985, 1986, 1987, 1988, 1989
Regents of the University of California. Printed in the US.

Contents
What’s New in This Manual....................................................................................9
Manual Information...............................................................................................................................9
New and Changed Information.............................................................................................................9
Changes to the 520369-009R Version of the Manual.....................................................................9
Changes to the 520369-009 Version of the Manual........................................................................9
Changes to the 520369-007 Version of the Manual......................................................................10
Changes to the 520369-006 Version of the Manual......................................................................10
Changes to the 520369-005 Version of the Manual......................................................................10
Changes to the 520369-004 Version of the Manual......................................................................11
Changes to the 520369-003 Version of the Manual......................................................................11
Changes to the G06.18 Manual....................................................................................................11

About This Manual................................................................................................13
Organization of This Manual...............................................................................................................13
Related Manuals.................................................................................................................................13
Notation Conventions.........................................................................................................................13
General Syntax Notation...............................................................................................................13
Notation for Messages...................................................................................................................15
Notation for Management Programming Interfaces......................................................................16
Change Bar Notation.....................................................................................................................16

1 Introducing the Enscribe Record Manager........................................................18
Overview and Features.......................................................................................................................18
Terminology........................................................................................................................................19
Disk File Organization.........................................................................................................................20
Unstructured Files.........................................................................................................................20
Structured Files.............................................................................................................................20
Partitioned (Multiple-Volume) Files.....................................................................................................21
File Identifiers................................................................................................................................21
Few Differences Among Partitions................................................................................................21
File Directory.......................................................................................................................................22
Audited Files.......................................................................................................................................22
Access Coordination...........................................................................................................................22
Waited and Nowait I/O........................................................................................................................22
Operations on Files.............................................................................................................................23
Creating Files................................................................................................................................23
Loading Files.................................................................................................................................23
Manipulating Records....................................................................................................................23
Comparison of Structured File Characteristics...................................................................................24

2 Positioning Within Structured Files....................................................................25
Structured File Records......................................................................................................................25
Access Paths......................................................................................................................................27
Current Key Specifier and Current Access Path...........................................................................27
Current Key Value and Current Position........................................................................................29
Positioning Mode and Comparison Length...................................................................................29
Approximate Positioning................................................................................................................30
Generic Positioning.......................................................................................................................30
Exact Positioning...........................................................................................................................31
Alternate Keys....................................................................................................................................31
Key Specifier.................................................................................................................................32
Key Offset......................................................................................................................................32
Automatic Maintenance of All Keys...............................................................................................33
Null Value.................................................................................................................................33
Contents

3

Unique Alternate Key...............................................................................................................33
No Automatic Update....................................................................................................................33
Alternate Keys in a Key-Sequenced File.......................................................................................33
Alternate Keys in an Entry-Sequenced File...................................................................................34
Alternate Keys in a Relative File....................................................................................................34
Alternate-Key Files........................................................................................................................34
Alternate Keys and Record Locking..............................................................................................35
Record Locking Requests and Alternate Key Files..................................................................35
Implementation of Updates to Alternate Key Records.............................................................35
Transaction Aborts, Alternate Keys, and Locks.......................................................................36
SETMODE 4 (Set Lock Mode) and Alternate Key Files...........................................................36
SETMODE 4,6 and SETMODE 4,7 (Read through Lock with Warning)..................................36
Relational Access..........................................................................................................................36

3 System Procedures...........................................................................................38
File-System Procedures.....................................................................................................................38
Procedure Call Completion............................................................................................................40
File Number Parameters...............................................................................................................41
Tag Parameters.............................................................................................................................41
Buffer Parameter...........................................................................................................................41
Transfer Count Parameter.............................................................................................................41
Condition Codes............................................................................................................................41
Error Numbers...............................................................................................................................42
File Access Permissions................................................................................................................42
External Declarations....................................................................................................................43
Sequential I/O (SIO) Procedures........................................................................................................43

4 General File Creation and Access Information..................................................45
File Creation.......................................................................................................................................45
File Codes.....................................................................................................................................45
Disk Extent Sizes...........................................................................................................................45
File Formats Supported: Format 1 and Format 2..........................................................................45
Partition and File Format Compatibility....................................................................................47
File Size Limits..............................................................................................................................47
Files Secured With Enhanced File Privileges..........................................................................47
Partition Limit............................................................................................................................47
Key-Sequenced and Queue Files............................................................................................47
Other File Types.......................................................................................................................48
Files in the Range of 2 GB to 4 GB..........................................................................................48
Audit-Checkpoint Compression.....................................................................................................48
Write Verification............................................................................................................................49
File Access.........................................................................................................................................50
Opening and Closing Files............................................................................................................50
Opening Partitioned Files..............................................................................................................50
Read Reverse With Structured Files.............................................................................................51
Read Reverse and Position-to-Last Feature............................................................................51
Read Reverse and SAVEPOSITION........................................................................................51
Read Reverse and the Record Pointers..................................................................................51
File Expiration Dates.....................................................................................................................52
File Creation and Last-Opened Timestamps.................................................................................52
Using CONTROL 27 to Detect Disk Writes...................................................................................52
Using Cache Buffering or Sequential Block Buffering...................................................................53
Cache Buffering........................................................................................................................53
Sequential Block Buffering............................................................................................................54
Specifying the Appropriate Disk File ACCESSTYPE Parameter..................................................56
Refreshing the End-of-File (EOF) Pointer.....................................................................................57
4

Contents

Purging Data..................................................................................................................................57
Programmatically Allocating File Extents......................................................................................58
Programmatically Deallocating File Extents..................................................................................58

5 Unstructured Files.............................................................................................59
Enscribe Unstructured Files................................................................................................................59
Applicable System Procedures...........................................................................................................59
Types_Access.....................................................................................................................................59
Creating Unstructured Files................................................................................................................60
Buffer Size.....................................................................................................................................60
Disk Extent Size............................................................................................................................60
Restrictions on Partitioned Unstructured files..........................................................................61
Example: Creating an Unstructured File.......................................................................................61
Accessing Unstructured Files.............................................................................................................62
File Pointers...................................................................................................................................62
Sequential Access.........................................................................................................................63
Encountering the EOF During Sequential Reading..................................................................64
Random Access............................................................................................................................65
Appending to the End of a File......................................................................................................65

6 Key-Sequenced Files........................................................................................67
Enscribe Key-Sequenced Files...........................................................................................................67
Applicable System Procedures...........................................................................................................67
Types of Access..................................................................................................................................68
Key-Sequenced Tree Structure..........................................................................................................68
Unique Features of EKS Files............................................................................................................69
Creating Key-Sequenced Files...........................................................................................................70
Comparing LKS Files, LKS2 Files, Standard Queue Files, EKS Files, and EKS Files with
Increased Limits............................................................................................................................70
Converting a Legacy Key-Sequenced File to an Enhanced Key-Sequenced File........................72
Logical Records.............................................................................................................................72
Key-Sequenced Format 1 Files................................................................................................72
Key-Sequenced Format 2 Files................................................................................................72
Blocks............................................................................................................................................73
Disk Extent Size............................................................................................................................73
Primary Keys.................................................................................................................................74
Key Compression..........................................................................................................................74
Index Compaction..........................................................................................................................75
File Creation Examples.................................................................................................................75
Accessing Key-Sequenced Files........................................................................................................85
End-of-File (EOF) Pointer..............................................................................................................85
Sequential Access.........................................................................................................................85
Random Access............................................................................................................................85
Inserting Records..........................................................................................................................86
Deleting Records...........................................................................................................................86
Current Primary-Key Value............................................................................................................86
Access Examples..........................................................................................................................86

7 Queue Files.....................................................................................................106
Enscribe Queue Files.......................................................................................................................106
Applicable System Procedures.........................................................................................................106
Types of Access................................................................................................................................107
Queue File Structure.........................................................................................................................107
Primary Keys...............................................................................................................................107
Creating Queue Files........................................................................................................................107
Queue File Examples..................................................................................................................108
Contents

5

Accessing Queue Files.....................................................................................................................109
Specifying Sync-Depth................................................................................................................110
Queuing a Record.......................................................................................................................110
Special “Dummy” Record.......................................................................................................110
Dequeuing a Record....................................................................................................................110
Examining a Record....................................................................................................................113
Dequeuing With Positioning........................................................................................................113
Using the Current Key.................................................................................................................116
Specifying Timeout Periods.........................................................................................................116
Locking a Record.........................................................................................................................116
Network Considerations..............................................................................................................116
Performance Considerations.......................................................................................................116
Access Examples........................................................................................................................117
Communication Path Errors..............................................................................................................120

8 Entry-Sequenced Files....................................................................................122
Enscribe Entry-Sequenced Files......................................................................................................122
Applicable System Procedures.........................................................................................................122
Types of Access................................................................................................................................122
Creating Entry-Sequenced Files.......................................................................................................123
Logical Records...........................................................................................................................123
Blocks..........................................................................................................................................123
Disk Extent Size..........................................................................................................................124
File Creation Examples...............................................................................................................124
Example 1: Creating an Entry-Sequenced File......................................................................124
Example 2: Creating an Entry-Sequenced File With Alternate Keys.....................................126
Example 3: Creating an Alternate-Key File Programmatically...............................................128
Example 4: Creating a Partitioned Entry-Sequenced File......................................................128
Accessing Entry-Sequenced Files....................................................................................................130
Sequential Access.......................................................................................................................130
Random Access..........................................................................................................................130
Access Examples........................................................................................................................130
Example 1. Writing to an Entry-Sequenced File....................................................................131
Example 2. Reading Sequentially by Primary Key.................................................................131
Example 3. Reading Sequentially by Alternate Key...............................................................131
Example 4. Reading Randomly by Unique Alternate Key......................................................132

9 Relative Files...................................................................................................133
Enscribe Relative Files.....................................................................................................................133
Applicable System Procedures.........................................................................................................134
Types of Access................................................................................................................................134
Creating Relative Files......................................................................................................................135
Logical Records...........................................................................................................................135
Format 1 Files........................................................................................................................136
Format 2 Files........................................................................................................................136
Blocks..........................................................................................................................................136
Disk Extent Size..........................................................................................................................136
File Creation Examples...............................................................................................................137
Example 1: Creating a Relative File.......................................................................................137
Example 2: Creating a Relative File With Alternate Keys......................................................138
Example 3: Creating an Alternate-Key File............................................................................140
Example 4: Creating a Partitioned Relative File.....................................................................141
Accessing Relative File.....................................................................................................................143
The File Pointers.........................................................................................................................143
Effects of File-System Procedures on Pointers...........................................................................143
Sequential Access.......................................................................................................................145
6

Contents

Random Access..........................................................................................................................145
Inserting Records........................................................................................................................146
Deleting Records.........................................................................................................................146
File Access Examples.................................................................................................................146
Reading Sequentially by Primary Key....................................................................................146
Reading Sequentially by Alternate Key..................................................................................147
Writing Sequentially by Primary Key......................................................................................147
Random Access by Primary Key............................................................................................148
Updating Records..................................................................................................................148

10 File and Record Locking................................................................................150
Enscribe File and Record Locks.......................................................................................................150
Locking Modes..................................................................................................................................150
File Locking.......................................................................................................................................151
Record Locking.................................................................................................................................151
Generic Locking................................................................................................................................152
Interaction Between File Locks and Record Locks...........................................................................154
Lock Limits........................................................................................................................................154
Deadlock...........................................................................................................................................155
File Locking and Record Locking With Unstructured Files...............................................................155
TMF Locking Considerations............................................................................................................155
Errors in Opening Audited Files..................................................................................................158
Reading Deleted Records...........................................................................................................158
Batch Updates.............................................................................................................................159

11 Errors and Error Recovery.............................................................................160
Error Message Categories................................................................................................................160
Communication Path Errors..............................................................................................................160
Data Errors.......................................................................................................................................160
Device Operation Error.....................................................................................................................160
Extent-Allocation Errors....................................................................................................................160
Errors and Partitioned Files..............................................................................................................161
Failure of the Primary Application Process.......................................................................................161

12 File Loading...................................................................................................162
File Utility Program (FUP) Commands.............................................................................................162
Loading a Key-Sequenced File.........................................................................................................162
Defining a New Alternate Key...........................................................................................................162
Creating an Alternate-Key File..........................................................................................................163
Reloading a Key-Sequenced File Partition.......................................................................................163
Creating a Partitioned Alternate-Key File.........................................................................................163
Loading a Partitioned, Alternate-Key File.........................................................................................164

13 Support and other resources.........................................................................166
Accessing Hewlett Packard Enterprise Support...............................................................................166
Accessing updates............................................................................................................................166
Websites...........................................................................................................................................167
Customer self repair.........................................................................................................................167
Remote support................................................................................................................................167
Documentation feedback..................................................................................................................167

A ASCII Character Set........................................................................................168
B Block Formats of Structured Files...................................................................172
C Action of Current Key, Key Specifier, and Key Length....................................183
Variable Definitions...........................................................................................................................183
Function Definitions..........................................................................................................................183
Pseudocode Descriptions.................................................................................................................184
Contents

7

OPEN (FILE_OPEN_).................................................................................................................184
FILE_SETKEY_, KEYPOSITION:...............................................................................................184
FILE_SETPOSITION_, POSITION:.............................................................................................184
READ:..........................................................................................................................................184
READUPDATE:...........................................................................................................................185
WRITEUPDATE:..........................................................................................................................185
WRITE:........................................................................................................................................185

Index...................................................................................................................186

8

Contents

What’s New in This Manual
Manual Information
Abstract
This manual describes how to create, access, and load the five types of disk files supported by
the Enscribe software.
Product Version
Enscribe 1.0
Supported Release Version Updates (RVUs)
This publication supports J06.03 and all subsequent J-series RVUs, H06.03 and all subsequent
H-series RVUs, and G06.27 and all subsequent G-series RVUs until otherwise indicated by its
replacement publications. To use increased Enscribe limits, the minimum RVUs are H06.28 and
J06.17 with specific SPRs. For a list of the required SPRs, see SPR Requirements for Increased
Enscribe Limits for the H06.28/J06.17 Release (page 18).
Document History
Part Number

Product Version

Published

520369–009R

Enscribe 1.0

November 2015

520369–009

Enscribe 1.0

June 2014

520369-007

Enscribe G09

July 2012

520369-006

Enscribe G09

February 2012

520369-005

Enscribe G09

February 2011

520369-004

Enscribe G09

February 2011

520369-003

Enscribe G09

February 2006

520369-002

Enscribe G09

December 2002

New and Changed Information
Changes to the 520369-009R Version of the Manual
•

Updated Hewlett Packard Enterprise references.

Changes to the 520369-009 Version of the Manual
•

Throughout document, change “classic key-sequenced” to “legacy key-sequenced (LKS)”.

•

Throughout document, update increased partition size, block size, record length, key length,
and file size for format 2 legacy key-sequenced files (LKS2), format 2 enhanced
key-sequenced files (EKS), and standard format 2 Queue files.

•

Update definition of primary and secondary extent sizes for EKS files in Unique Features of
EKS Files (page 69) and in the table in Comparing LKS Files, LKS2 Files, Standard Queue
Files, EKS Files, and EKS Files with Increased Limits (page 70).

•

Add note about support for increased limits in Overview and Features (page 18) and Enscribe
Key-Sequenced Files (page 67).

•

Add paragraph about increased file size limits in Key-Sequenced and Queue Files (page 47).

•

Add table of SPRs required to achieve increased limits with H06.28 and J06.17 in SPR
Requirements for Increased Enscribe Limits for the H06.28/J06.17 Release (page 18).

Changes to the 520369-007 Version of the Manual
•

Added a note about the Restrictions on Partitioned Unstructured files (page 61).

Changes to the 520369-006 Version of the Manual
•

Added new procedures for 64-bit to File-System Procedures (page 38).

•

The following chapters have been updated to include the new procedures for 64- bit:

◦

Introducing the Enscribe Record Manager (page 18)

◦

Positioning Within Structured Files (page 25)

◦

System Procedures (page 38)

◦

General File Creation and Access Information (page 45)

◦

Unstructured Files (page 59)

◦

Key-Sequenced Files (page 67)

◦

Queue Files (page 106)

◦

Entry-Sequenced Files (page 122)

◦

Relative Files (page 133)

◦

File and Record Locking (page 150)

Changes to the 520369-005 Version of the Manual
Added a note to File Locking on page 10-3 about avoiding the frequent use of LOCKFILE and
UNLOCKFILE requests on partitioned files due to the significant overhead of these requests and
using record level locking instead.

Changes to the 520369-004 Version of the Manual
•

These topics have been updated to support Enscribe 64 partitions which is introduced as
of H06.22 and J06.11 and later RVUs.

◦

Overview and Features (page 18)

◦

Partitioned (Multiple-Volume) Files (page 21)

◦

File Formats Supported: Format 1 and Format 2 (page 45)

◦

Files Secured With Enhanced File Privileges (page 47)

◦

Key-Sequenced and Queue Files (page 47)

◦

Enscribe Key-Sequenced Files (page 67)

◦

Creating Key-Sequenced Files (page 70)

◦

Comparing LKS Files, LKS2 Files, Standard Queue Files, EKS Files, and EKS Files
with Increased Limits (page 70)

◦

Converting a Legacy Key-Sequenced File to an Enhanced Key-Sequenced File (page 72)

◦

Key-Sequenced Format 2 Files (page 72)
–

•

These topics have been updated in response to Genesis cases:

◦

•

Alternate Keys and Record Locking on page 2-17 and associated topics:

Alternate Keys and Record Locking (page 35) and associated topics:
–

Record Locking Requests and Alternate Key Files (page 35)

–

Implementation of Updates to Alternate Key Records (page 35)

–

Transaction Aborts, Alternate Keys, and Locks (page 36)

–

SETMODE 4 (Set Lock Mode) and Alternate Key Files (page 36)

–

SETMODE 4,6 and SETMODE 4,7 (Read through Lock with Warning) (page 36)

◦

Dequeuing a Record (page 110)

◦

Dequeuing From Audited Files (page 111)

◦

Approximate Positioning (page 30)

◦

Generic Positioning (page 30)

◦

Corrected FILE_SETKEY to FILE_SETKEY_ in several sections of the manual.

◦

Corrected minor grammatical and typographical errors reported via Genesis.

Added hyperlinked topics to the beginning of every chapter to make it easier to locate
information within a chapter.

Changes to the 520369-003 Version of the Manual
•

Clarified the behavior described under Reading Deleted Records (page 158), for the alternate
and primary key access.

•

Added a note on End-of-File values in Table 6 and added footnote.

•

Rebranded the manual with the latest terminology.

Changes to the G06.18 Manual
•

Added a caution note in Section 7 (Queue Files) to advise the user that the use of queue
files with multiple sub-queues can cause high utilization of CPU resources by the disk process
and affect performance.

•

Added a Performance Considerations section to discuss the practical limits on how many
processes should be used when multiple servers (dequeuing processes) are used on a
Queue File.

•

Changed a table entry to read “4 GB – 4 KB”. Also, changed the table entry for maximum
unpartitioned file size to “2 GB – 1 MB”.

About This Manual
This manual documents the Enscribe database record manager. It is written for programmers,
database designers, and analysts whose job is to design, develop, and maintain database
applications to be executed on HPE NonStop systems.

Organization of This Manual
Section

Description

Chapter 1: Introducing the Enscribe Record Manager

Provides an overview of Enscribe features

Chapter 2: Positioning Within Structured Files

Describes how to use primary and alternate keys for
positioning within structured files

Chapter 3: System Procedures

Summarizes the use of various system procedures that
allow you to create and manipulate Enscribe files.

Chapter 4: General File Creation and Access Information Presents file creation and file access information that allow
you to create and manipulate Enscribe files.
Chapter 5: Unstructured Files

Describes how to create and access unstructured files.

Chapter 6: Key-Sequenced Files

Describes how to create and access key-sequenced files.

Chapter 7: Queue Files

Describes how to create and access queue files.

Chapter 8: Entry-Sequenced Files

Describes how to create and access entry-sequenced
files.

Chapter 9: Relative Files

Describes how to create and access relative files.

Chapter 10: File and Record Locking

Describes the various file-locking and record-locking
capabilities.

Chapter 11: Errors and Error Recovery

Describes the various types of errors that can occur in the
Enscribe environment.

Chapter 12: File Loading

Provides a set of examples illustrating how to load data
into various types of Enscribe files.

Appendix A: ASCII Character Set

Shows the ASCII character set.

Appendix B: Block Formats of Structured Files

Describes the block format for Enscribe structured format
1 and 2 files (key-sequenced, queue, entry-sequenced,
and relative).

Appendix C: Action of Current Key, Key Specifier, and Key Shows how file-system operations affect file currency
Length
information.

Related Manuals
These NonStop manuals provide additional information that you might want to have available
for reference:
•

Guardian Procedure Calls Reference Manual

•

Guardian Programmer’s Guide

•

Guardian Disk and Tape Utilities Reference Manual

Notation Conventions
Hypertext Links
Blue underline is used to indicate a hypertext link within text. By clicking a passage of text with
a blue underline, you are taken to the location described.

General Syntax Notation
This list summarizes the notation conventions for syntax presentation in this manual.

UPPERCASE LETTERS. Uppercase letters indicate keywords and reserved words; enter these
items exactly as shown. Items not enclosed in brackets are required. For example:
MAXATTACH

lowercase italic letters. Lowercase italic letters indicate variable items that you supply. Items
not enclosed in brackets are required. For example:
file-name

computer type. Computer type letters within text indicate C and Open System Services (OSS)
keywords and reserved words. Type these items exactly as shown. Items not enclosed in brackets
are required. For example:
myfile.c

italic computer type.
Italic computer type

letters within text indicate C and Open System Services (OSS) variable items that you supply.
Items not enclosed in brackets are required. For example:
pathname

[ ] Brackets. Brackets enclose optional syntax items. For example
TERM [\system-name.]$terminal-name
INT[ERRUPTS]

A group of items enclosed in brackets is a list from which you can choose one item or none. The
items in the list may be arranged either vertically, with aligned brackets on each side of the list,
or horizontally, enclosed in a pair of brackets and separated by vertical lines. For example:
LIGHTS [ ON ]
[ OFF ]
[ SMOOTH [ num ] ]
K [ X | D ] address-1

{ } Braces. A group of items enclosed in braces is a list from which you are required to choose
one item. The items in the list may be arranged either vertically, with aligned braces on each
side of the list, or horizontally, enclosed in a pair of braces and separated by vertical lines. For
example:
LISTOPENS PROCESS { $appl-mgr-name }
{ $process-name }
ALLOWSU { ON | OFF }

| Vertical Line. A vertical line separates alternatives in a horizontal list that is enclosed in brackets
or braces. For example:
INSPECT { OFF | ON | SAVEABEND }

… Ellipsis. An ellipsis immediately following a pair of brackets or braces indicates that you can
repeat the enclosed sequence of syntax items any number of times. For example:
M address-1 [ , new-value ]...
[ - ] {0|1|2|3|4|5|6|7|8|9}...

An ellipsis immediately following a single syntax item indicates that you can repeat that syntax
item any number of times. For example
"s-char..."

Punctuation. Parentheses, commas, semicolons, and other symbols not previously described
must be entered as shown. For example:
error := NEXTFILENAME ( file-name ) ;
LISTOPENS SU $process-name.#su-name

Quotation marks around a symbol such as a bracket or brace indicate that the symbol is a required
character that you must enter as shown. For example:
"[" repetition-constant-list "]"

Item Spacing. Spaces shown between items are required unless one of the items is a punctuation
symbol such as a parenthesis or a comma. For example:
CALL STEPMOM ( process-id );

If there is no space between two items, spaces are not permitted. In the following example, there
are no spaces permitted between the period and any other items:
$process-name.#su-name

Line Spacing. If the syntax of a command is too long to fit on a single line, each continuation
line is indented three spaces and is separated from the preceding line by a blank line. This
spacing distinguishes items in a continuation line from items in a vertical list of selections. For
example:
ALTER [ / OUT file-spec / ] CONTROLLER
[ , attribute-spec ]...

!i and !o. In procedure calls, the !i notation follows an input parameter (one that passes data to
the called procedure); the !o notation follows an output parameter (one that returns data to the
calling program). For example:
CALL CHECKRESIZESEGMENT ( segment-id
, error

!I
!o

) ;

!i,o. In procedure calls, the !i,o notation follows an input/output parameter (one that both passes
data to the called procedure and returns data to the calling program). For example:
error := COMPRESSEDIT ( filenum ) ;

!i,o

!i:i. In procedure calls, the !i:i notation follows an input string parameter that has a corresponding
parameter specifying the length of the string in bytes. For example:
error := FILENAME_COMPARE_ ( filename1:length
, filename2:length ) ;

!i:i
!i:i

!o:i. In procedure calls, the !o:i notation follows an output buffer parameter that has a
corresponding input parameter specifying the maximum length of the output buffer in bytes. For
example:
error := FILE_GETINFO_ ( filenum
, [ filename:maxlen ] ) ;

!i
!o:i

Notation for Messages
The following list summarizes the notation conventions for the presentation of displayed messages
in this manual
Bold Text. Bold text in an example indicates user input typed at the terminal. For example:
ENTER RUN CODE
?123
CODE RECEIVED:

123.00

The user must press the Return key after typing the input.
Nonitalic text. Nonitalic letters, numbers, and punctuation indicate text that is displayed or
returned exactly as shown. For example:
Backup Up.

lowercase italic letters. Lowercase italic letters indicate variable items whose values are
displayed or returned. For example:
p-register
process-name

[ ] Brackets. Brackets enclose items that are sometimes, but not always, displayed. For example:
Event number = number [ Subject = first-subject-value

]
A group of items enclosed in brackets is a list of all possible items that can be displayed, of which
one or none might actually be displayed. The items in the list might be arranged either vertically,

with aligned brackets on each side of the list, or horizontally, enclosed in a pair of brackets and
separated by vertical lines. For example:
LDEV ldev [ CU %ccu | CU %... ] UP [ (cpu,chan,%ctlr,%unit) ]

{ } Braces. A group of items enclosed in braces is a list of all possible items that can be displayed,
of which one is actually displayed. The items in the list might be arranged either vertically, with
aligned braces on each side of the list, or horizontally, enclosed in a pair of braces and separated
by vertical lines. For example:
obj-type obj-name state changed to state, caused by
{ Object | Operator | Service }
process-name State changed from old-objstate to objstate
{ Operator Request. }
{ Unknown. }

| Vertical Line. A vertical line separates alternatives in a horizontal list that is enclosed in brackets
or braces. For example:
Transfer status: { OK | Failed }

% Percent Sign. A percent sign precedes a number that is not in decimal notation. The %þnotation
precedes an octal number. The %Bþnotation precedes a binary number. The %Hþnotation
precedes a hexadecimal number. For example:
%005400
%B101111
%H2F
P=%p-register E=%e-register

Notation for Management Programming Interfaces
The following list summarizes the notation conventions used in the boxed descriptions of error
lists in this manual
UPPERCASE LETTERS. Uppercase letters indicate names from definition files; enter these
names exactly as shown. For example:
ZCOM-TKN-SUBJ-SERV

lowercase letters. Words in lowercase letters are words that are part of the notation, including
Data Definition Language (DDL) keywords. For example:
token-type

!r.. The !r notation following a token or field name indicates that the token or field is required. For
example:
ZCOM-TKN-OBJNAME

token-type ZSPI-TYP-STRING.

!r

!o. The !o notation following a token or field name indicates that the token or field is optional. For
example:
ZSPI-TKN-MANAGER

token-type ZSPI-TYP-FNAME32.

!o

Change Bar Notation
Change bars are used to indicate substantive differences between this edition of the manual and
the preceding edition. Change bars are vertical rules placed in the right margin of changed
portions of text, s, tables, examples, and so on. Change bars highlight new or revised information.
For example:
The message types specified in the REPORT clause are different in the COBOL85 environment
and the Common Run-Time Environment (CRE).

The CRE has many new message types and some new message type codes for old message
types. In the CRE, the message type SYSTEM includes all messages except LOGICAL-CLOSE
and LOGICAL-OPEN.

1 Introducing the Enscribe Record Manager
Overview and Features
SPR Requirements for Increased Enscribe Limits for the H06.28/J06.17 Release
As of the H06.28 and J06.17 RVUs, format 2 legacy key-sequenced 2 (LKS2) files with increased
limits, format 2 standard queue files with increased limits, and enhanced key-sequenced (EKS)
files with increased limits are introduced. EKS files with increased limits support 17 to 128 partitions
along with larger record, block, and key sizes. LKS2 files with increased limits and format 2
standard queue files with increased limits support larger record, block, and key sizes. When a
distinction is not required between these file types, key-sequenced files with increased limits is
used as a collective term. To use increased Enscribe limits, the minimum RVUs are H06.28 and
J06.17 with the following specific SPRs. (These SPR requirements could change or be eliminated
with subsequent RVUs.)
Table 1 SPR Requirements for Increased Enscribe Limits for the H06.28/J06.17 Release
Products

J-Series SPR

H-Series SPR

Backup/Restore NSK

T9074H01^AGJ

T9074H01^AGJ

DP2

T9053J02^AZZ

T9053H02^AZN

File System

T9055J05^AJQ

T9055H14^AJP

FUP

T6553H02^ADH

T6553H02^ADH

NS TM/MP TMF DR

T8695J01^ALP

T8695H01^ALO

SMF

T8472H01^ADO

T8472H01^ADO

T8471H01^ADO

T8471H01^ADO

T8470H01^ADO

T8470H01^ADO

T8469H01^ADO

T8469H01^ADO

T8466H01^ADO

T8466H01^ADO

T8465H01^ADO

T8465H01^ADO

T8468H01^ABY

T8468H01^ABY

T9191J01^ACY

T9191H01^ACX

T9195J01^AES

T9195H01^AER

T9197J01^AEA

T9197H01^ADZ

TCP/IP FTP

T9552H02^AET

T9552H02^AET

TNS/E COBOL Runtime Library

T0357H01^AAO

T0357H01^AAO

SQL/MP

NOTE: As of the H06.22 and J06.11 RVUs, a new Enscribe file type: enhanced key-sequenced
(EKS) file is introduced and extends the Enscribe partition maximum to 64. An EKS file supports
17 to 64 partitions. The previous Enscribe key-sequenced file type supports 1 to 16 partitions
and is referred to as a legacy key-sequenced (LKS) file in this manual. When a distinction is not
required between these file types, key-sequenced file is used as a collective term.
The Enscribe record manager, supported by the Guardian file system, provides high-level access
to records in a database. Distributed across two or more processors, the software helps ensure
data integrity if a processor module, I/O channel, or disk drive fails.

18

Introducing the Enscribe Record Manager

This manual describes the use of the software with the DP2 disk process. Some of the most
notable Enscribe features are:
•

Five disk file structure types:

◦

unstructured

◦

key-sequenced:
–

legacy key-sequenced (1 to 16 partitions, file format 1 and 2)

–

legacy key-sequenced with increased limits (1 to 16 partitions, larger record size,
larger block size, larger key size, file format 2 only)

–

enhanced key-sequenced (17 to 64 partitions, file format 2 only)

–

enhanced key-sequenced with increased limits (17 to 128 partitions, larger record
size, larger block size, larger key size, file format 2 only)

◦

queue

◦

entry-sequenced

◦

relative

•

File Formats: format 1 and format 2

•

Partitioned (multiple-volume) files

•

Multiple-key access to records

•

Relational access among files (where a field value from one file is used as a key to access
a data record in another file)

•

Optional automatic maintenance of all keys and optional key compression in key-sequenced
data or index blocks

•

Support of transaction auditing through the NonStop Transaction Management Facility (TMF).

•

Optional compression of audit-checkpoint records

•

Record locking and file locking

•

Cache buffering

•

Optional sequential block buffering

Terminology
To create and use Enscribe files, you should be familiar with these terminologies:
•

File: a collection of related records, physically organized as a number of extents on disk,
that is referenced by a Guardian file name. Structured files (entry-sequenced, key-sequenced,
queue, and relative files) are further subdivided into blocks of records.

•

Format 1 and 2: Format is a static attribute of a file and is established when the files is
created. Format 2 files, introduced with the D46 release, differ from format 1 files in these
ways: larger partitions than the current 2 GB minus 1 MB format 1 file partition and larger
primary keys and alternate-key records for relative and entry-sequenced files.

•

Logical record: the unit of information transfer between your application program and the
file system; unless you are using sequential block buffering, the logical record is also the
unit of information transfer between the file system and the disk process. The maximum
logical record size is specified as a number of bytes.

•

Sector: the smallest unit of disk I/O or physical addressing (512 bytes in length for all currently
supported disk drives).
Terminology

19

•

Extents: a unit of storage allocation for a file to be allocated as contiguous space on disk.
Each extent consists of some specified number of 2048-byte pages.

•

Block: the unit of physical I/O. A block consists of one or more logical records plus some
control information for structured files. When you are using sequential block buffering, a
block is the unit of transfer between the file system and the disk process. The block size is
specified as a number of bytes. The block sizes currently supported are 512 bytes, 1 KB, 2
KB, and 4 KB. 32 KB block size is only supported for key-sequenced files with increased
limits.

•

Key: a value associated with a record (a record number, for example) or contained within a
record (as a field) that can be used to locate one record or a subset of records in a file.

Disk File Organization
A disk file must be created before it can be accessed. You can create a file either by calling the
FILE_CREATE_ procedure or by using the File Utility Program (FUP) CREATE command, then
designate the file as either permanent or temporary. A permanent file remains in the system after
access is terminated; a temporary file is deleted when all its openers have closed it. You also
specify the file's type when you create it. Taken as a group, key-sequenced, queue,
entry-sequenced, and relative files are known as structured files. The facilities available with
structured files differ significantly from those available with unstructured files.
The disk process allocates physical storage to files in the form of extents, each consisting of
some number of contiguous 2048-byte pages on the disk.
A partitioned file (one having extents on more than one disk volume) other than a key-sequenced
file is limited to 16 extents per partition. The maximum number of extents in a non partitioned file
or a partitioned file is restricted by the maximum label size up to a limit of 978 extents per file (or
per partition for partitioned key-sequenced files). The maximum label size is further constrained
by the number of alternate keys and partitions defined for this file, by the file format, and by
whether the file is an SMF file. Within this limit, you can use the MAXEXTENTS attribute to set
an arbitrary limit for any nonpartitioned file (or for any partition of a key-sequenced file).
NOTE: For all Enscribe file types, the disk process constrains the use of MAXEXTENTS such
that any partition is always smaller than two gigabytes if the file is format 1.
In any case, the first extent is designated the primary extent and can differ in size from the
remaining secondary extents. This allows a file to be created with a large primary extent, to
contain all the data to be initially placed in the file, and smaller secondary extents to use minimal
increments of disk space as the file grows.
An application process can allocate one or more extents in an open file by way of a CONTROL
21 procedure call. The CONTROL procedure can also deallocate unused extents.

Unstructured Files
An unstructured disk file is essentially a large byte array. Most often it is used as a code file or
an edit file, not as a data file. The organization of an unstructured disk file (the lengths and
locations of records within the file) is entirely the responsibility of the application process.
Data stored in an unstructured file is addressed in terms of a relative byte address (RBA). A
relative byte address is an offset, in bytes, from the first byte in the file; the first byte is at RBA
zero.

Structured Files
The Enscribe product provides four types of structured files: key-sequenced, queue,
entry-sequenced, and relative. Data transfers between an application process and a structured
disk file are done in terms of logical records and record keys.

20

Introducing the Enscribe Record Manager

For key-sequenced files, the primary key is a particular data field, designated by the user, within
each data record. For queue files, the primary key resides within the data record and consists
of an 8-byte timestamp plus an optional user key. For entry-sequenced files, the primary key is
a block number and record number, external to the data record, specifying the record's storage
location within the file. For relative files, the primary key is an ordinal number, again external to
the data record, denoting the record's position within the file.
In addition to access by primary key, you can specify alternate keys for key-sequenced,
entry-sequenced, and relative files. Queue files cannot have alternate keys.
Several NonStop software products, such as Enform and Enable, are available to help you define
and access Enscribe structured files.

Partitioned (Multiple-Volume) Files
When you create a file, you can designate it to reside entirely on a single volume or you can
have it partitioned over several volumes. Moreover, the separate volumes need not reside on
the same system; you can partition a file across network nodes.
Enhanced key-sequenced files can have 17 to 64 parts. For enhanced key-sequenced files with
increased limits, 17 to 128 partitions are permitted. Up to 16 partitions are permitted for all other
Enscribe file types. Queue files cannot be partitioned. The primary partition of an enhanced
key-sequenced file cannot contain user data and is instead used to store a portion of the file’s
label.
After a partitioned file is created, the fact that it resides on more than one volume and perhaps
on more than one node is transparent to the application program. The entire file is opened for
access by supplying the name of the primary partition to the FILE_OPEN_ procedure. Unless
you specify unstructured access, the file system rejects any attempt to open a secondary partition
of a file.
Partitioned files can be valuable for a number of reasons. The most obvious one is that a file can
be created whose size is not limited by the capacity of a physical disk drive. In addition, by
spreading a file across more than one volume, you can increase the concurrency of access to
records in separate partitions of the file.
If the file is located on multiple volumes on the same controller, the operating system takes
advantage of the controller's overlapped seek capability; that is, many drives can be seeking
while one is transferring. If the file spans volumes connected to different controllers on the same
processor, overlapping transfers will occur up to the limit of the I/O channel's bandwidth. If the
file resides on volumes connected to controllers on different processors, the system performs
overlapped processing of requests and overlapped transfers not limited by the bandwidth of a
single I/O channel.
Partitioned files can also accommodate more locks, because the locking limit applies to each
partition rather than the whole file.
Partitioned file records can also reside in multiple caches, which can result in fewer disk accesses.

File Identifiers
Each partition has a directory entry on the volume on which it resides. The file names for all
partitions are identical except for the different volume names.

Few Differences Among Partitions
All the partitions of a file must be either audited by TMF or not audited; they cannot be mixed.
Primary and secondary extent sizes can differ from one partition to another within the same
partitioned file. In addition, the MAXEXTENTS value can differ from one partition to another within
a key-sequenced file. These and the volume names are the only file attributes on which partitions
can differ.

Partitioned (Multiple-Volume) Files

21

File Directory
A disk volume's file directory holds information about all the files on that volume. You govern the
size of this directory, either during system generation or when using the Subsystem Control
Facility (SCF) to label the disk, by estimating how many files you want each directory extent to
hold. The system translates this to an approximate extent size when it creates the actual directory
file. The actual number of files that fit in a directory extent varies according to the types of files
involved, because some file types need larger file labels than other types. Therefore, the actual
capacity might not always be precisely what you specified.
The disk process can potentially create as many as 987 directory extents, so the creation of too
many files to fit in the currently allocated directory extent space merely causes the disk process
to allocate another directory extent.
CAUTION: Never write to a file directory. Any attempt by an application process to alter the
content of a file directory can cause directory corruption and/or a DP2 halt.

Audited Files
In a system with TMF, any database file can be designated as an audited file. To help maintain
database consistency, TMF audits all transactions involving files designated as audited files.
That is, TMF maintains images (in an audit trail) of the database changes made by those
transactions. If necessary, TMF can use the audit trail later to back out failed transactions or to
restore audited files that some system failure has rendered inconsistent.
TMF also uses a record-locking mechanism to perform concurrency control for audited files. This
feature ensures that none of a given transaction's changes are visible to other, concurrent
transactions until all the given transaction's changes are either committed or aborted and backed
out.

Access Coordination
Several different processes can have access to one file at the same time. For coordination of
simultaneous access, each process must indicate, when opening a file, how it intends to use that
file. Each process must specify both an access mode and an exclusion mode.
The access mode specifies which operations are to be performed. The access mode can specify
read/write (the default access mode), read-only, or write-only access.
The exclusion mode specifies how much access is granted to other processes. The exclusion
mode can specify shared, exclusive, or protected access.
The access and exclusion modes operate on a file from the time it is opened until the time it is
closed. To prevent concurrent access to a disk file for short periods of time, two locking
mechanisms are provided: file locking and record locking. TMF enforces a special set of locking
rules for audited files.

Waited and Nowait I/O
The software allows an application process to execute concurrently with its file operations by
means of nowait I/O.
The default is waited I/O; when designated file operations are performed, the application process
is suspended until the operation completes.
Nowait I/O means that when designated file operations are performed, the application process
is not suspended. The application process executes concurrently with the file operation. The
application process waits for an I/O completion in a separate file system procedure call.
Waited and nowait I/O are described in the Guardian Programmer's Guide. For more information,
also see the descriptions of the FILE_OPEN_, READ, FILE_READ64_, AWAITIO and
FILE_AWAITIO64_ procedures in the Guardian Procedure Calls Reference Manual.
22

Introducing the Enscribe Record Manager

Operations on Files
Common file operations include creating files, describing record formats, loading files, and
manipulating records.Table 2 (page 23) summarizes the record management functions that are
most commonly used with Enscribe files.

Creating Files
You create disk files either by calling the FILE_CREATE_ system procedure or by issuing FUP
commands:
•

Programmatic creation of disk files is accomplished by supplying the appropriate parameters
to the FILE_CREATE_ or FILE_CREATELIST_ procedure.

•

The FUP commands SET, RESET, and SHOW let you specify, display, and modify creation
parameters (such as file type, record length, key description, and so forth) before actually
creating a file. If you like, you can set the creation parameters to be like those of an existing
file. The FUP CREATE command then creates a file with the currently set parameters. The
ALTER command lets you change some of those parameters after the file is created. FUP
accepts commands from an online terminal or from a command (OBEY) or IN file.

Loading Files
You can use FUP to load data into existing Enscribe files. You specify the set of records to be
loaded and the file's data block and index block loading factor. The loading factor determines
how much free space to leave within a block. FUP attempts to optimize access to a file by placing
the lowest level index blocks on the same physical cylinder as their associated data blocks, thus
reducing the amount of head repositioning.

Manipulating Records
You can manipulate records in an Enscribe file by calling file-system procedures. Record
management functions and the associated system procedures are summarized in Table 2
(page 23)
Table 2 Record Management Functions Summary
Function

Description

Procedures

Delete

Deletes the record in a key-sequenced, queue, or relative FILE_WRITEUPDATE64_,
file as indicated by a primary-key value.
WRITEUPDATE

Find

Sets the current position, access path, and positioning
FILE_SETPOSITION_,
mode for a file. This can indicate the start of a subset of
FILE_SETKEY_, KEYPOSITION,
records in anticipation of reading the set sequentially, or it POSITION
can specify a record for subsequent updating.

Insert

Inserts a new record into a file according to its primary-key FILE_WRITE64_, WRITE
value.

Lock

Locks the whole file, just the current record, or a set of
records containing the same generic key.

FILE_LOCKFILE64_,
FILE_LOCKREC64_,
FILE_READLOCK64_,
FILE_READUPDATELOCK64_,
LOCKREC, LOCKFILE,
READLOCK,
READUPDATELOCK

Read

Reads a subset of records sequentially.

FILE_READ64_, READ

Unlock

Unlocks the whole file, the current record in a file, or all the FILE_UNLOCKFILE64_,
records in a file.
FILE_UNLOCKREC64_,
FILE_WRITEUPDATEUNLOCK64_,

Operations on Files

23

Table 2 Record Management Functions Summary (continued)
Function

Description

Procedures
UNLOCKREC, UNLOCKFILE,
WRITEUPDATEUNLOCK

Update

Updates a record in a random position in a file.

FILE_READUPDATE64_,
FILE_WRITEUPDATE64_,
READUPDATE, WRITEUPDATE

Comparison of Structured File Characteristics
The Enscribe product provides four types of structured files: key-sequenced files, queue files,
entry-sequenced files, and relative files. Table 3 (page 24) compares the characteristics of the
four types of structured files.
Table 3 Comparison of Structured Files
Key-Sequenced

Queue

Entry-Sequenced

Relative

Records are ordered by
value in primary-key field

Records are ordered first by Records are in the order in Records are ordered by
user key (if present) and
which they are entered
relative record number
then by timestamp

Access is by primary or
alternate key

Access is by primary key
Access is by record address Access is by record number
(consisting of an optional
or alternate key
or alternate key
user key and a timestamp).

Length of primary key
varies. Key is actually part
of record.

Length of primary key varies Record address is primary
but must be at least 8 bytes key. Length: 8 bytes.
to hold a timestamp.

Record number is primary
key. Length: 8 bytes.

The software uses index
blocks to locate primary key,
which is stored in the
record.

The software uses index
The software uses record
blocks to locate primary key, address to find physical
which is stored in the
location of record in file.
record.

The software uses record
number to calculate the
physical location of record
in file.

Space occupied by a record Space occupied by a record Space occupied by a record Space allowed per record is
depends on length specified depends on length specified depends on length specified specified when the file is
when written.
when written.
when written.
created.
Free space in block or at
Free space in block or at
Space at end of file is used Empty positions in file are
end of file is used for adding end of file is used for adding for adding records.
used for adding records.
records.
records.
Records can be deleted,
shortened, or lengthened
(within the maximum size
specified).

Records can only be
deleted.

Space freed by deleting or Space freed by deleting a
shortening a record can be record can be reused.
reused.

24

Introducing the Enscribe Record Manager

Records cannot be deleted, Records can be deleted,
shortened, or lengthened. shortened, or lengthened
(within the maximum size
specified).
deleted, but its space can
be used for another record
of the same size.

Space freed by deleting a
record can be reused.

2 Positioning Within Structured Files
Structured File Records
A record in an Enscribe structured file consists of one or more data fields, as illustrated in Figure 1
(page 25)
Figure 1 A Record With Three Fields in a Structured File
CUSTOMER Record
Name

Address

Region

Fields

Each record in a structured file is uniquely identified among other records in that file by the value
of its primary key. Figure 2 (page 26) illustrates the primary keys for the four different types of
structured files:
•

The primary key for key-sequenced files is a particular data field within each record.

•

The primary key for a queue file consists of a user key and a timestamp within each record.

•

The primary key for entry-sequenced files is a record address maintained by the software.

•

The primary key for relative files is a record number maintained by the software.

The records within structured files are stored in ascending order by primary-key value.

Structured File Records

25

Figure 2 Primary Keys in Structured Files
Key-Sequenced Files:
Name

Address

Region

Primary Key
Queue Files:
Mfg. Site

Timestamp

Description

Part Number

Primary Key

Entry-Sequenced Files:


Name

Account Number

Primary Key

Relative Files:


Item

Description

Primary Key

Except for queue files, structured files can also include up to 255 alternate-key fields. As illustrated
in Figure 3 (page 26), an alternate key is a designated data field within the record whose values
can be used at execution time to logically subdivide the overall file into meaningful subsets of
records. In an employee data file, for example, one data field in the record format might be the
employee's region code; if you define that field as an alternate key, you can access only those
data records that pertain to the employees who all reside in a particular geographic region.
As illustrated in Figure 4 (page 27), primary-key values are always unique, but alternate-key
values can be the same from one record to another.
Figure 3 An Alternate-Key Field

Name

Address

Region

Alternate-Key Field

The software lets you use the primary-key value to locate one unique record among other records
in the same file. For example, in Figure 4 (page 27), the name field is the primary key and the
primary-key value JONES, J.A. locates the only record having that name.

26

Positioning Within Structured Files

By using alternate-key values, you can process a subset of records that all contain the same
value in a particular data field. For example, using Figure 4 (page 27) again, the REGION field
is defined as an alternate key and the value CENTRAL provides you with access to two records.
Figure 4 Using Key Values to Locate Records
In a key-sequenced file, only one record can
have the primary-key value JONES, J.A.
JONES, J.A.

DAYTON, OHIO

CENTRAL

MOORE, Q.A.

LOS ANGELES, CALIFORNIA

WESTERN

SMITH, S.A.

CHICAGO, ILLINOIS

CENTRAL

Two or more records, however, can have the value
CENTRAL in their region alternate-key fields

Access Paths
Each key in a structured file provides a separate access path through the records in that file.
Records in any given path are accessed by ascending key values. In the case of duplicate
alternate-key values, the records containing the same key value are accessed within that path
in the order in which they appear in the alternate-key file.
Normally, duplicate alternate-key records are stored in the alternate-key file in ascending order
by their associated primary-key values. When you create an alternate-key file, however, you can
specify (by way of the alternate-key-params array) that duplicate alternate-key records be stored
in the order in which they are added to the file.
Note that all alternate-key files for any given primary database file must use the same ordering
convention for records with duplicate keys. That is, if one alternate-key file for a particular primary
file contains insertion-ordered duplicate key records, then all the alternate-key files for that primary
file must do so.
When you perform a read or write operation that uses or creates an insertion-ordered duplicate
alternate-key record, the file system returns an advisory error code (CCL with a code of 551)
upon completion of the particular system procedure call.

Current Key Specifier and Current Access Path
A 2-byte key specifier uniquely identifies each key field as an access path for positioning. The
key specifier for primary keys is defined as binary zero (ASCII nullnull). Key specifiers for
alternate-key fields are defined by the application and are assigned when the file is created.
Figure 6 (page 29) shows a typical record structure with a primary key and three alternate keys.
The current key specifier defines the current access path, which affects the order of the records
of the file (see Figure 5 (page 28)). The current access path is implicitly set to the file's primary
key when a file is opened; for entry-sequenced and relative files, the current access path is also
set to the primary key of the file when a call is made to the POSITION procedure. The access
path is set explicitly by calling the KEYPOSITION procedure.

Access Paths

27

Figure 5 Access Paths
Employee
Number

Records in Order by
EMPLOYEE NUMBER
Access Path

RYAN
KING

C
A

005
008
010
011

FISH
ADAMS
BROWN
STEVENS

D
B
A
C

012
013

OBRIEN
MASTERS

D
C

016

WATSON

B

ADAMS

B
A

005
002
013

BROWN
FISH
KING
MASTERS

D
A
C
D
C

011

OBRIEN
RYAN
STEVENS

016

WATSON

B

002

Access
Path
KING

A

010
008
016

BROWN
ADAMS
WATSON

A
B
B

001
011

RYAN
STEVENS

C
C

013
005

MASTERS
FISH

C
D

012

OBRIEN

D

012
001

Records in Order by
DEPT Access Path

Dept

001
002

Access
Path
008
010
Records in Order by
NAME Access Path

Name

Address
(Not an
Access Path)

C

Access Path

28

Positioning Within Structured Files

Figure 6 Key Fields and Key Specifiers
Primary-Key
Field

PART NO.

Alternate-Key Fields

DESCRIPTION

ON-HAND

0
System-Defined
Key Specifier

PRICE

LOCATION

OH

LO

VENDOR
VN

Application-Defined Key Specifiers

Current Key Value and Current Position
The current key value defines a file's current position. You can set the current key value explicitly
by calling the FILE_SETKEY_, FILE_SETPOSITION_,POSITION or KEYPOSITION procedure.
FILE_SETKEY_ and KEYPOSITION set a position by primary key for key-sequenced and queue
files and by alternate key for key-sequenced, entry-sequenced, and relative files.
FILE_SETPOSITION_ and POSITION set a position by primary key for entry-sequenced and
relative files. After a call to FILE_READ64_/READ, the current key value is implicitly set to the
key value of the current access path in the record just read. Figure 7 (page 29) demonstrates
the use of KEYPOSITION in a key-sequenced file.
The current position determines the record to be locked (by a call to
FILE_LOCKREC64_/LOCKREC) or accessed (by a call to FILE_READ[LOCK]64_, READ[LOCK],
FILE_READUPDATE[LOCK]64_, READUPDATE[LOCK], FILE_WRITEUPDATE[UNLOCK]64_,
or WRITEUPDATE[UNLOCK]). A record need not exist at the current position. When a file is
opened, the current position is that of the first record in the file as defined by the file's primary
key.
Figure 7 Current Position
Record
Primary Key
ADAMS
key : = "FISH" ;

BROWN

CALL KEYPOSITION (fnum, key) ;

COLLINS

#1 CALL READ (fnum, ... ) ;

FISH

#2 CALL READ (fnum, ... ) ;

JACKSON

#3 CALL READ (fnum, ... ) ;

KING
MASTERS
OBRIEN

Current Position after
KEYPOSITION and
READ #1
Current Position after
READ #2
Current Position after
READ #3

RYAN

Positioning Mode and Comparison Length
A subset of records in a designated access path can be described by a positioning mode and a
key value. The positioning modes are approximate, generic, and exact. Approximate mode selects
all records whose access path key values are equal to or greater than the supplied key value.
Access Paths

29

Generic mode selects all records whose access path key value matches a supplied partial value.
Exact mode selects only those records whose access path key value matches the supplied key
value exactly. Figure 8 (page 30) shows examples of subsets returned by each positioning mode.
The positioning mode, comparison length, and current key value supplied in a KEYPOSITION
procedure call together specify a subset of records and the first record in that subset to be
accessed. The subset of records in the current access path can consist of all, part, or none of
the records in a file.
Figure 8 Approximate, Generic, and Exact Subsets
Approximate

Generic

Exact

Find "JONES"

Find "JONES"

Find "JONES, K.A."

HUNT, H.L.

HUNT, H.L.

HUNT, H.L.

IRWIN, F.J.

IRWIN, F.J.

IRWIN, F.J.
Start

Last
Record
in File

Start

JONES, A.B.

JONES, A.B.

JONES, A.B.
Start

JONES, K.A.

JONES, K.A.

JONES, K.A.

JONES, M.P.

JONES, M.P.

JONES, M.P.

JONES, Z.Z.

JONES, Z.Z.

JONES, Z.Z.

JORDAN, W.R.

JORDAN, W.R.

KANE, C.T.

KANE, C.T.

KING, M.L.
LACEY, G.T.

Approximate
Subset

LANG, M.N.

Generic
Subset

JORDAN, W.R.

Exact
Subset

KANE, C.T.

KING, M.L.

KING, M.L.

LACEY, G.T.

LACEY, G.T.

LANG, M.N.

LANG, M.N.

MEYER, D.J.

MEYER, D.J.

MEYER, D.J.

Reading the file
sequentially
returns 10 records,
then an EOF.

Reading the file
sequentially
returns 4
records,
then an EOF.

Reading the file
sequentially
returns 1
record,
then an EOF.

The positioning mode and comparison length (as well as the current key specifier and current
key value) are set explicitly by the FILE_SETKEY_ and KEYPOSITION procedures and implicitly
by the FILE_OPEN_, FILE_SETPOSITION_ and POSITION procedures. The software supports
three positioning modes:
•

approximate

•

generic

•

exact

Approximate Positioning
Approximate positioning means the first record accessed is the one whose key field, as indicated
by the current key specifier, contains a value equal to or greater than the current key value for
the number of bytes specified by the comparison length. After approximate positioning, sequential
FILE_READ64_/READ operations to the file return ascending records in the current access path
until the last record in the file is read; an EOF indication is then returned. When a file is opened,
the positioning mode is set to approximate and the comparison length is set to 0.

Generic Positioning
Generic positioning means the first record accessed is the one whose key field, as designated
by the current key specifier, contains a value equal to the current key value for the number of
bytes specified by the comparison length. After generic positioning, sequential
FILE_READ64_/READ operations to the file return ascending records whose key matches the

30

Positioning Within Structured Files

current key value (for the comparison length). When the current key no longer matches, an EOF
indication is returned.
NOTE: For entry-sequenced and relative files, generic positioning by the primary key is the
equivalent of exact positioning.

Exact Positioning
Exact positioning means the only records accessed are those whose key field, as designated by
the current key specifier, contains a value that is both:
•

exactly as long as the specified comparison length

•

equal to the current key value.

When the current key no longer matches, an EOF indication is returned. Exact positioning
accesses no more than one record.

Alternate Keys
For each file having one or more alternate keys, at least one alternate-key file exists. Each record
in an alternate-key file consists of:
•

Two bytes for the key-specifier

•

The alternate-key value

•

The primary-key value of the associated record in the primary file

Thus, the length of an alternate-key record in bytes, is:
2 + alternate-key field length + primary-key length
Figure 9 (page 32) shows how alternate keys are implemented.

Alternate Keys

31

Figure 9 Alternate-Key Implementation
Primary Data file Record Format:
Alternate-Key

Primary-Key

PART NO.

DESCRIPTION

0
Key Specifier

ON-HAND

PRICE

OH

LOCATION
LO

VENDOR
VN

Alternate-Key File Record Format (Access Path OH):
OH

ON-HAND

PART NO.

Key
Specifier

Field Value

PrimaryKey Value

Sample Data in Primary Data File:
0115

TOASTER

20

12.50

C

TWR

0201

T.V. SET

5

200.00

A

ACME

0205

PHONOGRAPH

52

55.00

B

ACR

0206

RADIO

97

9.95

A

BROWN

0310

FRY PAN

19

37.50

D

SMITH

0322

MIXER

12

69.95

D

ACME

Key Specifier
To identify a particular data field as an alternate-key access path, you must differentiate it from
other fields by assigning it a 2-byte key specifier (such as OH for the on-hand field). You supply
the 2-byte key specifier when you create the primary file.

Key Offset
For each alternate key you must specify its offset from the start of the record (where the
alternate-key field begins) when creating or altering characteristics of the primary file.
Consider these when choosing the offset of an alternate-key field:

32

•

An alternate-key field can begin at any offset in the record.

•

Alternate-key fields can overlap.

•

Alternate-key fields are fixed-length but need not contain a data value (that is, they can
contain a null value) when inserting or updating a record.

•

If any part of a given alternate-key field is present when inserting or updating a record, the
entire field must be present.

•

If the key field is to be treated as a data type other than STRING, the specified offset must
be such that the field begins on a word boundary.

Positioning Within Structured Files

Automatic Maintenance of All Keys
When a new record is added to a file or a value in an alternate-key field is changed, the software
automatically updates the indexes to the record (the value of a record's primary key cannot be
changed). This operation is entirely transparent to the application program.
If more key fields are later added to a file, but existing fields in that file are not relocated, existing
programs that access the file need not be rewritten or recompiled.

Null Value
You can assign a null value to any alternate key. You can choose any character as the null value;
the most commonly used are ASCII blank (%40) and binary zero.
If a record is inserted and one of its alternate-key fields contains only bytes of the null value, an
alternate-key reference is not added to the alternate-key file. If a record is updated and one of
its alternate-key fields is changed to contain only bytes of the null value, the associated
alternate-key reference is deleted from the alternate-key file.
If a structured file is read sequentially by alternate key, any records containing the null value in
that field are skipped. Instead, the next record returned (if any) is the next one not having the
null value in that alternate-key field. A null value is a byte value that, when encountered in all
positions of the indicated key field during a record insertion, causes the alternate-key file entry
for the field to be omitted.

Unique Alternate Key
An alternate-key field can be specified to require a unique value in each record. If you try to insert
a record that duplicates an existing record's value in a unique key field, the insertion is rejected
with an error 10 (“record already exists”). When using nonunique alternate keys, such
an insertion would be permitted. If a file has one or more unique alternate keys, remember that:
•

For each alternate-key field having a unique key-length, you must create a separate
alternate-key file.

•

More than one unique alternate key of the same key-length can be referred to by the same
alternate-key file; this is illustrated by the sample alternate-key file following Figure 9 (page 32)

No Automatic Update
You can designate that the alternate-key file contents for an alternate key not be automatically
updated by the system when the value of an alternate-key field changes. Two reasons for doing
so are:
•

Certain fields might not be referred to until a later date. Therefore, they can be updated in
a batch (one-pass) mode more efficiently.

•

A field can have multiple null values. If that is the case, your application program must have
the alternate-key file open separately and must determine itself whether or not the field
contains a null value. If the field does not contain a null value, your program then inserts the
appropriate alternate-key reference into the alternate-key file.

Alternate Keys in a Key-Sequenced File
You might use alternate keys in a key-sequenced file whose records consist of the vendor name
and the part number. The primary key to this file would be the part number (it could not be the
vendor name, because that is not unique). To produce a report of all parts supplied by a given
vendor, generic positioning would be done via the desired vendor. Then the file would be read
sequentially until the vendor name field is not equal to the desired vendor (at which time the
system returns an end-of-file indication). The records associated with a given vendor would be
returned in ascending order of the part number.

Alternate Keys

33

Alternate Keys in an Entry-Sequenced File
You might use alternate keys in an entry-sequenced file within a transaction-logging file. The
primary key (a record address) would indicate the order in which transactions occurred. An
alternate-key field might identify the terminal that initiated a transaction. To list all transactions
for a given terminal in the order in which they occurred, generic positioning uses the field value
of the desired terminal, and the file is then read sequentially.

Alternate Keys in a Relative File
You might use alternate keys in a relative file of employee data. The primary key (a record
number) would be an employee number. One alternate-key field would be an employee name.

Alternate-Key Files
For each primary structured file having one or more alternate keys, you must create at least one
corresponding alternate-key file. An alternate-key file can be partitioned to span multiple volumes.
Each record in an alternate-key file refers to only one alternate key, but the file can contain
references to more than one alternate key. Thus, with five alternate keys, the alternate-key file
would have five records for each primary-file record (provided that none of the primary-file records
contains a null value in any of the alternate-key fields). The primary file can also have multiple
alternate-key files. For example, one might contain references to three of the alternate keys, with
a second alternate-key file containing references to the other two keys.
Here are some reasons you might want to have separate alternate-key files:
•

A unique alternate key cannot share a file with other keys of different lengths.

•

Each individual alternate-key file is smaller than a combined file with several alternate-key
references, so fewer index references are needed to locate a given alternate key.

•

Frequent updating of one alternate key fragments the file. With separate files, this
fragmentation would not affect references to the other keys.

Here are two reasons why you do not want to have separate alternate-key files:
•

System control-block space is allocated for each opening of an alternate-key file (that is,
each opening of the primary file).

•

A file control block (FCB) is allocated for the first opening of an alternate-key file.

Figure 10 (page 34) illustrates the record structure of an alternate-key file. The length of a record
in an alternate-key file is:
2 bytes for the key-specifier
+ the key-length of the longest alternate key included in
the record
+ the key-length of the associated primary key
The user defines the data file’s primary key length if the data file is key sequenced. If it is a relative
or entry sequenced data file, then its primary key length is 4 if it is format 1 or 8 if it is format 2.
Figure 10 Record Structure of an Alternate-Key File

Key Specifier
(two bytes)

34

Positioning Within Structured Files

Alternate
Key

Data File's
Primary Key

Note that if the primary-key file is audited, the alternate-key files also must be audited, unless
keys are not automatically being updated. The primary-key length of an alternate-key file, as
distinguished from the data file's primary key, depends on whether the file contains unique key
references. With nonunique key references, the file's primary key is the entire record, so its
primary-key length is the same as its record length.
If an alternate-key file contains a single, nonunique key, that key can be no longer than
2048 (maximum key-length of the alternate-key file for
key-sequenced files with increased limits)
- 2 for the key-specifier
- the key-length of the data file's primary key
Thus, if a data file's primary key is 33 bytes long, nonunique alternate keys within that file cannot
be more than 2048 - 2 - 33 = 2013 bytes long. If the alternate-key file contains unique key
references, its primary key is the key specifier and the unique key. Therefore, the primary-key
length is:
2 for the key-specifier
+ key-length of the unique alternate-key field
Thus, a unique alternate key can be as long as 2048 - 2 = 2046 bytes, regardless of the data
file's primary key.

Alternate Keys and Record Locking
There are important considerations for alternate key locking particularly when aborting transactions.
This section describes Enscribe’s handling of record locks for alternate key files and assumes a
typical scenario in which an application opens a primary file and Enscribe internally opens the
primary file’s alternate key files but does not make those internal opens available to the application.

Record Locking Requests and Alternate Key Files
An application request to lock a record requires a file number as input. The file number is
necessarily that of the primary file, since the application has no file number for any alternate key
file.
If the request is FILE_READ[UPDATE]LOCK64_, READ[UPDATE]LOCK, FILE_LOCKREC64_
or LOCKREC, Enscribe locks the referenced primary file record but does not lock any alternate
key records. There is no need to do so as long as the alternate key record is not being changed.
If the request is FILE_WRITEUPDATE[UNLOCK]64_/WRITEUPDATE[UNLOCK], Enscribe locks
any affected alternate key records. For audited files, the locks are held until the transaction
commits or aborts. For unaudited files, the locks are released when the application unlocks the
corresponding primary record.
If the request is FILE_WRITE64_/WRITE and the file is audited, Enscribe locks inserted alternate
key records and holds the locks until the transaction commits or aborts. If the request is
FILE_WRITE64_/WRITE and the file is unaudited, Enscribe does not lock inserted alternate key
records unless SETMODE 149,1 is in effect, in which case alternate key records are locked upon
insertion and unlocked when insertion of the primary record and all of its alternate key records
have completed.

Implementation of Updates to Alternate Key Records
Deletion/Insertion Sequence
If a null value is defined for an alternate key and an application updates that alternate key field
from a non-null value to the null value, Enscribe deletes the corresponding alternate key record.
Alternate Keys

35

If a null value is defined for an alternate key and an application updates that alternate key field
from the null value to a non-null value, Enscribe inserts a corresponding alternate key record.
If an application updates an alternate key field from one non-null value to another, Enscribe
deletes the corresponding old alternate key record and inserts a new one. The deletion/insertion
sequence is necessary because the alternate key value is part of the primary key of the alternate
key file, and primary keys cannot be updated.

Transaction Aborts, Alternate Keys, and Locks
Backout of an aborted transaction executes asynchronously with respect to running applications.
Because backout of alternate key insertions and deletions requires corresponding deletions and
insertions which the system must protect with internally generated locks, transaction aborts can
cause alternate key records to be locked and unlocked asynchronously with respect to an
application's locking and unlocking of records in the primary file. In particular, it is possible for
one process to have a primary record locked and for the system to lock a corresponding alternate
key record on behalf of an aborting transaction of another process.

SETMODE 4 (Set Lock Mode) and Alternate Key Files
The SETMODE procedure call requires a file number as input. The file number is necessarily
that of the primary file, since the application has no file number for any alternate key file.
Enscribe propagates SETMODE 4 to all alternate key files. The software also propagates
SETMODE 4 to all secondary partitions of the primary file and alternate key files if any are
partitioned.

SETMODE 4,6 and SETMODE 4,7 (Read through Lock with Warning)
Both SETMODE 4,6 and 4,7 allow FILE_READ64_, FILE_READUPDATE64_, READ and
READUPDATE to read locked records. Such reads complete with warning code 9. With SETMODE
4,6 in effect, FILE_LOCKFILE64_, FILE_LOCKREC64_, LOCKFILE, LOCKREC,
FILE_READ[UPDATE]LOCK64_, READ[UPDATE]LOCK, FILE_WRITE[UPDATE][UNLOCK]64_,
and WRITE[UPDATE][UNLOCK] requests wait for lock release if the record or file in question is
locked; with SETMODE 4,7, such requests are rejected with error 73.
SETMODE 4,6 and 4,7 can help applications to handle the asynchronous locking of alternate
key records caused by transaction aborts. With SETMODE 4,6, a process whose write to a
primary file collides with another process's system-generated lock of an aborting transaction will
wait until the system-generated lock is released. This approach makes the lock contention invisible
to the application in exchange for the possibility of an occasional lock wait. With SETMODE 4,7
in the same situation, a process can receive error 73 when writing to a primary record for which
it holds a lock (because of a conflicting system-generated lock on an alternate key record). This
approach avoids lock waits in exchange for the need to design the process to handle error 73
on write as retryable.

Relational Access
Relational access among structured files in a database is accomplished by obtaining a value
from a field in a record in one file and using that value as a key to locate a record in another file.
Figure 11 (page 37) shows an example of relational access. All four of the files that are shown
are primary data files. The illustrates a query operation in which the user wants to obtain
information about all orders that were placed on 10-17-95.

36

Positioning Within Structured Files

In response to the user query command, the application program uses the date alternate-key
field to locate the order summary records in the Order Header File that were placed on 10-17-95.
For each applicable order summary record, the program:
•

Uses the Name field value from the order summary record as an exact primary key to obtain
the associated customer record from the customer file.

•

Uses the Order Number field value from the order summary record as a generic primary key
to obtain the associated line item records from the order detail file.

•

Uses the Part Number field value from the line item records as exact primary keys to obtain
the associated inventory record from the inventory file.

Figure 11 Relational Access Among Structured Files
Order No.

Name

Date

0021

JONES, J.A.

10-17-95

0022

ADAMS, A.B.

10-18-95

0023

WATSON, N.A. 10-20-95

0030

SMITH, C.J.

10-24-95

0032
0034

BROWN, E.G.
CARTER, J.M.

10-26-95
11-07-95

Total

Order
Header
File

Name

Customer
File

Address

Region

ADAMS, A.B.

LOS ANGELES, CA

5

BROWN, E.G.

PITTSBURGH, PA

2

CARTER, J.M.

PLAINS, GA

3

JONES, J.A.

LAS VEGAS, NEV

4

SMITH, C.J.

BOSTON, MASS

1

WATSON, N.A.

CUPERTINO, CA

5

Item
Order No. / Item No. Part No. Quantity Total
0021

0001

0201

0001

0021

0002

0310

0002

0022
0023

0001
0001

0115
0205

0006
0002

0023

0002

0206

0025

Part No.

Description

Order
Detail
File

On-Hand Price

0115

TOASTER

20

12.50

0201
0205

T.V. SET
PHONOGRAPH

5
52

200.00
55.00

0206
0310
0427

RADIO
FRY PAN
MIXER

210
19
97

9.95
37.50
69.95

Inventory
File

Alternate Keys

37

3 System Procedures
File-System Procedures
You can use file-system procedures or a separate set of sequential I/O (SIO) procedures to
create and access Enscribe files. The two sets of procedures are mutually exclusive; with regard
to any given file, use one set or the other.
Table 4 (page 38) summarizes the functions of the applicable file-system procedures.
Table 4 File-System Procedures

38

Procedure

Description

AWAITIO[X]

Waits for completion of an outstanding I/O operation pending on an open
file.

CANCELREQ

Cancels the oldest outstanding operation, optionally identified by a tag,
on an open file.

CONTROL_

Executes device-dependent operations on an open file.

DISK_REFRESH_

Writes information (such as the EOF pointer) in file control blocks (FCBs)
to the associated physical disk volume. Supersedes REFRESH.

FILE_ALTERLIST_

Changes certain attributes (such as file type and file code) of a disk file
that are normally set upon creation. Supersedes ALTER.

FILE_AWAITIO64_

Waits for completion of an outstanding I/O operation pending on an open
file.

FILE_CLOSE_

Terminates access to a file and purges a temporary disk file. Supersedes
CLOSE.

FILE_CONTROL64_

Executes device-dependent operations on an open file.

FILE_CREATE_

Creates a new structured or unstructured disk file. The file can be
permanent or temporary. Supersedes CREATE.

FILE_CREATELIST_

Creates a new structured or unstructured disk file and specifies
alternate-key information, partition information, or other attributes.
Supersedes CREATE.

FILE_GETINFO_

Provides limited information about a file identified by file number.
Supersedes FILEINFO, FILEINQUIRE, and FILERECINFO.

FILE_GETINFOBYNAME_

Provides limited information about a file. File is identified by name.
Supersedes FILEINFO, FILEINQUIRE, FILERECINFO, DEVICEINFO,
and DEVICEINFO2.

FILE_GETINFOLIST_

Provides detailed information about a file. File is identified by file number.
Supersedes FILEINFO, FILEINQUIRE, and FILERECINFO.

FILE_GETINFOLISTBYNAME_

Provides detailed information about a file identified by file name.
Supersedes FILEINFO, FILEINQUIRE, and FILERECINFO.

FILE_LOCKFILE64_

Locks an open disk file, making it inaccessible to other accessors.

FILE_LOCKREC64_

Locks a record (or a set of records if generic locking is enabled for a
key-sequenced file) in an open disk file so that other processes cannot
access it.

FILE_OPEN_

Establishes communication with a file and returns a file number.
Supersedes OPEN.

FILE_PURGE_

Deletes a disk file that is not open. Supersedes PURGE.

FILE_READ64_

Following positioning, returns the first record of a subset; otherwise, it
returns the next record in the current access path.

FILE_READLOCK64_

Is the same as FILE_READ64_, but it locks the record before reading it.

System Procedures

Table 4 File-System Procedures (continued)
Procedure

Description

FILE_READUPDATE64_

Returns the record indicated by the current key value;
FILE_READUPDATE64_ is used to randomly read an open file.

FILE_READUPDATELOCK64_

Is the same as FILE_READUPDATE64_, but it locks the record before
reading it.

FILE_RENAME_

Changes the name of an open file. If the file is temporary, causes the file
to be made permanent. Supersedes RENAME.

FILE_RESTORE_POSITION_
Sets position by primary or by alternate key within key-sequenced,
FILE_SAVEPOSITION_ FILE_SETKEY_ entry-sequenced, relative, and queue files; defines a subset of the file
for subsequent access by setting the current position, access path, and
positioning mode. This procedure expects the primary keys for relative
and entry-sequenced files to be 8 bytes long. Supersedes KEYPOSITION.
FILE_SETMODENOWAIT64_

Sets device-dependent functions for an open file.

FILE_SETPOSITION_

Sets position by primary key within an entry-sequenced or relative file;
defines a subset of the file for subsequent access by setting the current
position, access path, and positioning mode; also can specify new current
position within an unstructured file. Procedure accepts an 8-byte record
specifier so it can work with format 2 files. Supersedes POSITION.

FILE_UNLOCKFILE64_

Unlocks an open disk file currently locked by the caller; unlocks any
records in the file that are currently locked by the caller.

FILE_UNLOCKREC64_

Unlocks a record currently locked by the caller. If generic locking is
enabled, calls to FILE_UNLOCKREC64_ are ignored.

FILE_WRITE64_

Inserts (adds) a new record into an open disk file location positioned by
the last call to READ[X], FILE_READ64_, READUPDATE[X] or
FILE_READUPDATE64_.

FILE_WRITEUPDATE64_

Replaces (updates) or deletes data in the record indicated by the current
key value of an open file.

FILE_WRITEUPDATEUNLOC K64_

Is the same as FILE_WRITEUPDATE64_, but unlocks the record after
its contents are updated or deleted.

FILEERROR

Helps determine whether a failed call should be retried.

FILENAME_FINDNEXT_

Returns the next name in a set of named entities. The set is defined in
a call to FILENAME_FINDSTART_. Supersedes GETDEVNAME and
NEXTFILENAME.

FILENAME_FINDNEXT64_

Returns the next name in a set of named entities. The set is defined in
a call to FILENAME_FINDSTART_. Supersedes GETDEVNAME and
NEXTFILENAME.

FILENAME_FINDSTART_

Sets up a search of named entities.

FNAMECOLLAPSE

Collapses an internal file identifier to external form.

FNAMECOMPARE

Compares two internal file identifiers to determine whether they refer to
the same file or device.

FNAMEEXPAND

Expands an external file identifier to internal form.

KEYPOSITION

Sets position by primary key within a key-sequenced or queue file or by
alternate key within key-sequenced, entry-sequenced, and relative files;
defines a subset of the file for subsequent access by setting the current
position, access path, and positioning mode. This procedure expects the
primary keys for relative and entry sequenced files to be 4 bytes long.

LOCKFILE

Locks an open disk file, making it inaccessible to other accessors.

File-System Procedures

39

Table 4 File-System Procedures (continued)
Procedure

Description

LOCKREC

Locks a record (or a set of records if generic locking is enabled for a
key-sequenced file) in an open disk file so that other processes cannot
access it.

POSITION

Sets position by primary key within an entry-sequenced or relative file;
defines a subset of the file for subsequent access, by setting the current
position, access path, and positioning mode; also can specify new current
position within an unstructured file. Procedure accepts a 4-byte record
specifier; it cannot be used with files larger than 4 GB.

READ[X]

Following positioning, returns the first record of a subset; otherwise, it
returns the next record in the current access path.

READLOCK[X]

Is the same as READ[X], but locks the record before reading it.

READUPDATE[X]

Returns the record indicated by the current key value; READUPDATE[X]
is used to randomly read an open file.

READUPDATELOCK[X]

Is the same as READUPDATE[X] except that it locks the record before
reading it.

REPOSITION

Restores the disk file position information saved with a previous
SAVEPOSITION call.

SAVEPOSITION

Saves the current disk file position information; a later call to REPOSITION
restores the saved position.

SETMODE

Sets device-dependent functions in an open file.

SETMODENOWAIT

Sets device-dependent functions for an open file.

UNLOCKFILE

Unlocks an open disk file currently locked by the caller; unlocks any
records in the file that are currently locked by the caller.

UNLOCKREC

Unlocks a record currently locked by the caller. If generic locking is
enabled, calls to UNLOCKREC are ignored.

WRITE[X]

Inserts (adds) a new record into an open disk file location positioned by
the last call to READ[X] or READUPDATE[X].

WRITEUPDATE[X]

Replaces (updates) or deletes data in the record indicated by the current
key value of an open file.

WRITEUPDATEUNLOCK[X]

Is the same as WRITEUPDATE[X], but unlocks the record after its
contents are updated or deleted.

Procedure Call Completion
If a file is open with nowait I/O specified, calls to CONTROL, FILE_CONTROL64_,
FILE_LOCKFILE64_, FILE_LOCKREC64_, FILE_READ64_, FILE_READLOCK64_,
FILE_READUPDATE64_, FILE_READUPDATELOCK64_, FILE_UNLOCKFILE64_,
FILE_UNLOCKREC64_, FILE_WRITE64_, FILE_WRITEUPDATEUNLOCK64_,
FILE_SETMODENOWAIT64_, LOCKFILE, LOCKREC, READ[X], READLOCK[X],
READUPDATE[X], READUPDATELOCK[X], UNLOCKFILE, UNLOCKREC, WRITE[X],
WRITEUPDATEUNLOCK[X], or SETMODENOWAIT must be completed by a corresponding call
to AWAITIO[X]/FILE_AWAITIO64_.
If a file is open with nowait I/O specified, calls to FILE_RENAME_,
FILE_SETKEY_,FILE_SETPOSITION_,KEYPOSITION, POSITION, REPOSITION, SETMODE,
FILE_SETMODENOWAIT64_ or SETMODENOWAIT are rejected with file-system error 27 if
there are any outstanding operations pending. Regardless of whether the file was opened with
waited or nowait I/O specified, a return from a call to CANCELREQ, FILE_CLOSE_,
FILE_CREATE_, FILE_GETINFO_, FILE_GETINFOBYNAME_, FILE_GETINFOLIST_,
FILE_OPEN_ (unless options .<1> = 1), FILE_PURGE_, FILE_RENAME_,
40

System Procedures

FILENAME_FINDNEXT64_, FILENAME_FINDNEXT_, KEYPOSITION, POSITION, or SETMODE
indicates a completion.

File Number Parameters
All of the file-system procedures except DISK_REFRESH_, FILE_CREATE_,
FILE_GETINFOBYNAME_, FILE_OPEN_, FILE_PURGE_, FILENAME_FINDNEXT64_, and
FILENAME_FINDNEXT_, use the filenum parameter returned by the FILE_OPEN_ procedure
to identify which file the call refers to. The FILE_CREATE_, FILE_GETINFOBYNAME_,
FILE_OPEN_, and FILE_PURGE_ procedures refer to the file by filename; the LASTRECEIVE
and FILE_REPLY64_, REPLY procedures always refer to the $RECEIVE file. For every procedure
except FILE_OPEN_ and AWAITIO[X]/FILE_AWAITIO64_ that has afilenum parameter, the
file number is an INT:value parameter.

Tag Parameters
An application-specified double integer (INT(32)) tag can be passed as a calling parameter when
an I/O operation (read or write) is initiated with a nowait file. The tag is passed back to the
application process, through the AWAITIO[X]/FILE_AWAITIO64_ procedure, when the I/O
operation completes. The tag is useful for identifying individual file operations and can be used
in application-dependent error recovery routines.

Buffer Parameter
The buffer parameter in a file-system procedure call specifies where the data is to be read from
or written to.
For I/O operations such as FILE_READ64_, READ, FILE_WRITE64_ or WRITE, the designated
buffer must be of the type integer (INT) or double-integer (INT(32)) and it must reside in the user's
data area (P-relative read-only arrays are not permitted).
For extended I/O operations such as READX or WRITEX, the designated buffer must be of type
INT or INT(32) and it can reside in either the user's data area or an extended data segment
(P-relative read-only arrays are not permitted).

Transfer Count Parameter
The read-count or write-count parameter in a file-system procedure call specifies how many
bytes are to be read or written.
A SETMODE procedure call with a function code of 141 enables and disables bulk transfers of
data between an extended data segment (or the upper 32 K of the data stack) and a DP2 disk
file that has been opened for unstructured access. Note that the SETMODE 141 call requires
that the file be opened for unstructured access (bit 2 of open^flags = 1) and for exclusive access
(bits 10 and 11 of open^flags = 2).
With the bulk transfer feature disabled, you can transfer from 0 to 4096 bytes in a single operation.
With the bulk transfer feature enabled, you can transfer up to 30 K bytes in a single operation.
The amount of data transferred must be a multiple of 2 K bytes. Note that with the bulk transfer
feature enabled, the only data transfer I/O operations that are allowed are READX,
READUPDATEX, WRITEX, and WRITEUPDATEX.

Condition Codes
Some file-system procedures return a condition code indicating the outcome of the operation.
For these procedures, the condition code should always be checked after a call to a file-system
procedure and should be checked before an arithmetic operation is performed or a value is
assigned to a variable. Generally, the condition codes have these meanings:
< (CCL)
An error occurred (call the file system FILE_GETINFO_ procedure to determine the
error).
File-System Procedures

41

> (CCG)

A warning message was generated (typically EOF, but see the individual procedures
for the meaning of CCG or call FILE_GETINFO_ to get an error number).

= (CCE)

The operation was successful.

Error Numbers
An error number is associated with each call completion. As shown in Table 5, the error numbers
fall into three major categories. The setting of the condition code indicates the general category
of the error associated with a completed call.
Table 5 Error Number Categories
Error Number

Condition Code

Category

0

= (CCE)

No error. The operation executed successfully.

1-9

> (CCG)

Warning. The operation executed with the exception of the indicated
condition. For warning 6 (system message received), data is returned in
the application process buffer.

10-255, 512-32767

< (CCL)

Error. The operation encountered an error or a special condition (such
as a transaction abort for an audited file) that the application must
recognize. For data transfer operations, either none or part of the specified
data was transferred (except data communication error 165, which
indicates a normal completion with data returned in the application
process buffer).

300-511

< (CCL)

Application-defined error. These error numbers are reserved
for use by application processes.

You can obtain the error number associated with an operation on an open file using the
FILE_GETINFO_ system procedure and passing the file number of the file in error:
status := FILE_GETINFO_ ( filenum, lasterror ) ;
The function value returned tostatus indicates the success of the call to FILE_GETINFO_.
Usually this value is 0 unless a programming error is made, such as supplying an invalid file
number. The error associated with the preceding operation (such as FILE_READ64_, READ,
FILE_WRITE64_ or WRITE) is returned to the second parameter ( lasterror ).
You can obtain the error number of a preceding AWAITIO[X]/FILE_AWAITIO64_ on any file or
of a waited FILE_OPEN_ that failed, using FILE_GETINFO_ with file number -1:
status := FILE_GETINFO_ ( -1, lasterror ) ;
Note that if the FILE_OPEN_ procedure fails, it sets the filenum parameter to -1.
Similarly, you can get the error number of a preceding FILE_CREATE_ or FILE_PURGE_
operation that failed using FILE_GETINFO_ with filenum = -1.

File Access Permissions
The disk file must be open with read or read/write access for a FILE_READ64_,
FILE_READLOCK64_, FILE_READUPDATE64_, FILE_READUPDATELOCK64_, READ[X],
READLOCK[X], READUPDATE[X], or READUPDATELOCK[X] call to be successful; if not, the
call is rejected with an error 49 (access violation).
The disk file must be open with write or read/write access for CONTROL, FILE_CONTROL64_,
FILE_WRITE64_, FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITE[X],
WRITEUPDATE[X], or WRITEUPDATEUNLOCK[X] calls to be successful; if not, the call is
rejected with an error 49 (access violation).
The caller must have purge access to the disk file if FILE_PURGE_ or FILE_RENAME_ calls
are to be successful; otherwise the call is rejected with an error as 48 ( security violation).

42

System Procedures

External Declarations
Like all other procedures in an application program, the file-system procedures must be declared
before being called. These procedures, however, are declared externally to the application
program in a system file named $SYSTEM.SYSTEM.EXTDECS0. The compiler command
SOURCE, specifying this file, should be included in the source program after the global
declarations but before the first call to one of these procedures, as in this example:
global-declarations
?SOURCE $SYSTEM.SYSTEM.EXTDECS0 (external-procedure, ...)
procedure-declarations

Each external procedure used in the program should be specified in the SOURCE command.
For example,
?SOURCE $SYSTEM.SYSTEM.EXTDECS0 ( KEYPOSITION, WRITEUPDATE,
?
FILE_OPEN_, FILE_CLOSE, READ, WRITE, POSITION, )

compiles only the external declarations for the KEYPOSITION, WRITEUPDATE, FILE_OPEN_,
FILE_CLOSE_, READ, WRITE, and POSITION procedures.

Sequential I/O (SIO) Procedures
The sequential I/O (SIO) procedures summarized in Table 6 provides HPE Tandem Application
Language (TAL) programmers with a standardized set of procedures for performing common I/O
operations. These operations include reading and writing IN and OUT files, and BREAK from a
terminal. These procedures are primarily intended for system and user utility programs. The
primary benefit is that programs using these procedures can treat different file types in a consistent
and predictable manner.
The SIO procedures also contain a set of DEFINEs and LITERALs that allocate control-block
space, specify file-opening characteristics, and both set file and check file-transfer characteristics.
Table 6 SIO Procedures
Procedure

Function

CHECK^BREAK

checks whether the BREAK key was pressed

CHECK^FILE

retrieves file characteristics

CLOSE^FILE

closes a file

GIVE^BREAK

disables the BREAK key

OPEN^FILE

opens a file for access by the SIO procedures

READ^FILE

reads from a file

SET^FILE

sets or alters file characteristics

TAKE^BREAK

enables the BREAK key

WAIT^FILE

waits for the completion of an outstanding I/O operation

WRITE^FILE

writes to a file

SIO procedures have these characteristics:
•

All file types are accessed in a uniform manner. File access characteristics, such as access
mode, exclusion modes, and record size, are selected according to device type and the
intended access. Default characteristics are set to facilitate their most general use.

•

Error recovery is automatic. Each fatal error causes a comprehensive error message to be
displayed, all files to be closed, and the process to be aborted. Both the automatic error
handling and the display of error messages can be turned off so the program can do the
error handling.
Sequential I/O (SIO) Procedures

43

•

The OPEN^FILE procedure lets an application alter the characteristics of SIO operations
when a file is opened. Also, the SET^FILE procedure makes this possible before or after
the file is opened. Some optional characteristics are:

◦

Record blocking and deblocking

◦

Duplicative file capability, where data read from one file is automatically echoed to
another file

◦

An error-reporting file, where all error messages are directed. When a particular file is
not specified, the error-reporting file is the home terminal.

•

They can be used with the INITIALIZER procedure to make run-time changes. File transfer
characteristics, such as record length, can be changed using the operating system Command
Interpreter's ASSIGN command.

•

They retain information about the files in file control blocks (FCBs). There is one FCB for
each open file plus one common FCB that is linked to the other FCBs.

For a thorough discussion of the SIO procedures, refer to the Guardian Programmer's Guide.

44

System Procedures

4 General File Creation and Access Information
This chapter describes general file creation and access information for all Enscribe file types.

File Creation
This subsection discusses certain parameters that you can specify and capabilities that you can
enable when creating Enscribe files.

File Codes
When creating an Enscribe disk file, you can assign it an arbitrary numeric file code. This code
is typically used to categorize files according to the kind of information they contain.
File codes 100 through 999 are reserved; using them causes unpredictable results.
If you do not specify the file code, it defaults to 0.

Disk Extent Sizes
When you create an Enscribe file, you can specify the maximum amount of physical disk space
to be allocated for that file. Physical space is allocated in the form of extents. An extent is a
contiguous block of disk space that can range in size from a single page (2048 bytes) to 65,535
pages (134,215,680 bytes) for format 1 files or to 536,870,912 pages for format 2 files.
For EKS files with increased limits, the primary partition has a primary extent size greater than
or equal to 140 pages. Each secondary partition has its own primary and secondary extent size.
By default every Enscribe disk file and partition has 16 extents; you can specify that a particular
nonpartitioned file or the partitions of a key-sequenced file have more than that number.
The first extent is called the primary extent, and its size can differ from the secondary extents.
All of the secondary extents for a given file or partition are the same size as one another.
If you do not specify the primary and secondary extent sizes during file creation, they both default
to one page.
The extent size must be an integral multiple of either the buffer size (for unstructured files) or the
block size (for structured files); the buffer size or block size, in turn, must be 512 bytes, 1 KB, 2
KB, or 4 KB. 32 KB block size is only supported for key-sequenced files with increased limits.
The file system automatically rounds up the specified extent size, if necessary, to enforce this
requirement.
The file system also rounds up any extent size specified as an odd number of pages if the buffer
size or block size is 4096. Therefore, if you want to have a file with extent sizes consisting of an
odd number of pages, the buffer size or block size must be 2048 or less.
In addition, you can supply a value called MAXEXTENTS that specifies the maximum number
of extents (16 or greater) to be allocated for the file. If you do not specify the maximum number
of extents, it defaults to 16.
For partitioned files other than key-sequenced files, MAXEXTENTS is always 16 per partition.
For partitioned key-sequenced files, you can specify a MAXEXTENTS parameter greater than
16.
For non-partitioned files or partitioned key-sequenced files, you can also change the
MAXEXTENTS value dynamically during program execution by either issuing a CONTROL 92
procedure call or supplying a MAXEXTENTS parameter in a FUP ALTER command.

File Formats Supported: Format 1 and Format 2
The D46 release supports larger partitions then were previously supported. This change allows
files and file partitions to increase from the format 1 size of 2 gigabytes to the format 2 size of 1

File Creation

45

terabyte (although the upper limit of the actual file size depends upon the size of the largest
single disk).
Both file formats are supported. The user usually does not have to specify the format. If left
unspecified, the system chooses format 1.
File format 2 is required when:
•

An enhanced key-sequenced (EKS) file is used. EKS files are supported in J06.11 and
H06.22 and later RVUs.

•

A key-sequenced file with increased limits is used. To use increased Enscribe limits, the
minimum RVUs are H06.28 and J06.17 with specific SPRs. For a list of the required
H06.28/J06.17 SPRs, see SPR Requirements for Increased Enscribe Limits for the
H06.28/J06.17 Release (page 18).

•

An unpartitioned file (or a partition) has a maximum size that is over 2 GB – 1 MB.

•

A non-key-sequenced file has a maximum size that is 4 GB or more (counting all partitions).

•

An extent size is over 65535.

Users should take advantage of the properties of format 2 when appropriate.
Table 7 Comparison of Format 1 Versus Format 2 Files
File Attribute or Procedure Call

Format 1 Files

Format 2 Files

Block Size

512 bytes to 4 KB

512 bytes to 32 KB

Maximum Partitioned File Size
(non-key-sequenced)

4 GB - 4 KB

16 TB

Maximum Partitioned File Size
(key-sequenced)

4 GB - 4 KB

LKS2: 16 TB
EKS with increased limits: ~127 TB

Maximum Unpartitioned File Size (single 2 GB - 1 MB
partition)

~1 TB

Maximum Record Size:
Entry-Sequenced, Relative,
Key-Sequenced (LKS or EKS). Queue
files have the same record sizes as
Key-Sequenced files.

Entry-Sequenced block size - 24

Entry-Sequenced block size - 48

Relative block size - 24

Relative block size - 48

Key-Sequenced block size - 34

Key-Sequenced block size - 56
(except for 32 KB in which case it is
27648)

Extent Sizes (pages)

64 K - 1 pages (128 MB)

Using new 32-bit fields, extent sizes
can be larger than format 1 files.
(The limit is dictated by the largest
size of a single physical disk).

Maximum Number of Extents

Same (978 or less)

Usable value is smaller than format
1 limit (928 or less)

514 byte disks = 16 extents of
65504 pages = EOF of
2,146,435,072 bytes

May be larger than standard

1

End-of-File Values

512 byte disks = 16 extents of
65492 pages = EOF of
2,146,041,856 bytes
Number of Partitions

16 partitions

Non-Key-Sequenced: 16 partitions
LKS2: 16 partitions
EKS with increased limits: 128
partitions

46

General File Creation and Access Information

Table 7 Comparison of Format 1 Versus Format 2 Files (continued)
File Attribute or Procedure Call

Format 1 Files

Format 2 Files

File Types

All

All

Non-Key-Sequenced Primary Key Value 4-byte (32-bit) primary-key value
in Alternate Key Records
1

8-byte (64-bit) primary-key value

For unstructured format 1 files in 512 byte disks such as ESS/JBOD, the pri-extent-size and sec-extent-size must both
be divisible by 14. If the file is unpartitioned, DP2 automatically rounds up the size. The maximum page size that is
divisible by 14 is 65492, therefore the EOF (16 extents of 65492 pages) is 2,146,041,856 bytes.

Partition and File Format Compatibility
All partitions of a file are created with the same file format version (format 1 or 2).
For non-key-sequenced files, a partition that is created independently must have the same format
as all the other partitions of the file. If that partition does not have the same format, it cannot be
opened and a warning message of FEPARTFAIL is displayed.
Key-sequenced files with a mixture of partition formats, providing they meet all other compatibility
requirements, are accessible and can be opened. This should assist in the process of converting
large partitioned key-sequenced format 1 files to large partitioned key-sequenced format 2 files.
NOTE: Partition compatibility requires the same record and block sizes in all partitions. This
has consequences for some file types. In particular, for key-sequenced files with some record/block
size combinations, it may not be possible to have a mixture of formats among the partitions.

File Size Limits
Applications can encounter problems if the files it uses are too large. The following paragraphs
discuss limits and considerations for the different Enscribe file types.

Files Secured With Enhanced File Privileges
When format 1 Enscribe files are secured using the new OSS file privilege attributes, those files
are limited to approximately 953 secondary partitions (file label size of 3960 bytes). These new
file privilege attributes cannot be set on format 1 Enscribe files that have approximately 945
partitions (a file label size of 3926 bytes or greater).
These restrictions also apply to format 1 partitioned files. Format 2 Enscribe files are not affected.
Users with files affected by this limitation may reorganize the files to create larger primary and
secondary extents. Larger primary and secondary extents result in a lesser number of extents
for the same file. The following command lists the attributes of a file including the “File Label”
size:
fup info , detail
Use the following commands to create a new file with larger primary and secondary extent sizes:
fup dup , , ext (pri-ext-size), sec-ext-size)

Partition Limit
A single format 1 partition (or an unpartitioned format 1 file) is limited to a maximum of 2 GB
minus 1 MB. If you try to create a file or partition with extent sizes and maxextents that specify
a potential greater than this amount, then a format 2 file will be created (if the default system
format selection is in effect). If 2 GB minus 1 MB is exceeded when format 1 is explicitly specified,
or if the size exceeds 1 terabyte, then error 583 or 21 is returned.

Key-Sequenced and Queue Files
Legacy key-sequenced files can have up to 16 partitions and the maximum possible size is ~16
TB. EKS key-sequenced files without increased limits can have up to 64 partitions and the
File Creation

47

maximum possible size is ~63 TB. However, key-sequenced files greater than 2 GB may encounter
problems if programs use the 32-bit file-system attributes that describe them. In particular, the
End of File (EOF) and Maximum File Size attributes cannot describe files greater than
approximately 2 GB (as a signed integer) or 4 GB (unsigned) in the 32-bit form, so the 64-bit
forms should be used instead.
EKS key-sequenced files with increased limits can have up to 128 partitions and the maximum
possible size is ~127 TB.
Queue files cannot be partitioned.

Other File Types
Entry-sequenced and relative files can have up to 16 partitions. However, the system imposes
a limit of approximately 4 GB (4 GB minus 4 KB) on these types of files if they are format 1. The
system returns an error 21 if there is an attempt to exceed the limit.

Files in the Range of 2 GB to 4 GB
With files between 2 GB and 4 GB, applications might encounter problems with arithmetic
operations that involve signed 32-bit integers. The 32-bit values that are used by some file-system
attributes (such as EOF) must be interpreted as unsigned integers to prevent errors. Use of the
64-bit forms of these attributes instead is recommended.

Audit-Checkpoint Compression
When an Enscribe file is being audited by TMF or has been opened with a sync depth greater
than 0, updating a record in the particular file causes an audit-checkpoint (AC) record to be
created. The AC record, which describes changes incurred as a result of the update, is sent to
the backup disk process. If the file is being audited by TMF, then the AC record also is sent to
the audit trail's disk process and eventually written to the audit trail.
When a file is audited, the AC record is copied from place to place several times. The AC record
occupies permanent space in the audit-trail file and also occupies resident memory in the backup
disk process until the backup determines that the updated record has been written to disk. If the
file is not audited, the AC record is sent as a checkpoint message to the backup disk process,
where it occupies resident memory until it is no longer needed for takeover recovery.
An AC record includes:
•

a record header approximately 64 bytes long

•

a copy of the record before the update, or before-image

•

a copy of the record after the update, or after-image.

If a data record is 1000 bytes long, the AC record for its update would be 2064 bytes long.
AC compression shortens parts (2) and (3) of the AC record by omitting the unchanged fragments
of the data record. The AC record must include the record key (in a key-sequenced or queue
file), the relative byte address (in an unstructured or entry-sequenced file), or the record number
(in a relative file), but no other unchanged fields. For example, if only two 10-byte fields in a
1000-byte record were updated, the compressed AC record could be about 130 bytes long instead
of 2064 bytes. Although AC compression uses some extra CPU cycles, it has several advantages:

48

•

Processor and memory cycles are reduced during message transferal, although some extra
cycles are required to perform the compression.

•

Resident memory requirements in the backup CPU are reduced.

•

If the file is audited, audit-trail consumption is reduced and audit blocking is more efficient
because of the smaller AC records.

General File Creation and Access Information

Even when AC compression is enabled for a file, not every AC record is compressed. Also, some
limits are imposed to keep the space used for recording the compression from becoming greater
than the unchanged fragments that would be omitted.
•

If the record length is less than a certain limit, the disk process does not compress the record.
This limit is subject to change from release to release.

•

If an update changes the record length, the disk process does not compress the AC record.

•

If two changed fragments of a record are sufficiently close to each other, they and the bytes
between them are considered one changed fragment.

•

If more than a certain number of fragments are changed, the entire remainder of the record
is considered to be the last fragment.

•

After the changed fragments are identified, the total size of the prospective compressed AC
record is computed and compared to the size of a noncompressed AC record. If the savings
are insufficient, the noncompressed AC record is used.

Key-sequenced and queue records with large keys reduce the effectiveness of AC compression
because the key must be kept in the AC record.
When creating a file with the FILE_CREATE_ procedure, you enable or disable auditcheckpoint
compression by setting options bit 13 to 1 or 0, respectively.
When creating a file with FUP, you enable or disable audit-checkpoint compression by specifying
AUDITCOMPRESS or NO AUDITCOMPRESS, respectively, in the FUP CREATE command.
When you open a file, the audit-compression feature is enabled or disabled at that time depending
upon what was specified for the file when it was created. During program execution, you can
enable or disable this feature dynamically by:
•

Specifying AUDITCOMPRESS or NO AUDITCOMPRESS, respectively, in a FUP ALTER
command, or by

•

Specifying param1 = 1 or 0, respectively, in a SETMODE 94 procedure call.

When you do so, however, whatever you designate only applies until you reverse it with a
subsequent FUP ALTER command or SETMODE 94 call or until the file is closed.

Write Verification
When creating Enscribe disk files, you can enable the write verification feature. This feature
ensures the integrity of each subsequent write operation to that file. With write verification enabled,
the just-written data is read back from the disk and compared with the corresponding data in the
memory of the CPU. Note, however, that this requires an additional disk revolution.
When creating a file with the FILE_CREATELIST_ procedure, you enable or disable write
verification by setting item code 73 to 1 or 0, respectively.
When creating a file with FUP, you enable or disable write verification by specifying
VERIFIEDWRITES or NO VERIFIEDWRITES, respectively, in the FUP CREATE command.
When you open a file, the write verification feature is enabled or disabled at that time depending
upon what was specified for the file when it was created. During program execution, you can
enable or disable this feature dynamically by:
•

Specifying VERIFIEDWRITES or NO VERIFIEDWRITES, respectively, in a FUP ALTER
command, or by

•

Setting bit 15 of the param1 parameter to 1 or 0, respectively, in a SETMODE 3 procedure
call.

When you do so, however, whatever you designate only applies until you reverse it with a
subsequent FUP ALTER command or SETMODE 3 call or until the file is closed.

File Creation

49

File Access
The following paragraphs describe different ways to access Enscribe files.

Opening and Closing Files
You use the FILE_OPEN_ procedure to establish communication with a permanent disk file:
LITERAL name^length = 23,
syncdpth = 1;
LITERAL usebigkeys = 1D;
INT error;
INT filenum;
STRING .filename [0:22] := "$VOL1.MYSUBVOL.DATAFILE";
error := FILE_OPEN_(filename:name^length,
filenum,,,,syncdpth,
! read-write access,
,,,,usebigkeys);
! shared access,
! waited I/O,
! syncdepth = 1
! use 64-bit primary key

NOTE: With the release of D46, users may now use 64-bit primary keys instead of 32-bit values
for unstructured, relative or entry-sequenced disk files. If the default 32-bit keys are used, only
files up to 4 GB can be opened. If the 64-bit selection is used, access to any size file is allowed,
but 32-bit interfaces such as POSITION must be avoided.
Once the file is open, use the file number (FILENUM) returned by the FILE_OPEN_ procedure
to identify the file to other file-system procedures.
Use the FILE_CLOSE_ procedure to terminate access to a disk file:
error := FILE_CLOSE_(filenum);
If you do not explicitly close the file, the file remains open until the process stops, at which point
all files are automatically closed.
To establish communication with a temporary file, use the temporary file name returned by the
FILE_CREATE_ procedure:
LITERAL temp^name^len = 256;
INT namelen;
INT error;
INT temp^filenum;
STRING .temp^filename [0:temp^name^len-1];
temp^filename ':=' "$VOL";
namelen := 4;
error := FILE_CREATE_ (temp^filename:temp^name^len, namelen);
error := FILE_OPEN_ (temp^filename:namelen,
temp^filenum);

FILE_CREATE_ returns a file name that you can use when you call FILE_OPEN_.
Temporary files are purged when you close them. If you do not want a temporary file to be purged,
call FILE_RENAME_ using the file number returned from FILE_OPEN_ to make the file permanent.

Opening Partitioned Files
When you open the primary (first) partition of a partitioned file, all of the associated secondary
partitions are also opened automatically. If a secondary partition cannot be opened, access to
the file is still granted but the FILE_OPEN_ procedure returns a code 3 warning indication and
some operations might not work. You can call the FILE_GETINFOLIST_ procedure to identify
the highest numbered partition that did not open.
Individual partitions cannot be opened separately unless you specify unstructured access in the
FILE_OPEN_ call.
50

General File Creation and Access Information

Read Reverse With Structured Files
You can read Enscribe structured files (key-sequenced, queue, entry-sequenced, and relative)
sequentially in descending key or record number order. You enable this feature by setting a bit
in the options parameter of FILE_SETKEY_ or the positioningmode parameter of the
KEYPOSITION procedure call.

Read Reverse and Position-to-Last Feature
Normally the KEYPOSITION procedure resets the file pointers so that they point to the first record
that satisfies the positioning criteria specified by the key-value, key-len, compare-len, and
positioning-mode parameters. When reading a file in reverse order, however, you probably want
to point to the last record in the file that satisfies the positioning criteria. You enable the
position-to-last feature by setting a second bit in the positioning-mode parameter of the
KEYPOSITION procedure call.
For example, consider the record sequence:
Record Number

Key Value

0

AAA

1

ABA

2

ABB

3

ABC

Following an approximate KEYPOSITION to key-value AB with a specified key-length of 2 and
read-reverse enabled, a call to FILE_READ64_/READ would return record number 1 from the
set of records shown in the preceding example. The same call to KEYPOSITION, but with
position-to-last enabled by the positioning-mode parameter, would instead result in record number
3 being returned by the FILE_READ64_/READ call.
For the primary key of entry-sequenced and relative files, the key value parameter to
KEYPOSITION is a 4-byte string containing a doubleword record number value. When using
read reverse and approximate positioning in conjunction with those types of files, initial positioning
is performed to the first record whose record number is equal to or less than the record number
passed in key-value. Records are then returned in descending record number order by successive
calls to FILE_READ64_/READ. The position-to-last option is ignored for KEYPOSITION operations
to an exact record number in an entry-sequenced or relative file.
Positioning to the last record in a file with KEYPOSITION is accomplished by specifying a key
length of 0 and specifying approximate positioning, read-reverse, and position-to-last in the
positioning-mode parameter. Following such a KEYPOSITION operation, the subsequent call to
FILE_READ64_/READ will return the last record in the file.

Read Reverse and SAVEPOSITION
Because of the read reverse feature, the SAVEPOSITION system procedure requires a 7-word
positioning buffer to save the current position in an entry-sequenced or relative file that has no
alternate keys.
Only four words of the positioning buffer are used when read forward positioning is in effect.
Read reverse has no impact on the required size of the positioning buffer for key-sequenced
files, queue files, entry-sequenced files with alternate keys, and relative files with alternate keys.

Read Reverse and the Record Pointers
For entry-sequenced and relative files, the state of the current-record and next-record file pointers
following a FILE_READ64_, READ, FILE_WRITE64_ or WRITE are:
Current-record pointer = record number or address of the last record read or written.
File Access

51

Next-record pointer = record number or address that follows the current-record pointer.
For entry-sequenced files, the record pointers contain a record address; for relative files, the
record pointers contain a relative record number. The contents of the current-record and
next-record pointers are accessible with the FILE_GETINFOLIST_ system procedure.
Following a call to FILE_READ64_/READ when reverse-positioning mode is in effect, the
next-record pointer contains the record number or address that precedes the current record
number or address.
Following a read of the first record in a file (where the current-record pointer is 0) when
reverse-positioning mode is in effect, the next-record pointer contains an invalid record number
or address because no previous record exists. In such a case, a subsequent call to
FILE_READ64_/READ will result in a CCG completion with file-system error code 1 (EOF) and
a call to FILE_WRITE64_/WRITE results in a file-system error code 550 (illegal position) because
an attempt was made to write beyond the beginning of the file.

File Expiration Dates
Each file has an associated expiration date value in the form of a 4-word timestamp. For purge
operations this value is checked against the current time; if it is later than the current time, the
purge is disallowed and a 1091 error code is returned. This check is in addition to, and separate
from, the usual purge authority checking. You can set the expiration date of a file by using the
FILE_ALTERLIST_ system procedure with an item code of 57. The initial expiration date value
when a file is created is zero, which represents a date far in the past, so all files are initially
purgeable as far as the expiration date is concerned.
NOTE: Any Enscribe files existing before the C10 software release are presumed to have a
zero expiration date.
When you change the expiration date of a file, it is not changed for any associated alternate-key
files but is changed for the secondary partitions of a partitioned file (unless the partonly parameter
was set to 1 in the FILE_ALTERLIST_ call). You must have read and write authority to change
the expiration date of a file. In addition, you cannot set an expiration date for a temporary file
because such files are automatically purged when you close them.

File Creation and Last-Opened Timestamps
Each file has associated with it a creation date value and a last-opened date value in the form
of 4-word timestamps.
You can obtain the creation date or last-opened date of a file by issuing a FILE_GETINFOLIST_
procedure call.

Using CONTROL 27 to Detect Disk Writes
For nonpartitioned files, you can use the CONTROL/FILE_CONTROL64_ system procedure with
a function code of 27 to detect when a disk write operation (FILE_WRITE64_,
FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITE, WRITEUPDATE, or
WRITEUPDATEUNLOCK) completes for the file designated by the specified file number.
This procedure call is useful in application environments where several different processes are
accessing the same database files and where you must quickly determine that the content of
certain critical records has changed.
Note that a CONTROL 27 call completion does not guarantee that any data in the file has actually
changed; it merely indicates that a disk write has completed against the file and it is a reasonable
time to examine the critical record(s) for new data.
To assure that no updates are missed as you read a record, first issue a nowait CONTROL 27
call against the file through one file open, read the record through another file open, and then
check for a completion of the CONTROL 27 call. If you issued the CONTROL 27 call after reading
52

General File Creation and Access Information

the record, a disk write by another process may have occurred between your read call and the
CONTROL 27 call.
Because the automatic resending of a CONTROL 27 request could be queued behind a disk
write request by another process (thus missing it), the file open through which you issue the
CONTROL 27 call should have a sync depth of 0. In such a case, you should treat path errors
(200-211) and network errors (240-249) as successful completions in that you then immediately
check the critical record(s) for new data.

Using Cache Buffering or Sequential Block Buffering
The Enscribe product provides two buffer management options, cache buffering and sequential
block buffering, that you can sometimes use to make I/O operations more efficient.

Cache Buffering
The cache, or buffer pool, is an area of main memory reserved for buffering blocks read from
disk. You use the PUP SETCACHE command to specify the cache size.
When a process reads a record, the software first checks the cache for the block that contains
the record. If that block is already in the cache, the record is transferred from the cache to the
application process. If the cache does not contain the block, the block is read from the disk into
the cache and then the requested record is transferred to the application process.
If no space is available in the cache when a block must be read in, some other block must be
selected to be overlaid. A choice of three different cache access types is available: sequential
access, random access, and system managed.
When a process writes a record, what happens differs according to the options selected when
the file was opened. If the buffered cache feature is not used, the cache block that contains the
record is modified, and then immediately written to disk. If the block to be modified is not in the
cache, it is first read from the disk. The modified block remains in cache, however, until the buffer
space is needed for overlay; this is called write-through cache.
You can open a file with buffered cache so that the cache contents are written to disk, or flushed,
less frequently. If several data changes occur to records in the same block in the cache, transaction
time is faster because less I/O to the disk is required. Database changes, however, do not get
into the actual disk file until the cache block is flushed for some reason. These situations cause
a block to be flushed:
•

Any opener closes the file.

•

The SETMODE procedure forces flushing.

•

TMF forces flushing.

•

Space is needed for a new block to be read into cache. The disk process selects the least
recently used data block and flushes it to make room for the new one.

•

The cache configuration is changed.

•

The buffer size of an unstructured file is changed by a SETMODE procedure call, causing
all cache buffers for that file to be flushed.

•

The DISK_REFRESH_ procedure, or equivalent command, is used on the file.

•

When the disk process has been idle for a sufficient period of time, it uses the free time to
flush modified cache buffers until it receives a user request.

Any file can be either buffered or write-through; the defaults are buffered for audited files and
write-through for non audited files.
Write-through cache is the default for nonaudited files, because a system failure or unplanned
disk process takeover (with a sync-depth of 0) could cause the loss of buffered updates and an
application might not detect or handle such a loss properly. Such a loss of buffered updates
File Access

53

would be indicated by error 122. Buffered cache is the default for audited files because TMF can
recover committed, buffered updates lost due to a system failure.
NOTE: Be careful in using the combination of nonaudited, buffered files with a sync-depth of
0 (no checkpointing). This combination provides high-performance updates but might compromise
data integrity in certain situations. Restartable applications (old master to new master, for example)
are not a concern. However, with online transaction applications there is a risk that some updates
buffered in the cache could be lost if there is a primary CPU failure. This is not a problem if the
primary-to-backup switch is deliberately set or is due to a controller path error, because no
processor failure is involved. If there is a disk process backup takeover due to primary CPU
failure, the disk process returns an error 122 on the next request of any kind for that file, indicating
a possible prior loss of buffered updates.
If a nonaudited buffered file with a sync-depth of 0 is used, the application should use SETMODE
95 to flush the buffered updates to disk before closing the file. The application should not depend
on the FILE_CLOSE_ procedure to do this, because FILE_CLOSE_ does not return an error and
consequently there would be no indication of a possible prior loss of buffered updates (error 122).
The disk process avoids fragmentation of cache memory space by grouping all 4096- byte blocks
in one area, all 2048-byte blocks in another area, and so forth. You set the amount of cache
memory devoted to each block size by using the PUP SETCACHE command. For the system
disk, the system operator sets the amount of cache memory devoted to each block size during
system configuration.
The disk process cache manager maintains ordered lists of its cache blocks (one for each size
of cache block), with the most recently used at the top of the list and the least recently used at
the bottom. When the cache manager needs a new block, it typically uses the entry at the bottom
of the appropriate list. After a block has been used, its entry moves to the top of the list and it
thereby becomes the most recently used block. As blocks are used, the various entries in the
list gradually migrate downward toward the bottom of the list.
Index and bit-map blocks, however, are kept longer in cache than are data blocks. The cache
manager always uses data blocks whenever they reach the bottom of the list, but allows index
and bit-map blocks to migrate through the list twice before using them.
Because this technique is believed to be advantageous in every application environment, there
is no way to disable it.

Sequential Block Buffering
When reading a file sequentially, you can reduce system overhead if you enable sequential block
buffering when you open the file. Note that this applies to read access only.
Sequential block buffering essentially relocates the record deblocking buffer from the disk process
to your application's process file segment (PFS). The software then uses the PFS buffer to
deblock the file's records.
Without sequential block buffering, the file system must request each record separately from the
disk process; for each record, this involves sending an interprocess message and changing the
environment. With sequential block buffering enabled, an entire block is returned from the disk
process and stored in the PFS buffer. Once a block is in the PFS buffer, subsequent read access
to records within that block is performed entirely by the file system (not the disk process) and
requires no hardware disk accesses, no communication with the disk process, and no environment
changes.
If sequential block buffering is to be used, the file usually should be opened with protected or
exclusive access. Shared access can be used, although it can cause some problems.

54

General File Creation and Access Information

Reading the buffered data does not use the disk process until:
•

The block has been traversed, at which time the disk process fetches another block.

•

An intervening FILE_SETPOSITION_, FILE_SETKEY_, POSITION, or KEYPOSITION is
performed. In this case, the next READ request causes a new block to be fetched.

•

A disallowed request (such as FILE_READUPDATELOCK64_, FILE_READLOCK64_,
FILE_READUPDATE64_, READUPDATELOCK, READLOCK, READUPDATE,
FILE_LOCKREC64_, LOCKREC, or a write request)

Considerations
Note that sequential block buffering is meaningful only for sequential reading of multiple records
of a structured file. Neither random reading nor any writing can take advantage of the sequential
buffer. In fact, because they always involve the disk process, write operations automatically clear
the buffer.
Sequential block buffering ignores any record locks that are currently in effect for the records in
the block. Sequential block buffering does not, however, bypass a file lock when the block is first
retrieved from the disk process.
To change a record that has been read from a block buffer, you should first perform intervening
FILE_SETPOSITION_, FILE_SETKEY_, POSITION, KEYPOSITION, FILE_READLOCK64_,
FILE_READUPDATELOCK64_, READLOCK, or READUPDATELOCK operations to fetch the
record. Doing so:
•

Ensures that the record has not been altered or deleted by another user since the block was
read.

•

Ensures that the record is not currently locked by another process.

•

Locks out other processes from the record to be updated.

FILE_OPEN_ Parameters
The FILE_OPEN_ procedure's sequential-block-buffer and buffer-length parameters govern
creation of the buffer.
The sequential-block-buffer parameter serves only as a numeric buffer identifier, because the
file system allocates the buffer space from the PFS. This parameter can be omitted if buffer space
is not to be shared.
The buffer-length parameter is the more significant parameter because:
•

If it is zero, absent, or longer than the space available in the PFS, the open operation
succeeds but returns an indication with warning 5 (failure to provide sequential buffering)
and block buffering is not used.

•

If it is greater than the file's block size, the buffer will be created with the specified size.

•

If it is nonzero but not greater than the file's block size, the buffer size will equal the block
size. For example, if a file with block size 4096 is opened with a buffer-length parameter of
128, the buffer will be created for a block size of 4096.

Alternate-Key Files
If you want to use an alternate-key access path and the alternate-key file's block size is larger
than that of the primary file, open the primary file with the larger buffer-length parameter.
If access to a primary file uses sequential block buffering, access to all associated alternate-key
records also uses it.
After FILE_SETKEY_ or KEYPOSITION with a nonzero key specifier, the first
FILE_READ64_/READ request causes the disk process to fetch a data block from the alternate-key
file into the buffer area. The disk process then fetches a single record from the primary data file
File Access

55

by using the alternate-key specification in the buffer. Thus the benefits and limitations of sequential
block buffering apply to the alternate-key file I/O, not to the primary file I/O.

Shared File Access
For sequential block buffering, the file usually should be opened with protected or exclusive
access. Combining sequential block buffering and shared access is allowed, but be aware that
this combination can cause concurrency problems.
If another process is updating data copied into the block buffer, those updates might not be seen
by the process using the buffer. For example, assume process A is reading a buffered block of
data while process B inserts a new record into that block on the disk. The new record will not be
in the buffer that process A is reading. Although process A's user might expect to see the record
that process B inserted, that record will not be in the buffer unless process A reads that block
again.

Sharing Buffer Space
You can have two or more files share the same buffer space by specifying identical
sequential-block-buffer parameters in FILE_OPEN_. This can result in significant memory
consumption savings in some applications.
When using this feature, however, be certain that the first file opened either has the largest block
size or is opened with enough buffer space to accommodate the largest file. If a file tries to share
a buffer that was already created with a smaller block size, the open operation succeeds but
returns an indication with warning 5 (failure to provide sequential buffering) and block buffering
is not used.
A shared buffer can be useful when reading whole blocks of data from several files, but it would
be inefficient when reading a single record or switching between files on successive reads,
because the buffer is refilled each time a new file or random record is read.
If you omit the sequential-block-buffer parameter when opening a file on a NonStop Operating
system, the file cannot share a buffer.

Specifying the Appropriate Disk File ACCESSTYPE Parameter
A parameter called ACCESSTYPE is associated with each disk file. This parameter in effect tells
the disk process how to use its buffer and cache space when reading from and writing to the
associated file. You use SETMODE 91 calls to examine or set ACCESSTYPE.
Choosing the most appropriate ACCESSTYPE for each of an application's files can increase the
efficiency with which the disk process carries out its tasks. The various access modes are:
•

Random access. When you specify random access, the disk process employs a least recently
used (LRU) approach to reusing cache space. This practice tends to keep frequently used
blocks in cache memory instead of reading them in from the disk every time they are needed.

•

Sequential access. When you specify sequential access, the disk process uses essentially
the same LRU algorithm that it does for random access but does so in such a way that the
least recently used data blocks are removed from the cache sooner. With sequential access,
the least recently used data block survives in cache approximately half as long as it would
for random access. This practice prevents cache memory from being filled with data blocks
that you probably do not need again.

•

There are two cases that tend to call for this type of access: one being the truly sequential
case and the other being the case where you are accessing a very large file randomly.

•

System-managed access. When you specify system-managed access, the disk process
decides whether you are accessing the file randomly or sequentially based upon your previous
usage and optimizes its behavior accordingly. This is the default access type.
Direct I/O. When you specify direct I/O access, the disk process bypasses cache memory
completely if the file has been opened for write-through, unstructured access in either

•
56

General File Creation and Access Information

exclusive read/write or protected read-only mode. This type of access might be desirable,
for example, in an application that requires fast unstructured access and derives no real
benefit from the use of cache memory.

Refreshing the End-of-File (EOF) Pointer
Each file's end-of-file (EOF) pointer is kept in its file control block (FCB) in main memory. To
maximize performance, the EOF pointer is normally written to the file's disk label only when
needed.
Although refreshing the file's disk label only under limited conditions maximizes system
performance, certain considerations should be taken into account. These considerations do not
apply in the case of TMF audited files, because the EOF is recovered by the autorollback feature.
•

If an open file is backed up, the EOF pointer in the file label copy on tape does not reflect
the actual state of the file. An attempt to restore such a file results in an error.

•

If the system is shut down (each processor module has been reset) while a file is open, the
EOF pointer in the file label on disk does not reflect the actual state of the file.

•

If a total system failure occurs (such as that caused by a power failure that exceeds the limit
of memory battery backup) while a file is open, the EOF pointer in the file label on disk will
not reflect the actual state of the file.

There is an autorefresh option for Enscribe files that you can enable or disable by using FUP
ALTER commands or FILE_CREATE_ system procedure calls. This option, when enabled,
causes the disk label to be refreshed automatically each time the file label changes, including
the EOF pointer field. This autorefreshing is always on for key-sequenced and queue files; any
REFRESH setting is ignored.
The additional I/O caused by the REFRESH ON option can decrease processing throughput
significantly. For applications that cannot afford this overhead, the EOF pointer in the file label
on disk can be forced to represent the actual state of a file through periodic use of the
DISK_REFRESH_ procedure. Execution of REFRESH writes the information contained in any
FCBs to the file labels on the associated disk volume.
The REFRESH option can also be set with the PUP REFRESH command. The REFRESH
command is useful before backing up a file that is always open (for example, where the application
is always running). At some point during the day when the system is quiescent (no transactions
are taking place), issue a REFRESH command for all volumes in the system. Then, when the
files are backed up, the file labels on the backup tape will represent the actual states of each file.
To use the equivalent SCF command, enter SCF CONTROL DISK $, REFRESH at
the TACL prompt.
System operators use the REFRESH command before initiating a total system shutdown to
ensure that all file labels on disk correctly represent the actual state of each file. The disk process,
when idle, periodically refreshes changed EOF pointers to the file label on disk regardless of the
various REFRESH option states.

Purging Data
Either the FUP PURGEDATA command or the CONTROL/FILE_CONTROL64_ procedure's
purge data operation can logically, but not physically, remove all data from a file by resetting
pointers to relative byte 0. Also, either the FILE_PURGE_ procedure or the FUP command
PURGE can delete a file from the disk directory.
Following are four ways to logically purge data from an Enscribe file:
1. The FUP PURGE command
2. The FILE_PURGE_ system procedure
3. The FUP PURGEDATA command
4. The CONTROL 20 system procedure
File Access

57

None of these actually physically erases data. Instead, they all reset various pointers to indicate
that either:
•

The file no longer exists (FUP PURGE command or the FILE_PURGE_ system procedure)

•

The file exists but contains no data (FUP PURGEDATA command or CONTROL 20 system
procedure)

In the first case, if the file space is subsequently reallocated to another file, the new file's owner
can read the logically purged data. For security reasons, you might want to avoid this. You can
do so by enabling the CLEARONPURGE option prior to purging the file. You enable
CLEARONPURGE by using either the SETMODE 1 system procedure or the FUP SECURE
command. Having done so, all of the data in the file is physically erased (overwritten with zeros)
when the file is purged. CLEARONPURGE has no effect in conjunction with the FUP PURGEDATA
command.
For example, the TAL code resets the current-record, next-record, and EOF pointers of the
particular file to point to relative byte 0 and updates the EOF pointer in the file label on disk:
LITERAL purgedata = 20;
CALL CONTROL ( filenum, purgedata );
IF < THEN...

The file still exists, but it now logically contains no data.
You can also use the CONTROL 21 system procedure (allocate/ deallocate extents) in conjunction
with CONTROL 20 to logically purge a file's data and then deallocate all of its extents:
LITERAL purgedata = 20,
alloc^op = 21,
dealloc = 0;
CALL CONTROL ( filenum, purgedata );
IF < THEN ...
CALL CONTROL ( filenum, alloc^op, dealloc );
IF < THEN ...

The file still exists, but it now logically contains no data and all of its extents have been released
(deallocated).
CONTROL 21 can be used to deallocate extent space beyond the EOF even when the EOF
points to a relative byte greater than zero.

Programmatically Allocating File Extents
You can use the CONTROL 21 system procedure to allocate one or more file extents for an open
file. For example, to allocate 16 extents to a newly created file, open the file and then issue a
CONTROL 21 procedure call:
LITERAL alloc^op = 21,
max^ext = 16;
CALL CONTROL ( filenum, alloc^op, max^ext );
IF < THEN ...

NOTE:

If all extents cannot be allocated because the file label is full, error 43 is returned.

Programmatically Deallocating File Extents
You can also use the CONTROL 21 system procedure to deallocate any file extents beyond the
extent to which the EOF pointer is currently pointing.
For example, to deallocate any unused extents in a file, open the file and then issue a CONTROL
21 procedure call:
LITERAL alloc^op = 21,
dealloc = 0;
CALL CONTROL ( filenum, alloc^op, dealloc );

The file still exists, but all file extents beyond the EOF extent are deallocated.
58

General File Creation and Access Information

5 Unstructured Files
Enscribe Unstructured Files
An Enscribe unstructured file is essentially a byte array on disk that starts at byte address zero
and continues sequentially upward through whatever byte address is identified by the end-of-file
(EOF) pointer. The file system imposes no further structure on such files. How data is grouped
into records and how records are ordered within the file are the responsibility of the application
process.
The files created by the EDIT or TEDIT utilities, for example, are unstructured. What structure
they do have is imposed by the utilities themselves, not by the Enscribe software. Such files can
be read by the EDITREAD procedure, by the sequential I/O (SIO) routines, or by EDIT or TEDIT.
EDIT and TEDIT files are identifiable by the file code 101.
Application designers typically use unstructured files for exclusive (nonshared), intermediate
storage of fixed-length data records that are accessed sequentially.
Access to the data in unstructured files is accomplished using a relative byte address (RBA)
maintained by the Enscribe software and the read-count or write-count parameter supplied by
the application process in system procedure calls such as FILE_READ64_, FILE_WRITE64_,
FILE_READUPDATE64_, READ[X], WRITE[X], and READUPDATE[X].

Applicable System Procedures
You use these system procedures to create and access Enscribe unstructured files:
•

FILE_CREATE_, FILE_CREATELIST_

•

FILE_OPEN_, FILE_CLOSE_, AWAITIO[X], FILE_AWAITIO64_

•

FILE_LOCKFILE64_, FILE_LOCKREC64_, FILE_UNLOCKFILE64_,
FILE_UNLOCKREC64_, LOCKFILE, LOCKREC, UNLOCKFILE, UNLOCKREC

•

FILE_SETPOSITION_, FILE_SAVEPOSITION_, FILE_RESTOREPOSITION_

•

FILE_READ64_, FILE_READLOCK64_, FILE_READUPDATE64_,
FILE_READUPDATELOCK64_, READ[X], READLOCK[X], READUPDATE[X],
READUPDATELOCK[X]

•

FILE_WRITE64_, FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_,
WRITE[X], WRITEUPDATE[X], WRITEUPDATEUNLOCK[X]

•

FILE_GETINFO_, FILE_GETINFOLIST_, FILE_GETINFOBYNAME_,
FILE_GETINFOLISTBYNAME_

•

SETMODE, CONTROL, FILE_CONTROL64_

Types_Access
The types of access associated with unstructured files are sequential access, random access,
and appending to the end of a file.
To perform sequential access, you use successive FILE_READ64_, FILE_READLOCK64_,
FILE_WRITE64_, READ[X], READLOCK[X], and WRITE[X] calls to operate upon consecutively
higher blocks of data. To perform random access, you use the FILE_SETPOSITION_ system
procedure to explicitly manipulate the content of the current-record and next-record pointers.
You can also use FILE_SETPOSITION_ to change the content of the next-record pointer so that
it points to the EOF position (for appending records to the end of the file); you do so by specifying
the value -1 as the desired RBA.
Enscribe Unstructured Files

59

Creating Unstructured Files
You create Enscribe unstructured files with the File Utility Program (FUP) or by calling either the
FILE_CREATE_ procedure or the FILE_CREATELIST_ procedure. When you create an
unstructured file, you must consider the buffer size and the disk extent sizes.

Buffer Size
The buffer size attribute lets you define the internal buffer size to be used by the disk process
when accessing an unstructured file. The buffer size attribute can be any of these: 512 bytes, 1
KB, 2 KB, or 4 KB.
When creating a file by using the FILE_CREATE_ procedure, you use the blocklen parameter
to specify the internal buffer size. When creating a file by using the FILE_CREATELIST_
procedure, you use item code 44 in the item-list to specify the internal buffer size.
When creating a file by using FUP, you use the BUFFERSIZE parameter to specify the desired
buffer size.
When you open a file, the buffer size is automatically set to the value that was specified for the
file when it was created.
During program execution, you can change the buffer size dynamically by specifying either a
BUFFERSIZE value in a FUP ALTER command or by way of param1 in a SETMODE 93 procedure
call
Note that the FUP ALTER command also changes the BUFFERSIZE parameter contained in
the file label on disk. The SETMODE 93 call, however, applies only until you reverse it by using
a FUP ALTER command or another SETMODE 93 system procedure call or until the file is closed.
If you specify an invalid buffer size, then the next higher valid size is used. The default buffer
size is 4096, the maximum possible. Note that the buffer size you specify has no effect on the
format of the data. Only 4 kb is supported for 512-b sector devices.
Because the buffer size attribute in effect defines the physical unit of transfer, the most efficient
physical data transfers are those that start on a buffer-sized boundary and whose read count or
write count is an integral multiple of the buffer size.
A buffer size that is exactly the same size as the anticipated transfer size lets the disk process
use its fixed-length cache management scheme most efficiently. For example, if it is reasonable
for your application to read and write its data in 1024-byte quantities and on 1024-byte boundaries
(that is, the first block of data starts at RBA 0, the second at RBA 1023, the third at 2047, and
so forth), the best buffer size attribute to specify would be 1024.
For example, suppose that you let the disk process use the default buffer size of 4096 and your
application program naturally does its transfers in blocks of 1024 bytes. In such a case, each
write of 1024 bytes will cause the disk process to first read a block of 4096 bytes, modify 1024
bytes of it in cache memory, and then write the 4096-byte block back to the disk. If the file is
being audited by TMF or was opened with a syncdepth greater than zero, then a large
audit-checkpoint (AC) record will also be generated because this appears to be a partial update
to a 4096-byte record.
If, instead, you specified a buffer size of 1024 and you are always reading and writing in multiples
of 1024, then each write of 1024 bytes will involve no read, a write of 1024 bytes, and no AC
record at all.
The performance difference in these two cases can be dramatic. The best practice for unstructured
files, whenever possible, is to always perform buffer-sized reads and writes starting at buffer-sized
boundaries.

Disk Extent Size
When you create an Enscribe file you can specify the size of the primary and secondary extents
(1 to 65,535 pages for a format 1 file, where a page is 2048 bytes). You can also specify the
60

Unstructured Files

maximum number of extents to be allocated for the file (16 or more for nonpartitioned unstructured
files). If you do not specify extent sizes, both the primary and secondary extent sizes default to
one page.
If you do not specify a maximum number of extents, MAXEXTENTS defaults to 16.
For nonpartitioned unstructured files, you can change the MAXEXTENTS value dynamically
during program execution by using either the SETMODE 92 system procedure or the FUP ALTER
command.

Restrictions on Partitioned Unstructured files
The following restrictions apply to partitioned unstructured files on an XP storage array and on
H-series, J-series, and S-series internal disks:
•

All extents must be a multiple of 14 pages.

•

All partitions must have identical extent sizes and maximum extents, because partitioning
depends on each partition having the same size.

Example: Creating an Unstructured File
The most efficient way to access unstructured disk files is by using buffer-sized reads and writes
starting at buffer-sized boundaries.
The file created in this example is designed to store fixed-length logical records that are 512
bytes long. Provided that your application program will always read and write in multiples of 512
(thus maintaining alignment on buffer-sized boundaries), selecting a buffer size of 512 allows
the disk process to perform most efficiently. If you designate the primary extent size as 6250
pages and the secondary extent size as 2500 pages, then the primary extent accommodates
25,000 of the 512-byte logical records and each secondary extent accommodates 10,000. When
all 16 extents are eventually used, the entire file accommodates 175,000 records.
Assume also that you want to identify the file by the file code 1234. You could create the file by
using the FUP commands:
> volume $volume1.subvol1
> fup
-set type u
-set code 1234
-set ext (6250,2500)
-set buffersize 512
-show
TYPE U
CODE 1234
EXT ( 6250 PAGES, 2500 PAGES )
BUFFERSIZE 512
MAXEXTENTS 16
-create datafile
CREATED - $VOLUME1.SUBVOL1.DATAFILE

You could also use the FILE_CREATE_ procedure to create the file by including the TAL code
in one of your application modules:
LITERAL name^length = 25,
pri^extent = 6250,
file^code = 1234,
sec^extent = 2500,
file^type = 0, ! file type = unstructured
buffer^size = 512;
INT error;
INT filenum;
INT namelen;
STRING .filename [0:name^length-1] :=
"$VOLUME1.SUBVOL1.DATAFILE";
namelen := name^length;
Creating Unstructured Files

61

error := FILE_CREATE_ (filename:name^length,
namelen, file^code, pri^extent,
sec^extent, , file^type, , , buffer^size);

Accessing Unstructured Files
This subsection discusses the pointers and different types of access associated with unstructured
files.

File Pointers
Three major pointers are associated with an Enscribe unstructured file:
Current-record pointer
Specifies the RBA of the location that was most recently read
from or written to.
Next-record pointer

Specifies the RBA of the next location to be read from or
written to.

EOF pointer

Specifies the RBA of the next even numbered byte following
the last data byte in the file unless the odd unstructured option
has been set for the file. If the odd unstructured option is set,
the EOF occurs at the next sequential byte after the last data
byte whether it is odd or even numbered.

When you open an unstructured file, both the current-record and next-record pointers point to
the first byte in the file (RBA zero).
Separate current-record and next-record pointers are associated with each opening of an
unstructured disk file so that if the same file is opened several times simultaneously, each opening
provides a logically separate access. The current-record and next-record pointers reside in the
file's access control block (ACB) in the application process environment.
A single EOF pointer, however, is associated with all opens of a given unstructured disk file. This
permits data to be appended to the end of a file by several different accessors. The EOF pointer
resides in the file's file control block (FCB) in the disk I/O process environment. A file's EOF
pointer value is copied from the file label on disk when the file is opened and is not already open.
The system maintains a working copy of the file's EOF pointer in the FCBs that are in both the
primary and backup system processes that control the associated disk volume.
You can explicitly change the content of the next-record pointer to that of the EOF pointer by
specifying an address of -1 in a FILE_SETPOSITION_ call. When appending to a file, the EOF
pointer is advanced automatically each time a new data record is added to the end of the file.
Note that in the case of partitioned files, the EOF pointer relates only to the final partition containing
data.
A file's EOF pointer is not automatically written through to the file label on disk each time it is
modified. Instead, for unstructured files, it is physically written to the disk only when one of these
events occurs:
•

A file label field is changed and the autorefresh option is enabled.

•

The last accessor of the file, closes the file.

•

The DISK_REFRESH_ procedure is called for the file.

•

The REFRESH command is executed for the file's volume.

When creating a file by using the FILE_CREATE_ system procedure, you enable or disable the
autorefresh feature by setting bit 10 of the options parameter to 1 or 0, respectively.
When creating a file by using FUP, you enable or disable the autorefresh feature by specifying
REFRESH or NO REFRESH, respectively, in the FUP CREATE command.
When you open a file, the autorefresh feature is enabled or disabled at that time depending upon
what was specified for the file when it was created. You can enable or disable this feature
62

Unstructured Files

dynamically during program execution by specifying REFRESH or NO REFRESH, respectively,
in a FUP ALTER command. When you do so, however, whatever you designate applies until
you reverse it with a subsequent FUP ALTER command or until the file is closed.
Table 8 summarizes the values that the various pointers are set to upon conclusion of the particular
system procedure.
In this table, count is the transfer count specified by the read or write procedure call. If the file
is an odd unstructured file, the value specified by count is the number of bytes transferred. If
the file is an even unstructured file, count is rounded up to an even number before the data is
transferred.
Table 8 File-Pointer Action
System Procedure

Pointer Values

CONTROL (write EOF)

EOF pointer := next-record pointer; file label's EOF pointer := EOF pointer;

CONTROL (purge data)

current-record pointer := next-record pointer := EOF pointer := 0; file label's EOF pointer
:= EOF pointer;

CONTROL (allocate/
deallocate extents)

file pointers are unchanged; file label's EOF pointer := EOF pointer;

FILE_CLOSE_ (last)

file label's EOF pointer := EOF pointer;

FILE_CREATE_

file label's EOF pointer := 0;

FILE_CREATELIST_

file label's EOF pointer := 0;

FILE_OPEN_ (first)

EOF pointer := file label's EOF pointer;

FILE_OPEN_ (any)

current-record pointer := next-record pointer := 0;

FILE_SETPOSITION_

current-record pointer := next-record pointer := relative-byte-address;

READ[X] or READLOCK[X] current-record pointer := next-record pointer; next-record pointer := next-record pointer
+$min (count, EOF pointer - next-record pointer);
READUPDATE[X]

file pointers are unchanged

READUPDATELOCK[X]

file pointers are unchanged

WRITE[X]

if next-record pointer = -1 then
begin
current-record pointer := EOF pointer;
EOF pointer := EOF pointer + count;
end
else
begin
current-record pointer := next-record pointer;
next-record pointer := next-record pointer + count;
EOF pointer:= $max(EOF pointer, next-record pointer);
end;

WRITEUPDATE[X]

file pointers are unchanged

WRITEUPDATEUNLOCK[X] file pointers are unchanged
Legend
:= means “is set to”
$max represents a function in which the larger of the two specified values is used. $min represents a function in
which the smaller of the two specified values is used.

Sequential Access
FILE_READ64_, FILE_READLOCK64_, READ[X], READLOCK[X], FILE_WRITE64_ and
WRITE[X] operations increment the next-record pointer by the number of bytes transferred,
thereby providing sequential access to the file.
Accessing Unstructured Files

63

If the file is an odd unstructured file, both the number of bytes transferred and the amount by
which the pointers are incremented are exactly the number of bytes specified by the write count
or read count parameter. If the file is an even unstructured file, the values of the write count and
read count parameters are rounded up to an even number before the transfer takes place and
the file pointers are incremented by the rounded-up value.

Example:
This sequence of system procedure calls illustrates how the file pointers are used when
sequentially accessing an unstructured disk file; the example assumes that these are the first
operations after the file is opened:
CALL
CALL
CALL
CALL

READ ( filenum, buffer, 512 );
READ ( filenum, buffer, 512 );
WRITEUPDATE ( filenum, buffer, 512 );
READ ( filenum, buffer, 512 );

The first READ transfers 512 bytes into the designated buffer starting at relative byte 0. Upon
completion of this READ operation, the next-record pointer points to relative byte 512 and the
current-record pointer points to relative byte 0.
The second READ transfers 512 bytes into the buffer starting at relative byte 512. Upon completion
of this READ operation, the next-record pointer points to relative byte 1024 and the current-record
pointer points to relative byte 512.
The WRITEUPDATE procedure then replaces the just-read data with new data in the same disk
location. The file system transfers 512 bytes from the buffer to the file at the position indicated
by the current-record pointer (relative byte 512). The next-record and current-record pointers are
not altered by the WRITEUPDATE operation.
The third READ transfers 512 bytes into the buffer starting at relative byte 1024 (the address in
the next-record pointer). Upon completion of this READ operation, the nextrecord pointer points
to relative byte 1536 and the current-record pointer points to relative byte 1024.

Encountering the EOF During Sequential Reading.
If you encounter the EOF boundary while reading an unstructured disk file, the data up to the
EOF location is transferred. A subsequent read request will return an EOF indication (condition
code CCG) because it is not permissible to read past the EOF location. If you do not alter the
pointers by using a FILE_SETPOSITION_ call, the EOF indication will be returned for every
subsequent read request.
For example, consider an unstructured file with the EOF location at relative byte 4096, as illustrated
in Figure 12 (page 65). Assume that an application program executes this sequence of 512-byte
reads starting at relative byte 0:
file^eof := 0;
WHILE NOT file^eof DO
BEGIN
CALL READ ( filenum, buffer, 512, num^read, .. );
IF > THEN file^eof := 1
ELSE
IF = THEN
BEGIN
...process the data...
END
ELSE ... ! error
END;

64

Unstructured Files

Figure 12 Example of Encountering the EOF
Read #1
(512
Bytes)

Read #2
(512
Bytes)

0
512
Relative Byte Address

Read #3
(512
Bytes)

1024

Read #8
(512
Bytes)

1536

3584

Read #9
(CCG)

4096
(EOF)

Each of the first eight READ calls transfers 512 bytes into the designated buffer, returns a
num^read of 512, and sets the condition code to CCE (operation successful).
The ninth READ fails, no data is transferred into the buffer, num^read is returned as zero, and
the condition code CCG indicates that you encountered the EOF.
If the read count is changed from 512 to 400, the results of executing the same read loop are
somewhat different, as illustrated in Figure 13 (page 65)
In this case, the first 10 READ calls each transfer 400 bytes into the designated buffer, return a
num^read of 400, and set the condition code to CCE (operation successful). The eleventh READ
transfers 96 bytes into the buffer, returns a num^read of 96, and sets the condition code to CCE.
The twelfth READ fails and sets the condition code to CCG.
Figure 13 Example of Encountering the EOF (Short READ)
Read #1
(400
Bytes)

Read #2
(400
Bytes)

0
400
Relative Byte Address

Read #10
(400
Bytes)

800

3600

Read #11 Read #12
(CCG)
(96
Bytes)

4000

4096
(EOF)

Random Access
You access Enscribe unstructured disk files by using the relative-byte-address parameter of the
POSITION system procedure to explicitly set the file pointers. To update data in an unstructured
disk file at relative byte address 81920, you could use this sequence:
CALL FILE_SETPOSITION_ ( filenum, 81920F );
CALL READUPDATE ( filenum, buffer, 512 );
CALL WRITEUPDATE ( filenum, buffer, 512 );

The call to FILE_SETPOSITION_ sets both the current-record and next-record pointers to relative
byte 81920.
The call to READUPDATE transfers 512 bytes from the disk to the designated buffer, starting at
relative byte 81920 in the disk file. Following the read operation, the file pointers are unchanged.
The WRITEUPDATE procedure replaces the just-read data with new data in the same location
on disk. The file system transfers 512 bytes from the buffer to the file at relative byte 81920.
Following the write operation, the file pointers are unchanged.

Appending to the End of a File
You can also use the FILE_SETPOSITION_ procedure to append data to the end of an
unstructured disk file. To set the next-record pointer to the EOF position, pass -1 as the relative
byte address parameter in a FILE_SETPOSITION_ call:
CALL FILE_SETPOSITION_ ( filenum, -1F );
Accessing Unstructured Files

65

The next-record pointer now contains -1. This indicates to the file system that subsequent WRITE
calls should append to the end of the file.
This WRITE call, if issued immediately after the FILE_SETPOSITION_ -1 call, appends 512
bytes to the end of the file:
CALL WRITE ( filenum, buffer, 512, num^written );

The file system transfers 512 bytes from the designated buffer to the relative byte address pointed
to by the EOF pointer. Upon completion of the WRITE operation, the EOF pointer is incremented
by 512, the current-record pointer points to the old EOF position, and the next-record pointer still
contains -1. A subsequent WRITE will also append to the end of the file.

66

Unstructured Files

6 Key-Sequenced Files
Enscribe Key-Sequenced Files
NOTE: As of the H06.28 and J06.17 RVUs, format 2 legacy key-sequenced 2 (LKS2) files with
increased limits, format 2 standard queue files with increased limits, and enhanced key-sequenced
(EKS) files with increased limits are introduced. EKS files with increased limits support 17 to 128
partitions along with larger record, block, and key sizes. LKS2 files with increased limits and
format 2 standard queue files with increased limits support larger record, block, and key sizes.
When a distinction is not required between these file types, key-sequenced files with increased
limits is used as a collective term. To use increased Enscribe limits, the minimum RVUs are
H06.28 and J06.17 with specific SPRs. (These SPR requirements could change or be eliminated
with subsequent RVUs.) For a list of the required H06.28/J06.17 SPRs, see SPR Requirements
for Increased Enscribe Limits for the H06.28/J06.17 Release (page 18).
NOTE: As of the H06.22 and J06.11 RVUs, a new Enscribe file type: enhanced key-sequenced
(EKS) file is introduced and extends the Enscribe partition maximum to 64. An EKS file supports
17 to 64 partitions. The previous Enscribe key-sequenced file type supports 1 to 16 partitions
and is referred to as a legacy key-sequenced (LKS) file in this manual. When a distinction is not
required between these file types, key-sequenced file is used as a collective term.
Enscribe key-sequenced files consist of variable-length records that are accessed by the values
contained within designated key fields. There are two types of keys: primary and alternate. All
records in a key-sequenced file contain a primary key. The use of alternate keys is optional.
The primary key field is designated when a key-sequenced file is created. It can be any set of
contiguous bytes within the data record. The records in a key-sequenced file are stored logically
in ascending order according to the value contained in their primary-key field.
A record can vary in length from one byte to the maximum record size specified when the file
was created. For the maximum record sizes of key-sequenced files, see Table 7 (page 46). The
number of bytes allocated for a record is the same as that written when the record was inserted
into the file. Each record has a length attribute that is optionally returned when a record is read.
A record's length can be changed after the record has been inserted (with the restriction that the
length cannot exceed the specified maximum record size). Records in a key-sequenced file can
be deleted.
A good example of the use of key-sequenced files in an application environment is an inventory
file in which each record describes a part. The primary key field for that file would probably be
the part number, so the file would be ordered by part number. Other fields in the record would
contain such information as vendor name, quantity on hand, and so forth, and one or more of
them can be designated as alternate key fields. Note that the Enscribe software is concerned
only with key fields; the content and location of all other fields in each record is solely the concern
of the application.

Applicable System Procedures
Use these system procedures to create and access Enscribe key-sequenced files:
•

FILE_CREATE_, FILE_CREATELIST_

•

FILE_OPEN_, FILE_CLOSE_, AWAITIO[X], FILE_AWAITIO64_

•

FILE_LOCKFILE64_, FILE_LOCKREC64_, FILE_UNLOCKFILE64_,
FILE_UNLOCKREC64_, LOCKFILE, LOCKREC, UNLOCKFILE, UNLOCKREC

•

FILE_SETKEY_, FILE_SETKEYPOSITION_, FILE_SAVEPOSITION_,
FILE_RESTOREPOSITION,
KEYPOSITION, SAVEPOSITION, REPOSITION
Enscribe Key-Sequenced Files

67

•

FILE_READ64_, FILE_READLOCK64_, FILE_READUPDATE64_,
FILE_READUPDATELOCK64_, READ[X], READLOCK[X], READUPDATE[X],
READUPDATELOCK[X]

•

FILE_WRITE64_, FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_,
WRITE[X], WRITEUPDATE[X], WRITEUPDATEUNLOCK[X]

•

FILE_GETINFO_, FILE_GETINFOLIST_, FILE_GETINFOBYNAME_,
FILE_GETINFOLISTBYNAME_

•

SETMODE, CONTROL, FILE_CONTROL64_

Types of Access
Key-sequenced files can be accessed either sequentially or randomly. Sequential access is
preferable, for example, when generating a report of the quantity on hand of all parts in an
inventory file. Random access is preferable when you want to identify the vendor of a particular
part.
When you read from a key-sequenced file by primary key, each FILE_READ64_/READ operation
retrieves the record containing the next sequentially higher primary-key value. Similarly, when
you read by an alternate key, each FILE_READ64_/READ operation retrieves the record containing
the next sequentially higher value in the specified alternate-key field.
The FILE_SETKEY_ or KEYPOSITION system procedure specifies which access path (primary
key or a particular alternate-key field) you want to use and the field value at which you want to
start.
If you do not use FILE_SETKEY_ or KEYPOSITION, access is by primary key and begins with
the first record in the file.
You can use FILE_SETKEY_ or KEYPOSITION during program execution to dynamically change
the access path and the current-record pointer.

Key-Sequenced Tree Structure
Key-sequenced files are physically organized as one or more bit-map blocks and a B-tree structure
of index blocks and data blocks. Figure 14 (page 69) illustrates a sample key-sequenced file
tree structure. Bit-map blocks within the file organize the free space of a structured file.
Each data block contains a header plus one or more data records, depending on the record size
and data-block size. For each data block there is an entry in an index block containing the value
of the key field for the first record in the data block and the address of that data block.
The position of a new record inserted into a key-sequenced file is determined by the value of its
primary-key field. If the block where a new record is to be inserted into a file is full, a block split
occurs. This means that the disk process allocates a new data block, moves part of the data from
the old block into the new block, and gives the index block a pointer to the new data block.
When an index block fills up, it is split in a similar manner: a new index block is allocated and
some of the pointers are moved from the old index block to the new one. The first time this occurs
in a file, the disk process must generate a new level of indexes. The disk process does this by
allocating a higher-level index block containing the low key and pointer to the two lower-level
index blocks, which in turn point to many data blocks. The disk process must do this again each
time the highest-level block is split.
The disk process sometimes performs a three-way block split, creating two new blocks and
distributing the original block's data or pointers (plus the new record or pointer) among all three.
If your record size is large, you should also use a large block size. If the block size is too small
to hold more than a few records, block splits occur more frequently, disk space usage is less
efficient, and performance is degraded.
68

Key-Sequenced Files

Typically, in a changing database most blocks will be approximately two-thirds full at any given
time. When using the FUP LOAD command to load data into a key-sequenced file, you can
specify how much empty space to provide for future growth.
Figure 14 Key-Sequenced B-Tree Structure
First (Highest)-Level Index Block
0

MOLLY

VINCE

Second-Level Index Block
0

CAROL

LOUISE

Data Blocks

1

AMY

BETTY

Empty

CAROL

CHRIS

Empty

LOUISE

MILLY

Empty

Second-Level Index Block
MOLLY

OLGA

2

STEVE

Data Record
MOLLY

NATE

Empty

Primary Key
OLGA

RUSTY

Empty

STEVE

ULENA

Empty

Saved
for Future
Insertions

Variable-Length
Physical Records

Legend
1
2

NATE is alphabetically greater than MOLLY but less than VINCE.
Go to the second-level index block that begins with MOLLY.
NATE is alphabetically greater than MOLLY but less than OLGA.
Go to the data block that begins with MOLLY.

Note that data records are never chained together in Enscribe key-sequenced files. Instead, the
tree structure is dynamically rebalanced to ensure that all records in the file can be accessed
with the same number of FILE_READ64_/READ operations, that number being the number of
levels of indexes plus one for the data block.

Unique Features of EKS Files
Enhanced Key-Sequenced Files (EKS) have these unique features:
•

The primary partition does not store user data but rather stores file meta data

•

When creating an EKS file, the partial key of the first secondary partition must be explicitly
set to all zeros.

Unique Features of EKS Files

69

•

When creating an EKS file, the primary extent size of the primary partition is adjusted based
on the block length of the file. The secondary extent size for the primary partition is ignored.

•

When accessing the primary partition of an EKS file in unstructured mode, reads on the file
return FEEOF (1) and writes return FEFILEFULL (45). This is because the meta data stored
in the primary partition cannot be accessed by non-privileged applications.

Creating Key-Sequenced Files
You create Enscribe legacy, legacy with increased limits, enhanced key-sequenced files, or
enhanced key-sequenced files with increased limits with the File Utility Program (FUP) or by
calling either the FILE_CREATE_ procedure or the FILE_CREATELIST_ procedure.
If you are using FUP to create a file that contains one or more alternate-key fields, FUP
automatically creates any required alternate-key files. If you are creating the file programmatically,
however, you must create any required alternate-key files yourself (one for each alternate-key
field).
When creating a key-sequenced file, your considerations include:
•

“Comparing LKS Files, LKS2 Files, Standard Queue Files, EKS Files, and EKS Files with
Increased Limits” (page 70)

•

“Converting a Legacy Key-Sequenced File to an Enhanced Key-Sequenced File” (page 72)

•

“Logical Records” (page 72)

•

“Disk Extent Size” (page 73)

•

“Primary Keys” (page 74)

•

“Key Compression” (page 74)

•

“Index Compaction” (page 75)

Comparing LKS Files, LKS2 Files, Standard Queue Files, EKS Files, and EKS Files
with Increased Limits
Table 9 Comparison of LKS Files, LKS2 Files, Standard Queue Files, EKS Files, and EKS
Files with Increased Limits

70

File Attribute

LKS and Standard
Queue File
Attributes Allowed
Values

LKS2 and Standard
Queue File
Attributes Allowed
Values

EKS File Attributes
Allowed Values

EKS Files with
Increased Limits
Allowed Values

Format Type

1 or 2

2

2

2
1

Number of Partitions

Up to 16

Up to 16

17 up to 64

17 up to 128

Extents for Primary
Partition

Up to 978

Up to 928

Up to 928

Up to 928

Extents for Secondary Up to 978
Partition

Up to 928

Up to 928

Up to 928

Partition File Extent
Sizes

Each partition has its
own primary and
secondary extent
size. The maximum
extent size for a
format 2 file is
536,870,912 pages.

The primary partition
has a primary extent
size greater than or
equal to 140 pages
and cannot be less
3
than 140 pages.
Each secondary
partition has its own
primary and
secondary extent
size.

The primary extent
size of the primary
partition is based on
the block length of the
file. The secondary
extent size for the
primary partition is
ignored. Each
secondary partition
has its own primary

Key-Sequenced Files

Each partition has its
own primary and
secondary extent
size. The maximum
extent size for a
format 1 file is 65535
pages, while the
maximum extent size
for a format 2 file is
536,870,912 pages.

2

Table 9 Comparison of LKS Files, LKS2 Files, Standard Queue Files, EKS Files, and EKS
Files with Increased Limits (continued)

File Attribute

LKS and Standard
Queue File
Attributes Allowed
Values

LKS2 and Standard
Queue File
Attributes Allowed
Values

EKS File Attributes
Allowed Values

EKS Files with
Increased Limits
Allowed Values
and secondary extent
size.

Block Length

512, 1 KB, 2 KB, 4 KB 512, 1 KB, 2 KB, 4 KB 512, 1 KB, 2 KB, 4 KB 512, 1 KB, 2 KB, 4
(With increased limits,
KB, 32 KB
32 KB is supported.)

Record Length

Format 1: Up to 4062 Up to 4040 (With
Up to 4040
Format 2: Up to 4040 increased limits, up to
27,648.)

Up to 27,648

Primary Key Length

Up to 255

Up to 2048

Up to 255 (With
Up to 255
increased limits, up to
2048.)

Alternate Key Length Up to ~255 (Not
Up to ~255 (With
Up to ~255
applicable to Enscribe increased limits, up to
Queue files.)
~2048.) (Not
applicable to Enscribe
Queue files.)

Up to ~2048

4

4

Up to 255

Up to 100 (Not
Up to 100 (Not
Up to 100
applicable to Enscribe applicable to Enscribe
Queue files.)
Queue files.)

4

4

Up to 100

Format 1: ~2 GB – 1
MB

Partition Partial Key
Length

Up to 255 (Not
Up to 255 (Not
Up to 255
applicable to Enscribe applicable to Enscribe
Queue files.)
Queue files.)

Number of Alternate
Key Files
Maximum Partition
Size

~1 TB

~1 TB

~1 TB

~16 TB

~63 TB

~127 TB

Format 2: ~1 TB
Maximum File Size

Format 1: ~32 GB –
16 MB
Format 2: ~16 TB

1

2

3

4

The primary partition of an enhanced key-sequenced file cannot contain user data and is used instead to store a portion
of the file’s label.
Although the maximum number of extents for the primary partition of an EKS files is configurable, in practice DP2 will
never allocate more than 1 extent.
Hewlett Packard Enterprise reserves the right to change this value in the future. The actual extent size will be increased
to the minimum if necessary.
Or limited by the file label space.

IMPORTANT: You might not be able to create key-sequenced files with all possible
combinations of number of secondary partitions, partial key length, and number of alternate keys
because of file label space limitations. For example, if you attempt to create a key-sequenced
file with 15 secondary partitions, 255-byte partial keys, and 100 alternate key files, the file creation
API returns an error 1027, indicating that the file cannot be created because of label restrictions.
To resolve this problem, reduce the number of secondary partitions, partial key length, or the
number of alternate keys.

Creating Key-Sequenced Files

71

Converting a Legacy Key-Sequenced File to an Enhanced Key-Sequenced File
The following scenario is an example where the number of partitions for a customer database is
increased beyond 16 partitions with a reconfiguration of the number of partitions, the number of
extents per partition, and the partition key for the first secondary partition.
A customer application revolves around the use of an Enscribe key-sequenced file with 16
partitions. Over time the number of requestors for the application has increased and I/O on the
key-sequenced file has become a bottleneck. The customer decides to increase the number of
partitions from 16 to 64 in order to provide higher disk I/O throughput and to also increase the
maximum size of the database from approximately 16 GB to approximately 200 GB. The customer
brings down their application, does a backup of the legacy key-sequenced file, then uses FUP
to create a new enhanced key-sequenced file with all attributes like the legacy file except the
following:
Table 10 Converting LKS Files to EKS Files
File Attribute

Legacy Key-Sequenced File

Enhanced Key-Sequenced File

Format Type

2

2

Number of Partitions

16

64

Maximum Number of Extents for the 928
Primary Partition File

16*

Maximum Number of Extents for the 928
Secondary Partition File

928

Primary Extent Size of Primary
Partition (in Pages)

536

28

Secondary Extent Size of Primary
Partition (in Pages)

536

28

Primary Extent Size of all Secondary 536
Partitions (in Pages)

1702

Secondary Extent Size of all
Secondary Partitions (in Pages)

1702

536

Partition Key of First Secondary
“BAAAAAAAAAAAAAA”
Partition (Partition Key Length of 15)**

[0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0]

*The primary partition of an enhanced key-sequenced file does not contain user data and is fixed at 16 maxextents
with a primary extent size of 28 pages. Note that internally only the primary extent of the primary partition is allocated
and used to store the file’s partition array information.
**The partition partial key for the first secondary partition is always a fixed value of all zeroes. In a legacy
key-sequenced file, the primary partition has an implicit partition partial key value of all zeroes and the first secondary
partition has a partial key value greater than all zeroes

Logical Records
A logical record is the unit of information transferred between an application program and the
file system.
When creating a key-sequenced file you must specify the maximum logical record length of that
file. The particular maximum record size that you choose when creating a file depends upon the
particular requirements of your application.

Key-Sequenced Format 1 Files
A logical record can be up to the block-size minus 34 bytes long.

Key-Sequenced Format 2 Files
A logical record can be up to the block-size minus 56 bytes long.
72

Key-Sequenced Files

Using the maximum allowed block size of 4096, the absolute maximum logical record size allowed
for a legacy key-sequenced file is 4062 bytes. Key-sequenced files with increased limits do not
have this 4062 byte limitation. Key-sequenced files with increased limits have a 27,648 byte limit.
The data records that you write to a key-sequenced file can be of varying lengths, but none can
exceed the maximum logical record size specified when the file was created. If you try to write
a record that is longer than the defined maximum record length, the file system rejects the
operation and returns an error 21 (illegal count).

Blocks
A block is the unit of information transferred between the disk process and the disk (or, when
you are using sequential block buffering, between the disk process and the process file segment).
A block consists of one or more logical records and, in the case of key-sequenced files, associated
control information. This control information, which is used only by the system, is summarized
in “Block Formats of Structured Files” (page 172).
The block size of a key-sequenced file with increased limits can be 512 bytes, 1 KB, 2 KB, 4 KB,
or 32 KB.
Regardless of the record length, the maximum number of records that can be stored in a single
block is 511 for a format 1 file. For a format 2 file, it is limited by the block and record sizes.
A record cannot span block boundaries (that is, it cannot begin in one block and end in another).
Therefore, the block size for a key-sequenced file must be at least:
•

record-length + 2 + 32 bytes for format 1 files

•

record-length + 4 + 52 bytes for format 2 files

For key-sequenced files, the disk process requires that the size of the file's index blocks (IBLOCK
parameter of a FUP SET command) and data blocks (BLOCK parameter of a FUP SET command)
be the same. Accordingly, when you are creating a key-sequenced file, the disk process ignores
whatever IBLOCK size you might specify and uses instead (as both the BLOCK and IBLOCK
values) whatever you specify for BLOCK.
When choosing the block size, remember that while longer index blocks require more space in
the cache buffer they can also reduce the number of indexing levels (thereby reducing the number
of accesses to the disk).
The block size of a key-sequenced file should be large in relation to the record size, and especially
so in relation to the key size, to reduce the number of block splits as records are inserted into
the file. Furthermore, a larger data block implies more data records per block and therefore fewer
index records and fewer index blocks.

Disk Extent Size
When you create an Enscribe file, you can specify these:
•

The size of the primary and secondary extents. The primary partition for format 2 files have
a primary extent size greater than or equal to 140 pages. Each secondary partition has its
own primary and secondary extent size. The maximum extent size for a format 2 file is
536,870,912 pages. Format 1 files are restricted to: 1 to 65,535 pages, where a page is
2048 bytes.

•

The maximum number of extents to be allocated for the file (16 or more for a key-sequenced
file or any of its partitions).

•

The system defaults to format 2 if any of the following is true:

◦

Secondary partition is greater than 15

◦

Primary or alternate key size is greater than 255

Creating Key-Sequenced Files

73

◦

Block size is greater than 4 KB

◦

Record size is greater than 4 KB

If you do not specify extent sizes, both the primary and secondary extent sizes default to one
page.
If you do not specify the maximum number of extents, MAXEXTENTS defaults to 16.
For key-sequenced files and any of their partitions, you can change the MAXEXTENTS value
dynamically during program execution using either the SETMODE 92 system procedure or the
FUP ALTER command.

Primary Keys
For key-sequenced files, you must define both the offset from the beginning of the record where
the primary-key field begins and the length of the key field. A few things to consider when choosing
the offset of the primary-key field are:
•

The primary-key field can begin at any offset within a record and can be of any length up to
2048:
$min(record-length minus offset, 2048)

•

If you will be using key compression in data blocks, the primary-key field must reside at the
very beginning of the record.

•

If the primary-key field is the final field in the record, it can be of variable length.

•

If the key field is to be treated as a data type other than STRING, the offset should be
chosen so that the field begins on a word boundary.

Note that the collating sequence by which the records within a key-sequenced file are arranged
is by ASCII code (actually unsigned binary). Consequently, if the data type of the key field is
binary, the presence of the sign bit will cause negative values to be treated as being greater than
positive values.

Key Compression
When creating a file, you can specify that the keys be compressed in data and/or index blocks.
The software compresses keys by eliminating leading characters that are duplicated from one
key to the next and replacing them with a 1-byte count of the duplicate characters. For example,
if these three records are inserted into a file with data compression enabled:
JONES, JANE
JONES, JOHN
JONES, SAM

what is actually written to the disk is:
0JONES, JANE
8OHN
7SAM

where the first character (0, 8, and 7, respectively) indicates the number of leading characters
that are identical to those of the primary key in the immediately preceding record.
When you are creating a file by using FUP, the DCOMPRESS, ICOMPRESS, and COMPRESS
parameters of the SET command designate whether key compression is to be applied to the
data blocks, the index blocks, or both. When you are creating a file by using the FILE_CREATE_
procedure, bits 11 and 12 of the options parameter designate what type of key compression, if
any, is to be used. If you use the FILE_CREATELIST_ procedure, item codes 68 and 69 designate
key compression.

74

Key-Sequenced Files

When deciding whether or not to use key compression, consider these:
•

Key compression can require one additional byte per record. Moreover, key compression
will always require additional system processing to expand the compressed records.

•

Key compression requires that the primary-key field begin at offset [0] of each record.
Consequently, you cannot use variable-length primary keys unless the entire record is the
primary-key field.

•

If there is considerable similarity among the records' primary-key values, then key
compression in data blocks is desirable.

•

If there is enough similarity among records that the first records of successive blocks have
similar primary-key values, then key compression of index blocks is also desirable.

•

Key compression in data blocks is useful for alternate-key files where several alternate keys
tend to have the same value.

Index Compaction
A separate mechanism is also automatically used to make all index records more compact
regardless of whether key compression is in effect. Index compaction differs from key compression
in that it eliminates the trailing portion of similar records, whereas key compression eliminates
the leading portion.
In an index block of a key-sequenced file there is one index record for each block (data or index)
below it in the tree. This index record is formed by comparing the first primary key of the block
with the last primary key of the previous block. If the two keys are identical for the first N bytes,
then the first N + 1 bytes of the block-starting key are used for the index record. For example,
with the four data blocks:
ALLEN, HARRY
ARKIN, ALAN
:
EICHER, DAVE
FRANKLIN, BEN

FRASER, IAN
GAULT, WILLY
:
HAM, JACK
JONES,JANE

JONES, JOHN
KILMER,JOYCE
:
LAINE, LOIS
LANSON,SAM

LARIMER, JO
LORE, KEVIN
:
MAILER, NORM
MARNER, SID

These three index records are actually written to disk:
FRAS
JONES, JO
LAR

File Creation Examples
The pages that follow present annotated examples showing how to create:
1. A key-sequenced file
2. A key-sequenced file with alternate keys
3. A key-sequenced format 2 file with alternate keys
4. An alternate-key file
5. A partitioned key-sequenced file

Example 1: Creating a Key-Sequenced File
This example shows how to create a credit file in which the individual records are to be accessed
by customer name.
The record format is:

Creating Key-Sequenced Files

75

Byte Offset:
34

0
name

134
address

142
current-balance

150
limit

Primary-Key
Field

With a record size of 150, selecting a block size of 2048 results in a blocking factor of 13 data
records per block:
N = (block-size - 32) / (record-size + 2)
13 = ( 2048 - 32) / ( 150 + 2)
If you designate the primary extent size as 5000 pages and the secondary extent size as 2000
pages, then the primary extent will accommodate 65,000 credit records and each secondary
extent will accommodate 26,000 additional credit records. When all 16 extents are eventually
used, the file will accommodate a total of 455,000 credit records.
The primary-key length is 34 bytes.
Assume also that you want to identify the file by the file code 1000 and that you want to enable
key compression for both data and index blocks. You could create the file by using these FUP
commands:
> volume $store1.svol1
> fup
-set type k
-set code 1000
-set ext (5000,2000)
-set rec 150
-set block 2048
-set compress
-set keylen 34
-show
TYPE K
CODE 1000
EXT ( 5000 PAGES, 2000 PAGES )
REC 150
BLOCK 2048
IBLOCK 2048
KEYLEN 34
KEYOFF 0
DCOMPRESS, ICOMPRESS
-create myfile
CREATED - $STORE1.SVOL1.MYFILE

Using the FILE_CREATE_ system procedure, you could create the file by including this TAL
code in one of your application modules.
In this code, the volume name and node name are not specified. FILE_CREATE_ obtains them
from the current value of the VOLUME attribute of the =_DEFAULTS DEFINE. For more
information on the =_DEFAULTS DEFINE, see the TACL Programming Guide.
LITERAL name^length = 12,
pri^extent = 5000,
file^code = 1000,
sec^extent = 2000,
file^type = 3,
options = %30, !data compression
rec^len = 150,
data^block^len = 2048,
key^len = 34,
76

Key-Sequenced Files

key^offset = 0;
INT error;
INT namelen;
STRING .filename [0:name^length-1] :=
"SVOL1.MYFILE";
namelen := name^length;
error := FILE_CREATE_ (filename:name^length, namelen,
file^code, pri^extent, sec^extent,, file^type,
options, rec^len, data^block^len, key^len,
key^offset);
IF Error <> 0 THEN ... ! error

Example 2: Creating a Key-Sequenced File With Alternate Keys
This example shows how to create a key-sequenced inventory control file in which the primary
key is the part number and both the storage location code and vendor number are alternate keys.
Byte Offset:
0

2
partno
Primary-Key
Field

32
descr

40
price

42
avail-qty

46
loc

54
vendor

Alternate-Key
Field LO

Alternate-Key
Field VN

You could create the file by using these FUP commands:
volume $store1.svol1
fup
-set type k
-set code 1001
-set ext (32,8)
-set rec 54
-set block 4096
-set keylen 2
-set altkey ("LO",keyoff 42,keylen 4)
-set altkey ("VN",keyoff 46,keylen 8)
-set altfile (0,invalt)
-show
TYPE K
CODE 1001
EXT ( 32 PAGES, 8 PAGES )
REC 54
BLOCK 4096
IBLOCK 4096
KEYLEN 2
KEYOFF 0
ALTKEY ( "LO", FILE 0, KEYOFF 42, KEYLEN 4 )
ALTKEY ( "VN", FILE 0, KEYOFF 46, KEYLEN 8 )
ALTFILE ( 0, $STORE1.SVOL1.INVALT )
ALTCREATE
-create inv
CREATED - $STORE1.SVOL1.INV
CREATED - $STORE1.SVOL1.INVALT

Using the FILE_CREATELIST_ system procedure, you could create the file by including this TAL
code in one of your application modules.
The volume name, subvolume name, and node name are not specified in the procedure call.
FILE_CREATELIST_ obtains them from the current value of the VOLUME attribute of the
=_DEFAULTS DEFINE.
Creating Key-Sequenced Files

77

?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
LITERAL name^length = 3,
num^altkeys = 2,
num^altkey^files = 1,
item^list^len = 13;
INT error;
INT error2;
INT namelen;
STRING .filename [0:name^length-1] := "INV";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
BEGIN
INT file^type;
INT file^code;
INT rec^len;
INT block^len;
INT key^offset;
INT key^length;
INT pri^extent;
INT sec^extent;
INT altkeys;
STRUCT altkey^descr [0:num^altkeys-1];
BEGIN
STRING key^specifier [0:1];
INT key^length;
INT key^offset;
INT key^filenum;
INT null^value;
INT attributes;
END;
INT num^alt^key^files;
STRUCT name^length^info [0:num^altkey^files-1];
BEGIN
INT file^name^len;
END;
STRING file^names [0:5];
END;
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
ZSYS^VAL^FCREAT^FILECODE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^KEYOFFSET,
ZSYS^VAL^FCREAT^KEYLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^NUMALTKEYS,
ZSYS^VAL^FCREAT^ALTKEYDESC,
ZSYS^VAL^FCREAT^NUMALTKEYFILES,
ZSYS^VAL^FCREAT^ALTFILELEN,
ZSYS^VAL^FCREAT^ALTFILENAMES ];
value^list.file^type := 3;
! key-sequenced
78

Key-Sequenced Files

value^list.file^code := 1001;
value^list.rec^len := 54;
value^list.block^len := 4096;
value^list.key^offset := 0;
value^list.key^length := 2;
value^list.pri^extent := 32;
value^list.sec^extent := 8;
value^list.altkeys := num^altkeys;
value^list.altkey^descr[0].key^specifier ':=' "LO";
value^list.altkey^descr[0].key^length := 4;
value^list.altkey^descr[0].key^offset := 42;
value^list.altkey^descr[0].key^filenum := 0;
value^list.altkey^descr[0].null^value := 0;
value^list.altkey^descr[0].attributes := 0;
value^list.altkey^descr[1].key^specifier ':=' "VN";
value^list.altkey^descr[1].key^length := 8;
value^list.altkey^descr[1].key^offset := 46;
value^list.altkey^descr[1].key^filenum := 0;
value^list.altkey^descr[1].null^value := 0;
value^list.altkey^descr[1].attributes := 0;
value^list.num^alt^key^files := num^altkey^files;
value^list.name^length^info[0].file^name^len := 6;
value^list.file^names ':=' "INVALT";
ERROR := FILE_CREATELIST_ (filename:name^length,namelen,
item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

When you use a system procedure to create your key-sequenced file, you must create your
alternate key files separately. For more information, see Accessing Key- Sequenced
Files“Accessing Key-Sequenced Files” (page 85)

Example 3: Creating a Key-Sequenced Format 2 File With Alternate Keys
This example creates the same file as in “Example 2: Creating a Key-Sequenced File With
Alternate Keys” (page 77), except that it creates a format 2 file.
You could create the file by using these FUP commands:
volume $store1.svol1
fup
-set type k
-set code 1001
-set ext (32,8)
-set format 2
-set rec 54
-set block 4096
-set keylen 2
-set altkey ("LO",keyoff 42,keylen 4)
-set altkey ("VN",keyoff 46,keylen 8)
-set altfile (0,invalt)
-show
TYPE K
FORMAT 2
CODE 1001
EXT ( 32 PAGES, 8 PAGES )
FORMAT 2
REC 54
BLOCK 4096
IBLOCK 4096
KEYLEN 2
KEYOFF 0
ALTKEY ( "LO", FILE 0, KEYOFF 42, KEYLEN 4 )
ALTKEY ( "VN", FILE 0, KEYOFF 46, KEYLEN 8 )
ALTFILE ( 0, $STORE1.SVOL1.INVALT )
Creating Key-Sequenced Files

79

ALTCREATE
-create inv
CREATED - $STORE1.SVOL1.INV
CREATED - $STORE1.SVOL1.INVALT

Using the FILE_CREATELIST_ system procedure, you could create the file by including this TAL
code in one of your application modules.
The volume name, subvolume name, and node name are not specified in the procedure call.
FILE_CREATELIST_ obtains them from the current value of the VOLUME attribute of the
=_DEFAULTS DEFINE.
?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
LITERAL name^length = 3,
num^altkeys = 2,
num^altkey^files = 1,
item^list^len = 14;
INT error;
INT error2;
INT namelen;
STRING .filename [0:name^length-1] := "INV";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
BEGIN
INT file^type;
INT file^code;
INT rec^len;
INT block^len;
INT key^offset;
INT key^length;
INT pri^extent;
INT sec^extent;
INT fileformat; !format 2
INT altkeys;
STRUCT altkey^descr [0:num^altkeys-1];
BEGIN
STRING key^specifier [0:1];
INT key^length;
INT key^offset;
INT key^filenum;
INT null^value;
INT attributes;
END;
INT num^alt^key^files;
STRUCT name^length^info [0:num^altkey^files-1];
BEGIN
INT file^name^len;
END;
STRING file^names [0:5];
END;
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
80

Key-Sequenced Files

ZSYS^VAL^FCREAT^FILECODE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^KEYOFFSET,
ZSYS^VAL^FCREAT^KEYLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^FILEFORMAT, !format 2
ZSYS^VAL^FCREAT^NUMALTKEYS,
ZSYS^VAL^FCREAT^ALTKEYDESC,
ZSYS^VAL^FCREAT^NUMALTKEYFILES,
ZSYS^VAL^FCREAT^ALTFILELEN,
ZSYS^VAL^FCREAT^ALTFILENAMES ];
value^list.file^type := 3; ! key-sequenced
value^list.file^code := 1001;
value^list.rec^len := 54;
value^list.block^len := 4096;
value^list.key^offset := 0;
value^list.key^length := 2;
value^list.pri^extent := 32;
value^list.sec^extent := 8;
value^list.fileformat := 2; !format 2
value^list.altkeys := num^altkeys;
value^list.altkey^descr[0].key^specifier ':=' "LO";
value^list.altkey^descr[0].key^length := 4;
value^list.altkey^descr[0].key^offset := 42;
value^list.altkey^descr[0].key^filenum := 0;
value^list.altkey^descr[0].null^value := 0;
value^list.altkey^descr[0].attributes := 0;
value^list.altkey^descr[1].key^specifier ':=' "VN";
value^list.altkey^descr[1].key^length := 8;
value^list.altkey^descr[1].key^offset := 46;
value^list.altkey^descr[1].key^filenum := 0;
value^list.altkey^descr[1].null^value := 0;
value^list.altkey^descr[1].attributes := 0;
value^list.num^alt^key^files := num^altkey^files;
value^list.name^length^info[0].file^name^len := 6;
value^list.file^names ':=' "INVALT";
ERROR := FILE_CREATELIST_ (filename:name^length,namelen,
item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

When you use a system procedure to create your key-sequenced file, you must create your
alternate key files separately. For more information, see “Accessing Key-Sequenced Files”
(page 85).

Example 4: Creating an Alternate-Key File
When you use FUP to create the primary file, FUP automatically creates any required alternate-key
files. If you create the primary file programmatically, however, you must create the alternate-key
file yourself as a separate operation.
You could create the alternate-key file for “Example 2: Creating a Key-Sequenced File With
Alternate Keys” (page 77) by including this TAL code in one of your application modules.
The volume name, subvolume name, and node name are not specified in the procedure call.
FILE_CREATE_ obtains them from the current value of the VOLUME attribute of the =_DEFAULTS
DEFINE.
LITERAL name^length = 6,
pri^extent = 32,
file^code = 1002,
sec^extent = 8,
file^type = 3,
rec^len = 12,
Creating Key-Sequenced Files

81

data^block^len = 4096,
options = %10, ! data compression
key^len = 12, ! max. alternate key length
! + primary-key length
! + 2
key^offset = 0;
INT error;
INT namelen;
STRING .filename [0:name^length-1] := "INVALT";
namelen := name^length;
error := FILE_CREATE_(filename:name^length, namelen,
file^code, pri^extent, sec^extent,, file^type,
options, rec^len, data^block^len, key^len,
key^offset);
IF Error <> 0 THEN ... ! error

Example 5: Creating a Partitioned, Key-Sequenced File
This example shows how to create a key-sequenced file that will span six partitions. The record
format is the same as in “Example 1: Creating a Key-Sequenced File” (page 75)
Byte Offset:
34

0

134

name

address

142
current-balance

150
limit

Primary-Key
Field

The file is to reside on six volumes and be partitioned in this manner:
name

82

address

region

curbal

limit

ADAMS

MIAMI, FL

SO

0000.00

0500.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

ROGERS

BOISE, ID

WE

1024.00

1500.00

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

Key-Sequenced Files

NOTE: If the file is an enhanced key-sequenced file (with more than 16 partitions), then the
primary partition is reserved for internal configuration information and does not contain data. In
this case, you must set the partition key value for the first secondary partition to zero.
To create the file with FUP, include SET PART commands to describe the partitioning.
> volume $part0.svol1
> fup
-set type k
-set code 1000
-set ext (50,20)
-set rec 150
-set block 4096
-set keylen 34
-set part (1,$part1,50,20,"DA")
-set part (2,$part2,50,20,"HA")
-set part (3,$part3,50,20,"LA")
-set part (4,$part4,50,20,"PA")
-set part (5,$part5,50,20,"TA")
-show
TYPE K
CODE 1000
EXT ( 50 PAGES, 20 PAGES )
PART ( 1, $PART1, 50 PAGES,
PART ( 2, $PART2, 50 PAGES,
PART ( 3, $PART3, 50 PAGES,
PART ( 4, $PART4, 50 PAGES,
PART ( 5, $PART5, 50 PAGES,
REC 150
BLOCK 2048
IBLOCK 2048
KEYLEN 34
KEYOFF 0
-create custfile
CREATED - $PART0.SVOL1.CUSTFILE

20
20
20
20
20

PAGES,
PAGES,
PAGES,
PAGES,
PAGES,

"DA")
"HA")
"LA")
"PA")
"TA")

To create a partitioned file when using the FILE_CREATELIST_ system procedure, place the
partition information into the value array. Place the appropriate value codes into the item list.
This TAL code creates a key-sequenced file partitioned across six volumes:
?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
LITERAL name^length = 26,
num^partitions = 5,
item^list^len = 14;
INT error;
INT error2;
INT namelen;
STRING .filename[0:name^length-1]:=
"\SYS.$PART0.SVOL1.CUSTFILE";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
Creating Key-Sequenced Files

83

BEGIN
INT file^type;
INT file^code;
INT rec^len;
INT block^len;
INT key^offset;
INT key^length;
INT pri^extent;
INT sec^extent;
INT partitions;
STRUCT part^info [0:num^partitions-1];
BEGIN
INT part^pri^extent;
INT part^sec^extent;
END;
STRUCT vol^name^len [0:num^partitions-1];
BEGIN
INT vol^name^act^len;
END;
STRING vol^names [0:29];
INT part^part^key^len;
STRING part^part^key^val [0:9];
END;
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
ZSYS^VAL^FCREAT^FILECODE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^KEYOFFSET,
ZSYS^VAL^FCREAT^KEYLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^NUMPRTNS,
ZSYS^VAL^FCREAT^PRTNDESC,
ZSYS^VAL^FCREAT^PRTNVOLLEN,
ZSYS^VAL^FCREAT^PRTNVOLNAMES,
ZSYS^VAL^FCREAT^PRTNPARTKEYLEN,
ZSYS^VAL^FCREAT^PRTNPARTKEYVAL ];
value^list.file^type := 3;
value^list.file^code := 1000;
value^list.rec^len := 150;
value^list.block^len := 4096;
value^list.key^offset := 0;
value^list.key^length := 34;
value^list.pri^extent := 50;
value^list.sec^extent := 20;
value^list.partitions := 5;
value^list.part^info[0].part^pri^extent := 50;
value^list.part^info[0].part^sec^extent := 20;
value^list.part^info[1].part^pri^extent := 50;
value^list.part^info[1].part^sec^extent := 20;
value^list.part^info[2].part^pri^extent := 50;
value^list.part^info[2].part^sec^extent := 20;
value^list.part^info[3].part^pri^extent := 50;
value^list.part^info[3].part^sec^extent := 20;
value^list.part^info[4].part^pri^extent := 50;
value^list.part^info[4].part^sec^extent := 20;
value^list.vol^name^len.vol^name^act^len[0] := 6;
value^list.vol^name^len.vol^name^act^len[1] := 6;
value^list.vol^name^len.vol^name^act^len[2] := 6;
value^list.vol^name^len.vol^name^act^len[3] := 6;
value^list.vol^name^len.vol^name^act^len[4] := 6;
value^list.vol^names ':=' "$PART1$PART2$PART3$PART4$PART5";
value^list.part^part^key^len := 2;
84

Key-Sequenced Files

value^list.part^part^key^val ':=' "DAHALAPATA";
ERROR := FILE_CREATELIST_ (filename:name^length,namelen,
item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

Byte counts for the values array are listed in the System Procedure Calls Reference Manual.

Accessing Key-Sequenced Files
The following paragraphs discuss the end-of-file pointer and how to access Enscribe
key-sequenced files.

End-of-File (EOF) Pointer
An EOF pointer is associated with each disk file and is shared by all opens of that file. For
key-sequenced files this pointer contains the relative byte address of the byte following the last
(highest address) block that currently contains data. Note that a key-sequenced file can have
empty blocks interspersed among in-use blocks. When you are adding data to a key-sequenced
file, the EOF pointer increments each time a new block is added because there are no empty
blocks.
The system maintains a working copy of the file's EOF pointer in the file control blocks (FCBs)
that are in both the primary and backup system processes that control the associated disk volume.
For Enscribe key-sequenced files, the EOF pointer is physically written to the disk when any of
these events occurs: any file label field is changed, the last accessor closes the file, the
DISK_REFRESH_ system procedure is called for the file or the REFRESH command is executed
for the file's volume.

Sequential Access
You perform sequential processing, in which a related subset of records is read in ascending
order within the current access path, by using the FILE_READ64_, FILE_READLOCK64_, READ
and READLOCK system procedures.
The records comprising a subset are indicated by the file's current positioning mode: approximate,
generic, or exact. A subset can be all or part of a file, or it can be empty. An attempt to read
beyond the last record in a subset, or to read an empty subset, returns an EOF indication.
The first call to FILE_READ64_, FILE_READLOCK64_, READ or READLOCK after a file-opening
or positioning operation reads the record (if any) at the current position. Subsequent calls to
FILE_READ64_, FILE_READLOCK64_, READ or READLOCK, without intermediate positioning,
return successive records (if any) in the designated subset.
After each call to FILE_READ64_, FILE_READLOCK64_, READ or READLOCK, the position of
the returned record becomes the current position.

Random Access
You perform random access processing by using the FILE_READUPDATE64_,
FILE_WRITEUPDATE64_, FILE_READUPDATELOCK64_, FILE_WRITEUPDATEUNLOCK64_,
READUPDATE, WRITEUPDATE, READUPDATELOCK, and WRITEUPDATEUNLOCK system
procedures. The update operation occurs at the record indicated by the current position. Random
processing implies that a record to be updated must exist. Therefore, if no record exists at the
current position (as indicated by an exact match of the current key value with a value in the key
field designated by the current-key specifier), the file system returns error code 11 (record not
found).
You cannot use FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITEUPDATE
or WRITEUPDATEUNLOCK to alter a record's primary key. If you need to do so, you must first

Accessing Key-Sequenced Files

85

delete the record and then reinsert it (using a FILE_WRITE64_/WRITE call) with the new key
value.
If updating or locking is attempted immediately after a call to FILE_SETKEY_ or KEYPOSITION
where a non-unique alternate key is specified, the updating or locking fails with an error 46 (invalid
key). However, if an intermediate call to FILE_READ64_, FILE_READLOCK64_, READ or
READLOCK is performed, then the updating or locking is permitted.

Inserting Records
You perform record insertion by using the FILE_WRITE64_/WRITE system procedure. Insertion
requires that no other record exists with the same primary-key value as the record being inserted.
Therefore, if such a record already exists, the operation fails with an error 10 (record already
exists). If the operation is part of a TMF transaction, the record is locked for the duration of the
transaction.
If an alternate key has been declared to be unique and an attempt is made to insert a record
having a duplicate value in such an alternate-key field, the operation fails with an error 10 (record
already exists).
Insertion of an empty record (where the write count parameter of the FILE_WRITE64_/WRITE
call is zero) is not valid for key-sequenced files.
The length of a record to be inserted must be less than or equal to the record length defined for
the file; if it is not, the insertion fails with an error 21 (invalid count).

Deleting Records
You perform record deletion by using the FILE_WRITEUPDATE64_,
FILE_WRITEUPDATEUNLOCK64_, WRITEUPDATE or WRITEUPDATEUNLOCK system
procedure with a write count of zero. Record deletion always applies to the current position in a
file.

Current Primary-Key Value
A key-sequenced file's current primary-key value is taken from the primary key associated with
the last FILE_READ64_, FILE_READLOCK64_, READ or READLOCK operation or
FILE_SETKEY_ or KEYPOSITION operation by primary key.
After opening a key-sequenced file, but before issuing the first read or FILE_SETKEY_ or
KEYPOSITION call, the current primary-key value is that of the first record in the file.

Access Examples
The access examples throughout the remainder of this section all use the customer record
definition:
Byte Offset:
0

34
name

134
address

Primary-Key
Field

The TAL declaration of a customer record is:
LITERAL name^len = 34,
address^len = 100,
region^len = 2;
86

Key-Sequenced Files

136
region

Alternate-Key
Field RG

144
curbal

152
limit

STRUCT customer^record (*);
BEGIN
STRING cust^name [0:name^len - 1];
! name
STRING cust^address [0:address^len - 1]; ! address
STRING cust^region [0:region^len - 1];
! region
! NO = northern
! SO = southern
! EA = eastern
! WE = western
FIXED (2) cust^curbal; ! current balance
FIXED (2) cust^limit; ! credit limit
END;
STRUCT .cust^rec (customer^record);

The contents of the CUSTOMER file are:
name

address

region

curbal

limit

ADAMS

MIAMI, FL

SO

0000.00

0500.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

ROGERS

BOISE, ID

WE

1024.00

1500.00

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

Example 1: Action of Current Position
This sample TAL code shows how to position by the primary-key value ROGERS:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "ROGERS";
CALL KEYPOSITION ( cust^filenum, key);

Successive read calls will then access the unshaded records in this illustration, in the order
shown:

Accessing Key-Sequenced Files

87

ADAMS

MIAMI, FL

SO

0000.00

0500.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

ROGERS

BOISE, ID

WE

1024.00

1500.00

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

Current Position After
KEYPOSITION Call

This sample TAL code shows how to position by the alternate-key value NO within the RG access
path:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "NO";
CALL KEYPOSITION ( cust^filenum, key, "RG");

Successive read calls will then access the unshaded records in this illustration, in the order
shown:

88

Key-Sequenced Files

Current Position After
KEYPOSITION Call

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

ADAMS

MIAMI, FL

SO

0000.00

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

ROGERS

BOISE, ID

WE

1024.00

1500.00

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

Example 2: Approximate Subset by Primary Key After OPEN
INT error;
INT .cust^filename[0:11],
cust^filenum;
error := FILE_OPEN_(cust^filename:name^length, cust^filenum);
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
CALL READ (cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
...
END;
END;
! read loop

Because no positioning is done between the OPEN call and the read loop, access is by the
primary-key value and starts with the first record in the file. There are 11 data records in the
sample file. The read loop is executed 12 times. The first 11 read calls return data records and
set the condition code to CCE, indicating a successful completion. The twelfth read call returns
no data and sets the condition code to CCG, indicating that the EOF was encountered.
This illustration visually represents the results of each read call executed within the read loop:

Accessing Key-Sequenced Files

89

Primary-Key
Field
1

ADAMS

MIAMI, FL

SO

0000.00

0500.00

2

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

3

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

4

EVANS

BUTTE, MT

WE

0010.00

0100.00

5

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

6

JONES

DALLAS, TX

SO

1234.56

2000.00

7

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

8

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

9

ROGERS

BOISE, ID

WE

1024.00

1500.00

10

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

11

SMITH

DAYTON, OH

NO

0010.00

0500.00

12

EOF

Example 3: Approximate Subset by Alternate Key
This sample TAL code shows how to perform approximate positioning by the alternatekey value
EA within the RG access path:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
! position to the first record that contains EA in the
!
region field
key ':=' "EA";
CALL KEYPOSITION ( cust^filenum, key, "RG" );
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
CALL READ (cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
...
END;
END;
! read loop

90

Key-Sequenced Files

The KEYPOSITION call sets the current position at the first record in the primary data file that
contains the value EA in the region (RG) field. Access is by the alternate-key access path RG.
Successive read calls within the read loop access all of the records in the primary data file that
contain the value EA or greater in the RG field. When two or more records contain the same
value in the RG field, those records are accessed in ascending order by the primary key. In
addition to returning a data record, each read call sets the condition code to CCE, indicating
successful completion.
The final read call in the read loop returns no data and sets the condition code to CCG, indicating
that the EOF was encountered. This illustration visually represents the results of each read call
executed within the read loop.
AlternateKey Field
RG
1

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

2

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

3

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

4

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

5

SMITH

DAYTON, OH

NO

0010.00

0500.00

6

ADAMS

MIAMI, FL

SO

0000.00

0500.00

7

JONES

DALLAS, TX

SO

1234.56

2000.00

8

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

9

EVANS

BUTTE, MT

WE

0010.00

0100.00

10

ROGERS

BOISE, ID

WE

1024.00

1500.00

11

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

12

EOF

Example 4: Generic Subset by Primary Key
This sample TAL code shows how to perform generic positioning by the primary-key value
BROWN:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "BROWN";
compare^len := 5;
generic = 1;
Accessing Key-Sequenced Files

91

CALL KEYPOSITION ( cust^filenum , key , ,
compare^len , generic );
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
CALL READ (cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1 ! end-of-file
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
:
END;
END;
! read loop

The KEYPOSITION call sets the current position at the first record in the primary data file that
contains the value BROWN as the first five characters in the primary-key field. Access is by the
primary-key access path.
Successive read calls within the read loop access all of the records in the primary data file that
contain the value BROWN as the first five characters in the primary-key field. Within that generic
subset, records are accessed in ascending order by the primary key. In addition to returning a
data record, each read call sets the condition code to CCE, indicating successful completion.
The final read call in the read loop returns no data and sets the condition code to CCG, indicating
that the EOF was encountered. This illustration visually represents the results of each read call
executed within the read loop:

Primary-Key
Field
1

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

2

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

3

EOF

Example 5: Exact Subset by Primary Key
This sample TAL code shows how to perform exact positioning by the primary-key value SMITH:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "SMITH";
exact = 2;
CALL KEYPOSITION ( cust^filenum, key, , , exact );
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
CALL READ (cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1 ! end-of-file
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
:

92

Key-Sequenced Files

END;

END;
! read loop

The KEYPOSITION call sets the current position at the first record in the primary data file that
contains the value SMITH as the first five characters in the primary-key field. Access is by the
primary-key access path.
Exact positioning by a primary-key value always gives you access to only one record in the
primary data file: the record at the current position after the KEYPOSITION call.
The read loop is executed twice. The first time through the loop, the read call returns the specified
data record and sets the condition code to CCE, indicating successful completion. The second
time through the loop, the read call returns no data and sets the condition code to CCG, indicating
that the EOF was encountered. This illustration visually represents the results of each read call
executed within the read loop:
Primary-Key
Field
1

2

SMITH

DAYTON, OH

NO

0010.00

0500.00

EOF

Example 6: Generic Subset by Nonentity Alternate Key
This sample TAL code shows how to perform generic positioning by the alternate-key value NO
within the RG access path:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "NO";
generic = 1;
CALL KEYPOSITION ( cust^filenum, key, "RG",, generic );
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
CALL READ (cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1 ! end-of-file
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
:
END;
END; ! read loop

The KEYPOSITION call sets the current position at the first record in the primary data file that
contains the value NO as the first two characters in the region (RG) field. Access is by the
alternate-key access path RG.
Successive read calls within the read loop access all of the records in the primary data file that
contain the value NO as the first two characters in the RG field. Within that generic subset, records
are accessed in ascending order by the primary key. In addition to returning a data record, each
read call sets the condition code to CCE, indicating successful completion.
The final read call in the read loop returns no data and sets the condition code to CCG, indicating
that the EOF was encountered. This illustration visually represents the results of each read call
executed within the read loop:

Accessing Key-Sequenced Files

93

AlternateKey Field
RG
1

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

2

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

3

SMITH

DAYTON, OH

NO

0010.00

0500.00

4

EOF

Example 7: Insertion of a Record Into a Key-Sequenced File
This sample TAL code shows how to insert a new record into a key-sequenced primary data file:
! blank the customer record
cust^rec ':=' " " & cust^rec FOR $LEN(cust^rec) -1 BYTES;
! move the new data into cust^rec
cust^rec.cust^name
cust^rec.cust^address
cust^rec.cust^region
cust^rec.cust^curbal
cust^rec.cust^limit

':='
':='
':='
:=
:=

"HEATHCLIFF";
"PORTLAND, OR.";
"WE";
0.00F;
500.00F;

! write the new record to disk
CALL WRITE (cust^filenum, cust^rec, $LEN(cust^rec) );
IF <> THEN ... ! error

The contents of the customer file after the insertion are:

94

Key-Sequenced Files

name

address

region

curbal

limit

ADAMS

MIAMI, FL

SO

0000.00

0500.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

HEATHCLIFF

PORTLAND, OR

WE

0000.00

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

ROGERS

BOISE, ID

WE

1024.00

1500.00

SANFORD

LOS ANGELES, CA

WE

0301.00

1000.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

Inserted

Example 8: Random Update
This example shows how to select a single data record and then change the content of one of
the fields in that record.
The KEYPOSITION call sets the current position at the record that contains the value HARTLEY
in the primary-key field. The READUPDATE call reads the data record into the application buffer
without altering the file pointers.
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "HARTLEY";
CALL KEYPOSITION (cust^filenum, key);
IF <> THEN ...
CALL READUPDATE (cust^filenum, cust^rec, $LEN(cust^rec) );
IF <> THEN ...

The data record read from the disk file into the application buffer is:

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

This sample TAL code changes the value in the current balance field of the record in the
application buffer and then writes the updated record from the buffer to the disk without altering
the file pointers.
:
cust^rec.cust^curbal := cust^rec.cust^curbal + 30.00F
:

Accessing Key-Sequenced Files

95

CALL WRITEUPDATE (cust^filenum, cust^rec, $LEN(cust^rec) );
IF <> THEN ...

The data record written from the application buffer to the disk file is:

HARTLEY

CHICAGO, IL

NO

0463.29

0500.00

Example 9: Random Update of a Nonexistent Record
This example shows an attempt to update a nonexistent record. Because the KEYPOSITION
procedure does no searching of indexes, the attempt to access the nonexistent record is not
discovered until the subsequent READUPDATE call.
The first four records in the primary data file are:

ADAMS

MIAMI, FL

SO

0000.00

0500.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

1000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

This sample TAL code tries to set the current position at the data record that contains the value
BROWN,C in the primary-key field, and then tries to read that record into the application buffer
in preparation for an update operation:
! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "BROWN,C";
exact := 2;
CALL KEYPOSITION (cust^filenum, key, , , exact );
IF <> THEN ...
CALL READUPDATE (cust^filenum, cust^rec, $LEN(cust^rec) );
IF < THEN
BEGIN
status := FILE_GETINFO_ (cust^filenum, error);
IF error = 11 THEN ... ! record not found
:
END;

The attempt to read the nonexistent record fails with a condition code of CCL and a file-system
error code 11.

Example 10: Sequential Reading via Primary Key With Updating
This sample TAL code changes the content of the limit field to 2000.00 within any data record
whose limit field value is currently >= 1000.00 and < 2000.00:
! position to the first record by primary key
compare^len := 0;
CALL KEYPOSITION ( cust^filenum, key, , compare^len);
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
96

Key-Sequenced Files

CALL READ ( cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1 ! end-of-file
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
IF cust^rec.cust^limit >= 1000.00F
AND cust^rec.cust^limit < 2000.00F THEN
BEGIN
cust^rec.cust^limit := 2000.00F;
CALL WRITEUPDATE
(cust^filenum, cust^rec, $LEN(cust^rec) );
IF < THEN ... ! error
END;
END;
END;
! read loop

This illustration shows the contents of the customer file after all of the applicable records have
been updated:
limit
ADAMS

MIAMI, FL

SO

0000.00

0500.00

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

2000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

HARTLEY

CHICAGO, IL

NO

0463.29

0500.00

HEATHCLIFF

PORTLAND, OR

WE

0000.00

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

RICHARDS

MINNEAPOLIS, MN

NO

0000.00

0500.00

ROGERS

BOISE, ID

WE

1024.00

2000.00

SANFORD

LOS ANGELES, CA

WE

0301.00

2000.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

Changed Fields

Example 11: Deleting a Record
This example shows how to select and delete the data record whose primary-key value is EVANS.
This illustration shows the contents of the applicable portion of the customer file before the
deletion:

Accessing Key-Sequenced Files

97

BROWN, B

BOSTON, MA

EA

0301.00

2000.00

EVANS

BUTTE, MT

WE

0010.00

0100.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

! blank the key
key ':=' " ";
key[1] ':=' key FOR name^len - 1 BYTES;
key ':=' "EVANS";
CALL KEYPOSITION (cust^filenum, key);
CALL WRITEUPDATE (cust^filenum, cust^rec , 0);
IF <> THEN ... ! error

This illustration shows the contents of the applicable portion of the customer file after the deletion:
BROWN, B

BOSTON, MA

EA

0301.00

2000.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

Example 12: Sequential Reading With Deletions Using Primary Key
This sample TAL code reads the customer file sequentially by primary-key value and deletes
any records whose current balance field contains 0.00:
! position to the first record by primary key
compare^len := 0;
CALL KEYPOSITION ( cust^filenum, key, , compare^len);
cust^eof := 0;
WHILE NOT cust^eof DO
BEGIN ! read loop
CALL READ ( cust^filenum, cust^rec, $LEN(cust^rec) );
IF > THEN cust^eof := 1 ! end-of-file
ELSE
IF < THEN ... ! error
ELSE
BEGIN ! process the record
IF cust^rec.cust^curbal = 0.00F THEN
BEGIN
CALL WRITEUPDATE ( cust^filenum, cust^rec, 0 );
IF < THEN ... ! error
:
END;
END;
END;
! read loop

This illustration shows the contents of the customer file after all of the applicable records have
been deleted:

98

Key-Sequenced Files

BROWN, A

REEDLEY, CA

WE

0256.95

0300.00

BROWN, B

BOSTON, MA

EA

0301.00

2000.00

HARTLEY

CHICAGO, IL

NO

0433.29

0500.00

JONES

DALLAS, TX

SO

1234.56

2000.00

KOTTER

NEW YORK, NY

EA

0089.00

0500.00

ROGERS

BOISE, ID

WE

1024.00

2000.00

SANFORD

LOS ANGELES, CA

WE

0301.00

2000.00

SMITH

DAYTON, OH

NO

0010.00

0500.00

Example 13: Relational Processing
This example illustrates relational processing in which fields from records in one file are used to
access data records in other files.
The example uses four files:
•

The same customer file used in Examples 1 through 12

•

An order file

•

An order detail file

•

An inventory file

The format of an order record is:
Byte Offset:
0

2

38

46

orderno

name

date

Primary-Key
Field

Alternate-Key
Field NA

Alternate-Key
Field DT

54
total

The TAL definition of an order record is:
LITERAL name^len = 36,
date^len = 8;
STRUCT order^struct (*);
BEGIN
FIXED(2) order^orderno;
STRING order^name [0:name^len - 1];
STRING order^date [0:date^len - 1];
FIXED(2) order^total;
END;

! order record
!
!
!
!
!
!
!
!

order number
name
date
total = 0 means
order not filled;
total <> 0 means
order filled but
not shipped

STRUCT .order (order^struct);

The contents of the order file are:
Accessing Key-Sequenced Files

99

orderno

name

date

total

0020

SMITH

95/09/30

0000.00

0021

JONES

95/10/01

0000.00

0176

BROWN, B

95/10/17

0000.00

0410

SANFORD

95/10/22

0000.00

0498

ROGERS

95/11/02

0000.00

0601

SMITH

95/11/08

0000.00

0622

HARTLEY

95/11/12

0000.00

0623

KOTTER

95/11/12

0000.00

The format of an order detail record is:
Byte Offset:
0

2
orderno

4
itemno

Primary-Key
Field

6
partno

8
qty

16
itemtot

Alternate-Key
Field PN

The TAL definition of an order detail record is:
STRUCT order^detail^struct (*); ! order detail record
BEGIN
FIXED(2) orderdet^orderno;
! order number
FIXED(2) orderdet^itemno;
! item number
FIXED(2) orderdet^partno;
! part number
FIXED(2) orderdet^itemtot;
! total=0 means item
END;
! not available
STRUCT .orderdet (order^detail^struct);

The contents of the order detail file are:

100 Key-Sequenced Files

orderno

itemno

partno

qty

itemtot

0020

0001

23167

00002

0000.00

0020

0002

02010

00001

0000.00

0020

0003

12950

00005

0000.00

0021

0001

00512

00022

0000.00

0021

0002

23167

00001

0000.00

0176

0001

32767

00001

0000.00

0410

0001

01234

00010

0000.00

0410

0002

03379

00010

0000.00

00010

0000.00

•

0623

0012

•

•

01234

The format of an inventory record is:
Byte Offset:
0

2
partno

32
descr

40
price

Primary-Key
Field

42
availqty

46
loc

54
vendor

Alternate-Key Alternate-Key Primary-Key
Field AQ
Field LO
Field VN

The TAL definition of an inventory record is:
LITERAL descr^len = 30,
loc^len = 4,
vendor^len = 8;
STRUCT inventory^struct (*);
!
BEGIN
FIXED(2) inv^partno;
!
STRING inv^descr [0:descr^len - 1]; !
FIXED(2) inv^price; ! price
FIXED(2) inv^availqty;
!
STRING inv^loc [0:loc^len - 1];
!
STRING inv^vendor [0:vendor^len - 1];!
END;

inventory record
part number
description
available quantity
location
vendor

STRUCT .inv (inventory^struct);

Accessing Key-Sequenced Files 101

The contents of the inventory file are:
partno

descr

price

availqty

loc

vendor

00002

HI-FI

0129.95

00050

A01

TAYLOR

00512

RADIO

0010.98

00022

G10

GRAND

00987

TV SET

0200.00

00122

A76

TAYLOR

02010

TOASTER

0022.50

00000

F22

ACME

03379

CLOCK

0011.75

00512

A32

ZARF

12950

TOASTER

0020.45

00010

C98

SMYTHE

20211

WASHER

0314.29

00005

B44

SOAPY

•

•

•

23167

ANTENNA

0022.50

00008

A01

TAYLOR

32767

IRON

0025.95

00051

A82

HOT

65535

DRYER

0299.50

00022

Z02

SOAPY

The sample TAL code shown later in this example finds all of the orders that are more than one
month old and then fills those orders; the code does so in five steps:
1. Using the date alternate-key field, read a record from the order file. The read loop terminates
upon encountering a record whose date field contains a value greater than or equal to a
specified order^limit date.
2. Using the name from the order record, read the appropriate customer record from the
customer file. Using information from both the order record and the customer record, print
an order header consisting of the order number and the customer name and address.
3. Using the order number from the order record, read the associated generic subset from the
order detail file.
4. Each record in the order detail file represents one line item. For each line item in the
appropriate generic subset, use the part number from the order detail record to read and
update the appropriate inventory record in the inventory file; then update the order detail
record and print the line item.
5. After all of the line items for the current order have been processed, update the total field of
the order record to reflect the total price of the order. Using the name from the order record,
update the current balance field in the appropriate customer record. Print the order total.
The sample TAL code is:
! position to beginning of file via date field
compare^len := 0;
CALL KEYPOSITION (order^filenum, key, "DT", compare^len);
order^eof := 0;
WHILE NOT order^eof DO
BEGIN ! reading order file via date field
102 Key-Sequenced Files

CALL READ (order^filenum, order, $LEN(order) );
IF > OR order.order^date >= limit^date THEN order^eof :=1
ELSE
BEGIN ! fill order
! read customer file
CALL KEYPOSITION (cust^filenum, order.order^name);
CALL READUPDATE (cust^filenum,cust^rec,
$LEN(cust^rec) );
! print the order header
! read order detail file for current order
compare^len := 2;
generic := 1;
CALL KEYPOSITION (orderdet^filenum,
order.order^orderno, , compare^len, generic);
orderdet^eof := 0;
WHILE NOT orderdet^eof DO
BEGIN
! read line item
CALL READ
(orderdet^filenum, orderdet,
$LEN(orderdet) );
IF > THEN orderdet^eof := 1
ELSE
BEGIN
CALL KEYPOSITION (inv^filenum,
orderdet.orderdet^partno);
CALL READUPDATE (inv^filenum, inv,
$LEN(inv) );
: ! update the inventory record
CALL WRITEUPDATE (inv^filenum, inv,
$LEN(inv) );
: ! update the order detail record
CALL WRITEUPDATE (orderdet^filenum,
orderdet, $LEN(orderdet) );
! print the line item
END;
END;
: ! update the order record
CALL WRITEUPDATE (order^filenum, order,
$LEN(order) );
: ! update the customer record
CALL WRITEUPDATE (cust^filenum, cust^rec,
$LEN(cust^rec) );
: ! print the total
END; ! of fill order
END; ! reading order file via date field

The records used for filling the first order are:
From the order file:

0020

SMITH

95/09/30

0000.00

From the customer file:

SMITH

DAYTON, OH

NO

0010.00

0500.00

Accessing Key-Sequenced Files 103

From the order detail file:

0020

0001

23167

00002

0000.00

0020

0002

02010

00001

0000.00

0020

0003

12950

00005

0000.00

From the inventory file:

23167

ANTENNA

0022.50

00008

A01

TAYLOR

02010

TOASTER

0022.50

00000

F22

ACME

12950

TOASTER

0020.45

00010

C98

SMYTHE

The following are the contents of those same records after filling the first order. In the order file:

0020

SMITH

95/09/30

0147.25

In the customer file:

SMITH

DAYTON, OH

NO

0157.25

0500.00

In the order detail file:

0020

0001

23167

00000

0045.00

0020

0002

02010

00001

0000.00

0020

0003

12950

00000

0102.25

Line Item not Filled (Put on Back-Order)

In the inventory file:

104 Key-Sequenced Files

23167

ANTENNA

0022.50

00006

A01

TAYLOR

02010

TOASTER

0022.50

00000

F22

ACME

12950

TOASTER

0020.45

00005

C98

SMYTHE

No Changes

Accessing Key-Sequenced Files 105

7 Queue Files
Enscribe Queue Files
An Enscribe queue file is a special type of key-sequenced disk file that can function as a queue.
Processes can queue and dequeue records in a queue file.
Queue files contain variable-length records that are accessed by values in designated key fields.
Unlike other key-sequenced files, queue files have primary keys but cannot have alternate keys.
The primary key for a queue file includes an 8–byte timestamp; you can add a user key if desired.
The disk processes inserts the timestamp when each record in inserted into the file and maintains
the timestamp during subsequent file operations.
Queue files provide these features:
•

Access by multiple requester or queuing processes, with multiple servers or dequeuing
processes allowed. Queue files are typically shared between multiple write processes and
one read process, and are typically used for fairly low volume work.
CAUTION: All waiting readers are dispatched for every transaction or queue read. Use
of queue files with multiple sub-queues can cause high utilization of CPU resources by the
disk process and significantly affect performance.

•

Protection against data loss with TMF. TMF is the main functional component of the TM/MP
product.

•

Flexible record ordering and selection; records can be prioritized; classed, or grouped as
needed by an application; the default ordering is approximately first-in first-out (using the
timestamp as the primary key).

•

Record-level locking to prevent incomplete information from being accessed and to ensure
that only one reader dequeues a specific record.

•

Notification when new records are added to the file.

These restrictions apply to queue files:
•

Queue files cannot be SQL objects.

•

You cannot define alternate keys or partitions for queue files.

The first part of this section describes queue file structure and discusses how to access queue
files. The remainder of the section contains examples showing how to create, open, and access
queue files.
NOTE: Enscribe queue files should not be confused with Queue Manager queue files as
described in the Queue Manager Manual. Despite the similarity in their names, they are entirely
different types of files.

Applicable System Procedures
Use these system procedures to create and access Enscribe queue files:
•

FILE_CREATE_, FILE_CREATELIST_, CREATE

•

FILE_OPEN_, FILE_CLOSE_, AWAITIO[X], FILE_AWAITIO64_

•

FILE_SETKEY_, FILE_SAVEPOSITION_, FILE_RESTOREPOSITION_, KEYPOSITION,
SAVEPOSITION, REPOSITION

•

FILE_READ64_, FILE_READLOCK64_, FILE_READUPDATE64_,
FILE_READUPDATELOCK64_, READ[X], READLOCK[X], READUPDATE[X],
READUPDATELOCK[X]

106 Queue Files

•

FILE_WRITE64_, WRITE[X]

•

FILE_GETINFO_, FILE_GETINFOLIST_, FILE_GETINFOBYNAME_,
FILE_GETINFOLISTBYNAME_

Types of Access
Like key-sequenced files, queue files can be accessed by applications either sequentially or
randomly.

Queue File Structure
Queue files are physically organized as one or more bit-map blocks and a B-tree structure of
index and data blocks. Organization is the same as for key-sequenced files, described in
“Key-Sequenced Files” (page 67). Queue files are distinguished from other key-sequenced files
by having item 48 of the FILE_GETINFOLIST_procedure set to 1. The superseded FILEINFO
procedure has bit 9 set in the file-type word if the file is a queue file.

Primary Keys
Each record in a queue file consists of a primary key and data. At a minimum, the primary key
consists of an 8–byte timestamp generated by the disk process when a record is inserted in the
file. In addition, you can define a user key that precedes the timestamp within the primary key.
The disk process maintains the timestamp as part of each record. This ensures that each record
has a unique key and it eliminates the need to use an application-defined key for insertion or
deletion of records. When you read a record from a queue file, the timestamp is part of the
returned data. When you write a record, the disk process places the timestamp in the low-order
eight bytes of the key, overwriting any information stored in those bytes.
Although you do not need to maintain or use the timestamp portion of the key, you do not need
to specify the eight bytes when you create the file. Thus, all key lengths must be defined as at
least eight bytes long. If you do not define a user key, the data begins at the eighth byte. If you
do supply a user key, it precedes the timestamp. The data begins at the length of your key plus
eight bytes. (For more information, see “Creating Queue Files” (page 107)
Figure 15 (page 107) shows the format of each physical record.
Figure 15 Queue File Record Format
User key
(optional)

Timestamp
(8 bytes)

Data

Creating Queue Files
To create a queue file, use the File Utility Program (FUP) or call the FILE_CREATE_ or
FILE_CREATELIST_ procedure. You cannot define partitions or alternate keys for queue files.
When you create a queue file, be sure to leave room for the 8–byte timestamp in the key. If you
do not need a user-defined key, specify a key length of eight bytes for the file. Otherwise, specify
the length of your key plus eight bytes. In addition, leave room for the 8–byte key in your record
length definition.
The key offset value must equal zero. You can omit the key specifier designation; however, if
you set it, it must equal zero.
When you create an Enscribe queue file, you can specify the size of the primary and secondary
extends. Format 1 files can have from 1 through 65,535 pages (where a page is 2048 bytes).
Format 2 files can have from 1 through 536,870,912 pages.

Types of Access 107

Queue File Examples
These examples illustrate the three different ways to create queue files.

Example 1: Creating a Queue File with FUP
This example shows how you might use FUP to create a queue file:
10> FUP
- SET TYPE K
- SET CODE 1001
- SET QUEUEFILE
- SET EXT (20,10)
- SET MAXEXTENTS 64
- SET KEYLEN 10
- SET REC 100
- SET AUDIT
- CREATE QFILE
- EXIT
>

Example 2: Creating a Queue File With the FILE_CREATE_Procedure
This TAL example creates a queue file using the FILE_CREATE_Procedure. The nod name is
snot specified in the procedure call, so FILE_CREATE_ obtains the node name from the current
value of the VOLUME attribute of the =_DEFAULTS DEFINE. For more information on the
=_DEFAULTS DEFINE, see the TACL Programming Guide.
STRING .QF^Name[0:33] := "$spool.lst.qfile"; ! File name
LITERAL QF^NameLength = 16;
! Length in
! bytes of file name
INT QF^NameLen;
LITERAL Key^Length = 8;
! Key length
! (must be >= 8)
INT Key^Len;
STRING .Key[0:Key^Length - 8];
! Application key
LITERAL Rec^Len = 100;
! Record length
INT Error;
! Returned error code
?SOURCE $SYSTEM.SYSTEM.EXTDECS0
(FILE_CREATE_,FILE_CREATELIST_)
QF^NameLen := QF^NameLength;
Key^Len := Key^Length;
Error := FILE_CREATE_(
QF^Name:34,
QF^NameLen,
1001,
20,
10,
64,
3,
%000102,
Rec^Len,
4096,
Key^Len,
0);
IF Error <> 0 THEN ...

!
!
!
!
!
!
!
!
!
!
!
!

filename:maxlen
filenamelen
filecode
primary-extent-size
secondary-extent-size
maximum-extents
file-type (key-sequenced)
options (queue file, audited)
recordlen
blocklen
keylen
key-offset (must be zero)
! error

Example 3: Creating a Queue File With the FILE_CREATELIST_ Procedure
This example creates a queue file using the FILE_CREATELIST_procedure:
! Create a Queue File with FILE_CREATELIST_
STRING .QF^Name[0:33] := "$spool.lst.qfile";
! File name
LITERAL QF^NameLength = 16;
! Length in
! bytes of file name
108 Queue Files

INT QF^NameLen;
LITERAL Key^Length = 8;

! Key length
! (must be >= 8)

INT Key^Len;
STRING .Key[0:Key^Length - 8];
! Application key
LITERAL Rec^Len = 100;
! Record length
INT Items[0:20];
! Attribute numbers
INT Value[0:40];
! Attribute values
INT Error;
! Returned error code
INT Error^Item;
! Returned item-in-error
?SOURCE $SYSTEM.SYSTEM.EXTDECS0
(FILE_CREATE_,FILE_CREATELIST_)
QF^NameLen := QF^NameLength;
Key^Len := Key^Length;
Items[ 0] := 41;
! File type
Value[ 0] := 3;
! = key-sequenced
Items[ 1] := 42;
! File code
Value[ 1] := 1001;
! = 1001
Items[ 2] := 43;
! Logical record length
Value[ 2] := Rec^Len;
! = Rec^Len
Items[ 3] := 44;
! Block length
Value[ 3] := 4096;
! = 4K
Items[ 4] := 45;
! Key offset
Value[ 4] := 0;
! = 0 (unconditional for queue files)
Items[ 5] := 46;
! Key length
Value[ 5] := Key^Len;
! = Key^Len
Items[ 6] := 48;
! Queue File opt. (can also use #71)
Value[ 6] := 1;
! = this is a Queue File
Items[ 7] := 50;
! Primary extent size
Value[ 7] := 20;
! = 20 pages
Items[ 8] := 51;
! Secondary extent size
Value[ 8] := 10;
! = 10 pages
Items[ 9] := 52;
! Maximum extents
Value[ 9] := 64;
! = 64 extents
Items[10] := 66;
! Audited file
Value[10] := 1;
! = audit this file
Items[11] := 67;
! Audit compression
Value[11] := 1;
! = audit compression (can be 0)
Items[12] := 68;
! Data compression
Value[12] := 0;
! = no data compression (can be 1)
Items[13] := 69;
! Index compression
Value[13] := 0;
! = no index compression (can be 1)
Error := FILE_CREATELIST_(
QF^Name:34,
QF^NameLen,
Items,
14,
Value,
28,
Error^Item);
IF Error <> 0 THEN ...

!
!
!
!
!
!
!

filename:maxlen
filenamelen
item-list
number-of-items
values
values-length in bytes
returned error-item
! error

Accessing Queue Files
Read and write operations to and from queue files differ from that of other key-sequenced files.
A write operation is called a queuing operation. When you access a queue file, a read operation
typically deletes the record from the file. This operation is called a dequeuing operation. To
dequeue a record, use the FILE_READUPDATELOCK64_/READUPDATELOCK[X] procedure.
You can also read a record without deleting it; to do this, use the FILE_READ64_/READ[X]
procedure.

Accessing Queue Files 109

Specifying Sync-Depth
When you open a queue file, you can specify a sync depth for the file. A non zero sync depth is
supported for all operations except for dequeuing; the sync depth for dequeuing operation must
equal zero.
If you specify a sync depth that I snot equal to zero for any operation other than dequeuing, the
file system attempts to recover from path-related errors (200, 201, 210, and 211). If you specify
a sync depth of zero, no path-related recovery is done and the application is responsible for
responding to path-related error conditions.
Because of the protection a nonzero sync depth provides, it is generally recommended that a
sync depth of one be used for all operations except dequeuing. This implies that multiple opens
need to be done for a queue file that is used simultaneously by the same process for enqueuing
and dequeuing operations if nonzero sync depth protection is desired. For more information
about recovery of retryable errors on queue files, see Communication Path Errors “Communication
Path Errors” (page 120).

Queuing a Record
To queue a record, call the FILE_WRITE64_/WRITE[X] procedure to write the record to the file.
The disk process sets the timestamp field in the key, which causes the record to be positioned
after other existing records that have the same high-order user key.
If the file is audited, the new record is available for read operations when the transaction associated
with the write operation commits. If the transaction aborts, the record is never available to read
operations.
If the file is not audited, the record is available as soon as the write operation completes
successfully.
Unlike other key-sequenced files, a write operation to a queue file will never encounter an error
10 (Duplicate record). This is because all queue file records have unique keys generated for
them.

Special “Dummy” Record
When the first record is written to a queue file, the disk process inserts a special dummy record
containing all zeros at the front of the file. This record ensures that the file never becomes empty,
avoiding the overhead of collapsing the file and then expanding it whenever the last record is
dequeued.
The dummy record is never dequeued through
FILE_READUPDATELOCK64_/READUPDATELOCK[X]. However, the record is visible under
these circumstances:
•

A FILE_READ64_, FILE_READLOCK64_, READ[X] or READLOCK[X] operation returns
the dummy record.

•

The command FUP INFO filename, STAT indicates that the record exists.

•

The command FUP COPY filename, newlife causes the dummy record to become a record
that can be dequeued by FILE_READUPDATELOCK64_/READUPDATELOCK[X].
Consequently, you should be careful using the FUP COPY command on queue files.

Dequeuing a Record
To dequeue a record, call the FILE_READUPDATELOCK64_/READUPDATELOCK[X] procedure.
If the read operation is successful, the disk process deletes the record from the file. If the disk
process cannot return a record because the file is empty or there are no unlocked records which
meet the selection criteria, the disk process retains the request until the file contains a record
that fits the request.

110

Queue Files

To read a record with the FILE_READUPDATELOCK64_/READUPDATELOCK[X] procedure,
these requirements must be met:
•

An application must have write access to the file.

•

The sync depth must be zero.

•

The record must not be locked.

•

The record must satisfy any key comparison rules defined by a prior call to the KEYPOSITION
procedure. (For more information about positioning, see Dequeuing With
Positioning“Dequeuing With Positioning” (page 113).)

The disk process skips over locked records until it reaches an unlocked record that satisfies the
record selection rules. The record selection rules are specified by the last invocation of
FILE_SETKEY_or KEYPOSITION. If the application does not call either of these procedures,
the disk process considers that all records in the file meet the selection rules. For more information,
refer to Dequeuing With Positioning“Dequeuing With Positioning” (page 113).
Records whose user keys are identical for the requested compare length are extracted according
to the timestamp generated at the time of insertion. The order of extraction may not be sequential
if locked records are encountered. Because each record is deleted after it is read, subsequent
calls to FILE_READUPDATELOCK64_/READUPDATELOCK[X] will reposition to the beginning
of the range of records which satisfies the selection rules.
The current primary-key value is not updated after the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation.

Example
Figure 16 (page 111) shows how two processes might access a queue file. If process A attempts
to dequeue a record while the file is empty, the process waits until the file contains a record.
Figure 16 Dequeuing a Record
Process A

Process B

Gets Record "1000"

READUPDATELOCK
READUPDATELOCK

File is Empty
(request queued)

WRITE:
Record "1001" inserted

Disk process returns record "1001"

The insertion of a new record causes the waiting Process A to be awakened and presented with
the new record.

Dequeuing From Audited Files
If the queue file is audited, the FILE_READUPDATELOCK64_/READUPDATELOCK[X] procedure
must be called from within a transaction. An application should commit the transaction only after
it processes the data it has extracted from the file, since the

Accessing Queue Files

111

FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation causes the record to be
deleted from the file.
If a transaction that is associated with a dequeue request aborts, the disk process reinserts the
record at the same logical location from which it came. The abort operation also awakens any
processes waiting to dequeue a record from the file.
If the read operation is not successful because the file is empty or all records are locked, the disk
process retains the request and waits until one of these events occurs:
•

The disk process waits until a transaction completes that includes insertion of a record.
When the new record is available, the disk process retries the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation. Note that either of these
can make a record available:

◦

A transaction that commits after inserting a record

◦

A transaction that aborts after dequeuing a record

◦

If a special queue-file timeout on the read operation expires, the disk process returns
an error 162 (operation timed out) to the requesting process.

One exception is the use of exact positioning. If the application requests exact positioning and
the file is empty or the record does not exist, the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation receives an error 11 (record
not found) and does not queue the request.
Generally, errors (other than operation timed out) on a
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation should be handled like errors
on normal write operations. That is, the transaction should be aborted.
Note the behavior of queue files when generic locking is used. If the lock key-length of a queue
file is less than the actual key length, the disk process will perform generic locking on inserted
records. Inserting a record when generic locking is enforced will lock existing records that have
the same key for the lock key-length. This prevents existing records with the matching generic
key from being dequeued until the encompassing transaction completes.

Impact of Records Causing Data Errors
When using audited queue files, there is an additional consideration for error processing. If a
dequeuing operation returns a bad record that causes the application to abort the transaction,
the bad record is reinserted into the file.
Consider the case where a transaction is started, a record is dequeued, and the contents of the
data returned to the application causes it to abort the transaction (either due to a programmatic
abort or process failure). The abort operation causes the bad record to be reinserted into the
queue file. If the application performs another dequeue operation, it retrieves the same record
and could possibly abort again.
Although this might not cause difficulties, the application would not progress past the bad record.
To avoid this situation, validate record contents prior to processing data.
This problem only affects audited operations; in the unaudited case, the bad record is not
reinserted into the file, but is lost.

Dequeuing Records and Nowait I/O
If the time limit expires prior to the queue file timeout, the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] request is canceled if it was a file-specific
call (that is, the file number is other than -1). With non file-specific calls,
FILE_READUPDATELOCK64_/READUPDATELOCK[X] is not canceled for the queue file. A
canceled FILE_READUPDATELOCK64_/READUPDATELOCK[X] can result in the loss of a

112

Queue Files

record from the queue file. This problem is particularly acute for queue files, since a dequeuing
operation can be delayed until the file contains a record that fits the request.
For audited queue files only, your application can recover from a timeout error by calling the
ABORTTRANSACTION procedure to ensure that any dequeued records are reinserted into the
file. The corresponding transaction must then be restarted.
NOTE: For unaudited queue files, your application should never call
AWAITIO[X]/FILE_AWAITIO64_ with a time limit greater than OD if a
READUPDATELOCK[X]/FILE_READUPDATELOCK64_ is pending. The recovery procedure
described above does not work on unaudited queue files.

Dequeuing From Unaudited Files
If the read operation is not successful because the file is empty or all records are locked, the
read is suspended until one of these events occurs:
•

The disk process waits until a FILE_WRITE64_/WRITE[X] operation completes successfully.

•

If a special queue file timeout on the read operation expires, the disk process returns an
error 162 (operation timed out) to the requesting process.

As with audited files, one exception is the use of exact positioning. If the application requests
exact positioning and the file is empty or the record does not exist, the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation receives an error 11 (record
not found) and does not queue the request.

Examining a Record
To read a record without deleting it, use the FILE_READ64_, FILE_READLOCK64_, READ[X]
or READLOCK[X] procedures. These procedures function exactly the same as when used for a
key-sequenced file. Note, however, that FILE_READ64_, FILE_READLOCK64_, READ[X] and
READLOCK[X] differ from FILE_READUPDATELOCK64_/READUPDATELOCK[X] in these
ways:
•

The disk process does not delete a record after reading it

•

If no record is available, the request is not retained and the disk process returns an error 1
(EOF)

•

A read operation returns the entire record, including the 8-byte timestamp. To delete the
record after examining it, use exact positioning and then call the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] procedure.

Dequeuing With Positioning
To change the access path and positioning dynamically, you can precede calls to
FILE_READUPDATELOCK64_/READUPDATELOCK[X] with a call to FILE_SETKEY_ or
KEYPOSITION. This method allows an application to move to a random position in the file,
establish a subset of records to be retrieved, and apply other selection rules according to the
specified parameters.
The disk process does not dequeue locked records. Locked records which exist within the desired
key range are skipped until an unlocked record is found or the key in a record is outside of the
desired range.

Approximate Positioning
Figure 17 (page 114) illustrates how approximate positioning works for a queue file when the call
to FILE_SETKEY_ (or equivalent call to KEYPOSITION) has these parameters:
key-value = "MA"
positioningmode = 0
comparelength is omitted = 2
Accessing Queue Files

113

The queue file has a key length of 10 bytes, so the user key length is 2 bytes.
Figure 17 Using Approximate Positioning With a Queue File
Process A

READUPDATELOCK
READUPDATELOCK

Process B

Get Record "MB1000"
File is Empty
(request is retained)

WRITE:
Record "MA1001" inserted

Disk process returns record "MA1001"
READUPDATELOCK

File is Empty
(request is retained)

WRITE:
Record "AA1002" inserted

(request is retained)

This example shows two special actions of the queue file, compared to a standard key-sequenced
file:
•

The second READUPDATELOCK call retrieved a record whose key was less than that in
the record previously retrieved. This behavior is different than that of an ordinary
key-sequenced file.

•

The second insertion in the file (key = “AA”) does not cause process A to be awakened,
because the key of the inserted record does not match the selection criteria established by
the KEYPOSITION call.

Generic Positioning
Figure 18 (page 115) illustrates how approximate positioning works for a queue file when the call
to FILE_SETKEY_ (or equivalent call to KEYPOSITION) has these parameters:
key-value = "TA"
comparelength = 2
key-value-len = 2
positioningmode = 1

The queue file has a key length of 10 bytes, so the user key length is 2 bytes.

114

Queue Files

Figure 18 Using Generic Positioning With a Queue File
Process
B

Process
A
READUPDATELOCK
READUPDATELOCK

Get Record "TA1000"
File is Empty
(request is retained)

WRITE:
Record "TA1001" inserted

Disk process returns record "TA1001"
READUPDATELOCK

File is Empty
(request is retained)
WRITE:
Record "TB1002" inserted
(request is retained)

WRITE:
Record "TA1003" inserted

Disk process returns record "TA1003"
READUPDATELOCK

File is Empty
(request is retained)

Note that the second insertion does not cause Process A to be awakened, because the user key
in the new record does not satisfy the key selection criteria. The third insertion does satisfy the
criteria, however, so the disk process returns the record to Process A and reawakens Process
A.
This example also illustrates how an application could use multiple servers or dequeuing processes
to read from the same file. Each server could access a subset of the file as designated by the
high-order field of the primary key (in this case, records with “TA” in the high-order key are being
dequeued by process A). In this manner, the high-order key file can be used to logically partition
the file across multiple servers.
The high-order key field can also be used to specify relative priority of a queued record. Records
with smaller valued keys are positioned before those of higher values. Thus, a server that always
reads from the start of the file will dequeue records in ascending key order. This permits
prioritization of records within the Queue File.

Exact Positioning
The use of exact positioning is not typical for queue files, since applications usually access queue
files in a specified order rather than by exact key value. You can, however, use exact positioning
for a queue file. For example, you might use the FILE_READ64_/READ[X] procedure to access
specific records within the file without changing their placement in the queue file, and then delete
specific records after examining them.

Accessing Queue Files

115

Using the Current Key
The current key for a queue file has meaning only after a FILE_READ64_/READ[X] operation.
Unlike standard key-sequenced files, you cannot assume the current key is accurate after the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation.
This behavior affects the operation of the FILE_GETINFOLIST_ and FILERECINFO operations.
The FILE_GETINFOLIST_ procedure does not return a meaningful current key value after a
FILE_WRITE64_, WRITE[X], FILE_READUPDATELOCK64_ or READUPDATELOCK[X] operation.
It can, however, return a current key value after a FILE_READ64_/READ[X] operation. The
FILERECINFO procedure does not return the current key value for queue files.

Specifying Timeout Periods
To specify a timeout period for read operations on queue files, use SETMODE function 128.
Otherwise, a default timeout period of 60 seconds applies. The purpose of the timeout period is
to limit the time spent on dequeue operations, especially for audited files. If the read operation
is not completed within the timeout period, an error 162 (operation timed out) is returned.
The parameters for the SETMODE functions 128 are:
param1
The high-order word of the timeout value (in units of one hundredth of a second).
param2

The low-order word of the timeout value (in units of one hundredth of a second).

The two words are combined to form a 32-bit integer for the timeout value. These values are
reserved:
-2D Default timeout period (60 seconds).
-1D

Infinite timeout period (timeout error is not returned.)

0D

No timeout period (error is returned immediately if record cannot be read.)

NOTE: Do not use the timeout option of AWAITIO[X]/FILE_AWAITIO64_ to complete a
READUPDATELOCK[X]/FILE_READUPDATELOCK64_ operation. The cancellation that occurs
after the timeout expires hides the fact that a record may have been dequeued from the file.

Locking a Record
To lock a record, perform a READLOCK[X]/FILE_READLOCK64_ operation. For audited files,
any records associated with an uncommitted transaction are also considered locked.

Network Considerations
You cannot access a queue file from a system running an operating system prior to D20.

Performance Considerations
Although multiple servers (dequeuing processes) can be used on a Queue File, there are practical
limits on how many processes should be used. Each time a transaction completes (for audited
Queue Files) or record is inserted (for non-audited Queue Files), the Disk Process will re-execute
each FILE_READUPDATELOCK64_/READUPDATELOCK operation which is waiting for a new
record. When there are many FILE_READUPDATELOCK64_/READUPDATELOCK operations
waiting, the overhead to perform this action can become excessive, and reduce the throughput
on the Queue File and/or affect applications sharing the CPU with the primary Disk Process. The
amount of impact is a factor on the number of read processes waiting at a given time, and the
speed of the CPU.
As a general guideline, do not use more than a few dozen dequeueing processes. Although
supported, having more than 100 processes for a Queue File can had adverse affects on a
system. As an alternative, consider using multiple queue files.

116

Queue Files

Access Examples
These examples show how to access queue files. For brevity, the timestamps shown in the
examples have been truncated to 4-byte numeric strings (for example, “1001”). If the key used
in the example is longer than eight bytes, the key is displayed as “”for
example, “AB1001”).

Example 1: Opening a Queue File
This TAL example opens a queue file:
INT QF^Num;
! Queue File number
STRING .QF^Name[0:33] := "$spool.lkp.qfile"; ! File name
LITERAL QF^NameLength = 16; ! Length in bytes of file name
INT Error;
! Returned error code
?SOURCE $SYSTEM.SYSTEM.EXTDECS0 (FILE_OPEN_)
!
! Open the Queue File
!Key^Len := Key^Length;
Error := FILE_OPEN_(
QF^Name:QF^NameLength,
QF^Num,
0,
0,
0,
0);

!
!
!
!
!
!
!

filename:length
filenum
access = read/write (can be > 0)
exclusion = shared (can be > 0)
nowait-depth = 0 (can be > 0)
sync-depth (must be 0 if
READUPDATELOCK is used)

Example 2: Enqueuing a Record
This example shows a TAL procedure that inserts a record into a queue file:
INT QF^Num;
! Queue File number
STRING .QF^Name[0:33] := "$spool.lkp.qfile"; ! File name
LITERAL QF^NameLength = 16;
! Length in bytes of file name
INT QF^NameLen;
LITERAL Key^Length = 8;
! Key length (must be >= 8)
INT Key^Len;
STRING .Key[0:Key^Length - 8];! Application key
LITERAL Rec^Len = 100;
! Record length
INT Byte^Count;
! Number of bytes read/written
INT Error;
! Returned error code
FIXED Trans^Tag;
! Transaction ID
STRING .Buffer[0:Rec^Len - 1]; ! Record buffer
STRING .Data[0:Rec^Len - Key^Length - 1]; ! Data
?SOURCE $SYSTEM.SYSTEM.EXTDECS0 (WRITE, BEGINTRANSACTION) ?SOURCE
$SYSTEM.SYSTEM.EXTDECS0 (ENDTRANSACTION)
! Enqueue a record into a Queue File
INT PROC ENQUEUE(Error);
INT .Error;
BEGIN
Buffer[0] ':=' Key FOR Key^Len - 8;

! Error code

! Move key into front
! of buffer
Buffer[Key^Len] ':=' Data FOR Rec^Len - Key^Len;
! Move data record
! into buffer
Error := BEGINTRANSACTION(Trans^Tag);! Start a transaction
CALL WRITE(QF^Num, Buffer, Rec^Len, Byte^Count);
! Write the record
IF = THEN
Error := 0
! Clear error code
ELSE
Accessing Queue Files

117

CALL FILEINFO(QF^Num, Error);
CALL ENDTRANSACTION;
RETURN Error <> 0;
END;

! Obtain error code
! End the transaction

Example 3: Dequeuing a Record
This TAL example dequeues the first record from a queue file. Note that the queue file must be
opened before calling this procedure.
INT QF^Num;
! Queue File number
STRING .QF^Name[0:33] := "$spool.lkp.qfile"; ! File name
LITERAL QF^NameLength = 16;
! Length in bytes of file name
INT QF^NameLen;
LITERAL Key^Length = 8;
! Key length (must be >= 8)
INT Key^Len;
STRING .Key[0:Key^Length - 8];
! Application key
LITERAL Rec^Len = 100;
! Record length
INT Byte^Count;
! Number of bytes read/written
INT Error;
! Returned error code
FIXED Trans^Tag;
! Transaction identifier
STRING .Buffer[0:Rec^Len-1];
! Record buffer
STRING .Data[0:Rec^Len - Key^Length - 1];
! Data being dequeued
?SOURCE $SYSTEM.SYSTEM.EXTDECS0 (KEYPOSITION,
?
ABORTTRANSACTION,
?
BEGINTRANSACTION,
?
ENDTRANSACTION,
?
FILEINFO,
?
READUPDATELOCK)
!
! Dequeue the first record from a Queue File
!
INT PROC DEQUEUE(Error);
! Returns # bytes in queue
! entry, or
INT .Error;
! returned error code (or zero)
BEGIN
! -1 if an error occurred.
Error := 0;
! Clear error code
! Position to beginning of file
CALL KEYPOSITION(
QF^Num,
! filenum
Key,
! key-value (not used)
,
! key-specifier (not needed)
0,
! length-word = zero (position to start)
0);
! positioning-mode = approximate
DO
BEGIN
Error := BEGINTRANSACTION(Trans^Tag); ! Start trans.
CALL READUPDATELOCK(QF^Num, Buffer, Rec^Len, Byte^Count);
! Read the first record
IF = THEN
! Check for errors
BEGIN
! No error occurred
Data[0] ':=' Buffer[Key^Len] FOR Byte^Count - Key^Len;
RETURN Byte^Count;
! Extract data and return
! Note: An ENDTRANSACTION call should be executed when
! the current queue record has been processed.
END;
!
! Process READUPDATELOCK error
!
! Determine which error occurred
status := FILE_GETINFO_ (QF^Num, Error);
IF Error = 162 then
! Timeout occurred
BEGIN
118

Queue Files

status := ENDTRANSACTION;
! Release this transaction
END
ELSE
! Some other error
BEGIN
status := ABORTTRANSACTION; !abort this transaction
RETURN -1;
END;
END
! Execute one dequeue operation
UNTIL 0;
END;

Example 4: Using KEYPOSITION for Generic Positioning
In this example, the queue file has a key-length of 10 bytes, so the user-key length is 2 bytes.
Note that you must open the queue file and specify a key range in key before calling
GET^GENERIC.
INT QF^Num;
! Queue File number
STRING .QF^Name[0:33] := "$pub1.spl1111.qfile"; ! File name
LITERAL QF^NameLength = 19;
! Length in bytes of file name
INT QF^NameLen;
LITERAL Key^Length = 10;
! Key length (must be >= 8)
INT Key^Len;
STRING .Key[0:Key^Length - 9];
! Application key
LITERAL Rec^Len = 100;
! Record length
INT Byte^Count;
! Number of bytes read/written
INT Length^Word;
! length-word parameter to
! KEYPOSITION
INT Error;
! Returned error code
INT Error^Item;
! Returned item-in-error
FIXED Trans^Tag;
! Transaction identifier
STRING .Buffer[0:Rec^Len - 1];
! Record buffer
STRING .Data[0:Rec^Len - Key^Length - 1];
! Data being enqueued/dequeued
!
?SOURCE $SYSTEM.SYSTEM.EXTDECS0 (FILE_OPEN_,
?
READ,
?
WRITE,
?
KEYPOSITION
?
FILE_CREATE_,
?
FILE_CREATELIST_
?
ABORTTRANSACTION,
?
BEGINTRANSACTION,
?
ENDTRANSACTION
?
FILEINFO,
?
READUPDATELOCK,
?
MYTERM,
?
STOP,
?
DEBUG
?
OPEN,
?
CLOSE);
!
! Dequeue a record within a generic key range
!
INT PROC GET^GENERIC(Error);
! Returns # bytes in queue
! entry, returned
INT .Error;
! error code, zero, or
BEGIN
! -1 if an error occurred.
Error := 0;
! Clear error code
Length^Word := 2;
! Select key-length = 2, and
Length^Word.<0:7> := 2;
! compare-length = 2.
CALL KEYPOSITION(
QF^Num,
Key,

! filenum
! key-value
Accessing Queue Files

119

0,
! key-specifier (must be zero)
Length^Word,
! length-word
1);
! positioning-mode = generic
! Note: In practice, it is only necessary to call
! KEYPOSITION once to establish the desired key range.
DO
BEGIN
Error := BEGINTRANSACTION(Trans^Tag); ! Start trans.
CALL READUPDATELOCK(QF^Num, Buffer, Rec^Len, Byte^Count);
! Read the next record
IF = THEN
! Check for errors
BEGIN
! No error occurred
Data[0] ':=' Buffer[Key^Len] FOR Byte^Count - Key^Len;
RETURN Byte^Count;
! Extract data and return
! Note: An ENDTRANSACTION call should be executed when
! the current queue record has been processed.
END;
!
! Process the READUPDATELOCK error
!
! Determine which error occurred
status := FILE_GETINFO_ (QF^Num, Error);
IF Error = 162 then
! Timeout occurred
BEGIN
status := ENDTRANSACTION;
! Release this transaction
END
ELSE
! Some other error
status := ABORTTRANSACTION;
! Abort this transaction
RETURN -1;
END
! Execute one dequeue operation
UNTIL 0;
END;
! PROC Get^Generic

Communication Path Errors
For queue file errors in the range of 200 through 211 (path loss, takeover, and CPU failure), and
for network path errors in the range of 246 through 249, the file system attempts recovery only
if the sync depth of the open file is greater than zero. However, dequeuing operations
(FILE_READUPDATELOCK64_/READUPDATELOCK[X] calls) require a sync depth of zero;
therefore, the file system cannot recover dequeuing failures due to path-related errors.
A process that only writes to (that is, it does not dequeue from) a queue file can ensure a recovery
attempt by setting the sync depth to one or greater (depending on how many outstanding
FILE_WRITE64_/WRITE[X] operations it intends to perform).
If the sync depth is zero but the file is audited, an application can recover from a path loss condition
by aborting the pending transaction.
Processes that dequeue (call FILE_READUPDATELOCK64_/READUPDATELOCK[X]) from an
audited queue file can invoke ABORTTRANSACTION and retry the
FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation. This will ensure that if a
record was deleted prior to the failure, it will be reinserted. Note, however, that all records modified
during the current transaction will be restored. Therefore, the application must be capable of
retrying the entire aborted transaction from the beginning.

120 Queue Files

Processes that access unaudited queue files have little means of recovery from path-related
errors. There are two possible error conditions that could result in lost or extra records in a queue
file:
•

A FILE_READUPDATELOCK64_/READUPDATELOCK[X] operation could encounter a
path-related error after a record was deleted. In this case, the contents of the record would
be lost.

•

A FILE_WRITE64_/WRITE[X] operation that encounters a path-related error might have
successfully inserted a record into the file. An attempt to retry the same
FILE_WRITE64_/WRITE[X] operation would result in the insertion of a second copy of the
same record with a different unique key value (different timestamp value).

In summary, if you require protection from path loss conditions, use audited files.

Communication Path Errors 121

8 Entry-Sequenced Files
Enscribe Entry-Sequenced Files
Enscribe entry-sequenced files are designed for sequential access. They consist of variable-length
records that are always appended to the end of the file; as a result, the records in the file are
arranged physically in the order in which they were added to the file.
Figure 19 (page 123) illustrates the structure of an entry-sequenced file.
The primary key of an entry-sequenced file consists of a record's block number (within the file)
and its record number (within the block). When used with FILE_SETPOSITION_, the key is an
8-byte value in which the block number occupies the leftmost 4 bytes of the key and the record
number occupies the rightmost 4 bytes. When used with POSITION, the key is a 4-byte value
whose format depends on the file's block size, as follows:
Block size

Number of bits for block

Number of bits for record

4096

20

12

2048

21

11

1024

22

10

512

23

9

The record’s address is typically used and manipulated internally by the file system, and there
is usually no reason for you to know its value. You can, however, obtain the address of the record
just read or written by using the FILE_GETINFOLIST_ system procedure.

Applicable System Procedures
You use these system procedures to create and access Enscribe entry-sequenced files:
•

FILE_CREATE_, FILE_CREATELIST_

•

FILE_OPEN_, FILE_CLOSE_, AWAITIO[X], FILE_AWAITIO64_

•

FILE_LOCKFILE64_, FILE_LOCKREC64_, FILE_UNLOCKFILE64_, FILE_UNLOCKREC64_,
LOCKFILE, UNLOCKFILE, LOCKREC, UNLOCKREC

•

FILE_READ64_, FILE_READLOCK64_, FILE_READUPDATE64_,
FILE_READUPDATELOCK64_, READ[X], READLOCK[X], READUPDATE[X],
READUPDATELOCK[X]

•

FILE_WRITE64_, FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITE[X],
WRITEUPDATE[X], WRITEUPDATEUNLOCK[X]

•

FILE_SETKEY_, FILE_SAVEPOSITION_, KEYPOSITION, POSITION, FILE_SETPOSITION_

•

FILE_GETINFO_, FILE_GETINFOLIST_, FILE_GETINFOLISTBYNAME_,
FILE_GETINFOBYNAME_

•

SETMODE, CONTROL, FILE_CONTROL64_

Types of Access
After creating the file, there are essentially three operations that you can perform:
1. Use FILE_WRITE64_/WRITE calls to add new records to the end of the file.
2. Use FILE_READ64_/READ calls to retrieve records from the file.
3. Use FILE_SETKEY_ or KEYPOSITION calls to specify an alternate-key access path and
then use FILE_READ64_/READ calls to retrieve records that contain the specified
alternate-key value.

122 Entry-Sequenced Files

You can also use the file and record locking system procedures FILE_LOCKFILE64_,
FILE_LOCKREC64_, FILE_UNLOCKFILE64_, FILE_UNLOCKREC64_, FILE_READLOCK64_,
LOCKFILE, UNLOCKFILE, READLOCK, LOCKREC, and UNLOCKREC.Enscribe entry-sequenced
files are not designed for random access. If the data records contain unique alternate-key values,
however, you can use KEYPOSITION in conjunction with FILE_READ64_, FILE_READLOCK64_,
READ or READLOCK to access them randomly.
NOTE: If an error occurs during an attempt to insert a record into an alternate-key file, 0-length
records might occur in the primary entry-sequenced file. This can also occur when a transaction
aborts that inserted records into an audited entry-sequenced file. The 0-length records are
substituted for the inserted records during TMF BACKOUT.
Figure 19 Entry-Sequenced File Structure

Creating Entry-Sequenced Files
You create Enscribe entry-sequenced files by using either the File Utility Program (FUP) or by
calling either the FILE_CREATE_ or the FILE_CREATLIST_ system procedures. If you wish to
explicitly create key-sequenced format 2 file, use the procedure call FILE_CREATELIST_ with
item code 195.
When you create a partitioned (multivolume) file, the file system automatically creates all of the
partitions of that file when the first partition is created.
If you use a system procedure to create an entry-sequenced file and the file contains alternate-key
fields, then you must also create one or more alternate-key files. If you are using FUP to create
the primary-key file, however, FUP automatically creates any required alternate-key files.
When creating an entry-sequenced file, you must consider the maximum logical record size, the
data block length, and disk extent sizes.
NOTE: Since the primary keys of entry-sequenced files are larger in format 2 files, the size of
alternate key records will also be larger. This may affect code that creates alternate-key files and
programs that directly read the contents of alternate-key files may be affected

Logical Records
A record is the unit of information transferred between an application program and the file system.
When creating an entry-sequenced file, you must specify the maximum logical record size of that
file. The particular maximum record size that you choose when creating a file depends upon the
particular requirements of your application.
For entry-sequenced files, the maximum length of a logical record is 24 bytes (or 48 bytes for
format 2 files) less than the block size. The maximum allowed block size for format 2 files is 4
KB.
The data records that you write to an entry-sequenced file can be of varying lengths, but none
can exceed the maximum logical record size specified when the file was created. If you try to
write a record that is longer than the defined maximum record length, the file system rejects the
operation and returns an error 21 (illegal count).

Blocks
A block is the unit of information transferred between the disk process and the disk. A block
consists of one or more logical records and, in the case of entry-sequenced files, associated
control information. This control information, which is used only by the system, is summarized
in “Block Formats of Structured Files” (page 172).
The block size of an Enscribe entry-sequenced file must be 512 bytes, 1 KB, 2 KB, or 4 KB.
Creating Entry-Sequenced Files 123

The block size must include 22 bytes (format 1 files) and 44 bytes (format 2 files) per block for
block control information and 2 or 4 bytes per record for record control information. Therefore,
the maximum number of records that you can store in each block is
Format 1 Files
N = ( block-size - 22 ) / ( record-size + 2 )

Format 2 Files
N = ( block-size - 44) / ( record-size + 4 )

If records are of varying lengths, then N is the average number of records per block and record-size
is the average record length.
Regardless of the record length, the maximum number of records that can be stored in a single
block is 511 for a format 1 file.
A record cannot span block boundaries (that is, it cannot begin in one block and end in another).
Therefore, the block size for an entry-sequenced file must be at least record-length + 2 + 22
bytes for format 1 files and record-length + 4 + 44 bytes for format 2 files.

Disk Extent Size
When you create an Enscribe entry-sequenced file, you can specify:
•

The size of the primary and secondary extents. Format 1 files can have from 1 through
65,535 pages (where a page is 2048 bytes), while format 2 files can have from 1 through
536,870,912 pages.

•

The maximum number of extents to be allocated for the file (16 or more for nonpartitioned
entry-sequenced files).

If you do not specify extent sizes, both the primary and secondary extent sizes default to one
page.
If you do not specify the maximum number of extents, MAXEXTENTS defaults to 16.
For nonpartitioned entry-sequenced files, you can change the MAXEXTENTS value dynamically
during program execution by using either the SETMODE 92 system procedure or the FUP ALTER
command.

File Creation Examples
The pages that follow present annotated examples showing how to create:
1. An entry-sequenced file
2. An entry-sequenced file with alternate keys
3. An alternate-key file
4. A partitioned entry-sequenced file

Example 1: Creating an Entry-Sequenced File
This example shows how to create a file for logging summary records of financial transactions
as they occur. Because the records will always be written to the file sequentially in the order in
which they are generated, it is reasonable to use an entry-sequenced file for storing them.
Assume that the desired record format is:

124 Entry-Sequenced Files

Byte Offset:
0

10

16

transid

40

date

24
time-stamp

45
trans-type

account-number

55
amount-transacted

60
terminal-number

With a record size of 60, selecting a block size of 4096 results in a blocking factor of 65 records
per block:
N = (B - 22) / (R + 2)
65 = (4096 - 22) / (60 + 2)

If you designate the primary extent size as 1000 pages and the secondary extent size as 500
pages, then the primary extent can accommodate 32,500 transaction summary records and each
secondary extent can accommodate 16,250 transaction summary records. If all 16 extents are
eventually used, the file will accommodate a total of 276,250 transaction summary records
You could create the file by using these FUP commands:
>volume $store1.svol1
>fup
-set type e
-set ext (1000,500)
-set rec 60
-set block 4096
-show
TYPE E
EXT ( 1000 PAGES, 500 PAGES )
REC 60
BLOCK 4096
-create tranfile
CREATED - $STORE1.SVOL1.TRANFILE

Using the FILE_CREATE_ system procedure, you could create the file by including this TAL
code in one of your application modules:
LITERAL name^length = 22,
pri^extent = 1000,
sec^extent = 500,
rec^len = 60,
data^block^len = 4096,
file^type = 2; ! entry-sequenced
INT filenum;
INT error;
INT namelen;
STRING .filename [0:21] := "$STORE1.SVOL1.TRANFILE";
?NOLIST
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATE_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
namelen := name^length;
ERROR := FILE_CREATE_ (filename:name^length,namelen,,
pri^extent, sec^extent,, file^type,, rec^len,
data^block^len);
Creating Entry-Sequenced Files 125

ERROR := FILE_OPEN_ (filename:name^length, filenum);
ERROR := FILE_CLOSE_ (filenum);
END;

Example 2: Creating an Entry-Sequenced File With Alternate Keys
This example shows how to create the file illustrated in Section : Example 1: Creating an
Entry-Sequenced File, but defines the terminal-number field as an alternate key.
Byte Offset:
0

10

16

transid

40

date

24
time-stamp

45
trans-type

account-number

55
amount-transacted

60
terminal-number
Alternate-Key
Field TN

You could create the file by using these FUP commands:
>volume $store1.svol1
>fup
-set type e
-set ext (1000,500)
-set rec 60
-set block 4096
-set altkey ("tn",keyoff 55,keylen 5)
-set altfile (0,alttran)
-show
TYPE E
EXT ( 1000 PAGES, 500 PAGES )
REC 60
BLOCK 4096
ALTKEY ( "TN", FILE 0, KEYOFF 55, KEYLEN 5 )
ALTFILE ( 0, $STORE1.SVOL1.ALTTRAN )
ALTCREATE
-create tranfile
CREATED - $STORE1.SVOL1.TRANFILE
CREATED - $STORE1.SVOL1.ALTTRAN

Using the FILE_CREATE_ system procedure, you could create the file by including this TAL
code in one of your application modules:
LITERAL name^length = 22,
num^altkeys = 1,
num^altkey^files = 1,
item^list^len = 10;
INT error;
INT error2;
INT namelen;
STRING .filename [0:name^length-1] :=
"$STORE1.SVOL1.TRANFILE";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
BEGIN
INT file^type;
INT logical^reclen;
126 Entry-Sequenced Files

INT block^length;
INT pri^extent;
INT sec^extent;
INT altkeys;
STRUCT altkey^descr [0:num^altkeys-1];
BEGIN
STRING key^specifier [0:1];
INT key^length;
INT key^offset;
INT key^filenum;
INT null^value;
INT attributes;
END;
INT num^alt^key^files;
STRUCT name^length^info [0:num^altkey^files-1];
BEGIN
INT file^name^len;
END;
STRING file^names [0:20];
END;
?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^NUMALTKEYS,
ZSYS^VAL^FCREAT^ALTKEYDESC,
ZSYS^VAL^FCREAT^NUMALTKEYFILES,
ZSYS^VAL^FCREAT^ALTFILELEN,
ZSYS^VAL^FCREAT^ALTFILENAMES ];
value^list.file^type := 2; ! entry-sequenced
value^list.logical^reclen := 60;
value^list.block^length := 4096;
value^list.pri^extent := 1000;
value^list.sec^extent := 500;
value^list.altkeys := num^altkeys;
value^list.altkey^descr[0].key^specifier ':=' "TN";
value^list.altkey^descr[0].key^length := 5;
value^list.altkey^descr[0].key^offset := 55;
value^list.altkey^descr[0].key^filenum := 0;
value^list.altkey^descr[0].null^value := 0;
value^list.altkey^descr[0].attributes := 0;
value^list.num^alt^key^files := num^altkey^files;
value^list.name^length^info[0].file^name^len := 21;
value^list.file^names ':=' "$STORE1.SVOL1.ALTTRAN";
ERROR := FILE_CREATELIST_ (filename:name^length,namelen,
item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

When you use a system procedure to create your entry-sequenced file, you must create your
alternate key files separately, as shown in the next example.

Creating Entry-Sequenced Files 127

Example 3: Creating an Alternate-Key File Programmatically
When you use FUP to create the primary file, FUP automatically creates any required alternate-key
files. If you create the primary file programmatically, however, you must create the alternate-key
file yourself as a separate operation.
You could create the alternate-key file for the previous example (Example 2) by including this
TAL code in one of your application modules:
LITERAL name^length = 21,
pri^extent = 30,
sec^extent = 15,
file^type = 3,
rec^len = 11,
data^block^len = 4096,
key^length = 11, ! maximum alt.-key length
! + big files primary-key length
! + 2
key^offset = 0;
INT error;
INT namelen;
STRING .filename [0:name^length-1]
:= "$STORE1.SVOL1.ALTTRAN";
namelen := name^length;
error := FILE_CREATE_(filename:name^length, namelen,,
pri^extent, sec^extent,, file^type,, rec^len,
data^block^len, key^length, key^offset);
IF Error <> 0 THEN ... ! error

Example 4: Creating a Partitioned Entry-Sequenced File
This example shows how to create the file illustrated in Example 1: Creating an Entry- Sequenced
File, but enables it to ultimately span four partitions.
You could create the file by using these FUP commands:
>volume $store1.svol1
>fup
-set type e
-set ext (1000,500)
-set rec 60
-set block 4096
-set part (1,$store2,1000,500)
-set part (2,$store3,1000,500)
-set part (3,$store4,1000,500)
-show
TYPE E
EXT ( 1000 PAGES, 500 PAGES )
REC 60
BLOCK 4096
PART ( 1, $STORE2, 1000, 500 )
PART ( 2, $STORE3, 1000, 500 )
PART ( 3, $STORE4, 1000, 500 )
-create tranfile
CREATED - $STORE1.SVOL1.TRANFILE

Note that each partition must reside on a separate disk volume. Within those volumes, however,
the partitions all have the same subvolume name and file name (SVOL1.TRANFILE in this
example). All four partitions are created at the same time.
When all 16 extents of the primary partition (#0) have been entirely used, the file system
automatically begins using partition #1; when all 16 extents of that partition have been entirely
used, the file system then begins using partition #2; and so forth.
128 Entry-Sequenced Files

Using the FILE_CREATELIST_ system procedure, you could create the file by including this TAL
code in one of your application modules:
LITERAL name^length = 22,
num^partitions = 3,
item^list^len = 9;
INT error;
INT error2;
INT namelen;
STRING .filename [0:name^length-1] :=
"$STORE1.SVOL1.TRANFILE";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
BEGIN
INT file^type;
INT logical^reclen;
INT block^length;
INT pri^extent;
INT sec^extent;
INT partitions;
STRUCT part^info [0:num^partitions-1];
BEGIN
INT part^pri^extent;
INT part^sec^extent;
END;
STRUCT vol^name^len [0:num^partitions-1];
BEGIN
INT vol^name^act^len;
END;
STRING vol^names [0:21];
END;
?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^NUMPRTNS,
ZSYS^VAL^FCREAT^PRTNDESC,
ZSYS^VAL^FCREAT^PRTNVOLLEN,
ZSYS^VAL^FCREAT^PRTNVOLNAMES];
value^list.file^type := 2;
! entry-sequenced
value^list.logical^reclen := 60;
value^list.block^length := 4096;
value^list.pri^extent := 1000;
value^list.sec^extent := 500;
value^list.partitions := 3;
value^list.part^info[0].part^pri^extent := 1000;
value^list.part^info[0].part^sec^extent := 500;
value^list.part^info[1].part^pri^extent := 1000;
value^list.part^info[1].part^sec^extent := 500;
Creating Entry-Sequenced Files 129

value^list.part^info[2].part^pri^extent := 1000;
value^list.part^info[2].part^sec^extent := 500;
value^list.vol^name^len.vol^name^act^len[0] := 7;
value^list.vol^name^len.vol^name^act^len[1] := 7;
value^list.vol^name^len.vol^name^act^len[2] := 7;
value^list.vol^names ':=' "$STORE2$STORE3$STORE4";
ERROR := FILE_CREATELIST_ (filename:name^length,namelen,
item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

Accessing Entry-Sequenced Files
You can perform three basic operations with an entry-sequenced file:
•

Add (FILE_WRITE64_/WRITE) records to the end of the file.

•

Read (FILE_READ64_, FILE_READLOCK64_, READ or READLOCK) records sequentially
according to either their primary keys or a specified alternate-key value.

•

Specify the desired alternate-key access path (FILE_SETKEY_ or KEYPOSITION).

In addition, you can use FILE_GETINFOLIST_ to obtain the address of the record just read or
written, and you can use FILE_SETKEY_ or KEYPOSITION in conjunction with unique
alternate-key values to read individual records in a random manner.

Sequential Access
Enscribe entry-sequenced files are designed for sequential access. You always append new
data records to the end of the file using the FILE_WRITE64_/WRITE system procedure
When reading an entry-sequenced file, you generally do so in a sequential manner either by
primary key (all records in the file) or by a particular alternate-key value (all records in the file
that contain that value in the designated field).
When you open the file, the access path is by primary key. You use the FILE_SETKEY_ or
KEYPOSITION system procedure to change the access path from the primary key to a particular
alternate key and from one alternate key to another. After reading data records by a particular
alternate key, you can reset the access path back to the primary key (starting at the beginning
of the file) by using FILE_SETKEY_ or KEYPOSITION with both a key specifier and a key value
of 0.
If the data records are of variable lengths, you specify the maximum record length as the
read-count parameter in the FILE_READ64_, FILE_READLOCK64_, READ or READLOCK
procedure call. The file system recognizes the end of the physical record on the disk and returns
the actual data record length, in bytes, as the count-read parameter.

Random Access
If every data record in an entry-sequenced file contains a unique alternate-key value in a particular
field, you can use FILE_SETKEY_ or KEYPOSITION in conjunction with FILE_READ64_,
FILE_READLOCK64_, READ or READLOCK to read individual data records in a random manner.
For example, if the file contains transaction summary records and one of the fields in each data
record contains a unique transaction number, you could use that field as an alternate key to
locate any desired transaction record.

Access Examples
The remainder of this section presents annotated examples illustrating the most common ways
to access Enscribe entry-sequenced files.

130 Entry-Sequenced Files

Example 1. Writing to an Entry-Sequenced File
To append a new data record to the end of an entry-sequenced file you use WRITE or WRITEX
to add your data record to the file.
CALL WRITE (filenum, buffer, write^count);
IF <> THEN ... ! error

If you need to obtain the actual record address of the newly appended data record, use
FILE_GETINFOLIST_:
error := FILE_GETINFOLIST_ (filenum, itemlist, 1, result);

where itemlist is defined as:
itemlist := 12

! Return address of current record

Example 2. Reading Sequentially by Primary Key
Assume that the particular entry-sequenced file you are working with contains variable length
transaction summary records, the largest of which is 200 bytes in length. To read the entire file
sequentially, you merely open the file and then repeatedly call the READ system procedure until
you encounter the EOF mark.
error := FILE_OPEN_ (filename:length, filenum, ... );
read^count := 200;
eof := 0;
WHILE NOT eof DO
BEGIN ! read loop
CALL READ (filenum, buffer, read^count, count^read);
IF > THEN eof := 1
ELSE
IF < THEN ... ! error
ELSE
BEGIN
.
! process the record (the returned
.
!  parameter tells
.
! the record length in bytes)
END;
END;
! read loop

Example 3. Reading Sequentially by Alternate Key
Assume that you want to read only those records that contain the terminal number ATM37 in a
particular data field that was defined during file creation as an alternatekey field. Assume also
that the key specifier for that field is TN. You use KEYPOSITION to specify TN as the key specifier
and ATM37 as the key value. You then execute a read loop. As a result of the KEYPOSITION
call, Enscribe uses the alternate-key file associated with TN to access the desired data records
from the primary file. The read loop terminates upon encountering the EOF mark in the
alternate-key file.
STRING value [0:4];
INT specifier,
compare^length;
error := FILE_OPEN_ (filename:length, filenum, ... );
specifier := "TN";
value ':=' "ATM37";
compare^length := 5;
generic := 1;
CALL KEYPOSITION (filenum, value, specifier,
compare^length, generic);
read^count := 200;
eof := 0;
Accessing Entry-Sequenced Files 131

WHILE NOT eof DO
BEGIN ! read loop
CALL READ (filenum, buffer, read^count, count^read);
IF > THEN eof := 1
ELSE
IF < THEN ... ! error
ELSE
BEGIN
.
! process the record (the returned
.
!  parameter specifies
.
! the actual record length in bytes)
END;
END; ! read loop

Example 4. Reading Randomly by Unique Alternate Key
Assume that a particular entry-sequenced file contains transaction summary records and that
one of the defined alternate-key fields in each record contains a unique transaction number.
Assume also that the key specifier for that field is TX. If you want to read the data record for
transaction number AB0829, you use FILE_SETKEY_ , with exact positioning, to locate the
record and then use READ to read the record.
STRING value [0:5];
INT specifier,
value^length;
error := FILE_OPEN_ (filename:length, filenum, ... );
specifier := "TX";
value ':=' "AB0829";
value^length := 6;
exact := 2;
error := FILE_SETKEY_ (filenum,
value:value^length,specifier,exact);
read^count := 200; ! maximum data record size
CALL READ (filenum, buffer, read^count, count^read);
! the returned  parameter
! specifies the actual record length in bytes

132 Entry-Sequenced Files

9 Relative Files
Enscribe Relative Files
Enscribe relative files consist of fixed-length physical records on disk that are accessed by relative
record number. A record number is an ordinal value and corresponds directly to the record's
position in the file. The first record is identified by record number zero; succeeding records are
identified by ascending record numbers in increments of one.
Figure 20 (page 133) illustrates the structure of a relative file.
Each physical record position in a relative file occupies a fixed amount of space and each can
contain one variable-length data record (logical record). A logical record can vary in size from
zero, an empty record, to the maximum record size specified when the file was created. You can
change a record's logical length after it has been written to the file, but the lengths of all logical
records in the file must always be less than or equal to the constant size of the physical record.
Each logical record has a length attribute that can be returned when a record is read. Logical
records in a relative file can be logically deleted by issuing a write with a specified length of zero.
Once you have created the file and written a data record to it, all physical records preceding that
record are also created and actually occupy space on the disk even though they contain no data.
For example, if you create a relative file and then write a data record to record number 135,
records 0 through 134 are also physically created on the disk at that time even though they have
a logical record length of zero.
Note that this characteristic represents a limiting factor that could influence whether or not you
use the relative file type.
Figure 20 Relative File Structure
Record 0

Record 1

Record 2

Record 3

Empty

Fixed-length physical
records.
Each record position
occupies
a fixed amount of space
even
if the record contains no
data.
Da ta

Empty

Data

Data
Blocks

D a ta

Each record has a length
attribute.
Therefore, the data portion
(logical
record) can vary within the
physical
record.

The exact position where a new record is to be inserted into a relative file is specified by supplying
a record number to the FILE_SETPOSITION_ procedure. Alternatively, you can specify that
Enscribe Relative Files 133

records be inserted into any available position by supplying a record number of -2 to
FILE_SETPOSITION_ before inserting records into the file. You can specify that subsequent
records be appended to the end of a file by supplying a record number of -1 to the
FILE_SETPOSITION_ procedure.
For example, in a relative file in which only record number 10 contains data, you can position to
an empty location (such as record number 5) and use the WRITE procedure to insert a new
record in that location. If you position to record number -2, the record is written to some (not
necessarily the lowest) empty location. Using the READUPDATE procedure after positioning to
an empty location returns file-system error 11 (record not in file); the same positioning causes
the READ procedure to read the next nonempty record.
When -2 or -1 is specified for inserting records into a relative file, the actual record number
associated with the new record can be obtained through the FILE_GETINFOLIST_ procedure.
Relative files are best suited for applications where random access to fixed-length records is
desired and where the record number has some meaningful relationship to a particular piece of
data within each logical record. An inventory file, for example, could be a relative file with the
part number serving as the record number. Such usage, however, would probably be very wasteful
of disk space because part-numbering schemes often leave large gaps in the overall number
sequence; this could result in many records being allocated but not used. An invoice file with the
invoice number serving as the record number might be a better candidate for the relative file type
because there are typically no large gaps in that type of numbering scheme. In the latter case,
because your invoice numbers might begin at some large number such as 10000, you will likely
have to use an address conversion algorithm to generate a record number sequence that begins
at zero and then include the actual invoice number as a data field within the record.

Applicable System Procedures
•

FILE_CREATE_, FILE_CREATELIST_

•

FILE_OPEN_, FILE_CLOSE_, AWAITIO[X], FILE_AWAITIO64_

•

FILE_LOCKFILE64_, FILE_LOCKREC64_, FILE_UNLOCKFILE64_, FILE_UNLOCKREC64_,
LOCKFILE, LOCKREC, UNLOCKFILE, UNLOCKREC

•

FILE_SETKEY_, FILE_SETPOSITION_, POSITION, KEYPOSITION, SAVEPOSITION,
REPOSITION

•

FILE_READ64_, FILE_READLOCK64_, FILE_READUPDATE64_,
FILE_READUPDATELOCK64_, READ[X], READLOCK[X], READUPDATE[X],
READUPDATELOCK[X]

•

FILE_WRITE64_, FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITE[X],
WRITEUPDATE[X], WRITEUPDATEUNLOCK[X]

•

FILE_GETINFO_, FILE_GETINFOLIST_, FILE_GETINFOBYNAME_,
FILE_GETINFOLISTBYNAME_

Types of Access
You can refer to specific records within a relative file either by their primary key (relative record
number) or by the content of one or more alternate-key fields such as department number or zip
code, for example, in an employee file.
There are three major pointers associated with an Enscribe relative file:
Current-record pointer
Specifies the physical record that was most recently read from
or written to.
Next-record pointer

134 Relative Files

Specifies the next physical record that will be read from or
written to.

EOF pointer

Specifies the byte following the record with the highest address
that currently contains data. Note that the same EOF pointer
value is shared by all opens of a particular file.

When the data records of a relative file include one or more alternate-key fields, there are two
other values that are used for manipulating the pointers by way of alternatekey files:
Current key specifier
Identifies which alternate-key field is to be used for accessing
records in the file. When the current access path is by primary
key, the current key specifier value is zero.
Current key value

Identifies the particular alternate-key value that is currently
being used within the current access path. When the current
access path is by primary key, the current key value is the
address of the physical record that was most recently read from
or written to.

When you open a relative file, both the current-record and next-record pointers point to the first
record in the file and the access path is by primary key.
You can change the access path from the primary-key field to an alternate-key field, from one
alternate-key field to another, or back to the primary-key field at any time by using the
FILE_SETKEY_, FILE_SETPOSITION_, KEYPOSITION, and POSITION system procedures.
When the access path is by primary key, successive calls to the FILE_READ64_,
FILE_READLOCK64_, FILE_WRITE64_, READ, READLOCK, and WRITE system procedures
access successively higher physical records in the file. You can change the content of the
next-record pointer at any time to point to any specific record in the file using the
FILE_SETPOSITION_ system procedure. You can also use FILE_SETPOSITION_ to change
the content of the next-record pointer so that it points to the EOF position (for appending records
to the end of the file) or to the next available empty record
When the access path is by a particular alternate key, successive calls to the FILE_READ64_,
FILE_READLOCK64_, READ and READLOCK system procedures access successively higher
logical records that contain a specified value (or partial value) in that field. You can change the
current key-specifier and current key-value, and thereby the content of the next-record pointer,
at any time to point to the first record in the file that contains a particular value (or partial value)
in any alternate-key field using the FILE_SETKEY_ system procedure.
FILE_SETPOSITION_ always sets the access path to the primary key.
You can also change the access path from an alternate-key field back to the primary key
FILE_SETPOSITION_ once you do so, the next-record pointer points again to the first record in
the file (relative record number 0).

Creating Relative Files
You create Enscribe relative files by using the File Utility Program (FUP) or by calling either the
FILE_CREATE_ procedure or the FILE_CREATELIST_ procedure.
When you create a partitioned (multivolume) file, the file system automatically creates all of the
partitions of that file when the first partition is created.
If you are using a system procedure to create a relative file and the file contains alternate-key
fields, you must also create one or more alternate-key files. If you are using FUP to create the
primary-key file, however, FUP automatically creates any required alternate-key files.
When creating a relative file, you must consider the maximum logical record size, the data block
length, and disk extent sizes.

Logical Records
A logical record is the unit of information transferred between an application program and the
file system.
Creating Relative Files 135

When creating a relative file, you must specify the maximum logical record length of that file.
This parameter defines the size of the fixed-length physical records on the disk.
The maximum record size that you choose when creating a file depends upon the requirements
of your application.

Format 1 Files
For relative format 1 files, the maximum length of a logical record is 24 bytes less than the block
size. Using the maximum allowed block size of 4096, the absolute maximum logical record size
allowed for relative files is 4072 bytes.

Format 2 Files
For relative format 2 files, the maximum length of a logical record is 48 bytes less than the block
size. Using the maximum allowed block size of 4096, the absolute maximum logical record size
allowed for relative files is 4048 bytes. The error 579 will be returned if the record size exceeds
the applicable limit.
The data records that you write to a relative file can be of varying lengths, but none can exceed
the maximum logical record size specified when the file was created. If you try to write a record
that is longer than the defined maximum record length, the file system rejects the insert operation
with an error 21 (illegal count).

Blocks
A block is the unit of information transferred between the disk process and the disk. A block
consists of one or more logical records and, in the case of relative files, associated control
information. This control information, which is used only by the system, is summarized in “Block
Formats of Structured Files” (page 172).
The block size of an Enscribe relative file must be 512 bytes, 1 KB, 2 KB, or 4 KB.
The block size must include 22 or 44 bytes per block for block control information and 2 or 4
bytes per record for record control information. Therefore, the maximum number of records that
you can store in each block is:
N = (block-size - 22) / (record-size + 2) for Format 1 Files
N = (block-size - 44) / (record-size + 4) for Format 2 Files

Regardless of the record length, the maximum number of records that can be stored in a single
block is 511 for format 1 files and 32767 for format 2 files.
A record cannot span block boundaries (that is, it cannot begin in one block and end in another).
Therefore, the block size for a relative file must be at least record-length + 2 + 22 bytes for
format 1 files and record-length + 4 + 44 bytes for format 2 files

Disk Extent Size
When you create an Enscribe relative file, you can specify:
•

The size of the primary and secondary extents. Format 1 files can have from 1 through
65,535 pages (where a page is 2048 bytes), while format 2 files can have from 1 through
536,870,912 pages

•

The maximum number of extents to be allocated for the file (16 or more for a nonpartitioned
relative file)

If you do not specify extent sizes, both the primary and secondary extents sizes default to one
page.
If you do not specify a maximum number of extents, MAXEXTENTS defaults to 16.
For nonpartitioned relative files, you can change the MAXEXTENTS value dynamically during
program execution using either a SETMODE 92 procedure call or a FUP ALTER command.

136 Relative Files

File Creation Examples
The examples that follow show how to create a relative file, a relative file with alternate keys, an
alternate-key file, and a partitioned relative file.

Example 1: Creating a Relative File
This example shows how to create an employee data file in which the individual records are to
be accessed by employee number. If the employee numbering scheme starts at zero or one (for
the first employee) and proceeds sequentially upward in increments of one, it is reasonable to
use a relative file.
Byte offset:
0

40
name

75
home-address

90

100
salary

80
emp-#

85
dept-code

106
hire-date

job-code

112
termination-date

Note that while the employee number also happens to be included as data within the record, the
records are actually accessed by their relative record number.
Assuming a format 1 file, with a record size of 112, selecting a block size of 4096 results in a
blocking factor of 35 records per block:
N = (B - 22) / (R + 2)
35 = (4096 - 22) / (112 + 2)

If you designate the primary extent size as 60 pages and the secondary extent size as 30 pages,
then the primary extent will accommodate 1050 employee records and each secondary extent
will accommodate 525 additional employee records. When all 16 extents are eventually used,
the file will accommodate a total of 8925 employee records.
You could create the file by using these FUP commands:
>volume $store1.svol1
>fup
-set type r
-set ext (60,30)
-set rec 112
-set block 4096
-show
TYPE R

Creating Relative Files 137

EXT ( 60 PAGES, 30 PAGES )
REC 112
BLOCK 4096
MAXEXTENTS 16
-create empfile
CREATED - $STORE1.SVOL1.EMPFILE

Using the FILE_CREATE_ system procedure, you could create the same file by including the
TAL code in one of your application modules. The node name is not specified, so the
FILE_CREATE_ procedure obtains the node name from the current value of the VOLUME attribute
of the =_DEFAULTS DEFINE. For more information on the =_DEFAULTS DEFINE, see the
TACL Programming Guide.
LITERAL name^length = 21,
pri^extent = 60,
sec^extent = 30,
file^type = 1,
rec^len = 112,
data^block^len = 4096;
INT namelen;
INT error;
STRING .filename [0:name^length-1] :=
"$STORE1.SVOL1.EMPFILE";
namelen := name^length;
error := FILE_CREATE_ (filename:name^length,
namelen,, pri^extent, sec^extent,,
file^type,, rec^len, data^block^len);
IF error <> 0 THEN ... ! error

Example 2: Creating a Relative File With Alternate Keys
This example shows how to create the file illustrated in “Example 1: Creating a Relative File”
(page 137) but defines the department code field as an alternate key.
Byte Offset:
0

40
name

75
home-address

80
emp-#

85
dept-code

Alternate-Key
Field DP
90

100
salary

106
hire-date

112
termination-date

You could create the file by using these FUP commands:
>volume.$store1.svol1
>fup
-set type r
-set ext (60,30)
-set rec 112
-set block 4096
-set altkey ("DP",keyoff 80,keylen 5)
-set altfile (0,dept)
-show
TYPE R
138 Relative Files

job-code

EXT ( 60 PAGES, 30 PAGES )
REC 112
BLOCK 4096
ALTKEY ( "DP", FILE 0, KEYOFF 80, KEYLEN 5 )
ALTFILE ( 0, $STORE1.SVOL1.DEPT )
ALTCREATE
-create empfile
CREATED - $STORE1.SVOL1.EMPFILE
CREATED - $STORE1.SVOL1.DEPT

Using the CREATE procedure, you could create the same file by including this TAL code in one
of your application modules. The node name and volume name for the new file are obtained from
the current value of the VOLUME attribute of the =_DEFAULTS DEFINE.
LITERAL name^length = 13,
num^altkeys = 1,
num^altkey^files = 1,
item^list^len = 10;
INT error;
INT error2;
INT namelen;
STRING .filename [0:name^length-1] := "SVOL1.EMPFILE";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
BEGIN
INT file^type;
INT logical^reclen;
INT block^length;
INT pri^extent;
INT sec^extent;
INT altkeys;
STRUCT altkey^descr [ 0:num^altkeys-1];
BEGIN
STRING key^specifier [0:1];
INT key^length;
INT key^offset;
INT key^filenum;
INT null^value;
INT attributes;
END;

Creating Relative Files 139

INT num^alt^key^files;
STRUCT name^length^info [ 0:num^altkey^files-1];
BEGIN
INT file^name^len;
END;
STRING file^names [0:9];
END;
?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^NUMALTKEYS,
ZSYS^VAL^FCREAT^ALTKEYDESC,
ZSYS^VAL^FCREAT^NUMALTKEYFILES,
ZSYS^VAL^FCREAT^ALTFILELEN,
ZSYS^VAL^FCREAT^ALTFILENAMES ];
value^list.file^type := 1; ! relative
value^list.logical^reclen := 112;
value^list.block^length := 4096;
value^list.pri^extent := 60;
value^list.sec^extent := 30;
value^list.altkeys := num^altkeys;
value^list.altkey^descr[0].key^specifier ':=' "DP";
value^list.altkey^descr[0].key^length := 5;
value^list.altkey^descr[0].key^offset := 80;
value^list.altkey^descr[0].key^filenum := 0;
value^list.altkey^descr[0].null^value := 0;
value^list.altkey^descr[0].attributes := 0;
value^list.num^alt^key^files := num^altkey^files;
value^list.name^length^info[0].file^name^len := 10;
value^list.file^names ':=' "SVOL1.DEPT";
ERROR := FILE_CREATELIST_ (filename:name^length,namelen,
item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

Note that you must then create the alternate-key file separately. For more information see the
following section.

Example 3: Creating an Alternate-Key File
When you use FUP to create the primary file, FUP automatically creates any required alternate-key
files. If you create the primary file programmatically, however, you must create the alternate-key
file yourself as a separate operation. This example assumes the use of a format 1 file. To see
the difference with a format 2 file, see “Example 3: Creating a Key-Sequenced Format 2 File
With Alternate Keys” (page 79).
You could create the alternate-key file for “Example 2: Creating a Relative File With Alternate
Keys” (page 138) by including the TAL code in one of your application modules. Again, the node
name is obtained from the current value of the VOLUME attribute of the =_DEFAULTS DEFINE.

140 Relative Files

LITERAL name^length = 20,
pri^extent = 30,
sec^extent = 15,
file^type = 3,
rec^len = 11,
data^block^len = 4096,
key^length = 11,

! max. alternate key length
! + primary-key length
! + 2

key^offset = 0;
INT namelen;
INT error;
STRING .filename [0:name^length-1] :=
"$STORE1.SVOL1.INVALT";
namelen := name^length;
error := FILE_CREATE_(filename:name^length,
namelen,, pri^extent, sec^extent,,
file^type,, rec^len, data^block^len,
key^length, key^offset);
IF error <> 0 THEN ... ! error

Example 4: Creating a Partitioned Relative File
This example shows how to create the file illustrated in Example 1 but enables it to ultimately
span four partitions.
You could create the file by using these FUP commands:
volume $part1.svol1
>fup
-set type r
-set ext (60,30)
-set rec 112
-set block 4096
-set part (1,$part2,60,30)
-set part (2,$part3,60,30)
-set part (3,$part4,60,30)
-show
TYPE R
EXT ( 60 PAGES, 30 PAGES )
REC 112
BLOCK 4096
PART ( 1, $PART2, 60, 30 )
PART ( 2, $PART3, 60, 30 )
PART ( 3, $PART4, 60, 30 )
-create empfile
CREATED - $PART1.SVOL1.EMPFILE

Note that each partition must reside on a separate disk volume. Within those volumes, however,
the partitions all have the same subvolume name and file name (SVOL1.EMPFILE in this example).
All four partitions are created at the same time.
When all 16 extents of the primary partition (#0) have been entirely used, the file system
automatically begins using partition #1; when all 16 extents of that partition have been entirely
used, the file system then begins using partition #2; and so forth.
Using the FILE_CREATELIST_ procedure, you could create the same file by including the TAL
code in one of your application modules. The node name is not specified, so the
FILE_CREATELIST_ procedure obtains the node name from the current value of the VOLUME
attribute of the =_DEFAULTS DEFINE.
LITERAL name^length = 20,
num^partitions = 3,
item^list^len = 9;
Creating Relative Files 141

INT error;
INT error2;
INT namelen;
STRING .filename [0:name^length-1] := "$PART1.SVOL1.EMPFILE";
INT .item^list [0:item^list^len-1];
STRUCT value^list;
BEGIN
INT file^type;
INT logical^reclen;
INT block^length;
INT pri^extent;
INT sec^extent;
INT partitions;
STRUCT part^info [0:num^partitions-1];
BEGIN
INT part^pri^extent;
INT part^sec^extent;
END;
STRUCT vol^name^len [0:num^partitions-1];
BEGIN
INT vol^name^act^len;
END;
STRING vol^names [0:18];
END;
?NOLIST
?SOURCE $SYSTEM.ZSYSDEFS.ZSYSTAL(FILESYSTEM^ITEMCODES)
?SOURCE $SYSTEM.SYSTEM.EXTDECS0(FILE_CLOSE_,
?
FILE_OPEN_,
?
FILE_CREATELIST_,
?
READ)
?LIST
PROC DO^THE^WORK MAIN;
BEGIN
namelen := name^length;
item^list ':=' [ZSYS^VAL^FCREAT^FILETYPE,
ZSYS^VAL^FCREAT^LOGICALRECLEN,
ZSYS^VAL^FCREAT^BLOCKLEN,
ZSYS^VAL^FCREAT^PRIMEXTENTSIZE,
ZSYS^VAL^FCREAT^SCNDEXTENTSIZE,
ZSYS^VAL^FCREAT^NUMPRTNS,
ZSYS^VAL^FCREAT^PRTNDESC,
ZSYS^VAL^FCREAT^PRTNVOLLEN,
ZSYS^VAL^FCREAT^PRTNVOLNAMES];
value^list.file^type := 1; ! relative
value^list.logical^reclen := 112;
value^list.block^length := 4096;
value^list.pri^extent := 60;
value^list.sec^extent := 30;
value^list.partitions := 3;
value^list.part^info[0].part^pri^extent := 60;
value^list.part^info[0].part^sec^extent := 30;
value^list.part^info[1].part^pri^extent := 60;
value^list.part^info[1].part^sec^extent := 30;
value^list.part^info[2].part^pri^extent := 60;
value^list.part^info[2].part^sec^extent := 30;
value^list.vol^name^len.vol^name^act^len[0] := 6;
value^list.vol^name^len.vol^name^act^len[1] := 6;
value^list.vol^name^len.vol^name^act^len[2] := 6;
value^list.vol^names ':=' "$PART2$PART3$PART4";
error := FILE_CREATELIST_ (filename:name^length,namelen,
142 Relative Files

item^list, item^list^len, value^list,
$LEN(value^list), error2);
END;

Accessing Relative File
The following paragraphs discuss the file pointers and access methods for Enscribe relative files.

The File Pointers
Separate next-record and current-record pointers are associated with each opening of a relative
disk file so that if the same file is open several times simultaneously, each opening will provide
a logically separate access. The next-record and current-record pointers reside in the file's access
control block (ACB) in the application process environment.
A single EOF pointer, however, is associated with all openings of a given relative disk file. This
permits data to be appended to the end of a file by several different accessors. The EOF pointer
resides in the file's file control block (FCB) in the disk-I/O process environment. A file's EOF
pointer value is copied from the file label on disk when the file is opened and is not already open.
You can explicitly change the content of the next-record pointer to that of the EOF pointer by
specifying an address of -1 in a POSITION or FILE_SETPOSITION_ call.
When appending to a file, the EOF pointer is advanced automatically each time a new block is
added to the end of the data in the file. Note that in the case of partitioned files the EOF pointer
relates only to the final partition containing data.
A file's EOF pointer is not automatically written through to the file label on disk each time it is
modified. Instead, for relative files it is physically written to the disk only when one of these events
occurs:
•

A file label field is changed and the autorefresh option is enabled.

•

The last accessor closes the file.

•

The DISK_REFRESH_ procedure is called for the file.

•

The REFRESH command is executed for the file's volume.

When using the FILE_CREATE_ procedure, you enable the autorefresh option by setting options
bit 13 to 1. When using FUP, you enable the autorefresh option by issuing a SET REFRESH
command.
For files created with the autorefresh option disabled, you can subsequently enable autorefresh
by issuing a FUP ALTER command containing the REFRESH ON parameter

Effects of File-System Procedures on Pointers
The following paragraphs briefly describe how each applicable system procedure affects the
current access path, current-record pointer, and next-record pointer.
FILE_OPEN_
Sets the current access path to the primary-key field.
Changes the content of the current-record and next-record
pointers so that they both point to record number zero.
FILE_SETPOSITION,POSITION

Sets the current access path to the primary-key field.
Changes the content of the current-record and next-record
pointers so that they both point to the particular record
identified by the specified record number.
Record number -1 resets both pointers to the current EOF
position.

Accessing Relative File 143

Record number -2 resets both pointers to an available
empty record in the file.
FILE_SETKEY_, KEYPOSITION

FILE_READ64_,
FILE_READLOCK64_, READ or
READLOCK

Sets the current access path to the specified key field.
•

With nonunique alternate keys: changes the content
of the current-record and next-record pointers so that
they both point to the first (lowest) record in the file
that contains the specified key-value (or partial
key-value) in the specified alternate-key field.

•

With unique alternate keys: changes the content of
the current-record and next-record pointers so that
they both point to the particular record in the file that
contains the specified key-value in the specified
alternate-key field.

Returns the content of the record pointed by the next-record
pointer. When reading by primary key, FILE_READ64_,
FILE_READLOCK64_, READ and READLOCK skip empty
records.
Upon completion, FILE_READ64_, FILE_READLOCK64_,
READ and READLOCK change the pointers as:
•

current-record pointer = next-record pointer

•

next-record pointer = address of next higher record in
current access path

Note that if FILE_READ64_, FILE_READLOCK64_, READ
or READLOCK skip an empty record, they increment the
pointers one extra time for each record skipped so that the
pointers maintain the proper values.
FILE_WRITE64_ or WRITE

Writes to the record pointed to by the next-record pointer.
The particular record must be empty; if not, the operation
fails with an error 10 (record already exists).
Upon completion, FILE_WRITE64_/WRITE changes the
pointers as:
•

current-record pointer = next-record pointer

•

next-record pointer = address of next higher record in
current access path

The following procedures do not alter the pointers:
FILE_GETINFOLIST_
Returns the values of the current-record pointer and the
next-record pointer.
FILE_READUPDATE64_,
Returns the content of the record pointed to by the
current-record pointer. The particular record must already
FILE_READUPDATELOCK64_,
READUPDATE or READUPDATELOCK contain data; if not, the operation fails with an error 11
(record not in file).
FILE_WRITEUPDATE64_,
FILE_WRITEUPDATEUNLOCK64_,
WRITEUPDATE or
WRITEUPDATEUNLOCK

144 Relative Files

Writes to the record pointed to by the current-record
pointer. The particular record must already contain data;
if not, the operation fails with an error 11 (record not in file).

Sequential Access
The FILE_READ64_, FILE_READLOCK64_, FILE_WRITE64_, READ, READLOCK, and WRITE
system procedures provide sequential access to Enscribe relative files
If the current access path is by primary key, a succession of FILE_READ64_,
FILE_READLOCK64_, READ or READLOCK calls obtains data from successively higher physical
records in the file, skipping over empty physical records.
If the current access path is by a particular alternate-key field, a succession of FILE_READ64_,
FILE_READLOCK64_, READ or READLOCK calls obtains data from successively higher physical
records within the particular access path (that is, physical records that contain the current key-value
in the alternate-key field identified by the current key-specifier).
An attempt to read beyond the last record in either access path returns an EOF indication.
When you are writing data records, a succession of FILE_WRITE64_/WRITE calls writes data
to successively higher physical records in the file. Note that FILE_WRITE64_/WRITE will only
write data to empty physical records. If you attempt to FILE_WRITE64_/WRITE to a physical
record that already contains data, the operation fails with an error 10 (record already exists).
Upon completion of each FILE_READ64_, FILE_READLOCK64_, FILE_WRITE64_, READ,
READLOCK, or WRITE call, the current-record pointer is set to the present value of the next-record
pointer (thereby pointing to the record that was just read or written) and the next-record pointer
is incremented to point to the next higher physical record in the current access path.
When reading or writing sequentially by primary key, you can access different subsets of physical
records by using the FILE_SETPOSITION_ or POSITION system procedure calls. After each
FILE_SETPOSITION or POSITION call, the next FILE_READ64_, FILE_READLOCK64_,
FILE_WRITE64_, READ, READLOCK, or WRITE call accesses the physical record that you
positioned to, and subsequent FILE_READ64_, FILE_READLOCK64_, FILE_WRITE64_, READ,
READLOCK, or WRITE calls access successively higher physical records in the file.
When reading or writing sequentially by a particular alternate key, you can reposition to the start
of a new alternate-key access path using the FILE_SETKEY_ system procedure. After each
FILE_SETKEY_ call, the next FILE_READ64_, FILE_READLOCK64_, READ or READLOCK
call retrieves the first (lowest) physical record in the file that contains the specified key value in
the alternate-key field identified by the particular key specifier; subsequent FILE_READ64_,
FILE_READLOCK64_, READ or READLOCK calls retrieve successively higher physical records
in the particular access path.

Random Access
The update procedures FILE_READUPDATE64_, FILE_WRITEUPDATE64_,
FILE_READUPDATELOCK64_, FILE_WRITEUPDATEUNLOCK64_, READUPDATE,
WRITEUPDATE, READUPDATELOCK, and WRITEUPDATEUNLOCK, when used in conjunction
with FILE_SETPOSITION_, provide random access to Enscribe relative files. The updating
operation occurs at the record indicated by the current-record pointer. Random processing implies
that a record to be updated must exist. If the physical record indicated by the current-record
pointer is empty, the operation fails with an error 11 (record not found).
You cannot use FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITEUPDATE
or WRITEUPDATEUNLOCK to alter a record's primary key. If you need to do so, you must first
delete the record by using a FILE_WRITEUPDATE64_/WRITEUPDATE call with a write count
of zero, and then insert the record into the desired physical record by using a
FILE_SETPOSITION_ call followed by a FILE_WRITE64_/WRITE call.
If updating is attempted immediately after a call to FILE_SETKEY_ where a nonunique alternate
key is specified, the operation fails with an error 46 (invalid key). However, if you issue an
intermediate call to FILE_READ64_, FILE_READLOCK64_, READ or READLOCK, updating is
then permitted.

Accessing Relative File 145

Inserting Records
You insert data records into a relative file by using the FILE_WRITE64_/WRITE system procedure.
The data record is written to the physical record indicated by the next-record pointer. Note that,
for relative files, insertion requires that the referenced physical record be empty; if it is not, the
operation fails with an error 10 (duplicate record).
If an alternate key has been declared to be unique and an attempt is made to insert a record
having a duplicate value in such an alternate-key field, the operation fails with an error 10
(duplicate record).
Insertion of an empty record (one where write-count = 0) is not valid for relative files.
The length of a record to be inserted must be less than or equal to the record length defined for
the file; if it is not, then the insertion fails with an error 21 (invalid count).

Deleting Records
Record deletion, which is accomplished by way of a FILE_WRITEUPDATE64_,
FILE_WRITEUPDATEUNLOCK64_, WRITEUPDATE or WRITEUPDATEUNLOCK call with a
write-count of zero, always applies to the physical record indicated by the current-record
pointer.

File Access Examples
The remainder of this section presents annotated examples illustrating the most common ways
to access Enscribe relative files.
Example 1 Sample Relative File
Most of the examples use the following sample file:
name

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

nnnnnnnnnnnn
(empty)
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn
(empty)
(empty)
nnnnnnnnnnnn
nnnnnnnnnnnn
(empty)
nnnnnnnnnnnn
nnnnnnnnnnnn
nnnnnnnnnnnn

address

aaaaaaaaaaaaa

dept job salary region
code code
code
(DP)
(RG)
56
jjj ssssss 3

aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa

60
60
56
56
34
60
34
60
60
56

jjj
jjj
jjj
jjj
jjj
jjj
jjj
jjj
jjj
jjj

ssssss
ssssss
ssssss
ssssss
ssssss
ssssss
ssssss
ssssss
ssssss
ssssss

4
2
3
3
3
4
3
4
2
6

aaaaaaaaaaaaa
aaaaaaaaaaaaa

46
46

jjj ssssss 5
jjj ssssss 1

aaaaaaaaaaaaa
aaaaaaaaaaaaa
aaaaaaaaaaaaa

60
34
46

jjj ssssss 1
jjj ssssss 3
jjj ssssss 4

Reading Sequentially by Primary Key
Using the sample file in “Sample Relative File” (page 146), the sequence of READ calls issued
immediately after opening the file would read records 0, 2, 3, 4, and 5, respectively:
CALL READ (filenum, buffer, read^count);
CALL READ (filenum, buffer, read^count);
CALL READ (filenum, buffer, read^count);
146 Relative Files

! reads record 0
! reads record 2
! reads record 3

CALL READ (filenum, buffer, read^count);
CALL READ (filenum, buffer, read^count);

! reads record 4
! reads record 5

Note that this sequence skips empty records (record 1 in the sample file).
If you want to start reading records sequentially by primary key from some specified point within
the file, you could use a sequence such as:
CALL FILE_SETPOSITION_(filenum,10F); ! sets access
path = 0
! (primary key) and the
! next-record pointer = 10
CALL READ (filenum, buffer, read^count);
! reads record
CALL READ (filenum, buffer, read^count);
! reads record
CALL READ (filenum, buffer, read^count);
! reads record
CALL READ (filenum, buffer, read^count);
! reads record
CALL READ (filenum, buffer, read^count);
! reads record

10
11
14
15
17

Note that the sequence skips empty records (records 12, 13, and 16 in the sample file).

Reading Sequentially by Alternate Key
This sequence defines the desired key value as 60, the desired key specifier as DP (department
code), both the compare length and key length as 2 and exact positioning (2):
key^value := "60";
CALL FILE_SETKEY_(filenum, key^value:2,”DP”,2);

Using those specifications and the sample file illustrated in “Sample Relative File” (page 146), a
subsequent sequence of five READ calls accesses data records from the file as:
CALL
CALL
CALL
CALL
CALL

READ
READ
READ
READ
READ

(filenum,
(filenum,
(filenum,
(filenum,
(filenum,

buffer,
buffer,
buffer,
buffer,
buffer,

read^count);
read^count);
read^count);
read^count);
read^count);

!
!
!
!
!

reads
reads
reads
reads
reads

record
record
record
record
record

2
3
7
9
10

Writing Sequentially by Primary Key
You write data to empty physical records in a relative file by using FILE_WRITE64_/WRITE
procedure calls. The current access path must be the primary key field, which is the default when
a relative file is first opened.
Assuming that records 0 through 4 are currently empty, this sequence of five WRITE calls issued
immediately after opening the file would do this:
error := FILE_OPEN_ (filename:length, filenum)
! sets the access path = 0
! (primary key) and the
! next-record pointer = 0
CALL WRITE (filenum, buffer, write^count); ! writes
CALL WRITE (filenum, buffer, write^count); ! writes
CALL WRITE (filenum, buffer, write^count); ! writes
CALL WRITE (filenum, buffer, write^count); ! writes
CALL WRITE (filenum, buffer, write^count); ! writes

to
to
to
to
to

rec.
rec.
rec.
rec.
rec.

0
1
2
3
4

If you attempt to WRITE data to a record that is not empty, the operation fails with an error 10
(duplicate record).
To append new records to the end of a relative file, you use the FILE_SETPOSITION_ procedure
to point to the current EOF position and then issue successive WRITE calls. Assuming that the
EOF pointer currently contains the value 260, this sequence of calls appends five records to the
end of a relative file.
CALL FILE_SETPOSITION_(filenum,-1F);! sets next-rec.ptr.
= -1
CALL WRITE (filenum, buffer, write^count);!writes to rec. 260
CALL WRITE (filenum, buffer, write^count);!writes to rec. 261
Accessing Relative File 147

CALL WRITE (filenum, buffer, write^count);!writes to rec. 262
CALL WRITE (filenum, buffer, write^count);!writes to rec. 263
CALL WRITE (filenum, buffer, write^count);!writes to rec. 264

Note that this sequence also causes the EOF pointer to be incremented appropriately.
After any of the write operations, you can obtain the address of the newly appended record by
issuing this procedure call:
item := 202;
error := FILE_GETINFOLIST_ (filenum, item, 1, primary^key, 8);

To insert a new data record into any available empty physical record, you supply the value -2 in
a FILE_SETPOSITION_ call and then issue a WRITE call.
CALL FILE_SETPOSITION_ (filenum, -2F);
CALL WRITE (filenum, buffer, write^count);

After doing so, you can obtain the address of the physical record that was actually used by issuing
this procedure call:
item := 202;
error := FILE_GETINFOLIST_ (filenum, item, 1, primary^key, 8);

Random Access by Primary Key
You access individual records randomly within a relative file by using FILE_SETPOSITION_ calls
to explicitly identify the desired record by primary key (relative record number).
CALL FILE_SETPOSITION_ (filenum,38F); ! sets next-rec.ptr=38
CALL WRITE (filenum, buffer, write^count); ! writes to rec 38

Note that this sequence assumes that record 38 is currently empty. If you attempt to WRITE data
to a record that is not empty, the operation fails with an error 10 (file/record already exists).
CALL FILE_SETPOSITION_ (filenum, 76F); !sets next-rec.ptr=76
CALL READ (filenum, buffer, read^count); ! reads record 76

Note that this sequence assumes that record 76 actually contains data. If record 76 is empty,
the READ call accesses the next record higher than 76 that does contain data.

Updating Records
To update a record, the particular physical record being accessed must already contain data.
FILE_WRITE64_/WRITE cannot write to an occupied physical record. Conversely,
FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITEUPDATE and
WRITEUPDATEUNLOCK cannot write to an empty physical record.
After positioning to the particular record you wish to update, read the record using
FILE_READUPDATE64_, FILE_READUPDATELOCK64_, READUPDATE or READUPDATELOCK
to verify that it contains data.
FILE_READ64_, FILE_READLOCK64_, READ and READLOCK always access the next higher
nonempty record in the current access path, simply ignoring empty records. Consequently, they
might or might not access the particular record that you positioned to. FILE_READUPDATE64_,
FILE_READUPDATELOCK64_, READUPDATE and READUPDATELOCK, however, always
access whatever record is pointed to by the current-record pointer. The use of these procedures
(instead of FILE_READ64_, FILE_READLOCK64_, READ or READLOCK) therefore ensures
that you are indeed examining the content of the particular record that you positioned to regardless
of whether it contains data or is empty.
Having determined that the desired record contains data, you then need to change the desired
data fields in your application buffer and write the revised record back to the disk using
FILE_WRITEUPDATE64_, FILE_WRITEUPDATEUNLOCK64_, WRITEUPDATE or
WRITEUPDATEUNLOCK.
Referring to the sample data file illustrated in “Sample Relative File” (page 146), this sequence
of TAL statements updates the content of record 18:
148 Relative Files

CALL FILE_SETPOSITION_ (filenum, 18F); ! set next-record
! pointer = 18
CALL READUPDATE (filenum, buffer, read^count, count^read);
IF count^read > 0 THEN
BEGIN
buffer := changed^record;
CALL WRITEUPDATE (filenum, buffer, write^count);
END
ELSE ...
! the specified record is empty;
!
update not performed

Accessing Relative File 149

10 File and Record Locking
Enscribe File and Record Locks
Access to shareable Enscribe files among two or more processes is coordinated by file locks
and record locks.
Files can be either audited or nonaudited. An audited file is one that is being accessed under
the control of TMF.
For nonaudited files, locks are granted on a file-open basis; that is, they are requested and
granted in conjunction with individual file numbers associated with separate calls to the
FILE_OPEN_ system procedure. A file or record lock through one file number prevents access
to that file or record by any other file number, even within the same process.
For audited files, locks are granted on a transaction basis; that is, they are requested and granted
in conjunction with individual transaction identifiers (transids) associated with separate
BEGINTRANSACTION-ENDTRANSACTION statement pairs within an application program
module. A file or record lock through one transid prevents access to that file or record through
any other transid, even within the same process.
Multiple processes that are accessing the same disk file should always use either file or record
locking before performing any critical sequence of operations to that file.

Locking Modes
Six locking modes are available; they are summarized in this table:
Table 11 Locking Modes
Normal mode

Any attempt to lock a file, or to read or lock a record that
is already locked through a different file number or transid,
is suspended until the existing lock is released. This is
the default locking mode.

Reject mode

Any attempt to lock a file, or to read or lock a record that
is already locked through a different file number or transid,
is rejected with a file-system error 73 (file/record is locked);
no data is returned.

Read-through Normal mode

FILE_READ64_, FILE_READUPDATE64_, READ and
READUPDATE requests ignore existing record and file
locks; encountering a lock does not delay or prevent
reading the record. FILE_LOCKFILE64_,
FILE_LOCKREC64_, LOCKFILE, LOCKREC,
FILE_READLOCK64_, FILE_READUPDATELOCK64_,
READLOCK, and READUPDATELOCK are treated as in
normal mode.

Read-through/reject mode

FILE_READ64_, FILE_READUPDATE64_, READ and
READUPDATE requests ignore existing record and file
locks; encountering a lock does not delay or prevent
reading the record. FILE_LOCKFILE64_,
FILE_LOCKREC64_, LOCKFILE, LOCKREC,
FILE_READLOCK64_, FILE_READUPDATELOCK64_,
READLOCK, and READUPDATELOCK are treated as in
reject mode.

Read-warn/normal mode

FILE_READ64_, FILE_READUPDATE64_, READ and
READUPDATE requests ignore existing record and file
locks; although an existing lock will not delay or prevent
reading the record, it causes a CCG completion with a
warning code of 9. FILE_LOCKFILE64_,
FILE_LOCKREC64_, LOCKFILE, LOCKREC,
FILE_READLOCK64_, FILE_READUPDATELOCK64_,

150 File and Record Locking

Table 11 Locking Modes (continued)
READLOCK, and READUPDATELOCK are treated as in
normal mode.
Read-warn/reject mode

FILE_READ64_, FILE_READUPDATE64_, READ and
READUPDATE requests ignore existing record and file
locks; although an existing lock will not delay or prevent
reading the record, it causes a CCG completion with a
warning code of 9. FILE_LOCKFILE64_,
FILE_LOCKREC64_, LOCKFILE, LOCKREC,
FILE_READLOCK64_, FILE_READUPDATELOCK64_,
READLOCK, and READUPDATELOCK are treated as in
reject mode.

You use SETMODE 4 procedure calls to enable the desired locking mode. The particular mode
that you select determines what action occurs if you try to lock a file, or read or lock a record,
when the file or record is already locked.
If you issue a CONTROL, FILE_CONTROL64_, FILE_WRITE64_ or WRITE request when the
referenced file or any record within it is already locked through a different file number or transid,
the request is always rejected immediately with an error 73 (file/record is locked) regardless of
which locking mode you have selected.

File Locking
NOTE: A call to FILE_LOCKFILE64_/LOCKFILE is not equivalent to locking all of the records
in the file; locking all records individually would still allow someone else to insert new records,
whereas file locking would not.
You use FILE_LOCKFILE64_, FILE_UNLOCKFILE64_, LOCKFILE and UNLOCKFILE calls to
lock and unlock Enscribe disk files.
If you call FILE_LOCKFILE64_/LOCKFILE when the specified file and all of the records within it
are unlocked (or all of the existing record locks belong to you), the lock is granted and your
application process continues execution.
If you call FILE_LOCKFILE64_/LOCKFILE when either the specified file or any record within it
is already locked through a different file number or transid, the action taken depends upon the
locking mode that is in effect at the time of the call.
When you close a file, all of the locks that you own against it are released immediately (except
in the case of audited files, where the unlocking is delayed until all your transactions have been
either committed or aborted and backed out).
NOTE: Frequent use of the FILE_LOCKFILE64_, FILE_UNLOCKFILE64_, LOCKFILE and
UNLOCKFILE requests on partitioned files should be avoided, as there is additional overhead
to lock and unlock every partition of the file. This overhead can be significant even for files with
only 16 partitions. Hewlett Packard Enterprise recommends record level locking as a more efficient
alternative with partitioned files.

Record Locking
Record locking operates in much the same manner as file locking, but it allows greater concurrent
access to a single file.

File Locking 151

These procedures lock records within a file:
•

FILE_LOCKREC64_/LOCKREC locks the current record, as determined by the most recent
operation against the file.

•

FILE_READLOCK64_, FILE_READUPDATELOCK64_, READLOCK and
READUPDATELOCK lock the record to be read before reading it.

•

For audited files, FILE_WRITE64_/WRITE locks the record that is being inserted.

Note that if generic locking is enabled for a key-sequenced file, the
FILE_LOCKREC64_/LOCKREC procedure also locks any other records in the file whose keys
begin with the same character sequence as the key of the referenced record. Generic locking
applies only to key-sequenced files. If both the referenced record and its file are unlocked (or
the existing locks belong to you) when you call FILE_LOCKREC64_, FILE_READLOCK64_,
FILE_READUPDATELOCK64_, LOCKREC, READLOCK, or READUPDATELOCK, the lock is
granted and your application process continues execution.
If either the referenced record or its file is locked through a different file number or transid when
you call FILE_LOCKREC64_, FILE_READLOCK64_, FILE_READUPDATELOCK64_, LOCKREC,
READLOCK, or READUPDATELOCK, the action taken depends upon the locking mode that is
in effect at the time of the call.
These procedures unlock records within a file:
•

FILE_UNLOCKREC64_/UNLOCKREC unlocks the current record, as determined by the
most recent operation against the file.

•

FILE_UNLOCKFILE64_/UNLOCKFILE unlocks all of the records in the specified file that
were locked through the file number or transid associated with the
FILE_UNLOCKFILE64_/UNLOCKFILE call. In addition, if the file itself is locked through that
same file number or transid, FILE_UNLOCKFILE64_/UNLOCKFILE releases the file lock
as well.

•

For nonaudited files, FILE_WRITEUPDATEUNLOCK64_/WRITEUPDATEUNLOCK releases
the associated record lock after writing or deleting the record.

•

For audited files, ENDTRANSACTION unlocks all of the records that the transaction had
locked but does not do so until the transaction has been either committed or aborted and
backed out.

•

For nonaudited files, FILE_CLOSE_ unlocks all of the records that were locked through the
file number associated with the call.

Note that if generic locking is enabled for a key-sequenced file, calls to the
FILE_UNLOCKREC64_/UNLOCKREC procedure are ignored.
When you delete a record from a nonaudited file, the record lock is released immediately. When
you delete a record from an audited file, however, the lock is not released until the transaction
has been either committed or aborted and backed out.
Record locking provides maximum concurrency of access to a file while still guaranteeing the
logical consistency of the file's content. However, for complex updating operations involving many
records, record locking can involve a lot of system processing, consume a lot of memory required
by the locks, and increase the possibility of deadlock. In such cases, file locking might be
preferable.

Generic Locking
In addition to locking entire files or individual records within files, you can lock sets of records
within key-sequenced files whose keys all begin with the same character sequence. This is
referred to as generic locking.
You enable generic locking by issuing a SETMODE 123 procedure call that defines a generic
lock key length that is shorter than the key length defined for the particular file. You disable
152 File and Record Locking

generic locking by issuing a SETMODE 123 procedure call that defines a generic lock key length
that is either zero or equal to the key length defined for the particular file.
When generic locking is disabled, a record lock obtained with the
FILE_UNLOCKREC64_/LOCKREC file-system procedure locks a single record by locking the
specific key of that record.
When generic locking is enabled, a record lock obtained with the
FILE_UNLOCKREC64_/LOCKREC procedure locks all of the records whose keys begin with
the same byte string.
Note that when generic locking is enabled for a particular file, it applies to all opens of that file.
The length of the generic lock key length must be less than the length of the entire key. Note that
there are now two key lengths: the overall key length defined at file creation time and the generic
lock key length; each is defined on a per-file basis.
Consider this example:
File X is a key-sequenced file with a defined key length of 6. It contains records with these keys:
Aabcde
A1aabb
A2bbbb
A21ccc
A27def
B4dddd
B5abcd
C9dddd

If generic locking is enabled with a generic lock key length of 2, locking the record A2bbbb with
a FILE_UNLOCKREC64_/LOCKREC procedure call locks these subset of records:
A2bbbb
A21ccc
A27def

Note that the records containing the keys A21ccc and A27def are also locked because the first
two bytes of their record keys are identical to those of the locked record (A2bbbb). The records
containing the keys Aabcde and A1aabb are not locked, however, because the first two bytes of
their record keys do not exactly match those of the locked record.
The generic lock key length is stored in the file label and can be modified with SETMODE 123
procedure calls.
You can obtain the current generic lock key length programmatically by using the
FILE_GETINFOLIST_ system procedure. You can also obtain the current generic lock key length
interactively by using the File Utility Program (FUP) INFO command or change it interactively by
using the FUP ALTER command.
Generic locking is activated whenever the generic lock key length is nonzero and less than the
key length of the file. Note that the generic lock key length is initialized to the defined key length
of the file so that generic locking is initially deactivated.
The lengths of all generic key locks possible at any one time on a file is a constant. This means
that the generic lock key length cannot be changed if there are currently any locks in effect for
the file.
When generic locking is activated, calls to the FILE_UNLOCKREC64_/UNLOCKREC procedure
are ignored. Thus, with generic locking activated, you cannot unlock records either generically
or individually. You can, however, unlock all records in the file with the
FILE_UNLOCKFILE64_/UNLOCKFILE procedure.
The decision whether or not to use generic key locking should be made on a per-file basis and
applies to all processes that lock records in that file. Therefore, you should carefully analyze all
application programs that use that file to be certain that the benefits of generic locking to one
application are not offset by drawbacks to another application.
Generic Locking 153

The applications that benefit the most from generic locking are those that need to concurrently
lock a set of records that together form a generic subset. One generic lock could potentially
replace hundreds or thousands of individual record locks. In some application environments, the
use of generic locking could both improve performance (because there will be fewer calls to the
lock manager to allocate, deallocate and search locks) and reduce memory use (because there
are fewer locks).
Applications that should not use generic locking are those that lock individual, unrelated records.
Note that if one process owns a generic lock on a subset of records and a second process tries
to insert a record into that subset, the attempted insertion will fail and the second process will
get an error 73 (file/record is locked) whether or not the record actually exists.
For example, assume that there exists an empty key-sequenced file with a defined key length
of four and that generic locking is enabled with a generic lock key length of two. If process #1
inserts a record with the key AAaa, it thereby owns a generic lock for the byte-string AA. If process
#2 at that time attempts to insert a record with the key AAcc, the attempt is rejected with a CCL
and an error code 73.

Interaction Between File Locks and Record Locks
This discussion applies only if the default locking mode is in effect.
File locks take precedence over record locks. If you lock a file and then attempt to lock individual
records within that file, the record lock requests are ignored and have no effect.
For each file having one or more pending file lock requests, the requests are queued. In addition,
read calls that attempt to access a locked file are queued with the pending file lock requests.
When the current lock is released, the system grants whatever request is currently at the head
of the file lock queue. If the request is a file lock request, the lock is granted; if the request is a
read request, the read operation is performed.
Similarly, for a record having one or more pending record lock requests, the requests are queued.
In addition, read calls that attempt to access a locked record are queued with the pending record
lock requests. When the current lock is released, the system grants whatever request is currently
at the head of the queue for that record. If the request is a record lock request or a
READUPDATELOCK/FILE_READUPDATELOCK64_ request, the lock is granted; if the request
is a read request, the read operation is performed.
Lock requests do not wait behind other locks held by the same file number or transid. If a file
number or transid holds record locks and later requests a file lock (and no other file number or
transid has any locks pending against that file or any of its records), the record locks are
relinquished and replaced by the file lock.

Lock Limits
The disk process enforces lock limits that are specified through SYSGEN. For nonaudited files,
the default limit is 5000 locks per volume for each file number; for audited files, the default limit
is 5000 locks of all kinds per volume for each transid. For partitioned files, these criteria translate
into a default of 5000 locks per partition.
The limits do not imply that you can always get the maximum number of locks. For example,
there might not be enough physical memory space or internal buffer space available to get another
lock.
If the limit has been reached and you ask for an additional lock, the lock request is rejected with
an error 35 (unable to obtain I/O process control block). The disk process returns different error
codes for two other specific causes: error 37 (I/O process is unable to lock physical memory)
when there is not enough physical memory available and error 33 (I/O process unable to obtain
I/O segment space) when a buffer is full or too fragmented.

154 File and Record Locking

When a process reads a file that was opened with sequential block buffering, the disk process
ignores record locks (although it does honor file locks). The FUP COPY command, for example,
uses sequential block buffering and can therefore read locked records.

Deadlock
One problem that can occur when multiple processes require multiple record locks or file locks
is a deadlock condition. An example of deadlock is:
Process A

Process B

LOCKREC: record 1

LOCKREC: record 2

.

.

.

.

LOCKREC: record 2

LOCKREC: record 1

Here, process A has record 1 locked and is requesting a lock for record 2, while process B has
record 2 locked and is requesting a lock for record 1.
One possible way to avoid deadlock is to always lock the records in the same order. Thus, this
illustrated situation could never happen if each process requested the lock to record 1 before it
requested the lock to record 2.
Because it is sometimes impossible for an application program to know in which order the records
it must lock are going to be encountered, this approach is worth considering. For updates to
single records of the file, no special processing needs to be done. For an update involving two
or more records, however, the solution is to first lock some designated common record, and then
lock the necessary data records. This prevents deadlock among those processes requiring
multiple records, because they must first gain access to the common record, but still allows
maximum concurrency and minimum overhead for accessors of single records.

File Locking and Record Locking With Unstructured Files
You lock and unlock unstructured files in essentially the same way that you do structured files.
You lock records in unstructured files by positioning the file to the relative byte address of the
record to be locked and then calling the FILE_LOCKREC64_, LOCKREC, FILE_READLOCK64_,
FILE_READUPDATELOCK64_, READLOCK, or READUPDATELOCK procedure. Any other
user attempting to access the file at a point beginning at exactly that address sees the address
as being locked; the action taken is governed by the current locking mode.
NOTE: Only the starting point specified by the relative byte address is locked. Another
application could access part of the record if it specified a relative byte address somewhere else
within the record.

TMF Locking Considerations
When your application is running under the control of TMF, every transaction must lock all of the
records that it updates or deletes. To do so, the transactions can use either file locks or record
locks.
When a process changes an audited database, the disk process imposes these constraints to
prevent other transactions from either reading uncommitted changes or performing conflicting
operations:
•

Whenever a transaction inserts a new record into an audited file, the disk process
automatically obtains a lock based on the inserted record's primary-key value. This lock
prevents any other transaction from inserting a record with the same primary-key value as

Deadlock 155

the newly inserted record, and from reading, locking, updating, or deleting the newly inserted
record.
•

Before a transaction can update or delete an existing record in an audited file, the transaction
must previously have locked either the record or its file. If the transaction does not do so,
the attempt to update or delete the record is rejected immediately with an error 79.

•

The disk process retains all locks on inserted, updated, or deleted records in audited files
until the associated transactions are either committed or aborted and backed out. Note,
however, that for an FILE_UNLOCKREC64_/UNLOCKREC call following a
FILE_READLOCK64_/READLOCK call, the lock is released immediately.

•

Transactions should lock all of the records that they read and use in producing output
regardless of whether the transaction modifies the data. Doing so guarantees that the data
on which each transaction depends does not change before the transaction is either
committed or aborted and backed out.

By performing heavy activity against an audited database, an application process can generate
a large number of locks and thereby inadvertently create deadlock situations with other application
processes. Therefore, when designing your application, you should consider the coordinated
use of file locks and/or generic record locks among those processes that need access to the
same database.
A TMF transaction is begun by a call to BEGINTRANSACTION and terminated by a call to
ENDTRANSACTION.
Figure 21 illustrates how processes can acquire locks and update audited files and when the
disk process will release the locks.
If the complete set of currently active transactions requires too many locks, the attempt is rejected
with an error 33, 35, or 37.
File locks and record locks are owned by the current transid of the process that issued the lock
request. For example, a single transaction can send requests to several servers or multiple
requests to the same server class. In this situation, where several processes share a common
transid and the locks are held by the same transid, the locks do not cause conflict among the
processes participating in the transaction.

156 File and Record Locking

Figure 21 Record Locking for TMF
Transaction A
LOCK record 1
Change record 1
UNLOCK record 1
•
•
LOCK record 2
Delete record
2

Audited
File

Locks for records 1
and 2 will be held until
transaction A commits or is
aborted and backed out.

Transaction B
LOCKFILE
Change record 1
•
•
Change record 2
UNLOCKFILE

Audited
File

The file lock will be held until
transaction B commits or is
aborted and backed out.

Transaction C
LOCK record 1
Change record 1
•
•
LOCK record 2
No change to record 2
•
•
UNLOCKFILE

Audited
File

Lock for record 1 will be held
until transaction C commits
or
is aborted and backed out.
Lock for record 2 is released
immediately by
UNLOCKFILE.

Figure 22 (page 158) illustrates these principles:
•

The terminal control process (TCP) interprets BEGINTRANSACTION and obtains the transid
before requesting database activity from the servers.

•

The transid is transmitted to the servers as part of the request message, and any disk activity
performed by the servers is associated with the particular transid.

•

The particular transid owns the lock(s); all servers that are performing work for the same
transid can read, lock, add, delete, and change records in the audited files. For example,
server A can read and lock a record and server B can read or change the same record if
both servers are operating on behalf of the same transid.

TMF Locking Considerations 157

Figure 22 Record Locking by Transid
Transid

Server A

Transid

Audited
File

TCP

Transid

BEGIN-TRANSACTION
•
•
"transaction mode"
•
•
END-TRANSACTION

Server B

Transid

All locks and changes to
audited files are associated
with a transaction identifier
(transid).

Errors in Opening Audited Files
With TMF, locks can persist longer than the opener process because the locks are owned by
the transid instead of by the opener of a file. This means that even if a file has been closed by
all its openers, the disk process will effectively keep it open until all transactions owning locks in
the file have been either committed or aborted and backed out.
For files with pending transaction locks, these types of errors are possible:
•

Any attempt to open an audited file with exclusive access will fail with error 12 (file in use)
regardless of whether openers of the file exist.

•

FUP operations that require exclusive access, such as PURGE and PURGEDATA, will fail.
PURGE operations will fail with error 12 (file in use) while PURGEDATA operations will fail
with error 80 (invalid operation on audited file).

Error 80 will also be returned if the OPEN call specifies unstructured access to a structured
audited file.

Reading Deleted Records
If transaction T1 deletes a record and another transaction T2 attempts to read the same record
while T1 is still active, then:
•

If T2's request is a FILE_READ64_/READ call following exact positioning through the alternate
file, the request fails with an error 1 (end-of-file) irrespective of the locking mode specified.

•

If T2's request is a FILE_READ64_/READ call following exact positioning through the primary
file, the request either fails with an error 73 (file or record is locked) if reject locking mode is
in effect or it waits for T1 to complete if normal locking mode is in effect.

•

If T2's request is a FILE_READUPDATE64_/READUPDATE call, the request either fails
with an error 73 (file or record is locked) if reject locking mode is in effect or it waits for T1
to complete if normal locking mode is in effect. This behavior is true if the exact positioning
is through the primary file. If the exact positioning is through the alternate file, the request
waits for T1 to complete irrespective of locking mode.

158 File and Record Locking

Batch Updates
When programming for batch updating of audited files, you should either have the transaction
lock an entire file at a time by using the FILE_LOCKFILE64_/LOCKFILE procedure or carefully
keep track of the number of locks held. If you do not use FILE_LOCKFILE64_/LOCKFILE, the
disk process sets implicit locks as:
•

When a new record is inserted into an audited file, the disk process implicitly locks that
record.

•

When a record is deleted from an audited file, the disk process implicitly retains a lock on
that record.

These locks are not released until the transaction is either committed or aborted and backed out.
This means that transactions doing batch updates to audited files can acquire too many locks if
the transaction involves deleting, updating, or inserting a large number of records. The absolute
maximum number of locks that can be acquired by each transaction is 5000. Any attempt to
exceed the maximum number of locks will result in an error 33, 35, or 37.
If a TMF transaction calls FILE_LOCKFILE64_/LOCKFILE for a primary file,
FILE_LOCKFILE64_/LOCKFILE is automatically applied to any associated alternate-key files.
This prevents primary file updates from causing the alternate-key files to obtain record locks.

TMF Locking Considerations 159

11 Errors and Error Recovery
Error Message Categories
The file system generates a number of messages indicating errors or other special conditions.
You can encounter these messages during execution of any program module that uses system
procedures.
Both a condition code and an error number are associated with the completion of each file-system
procedure call. For successful completions, the condition code is CCE and the error number is
0.
The full range of error numbers can be subdivided into three general categories:
•

Warnings issued by the file system (1 through 9).

•

Errors encountered during standard file-system operations (10 through 255).

•

Error numbers reserved for application-dependent use (300 through 511).

Many of the file-system error numbers indicate that you made a programming error, such as
passing an invalid parameter or trying to initiate an illegal operation. Others indicate that the
system is not being operated properly. Still others are essentially informational messages in that
they merely inform you of particular device-oriented problems.

Communication Path Errors
A communication path error is a failure of a processor module, I/O channel, or disk controller
port that is part of the primary path to disk unit. For errors of this type, the file system will attempt
to switch to an alternate path and complete the I/O operation if you specified a sync depth greater
than zero when opening the particular file.
An error number within the range 200 through 211 indicates that the operation is retryable. For
specific information regarding communication path errors associated with queue files, see
Chapter 7: Queue Files

Data Errors
A data error indicates that all or part of the file must be considered invalid.
Data errors are signified by the error numbers 50 through 59, 120 through 139, and 190 through
199.

Device Operation Error
Device operation errors are signified by the error numbers 60 through 69 and 103. The file system
does not retry the failed operation when one of these types of error conditions occurs.
Errors 60-69 indicate that the device has been deliberately made inaccessible and, therefore,
the associated operation should not be retried.
Error 103 indicates that the entire system has experienced a power failure and the disk is in the
process of becoming ready. In such a case, you should periodically retry the failed operation.

Extent-Allocation Errors
Two error numbers are associated with programmatic allocation of disk extents: 43 (unable to
obtain disk space for file extent) and 45 (file is full).
This example, in conjunction with Figure 23 (page 161), illustrates both types of error.
A file is created with an extent size of 2048 bytes. Repetitive WRITE operations of 400 bytes are
then performed on the file:
loop: CALL WRITE ( filenum, buffer, 400, number^written );
IF < THEN
160 Errors and Error Recovery

BEGIN
status := FILE_GETINFO_ ( filenum, error );.
...
END
ELSE GOTO loop;

The first five WRITEs are successful (number^written = 400), but the sixth fails after transferring
48 bytes from the buffer to the disk (number^written = 48).
If insufficient disk space is available to allocate another extent, the error number returned by
FILE_GETINFO_ is 43 (unable to obtain disk space for file extent).
If the condition occurred because the current extent is the last one permitted in the file, then the
error number returned by FILE_GETINFO_ is 45 (file is full). You might be able to recover from
an error 45 by using a SETMODE 92 call to dynamically increase the maximum number of extents.
If extents cannot be allocated because the file label is full, FILE_GETINFO_ returns error 43
(unable to obtain disk space for file extent). FILE_GETINFO_ does not return error 45 because,
technically, the file is not full.
Note that an error 43 can also occur when allocating extents with a CONTROL 21 procedure
call.
Figure 23 Example Showing Extent-Allocation Error
Write #1
(400
Bytes)

Write #2
(400
Bytes)

Write #3
(400
Bytes)

Write #4
(400
Bytes)

Write #5
(400
Bytes)

Write #6
(48 Bytes)

(Data)
0

400

800

1200

1600

2000
2048

File Extent Zero

Errors and Partitioned Files
Each partition of a file can encounter error conditions independently of the file's other partitions.
This is especially significant for errors 42 through 45, which pertain to disk space allocation. For
errors 42 through 45 you might be able to correct the situation by using FUP to alter the size
characteristics of the partition where the error occurred.
In any case, after each CCL or CCG return, you can obtain the particular error number by calling
the FILE_GETINFO_ procedure, the partition number of the partition in error by calling the
FILE_GETINFOLIST_ procedure, and the volume name of the partition in error by examining
the file's partition parameter array either programmatically or by using FUP.

Failure of the Primary Application Process
A failure of the primary application process is actually a failure of the processor module where
the primary process of a primary/backup process pair is executing. Operations associated with
this type of failure must be retried by the backup application process when it takes over for the
primary process. Refer to the discussion of checkpointing in the Guardian Programmer's Guide
for information about how to recover from this type of error.

Errors and Partitioned Files 161

12 File Loading
File Utility Program (FUP) Commands
The File Utility Program (FUP) commands that you use to load data into an existing file are LOAD
and LOADALTFILE.
The LOAD command loads data into an existing structured disk file without affecting any related
alternate-key files. Any previous data in the file being loaded is lost. When loading data into
key-sequenced files, the input records can be in either sorted or unsorted order; unless you
specify the SORTED option, unsorted is assumed. For key-sequenced files, you can also specify
slack space (a percentage of data block and index block space) to be left for future insertions.
The LOADALTFILE command generates alternate-key records from a specified primary-key file,
sorts the generated records into ascending order by alternate-key value, and then loads the
sorted records into a specified alternate-key file. You can specify slack space for future insertions.
If your system does not have enough disk space available to perform the sorting operation in
conjunction with the file loading operation, you can do the two operations separately. To do this,
you would first use a FUP BUILDKEYRECORDS command to do the sorting; the sorted output
can, for example, be directed to a magnetic tape. You would then use a FUP COPY or LOAD
command to load the sorted records from the intermediate file into the destination alternate-key
file.
The examples in this section illustrate file loading operations that require a sequence of FUP
commands.
For more information about FUP, refer to the File Utility Program (FUP) Reference Manual.

Loading a Key-Sequenced File
For this example, file $VOL1.SVOL.PARTFILE is a key-sequenced file having three partitions.
The first secondary partition is $VOL2 and the second secondary partition is $VOL3.
Any record having a primary-key value in the range of zero up to but not including HA are to exist
in the primary partition; records with primary-key values from HA up to but not including RA are
to exist on $VOL2; records with primary-key values of RA or greater are to exist on $VOL3.
The records to be loaded into this file are 128 bytes long and are on tape in unsorted order, with
one record per block.
The FUP commands to perform this operation are:
-VOLUME $vol1.svol
-LOAD $TAPE, partfile

LOAD reads the records from tape drive $TAPE and sends them to the SORT process. When
all records have been read, sorting begins. When the sort is finished, the records are read from
the SORT process and loaded into the file according to the file's partial-key-value
specifications. The data and index block slack percentage is zero.

Defining a New Alternate Key
This example defines a new alternate-key field for the primary file $VOL1.SVOL.PRIFILE, whose
existing alternate-key file is $VOL1.SVOL.ALTFILE. The alternate-key records for the new key
field will be added to file ALTFILE.
The key specifier for the new key is NM, the key offset in the record is 4, the key length is 20,
and a null value of “ ” (blank) is specified for the new key field.
The FUP commands to perform this operation are:
-VOLUME $vol1.svol
-ALTER prifile, ALTKEY ( "NM", KEYOFF 4, KEYLEN 20, NULL " ")
-LOADALTFILE 0, prifile, ISLACK 10

162 File Loading

The LOADALTFILE command loads PRIFILE's key file 0 ($VOL1.SVOL.ALTFILE) with the
alternate-key records for key specifier NM and for any other alternate keys defined for key file
zero. An index block slack percentage of 10 is specified.

Creating an Alternate-Key File
This example creates an alternate-key file for the primary file $VOL1.SVOL.FILEA, which is an
entry-sequenced file. The new alternate-key file will be named $VOL1.SVOL.FILEB. The
alternate-key records for the new key field will be added to FILEB.
The key specifier for the new key is XY, the key offset in the record is 0, and the key length is
10.
The FUP commands to perform this operation are:
-VOLUME $vol1.svol
-CREATE fileb, type K, rec 16, keylen 16
-ALTER filea, ALTFILE ( 0, fileb ), ALTKEY ( "XY", KEYLEN 10)
-LOADALTFILE 0, filea

The CREATE command creates the alternate-key file ($VOL1.SVOL.FILEB). Both the record
length and key length are specified as 16 bytes (2 for the key specifier + 10 for the alternate-key
field lengths + 4 for the primary-key length).
The ALTER command changes the file label for FILEA so that it refers to FILEB as alternate-key
file 0 and contains the definition for the key field specified by key specifier XY.
The LOADALTFILE command loads FILEA's key file 0 ($VOL1.SVOL.FILEB) with the alternate-key
records for key specifier XY. An index block slack percentage of 0 is implied.

Reloading a Key-Sequenced File Partition
For this example, the primary partition of the partitioned file is $VOL1.SVOL.PARTFILE. Its first
secondary partition is on $VOL2 and its second secondary partition is on $VOL3. The secondary
partition on $VOL2 is to be reloaded.
The FUP commands to perform this operation are:
-VOLUME $vol1.svol
-SET LIKE $vol2.partfile
-SET NO PARTONLY
-CREATE temp
-DUP $vol2.partfile, temp, OLD, PARTONLY
-LOAD temp, $vol2.partfile, SORTED, PARTOF $vol1
-PURGE temp

The SET and CREATE commands create a file identical to $VOL2.SVOL.PARTFILE except that
the file is designated as a nonpartitioned file by means of NO PARTONLY.
The DUP command duplicates the data in the secondary partition ($VOL2.SVOL.PARTFILE)
into $VOL1.SVOL.TEMP.
The LOAD command reloads the secondary partition $VOL2.SVOL.PARTFILE from the file
$VOL1.SVOL.TEMP. The LOAD command includes the SORTED option because the records
in the TEMP file are already in sorted order.

Creating a Partitioned Alternate-Key File
This example creates a partitioned form of an alternate key file. Partitioning allows a file to hold
more data and to share I/Os between more than one physical disk. For this example, the primary
file has a primary-key field 10 bytes long and an alternate key field 7 bytes long, with the key
specifier “SN”. The alternate key file is $VOL1.SVOL.ALTFILE, which has not been created yet.
The alternate key values starting with the letters “A” through “L” will have records placed into the
first partition, and key values starting with the letters “M” through “Z” will be placed into the second
partition. The partitions of the alternate key file will reside on volumes $VOL1 and $VOL2.
Creating an Alternate-Key File 163

The FUP commands to perform this operation are:
-VOLUME $vol1.svol
-RESET
-SET TYPE K
-SET KEYLEN 19
-SET REC 19
-SET EXT (9000,1000)
-SET PART (1,$vol2,9000,1000,"SNM")
-CREATE altfile

If the primary file contains any data, the empty alternate key file will be loaded with the associated
key records. In this example, the primary file is named PRIFILE, and it specifies ALTFILE as its
alternate key file number 0.
The FUP command to load the newly created alternate file is:
-LOADALTFILE 0, prifile

For more information on FUP commands, see the File Utility Program (FUP) Reference Manual.

Loading a Partitioned, Alternate-Key File
For this example, primary file $VOL1.SVOL.PRIFILE is a key-sequenced file having a primary-key
field 10 bytes long. The file has three alternate-key fields identified by the key specifiers F1, F2,
and F3. Each of these alternate-key fields is 10 bytes long.
All of the alternate-key records are contained in a single alternate-key file that is partitioned over
three volumes. Each volume contains the alternate-key records for one alternate-key field; the
key specifier for each alternate-key field is also the partial-key value for the associated secondary
partition.
The alternate-key file's primary partition is $VOL1.SVOL.ALTFILE. That partition contains the
alternate-key records for the key specifier F1. The first secondary partition, $VOL2.SVOL.ALTFILE,
contains the alternate-key records for the key specifier F2. The second secondary partition,
$VOL3.SVOL.ALTFILE, contains the alternate-key records for the key specifier F3.
The commands to load the alternate-key records for key specifier F2 into $VOL2.SVOL.ALTFILE
are:
>FUP
-VOLUME $vol1.svol
-CREATE sortin, ext 30
-CREATE sortout, ext 30
-BUILDKEYRECORDS prifile,sortin,"F2",RECOUT 22,BLOCKOUT 2200
-EXIT
>SORT
FUP
-VOLUME $vol1.svol
-LOAD sortout, $vol2.altfile, SORTED, PARTOF $vol1, RECIN 22,
BLOCKIN 2200
-PURGE ! sortin, sortout

The CREATE commands create the disk file used as the output of BUILDKEYRECORDS (which
is also the input to SORT) and the disk file to be used as the output of SORT.
The BUILDKEYRECORDS command generates the alternate-key records for key specifier F2
of PRIFILE and writes the records to SORTIN. Record-blocking is used to improve the efficiency
of disk writes.
The SORT program sorts the alternate-key records. The key-field length for the sort is the same
as the alternate-key record length (22: 2 for the key specifier + 10 for alternate-key field length
+ 10 for the primary-key field length). The output file of the sort is SORTOUT.
164 File Loading

The LOAD command loads the secondary partition $VOL2.SVOL.ALTFILE with the alternate-key
records for key specifier F2. Note that the record blocking here is complementary to that used
with BUILDKEYRECORDS.

Loading a Partitioned, Alternate-Key File 165

13 Support and other resources
Accessing Hewlett Packard Enterprise Support
•

For live assistance, go to the Contact Hewlett Packard Enterprise Worldwide website:
www.hpe.com/assistance

•

To access documentation and support services, go to the HP Support Center – Hewlett
Packard Enterprise website:
www.hpe.com/support/hpesc

Information to collect
•

Technical support registration number (if applicable)

•

Product name, model or version, and serial number

•

Operating system name and version

•

Firmware version

•

Error messages

•

Product-specific reports and logs

•

Add-on products or components

•

Third-party products or components

Accessing updates
•

Some software products provide a mechanism for accessing software updates through the
product interface. Review your product documentation to identify the recommended software
update method.

•

To download product updates, go to either of the following:

◦

HP Support Center – Hewlett Packard Enterprise Get connected with updates from
HP page:
www.hpe.com/support/e-updates

◦

Software Depot website:
www.hpe.com/support/softwaredepot

•

To view and update your entitlements, and to link your contracts, Care Packs, and warranties
with your profile, go to the HP Support Center – Hewlett Packard Enterprise More Information
on Access to HP Support Materials page:
www.hpe.com/support/AccessToSupportMaterials
IMPORTANT: Access to some updates might require product entitlement when accessed
through the HP Support Center – Hewlett Packard Enterprise. You must have a Hewlett
Packard Enterprise Passport set up with relevant entitlements.

166 Support and other resources

Websites
Website

Link

Hewlett Packard Enterprise Information Library

www.hpe.com/info/enterprise/docs

HP Support Center – Hewlett Packard Enterprise

www.hpe.com/support/hpesc

Contact Hewlett Packard Enterprise Worldwide

www.hpe.com/assistance

Subscription Service/Support Alerts

www.hpe.com/support/e-updates

Software Depot

www.hpe.com/support/softwaredepot

Customer Self Repair

www.hpe.com/support/selfrepair

Insight Remote Support

www.hpe.com/info/insightremotesupport/docs

Serviceguard Solutions for HP-UX

www.hpe.com/info/hpux-serviceguard-docs

Single Point of Connectivity Knowledge (SPOCK)
Storage compatibility matrix

www.hpe.com/storage/spock

Storage white papers and analyst reports

www.hpe.com/storage/whitepapers

nl

Customer self repair
Hewlett Packard Enterprise customer self repair (CSR) programs allow you to repair your product.
If a CSR part needs to be replaced, it will be shipped directly to you so that you can install it at
your convenience. Some parts do not qualify for CSR. Your Hewlett Packard Enterprise authorized
service provider will determine whether a repair can be accomplished by CSR.
For more information about CSR, contact your local service provider or go to the CSR website:
www.hpe.com/support/selfrepair

Remote support
Remote support is available with supported devices as part of your warranty, Care Pack Service,
or contractual support agreement. It provides intelligent event diagnosis, and automatic, secure
submission of hardware event notifications to Hewlett Packard Enterprise, which will initiate a
fast and accurate resolution based on your product’s service level. Hewlett Packard Enterprise
strongly recommends that you register your device for remote support.
For more information and device support details, go to the following website:
www.hpe.com/info/insightremotesupport/docs

Documentation feedback
Hewlett Packard Enterprise is committed to providing documentation that meets your needs. To
help us improve the documentation, send any errors, suggestions, or comments to Documentation
Feedback (docsfeedback@hpe.com). When submitting your feedback, include the document
title, part number, edition, and publication date located on the front cover of the document. For
online help content, include the product name, product version, help edition, and publication date
located on the legal notices page.

Websites 167

A ASCII Character Set
Table 12 shows the USA Standard Code for Information Interchange (ASCII) character set, and
the corresponding code values in octal notation.
Table 12 ASCII Character Set
Character

Octal Value (left byte)

Octal Value (right byte)

Meaning

NUL

000000

000000

Null

SOH

000400

000001

Start of heading

STX

001000

000002

Start of text

ETX

001400

000003

End of text

EOT

002000

000004

End of transmission

ENQ

002400

000005

Enquiry

ACK

003000

000006

Acknowledge

BEL

003400

000007

Bell

BS

004000

000010

Backspace

HT

004400

000011

Horizontal tabulation

LF

005000

000012

Line feed

VT

005400

000013

Vertical tabulation

FF

006000

000014

Form feed

CR

006400

000015

Carriage return

SO

007000

000016

Shift out

SI

007400

000017

Shift in

DLE

010000

000020

Data link escape

DC1

010400

000021

Device control 1

DC2

011000

000022

Device control 2

DC3

011400

000023

Device control 3

DC4

012000

000024

Device control 4

NAK

012400

000025

Negative acknowledge

SYN

013000

000026

Synchronous idle

ETB

013400

000027

End of transmission block

CAN

014000

000030

Cancel

EM

014400

000031

End of medium

SUB

015000

000032

Substitute

ESC

015400

000033

Escape

FS

016000

000034

File separator

GS

016400

000035

Group separator

RS

017000

000036

Record separator

US

017400

000037

Unit separator

SP

020000

000040

Space

168 ASCII Character Set

Table 12 ASCII Character Set (continued)
!

020400

000041

Exclamation point

"

021000

000042

Quotation mark

#

021400

000043

Number sign

$

022000

000044

Dollar sign

%

022400

000045

Percent sign

&

023000

000046

Ampersand

'

023400

000047

Apostrophe

(

024000

000050

Opening parenthesis

)

024400

000051

Closing parenthesis

*

025000

000052

Asterisk

+

025400

000053

Plus

,

026000

000054

Comma

-

026400

000055

Hyphen (minus)

.

027000

000056

Period (decimal point)

/

027400

000057

Right slant

0

030000

000060

Zero

1

030400

000061

One

2

031000

000062

Two

3

031400

000063

Three

4

032000

000064

Four

5

032400

000065

Five

6

033000

000066

Six

7

033400

000067

Seven

8

034000

000070

Eight

9

034400

000071

Nine

:

035000

000072

Colon

;

035400

000073

Semicolon

<

036000

000074

Less than

=

036400

000075

Equals

>

037000

000076

Greater than

?

037400

000077

Question mark

@

040000

000100

Commercial "at"

A

040400

000101

Uppercase A

B

041000

000102

Uppercase B

C

041400

000103

Uppercase C

D

042000

000104

Uppercase D

E

042400

000105

Uppercase E

169

Table 12 ASCII Character Set (continued)
F

043000

000106

Uppercase F

G

043400

000107

Uppercase G

H

044000

000110

Uppercase H

I

044400

000111

Uppercase I

J

045000

000112

Uppercase J

K

045400

000113

Uppercase K

L

046000

000114

Uppercase L

M

046400

000115

Uppercase M

N

047000

000116

Uppercase N

O

047400

000117

Uppercase O

P

050000

000120

Uppercase P

Q

050400

000121

Uppercase Q

R

051000

000122

Uppercase R

S

051400

000123

Uppercase S

T

052000

000124

Uppercase T

U

052400

000125

Uppercase U

V

053000

000126

Uppercase V

W

053400

000127

Uppercase W

X

054000

000130

Uppercase X

Y

054400

000131

Uppercase Y

Z

055000

000132

Uppercase Z

[

055400

000133

Left square bracket

\

056000

000134

Left slant

]

056400

000135

Right square bracket

^

057000

000136

Circumflex

_

057400

000137

Underscore

`

060000

000140

Grave accent

a

060400

000141

Lowercase a

b

061000

000142

Lowercase b

c

061400

000143

Lowercase c

d

062000

000144

Lowercase d

e

062400

000145

Lowercase e

f

063000

000146

Lowercase f

g

063400

000147

Lowercase g

h

064000

000150

Lowercase h

i

064400

000151

Lowercase i

j

065000

000152

Lowercase j

170 ASCII Character Set

Table 12 ASCII Character Set (continued)
k

065400

000153

Lowercase k

l

066000

000154

Lowercase l

m

066400

000155

Lowercase m

n

067000

000156

Lowercase n

o

067400

000157

Lowercase o

p

070000

000160

Lowercase p

q

070400

000161

Lowercase q

r

071000

000162

Lowercase r

s

071400

000163

Lowercase s

t

072000

000164

Lowercase t

u

072400

000165

Lowercase u

v

073000

000166

Lowercase v

w

073400

000167

Lowercase w

x

074000

000170

Lowercase x

y

074400

000171

Lowercase y

z

075000

000172

Lowercase z

{

075400

000173

Opening brace

|

076000

000174

Vertical line

}

076400

000175

Closing brace

~

077000

000176

Tilde

DEL

077400

000177

Delete

171

B Block Formats of Structured Files
This appendix describes the block formats for key-sequenced, queue, entry-sequenced, and
relative files. A block in a structured file usually consists of a header, a record area, and a map
of offsets pointing to the beginning of each record. For relative files, an array of record lengths
replaces the offsets map.
Figure 24 (page 173) shows the format 1 block and Figure 31 (page 178) shows the format 2 block.
The data area of a key-sequenced or queue file begins with a bit-map block telling which data
and index blocks are in use. The second block is the root (highest-level) index block for the file.
The third block is either a second-level index block or the file's first data block.
The data area of a relative file also begins with a bit-map block telling which data blocks contain
at least one record. The block immediately following a bit-map block is always the first data block.
For entry-sequenced files, all blocks in the data area are data blocks.

172 Block Formats of Structured Files

Figure 24 Block Format for Structured Format 1 Files

[0]

eye-catcher

Length
in
Bytes
1

[1]

relative-sector-number

3

[4]

flags

1

[5]

index-level

1

[6]

volume-sequence-number

6

[12]

checksum

2

[14]

type-specific-block-header

Decimal
Offset

Common
Block
Header

[18, 20,
24, or
30]

[4, 6,
10, or
16]

(record 0)
(record 1)

Data
Area
(record N, where N = number-of-records -1)
free space (key-sequenced, queue, and
entry-sequenced files only)
(reserved)

2

byte offset from [0] to record N
(key-sequenced, queue, and
entry-sequenced files only)

size of record N
(relative file only)

2

byte offset from [0] to record 0
(key-sequenced, queue, and
entry-sequenced files only)

size of record 0
(relative file only)

2

byte offset from [0] to start of free space

Offsets
Map or
Recordsize
Array

[blocksize
- 2]

The fields in Figure 24 are defined as:
eye-catcher
is currently set to > but could be changed in a future
release.
relative-sector-number
identifies the relative 512-byte sector within the file.
flags
Bit 0: This bit is set (=1) if the block is broken (inconsistent).
Bits 1 and 2: These two bits are reserved for
decompression and are used internally for SQL
compression logic.
Bits 3 through 5: These three bits indicate the file type as:
000

(reserved)

001

Relative File
173

010

Entry-Sequenced File

011

Key-Sequenced or Queue File

100

(reserved)

101

(reserved)

110

(reserved)

111

Directory

Bits 6 and 7: These two bits indicate the block type as:

index-level
volume-sequence-number

checksum
type-specific-block-header

record

00

Data or Index

01

Bit Map (must be key-sequenced, queue, or relative file)

10

Free (must be key-sequenced or queue file)

11

(reserved)

contains the tree level of the block. If the block is not an
index block, level = 0.
identifies the last update of a structured block. This number
is incremented each time a change is made to the block,
regardless of whether the block is written to disk. For an
audited file, the volume sequence number is included in
the auditcheckpoint (AC) record. Later, during autorollback
or takeover, the number in the block header is compared
with the number in the AC record to determine whether the
AC record must be applied. For a nonaudited file, the
volume sequence number is included in the checkpoint AC
record.
is the software checksum over the entire block.
is the block-header area that differs according to the type
of file. For more information on illustrations of the different
block header types, see Figure 25 through Figure 29,
Figure 30 illustrates the arrangement of bit-map blocks
within key-sequenced, queue, and relative files.
can be a data or index record. The length of record N in a
key-sequenced, queue, or entry-sequenced file is:
offset-to-record N + 1 - offset-to-record N

A record must be able to fit into the record area of one
block. Thus the maximum record length for key-sequenced
or queue files is the block size minus 34 (30 bytes for the
header and 4 for the smallest possible offsets map).
The format of an index record is as:
0

N

Key value (variable length N-3)

byte 0

byte 1

byte 3

Relative Sector Number of
Block at Next Level

The relative-sector-number field in an index record
points to the start of the block associated with this key. A
null key value is used when KEYLEN = 0; this occurs in
any index record pointing to an index block or to the first
data record.
174 Block Formats of Structured Files

Figure 25 Index Block Header for Key-Sequenced and Queue Files
Offset
(Decimal)
0

common-block-header

14

number-of-records-allocated

16

(reserved)

24

(record 0)

Length
in
Bytes
14
2
8

The fields in Figure 25 are defined as:
common-block-header
is the 14-byte common block header shown in Figure 24.
number-of-records-allocated indicates how many records have been allocated in the
block.
Figure 26 Data Block Header for Key-Sequenced and Queue Files
Offset
(Decimal)
0

common-block-header

14

number-of-records-allocated

16
24
27
30

(reserved)
relative-sector-number
of next data block
relative-sector-number
of previous data block

Length
in
Bytes
14
2
8
3
3

(record 0)

The fields in Figure 26 are defined as:
common-block-header
is the 14-byte common block header shown in Figure 24.
number-of-records-allocated indicates how many records have been allocated in the
block.
relative-sector-number of
provides a link to the next logical block. The current block's
relative-sector-number is given in the common block
next data block
header.
relative-sector-number of
provides a link to the previous logical block.
previous data block

175

Figure 27 Header for Entry-Sequenced Data Block
Offset
(Decimal)
0

common-block-header

Length
in
Bytes
14

14

number-of-records-allocated

2

16

(reserved)

4

20

(record 0)

The fields in Figure 27 are defined as:
common-block-header
is the 14-byte common block header shown in Figure 24.
number-of-records-allocated indicates how many records have been allocated in the
block.
Figure 28 Header for Relative Data Block
Offset
(Decimal)
0

common-block-header

Length
in
Bytes
14

14

number-of-records-allocated

2

16

2

number-of-records-present

18

(reserved)

20

(record 0)

2

The fields in Figure 28 are defined as:
common-block-header
is the 14-byte common block header shown in Figure 24.
number-of-records-allocated indicates how many records have been allocated in the
block.
number-of-records-present
indicates how many records are present in the block.
Figure 29 Header for Bit-Map Block
Offset
(Decimal)
0

common-block-header

14

number-of-free-bits

18

bit-map

The fields in Figure 29 are defined as:
176 Block Formats of Structured Files

Length
in
Bytes
14
4
block size - 18

common-block-header
number-of-free-bits

bit-map

is the 14-byte common block header shown in Figure 24.
indicates how many bits in this bit-map identify blocks that are free
(empty) in a key-sequenced or queue file. For relative files, it
indicates how many bits identify blocks that are not full.
is an array of bits describing availability of index or data blocks.
For a key-sequenced or queue file, each bit tells whether the
corresponding block is free (0) or in use (1). For a relative file,
each bit tells whether there is room for at least one more record
in the corresponding block.
An empty bit-map has (8 * (block-size - 18) ) free bits.
With a 1024-byte block, for example, the map has 8048 available
bits.

Figure 30 Arrangement of Bit-Map Blocks
header

bits b(1) b(2) b(3) . . . b(n)
data or index block

Block 0 is the
first
bit-map block.
Block 1

•••

header

data or index block

Block N

bits b(1) b(2) b(3) . . . b(n)

Block N+1

data or index block

Block N+2

•••
data or index block

Block 2N+1

177

Figure 31 Block Format for Structured Format 2 Files
Decimal
Offset

Common
Block
Header

[0]

relative-block number

4

[4]

flags

2

[6]

block-level

2

[8]

large-block-flags

4

[12]

checksum

2

[14]

block-version

2

[16]

[28]

8

volume-sequence-number

[24]

Length
in
Bytes

checksum-32-bit

4

type-specific-block- header
(record 0)

Data
Area

(record N, where N = number-of-records -1)
free space (key-sequenced, queue, and
entry-sequenced files only)

Offsets
Map or
Recordsize
Array

byte offset from [0] to start of free
space
byte offset from [0] to record N
(key-sequenced, queue, and
entry-sequenced files only)

[blocksize
- 12]

(reserved)
size of record N
(relative file
only)

byte offset from [0] to record 0
(key-sequenced, queue, and
entry-sequenced files only)
(reserved)

size of record 0
(relative file
only)

4
4

4
8

The fields in Figure 31 are defined as:
relative-block-number
identifies the relative block number within the file.
flags
Bit 0: This bit is set (=1) if the block is broken (inconsistent).
Bits 1 and 2: These two bits are reserved for decompression
and are used internally for SQL compression logic.
Bits 3 through 5: These three bits indicate the file type as:

178 Block Formats of Structured Files

000

(reserved)

001

Relative File

010

Entry-Sequenced File

011

Key-Sequenced or Queue File

100

(reserved)

101

(reserved)

110

(reserved)

111

Directory

Bits 6 and7: These two bits indicate the block type as:
00

Data or Index

01

Bit Map (must be key-sequenced, queue, or relative file )

10

Free (must be key-sequenced or queue file)

11

(reserved)

block-level
large-block-flags

contains the tree level of the block.
Bit 0: This bit is set (=1) if the checksum is valid.
Bit 1: This bit is set (=1) if the 32-bit checksum is valid.
Bit 2: This bit is set (=1) if the partial checksum is used.

checksum
block-version
volume-sequence-number

is the software checksum over the entire block.
identifies which format (1 or 2) is being used for the block
identifies the last update of a structured block. This number
is incremented each time a change is made to the block,
regardless of whether the block is written to disk. For an
audited file, the volume sequence number is included in the
auditcheckpoint (AC) record. Later, during autorollback or
takeover, the number in the block header is compared with
the number in the AC record to determine whether the AC
record must be applied. For a nonaudited file, the volume
sequence number is included in the checkpoint AC record.
is a field reserved for future use and is currently unused.
can be a data or index record. The length of record N in a
key-sequenced, queue, or entry-sequenced file is

checksum-32-bit
record

offset-to-record N + 1 - offset-to-record N

A record must be able to fit into the record area of one block.
Thus the maximum record length for key-sequenced or queue
files is the block size minus 56 (40 bytes for the header, 8 for
the trailer and 8 for the smallest possible offsets map).
The format of an index record is as:
0

Key value (variable length N-3)

relative block number pointe

Relative Block Number
Associated With Key

The relative-block-number field in an index record points
to the start of the block associated with this key. A null key
value is used when KEYLEN = 0; this occurs for the first record
in an index block.

179

Figure 32 Index Block Header for Key-Sequenced and Queue Format 2 Files
Offset
(Decimal)
0

common-block-header

28

number-of-records-allocated

32

(reserved)

40

(record 0)

Length
in
Bytes
28
4
8

The fields in Figure 32 are defined as:
common-block-header
is the 28-byte common block header shown in Figure 31.
number-of-records-allocated indicates how many records have been allocated in the
block.
Figure 33 Data Block Header for Key-Sequenced and Queue Format 2 Files
Offset
(Decimal)
0

common-block-header

28

number-of-records-allocated

32
36
40

relative-block-number
of next data block
relative-block-number
of previous data block

Length
in
Bytes
28
4
4
4

(record 0)

The fields in Figure 33 are defined as:
common-block-header
is the 28-byte common block header shown in Figure 31.
number-of-records-allocated indicates how many records have been allocated in the
block.
relative-block-number of
provides a link to the next logical block. The current block's
relative-block-number is given in the common block
next data block
header.
relative-block-number of
provides a link to the previous logical block.
previous data block

180 Block Formats of Structured Files

Figure 34 Header for Format 2 Entry-Sequenced Data Block
Offset
(Decimal)
0

common-block-header

28

number-of-records-allocated

32

(record 0)

Length
in
Bytes
28
4
2

The fields in Figure 34 are defined as:
common-block-header
is the 28-byte common block header shown in Figure 31.
number-of-records-allocated indicates how many records have been allocated in the
block.
Figure 35 Header for Format 2 Relative Data Block

0

common-block-header

Length
in
Bytes
28

28

number-of-records-allocated

4

32

number-of-records-present

4

36

(record 0)

4

Offset
(Decimal)

The fields in Figure 35 are defined as:
common-block-header
is the 28-byte common block header shown in Figure 31.
number-of-records-allocated indicates how many records have been allocated in the
block.
number-of-records-present
indicates how many records are present in the block.
Figure 36 Header for Bit-Map Block
Offset
(Decimal)
0

common-block-header

28

number-of-free-bits

32

bit-map

Length
in
Bytes
28
4
block size - 32

The fields in Figure 36 are defined as:
181

common-block-header
number-of-free-bits

bit-map

182 Block Formats of Structured Files

is the 28-byte common block header shown in Figure 31.
indicates how many bits in this bit-map identify blocks that are free
(empty) in a key-sequenced or queue file. For relative files, it
indicates how many bits identify blocks that are not full.
is an array of bits describing availability of index or data blocks.
For a key-sequenced or queue file, each bit tells whether the
corresponding block is free (0) or in use (1). For a relative file,
each bit tells whether there is room for at least one more record
in the corresponding block.
An empty bit-map has 8 * (block-size - 32) free bits.
With a 1024-byte block, for example, the map has 7872 available
bits.

C Action of Current Key, Key Specifier, and Key Length
This appendix contains pseudocode descriptions of the behavior of basic file-system operations
and their relationships to file-currency information. The variables and functions used in the
pseudocode are defined first. By evaluating the pseudocode, you can determine the action of
the current key, key specifier, and key length for the different file-system operations.

Variable Definitions
These variables are used in the pseudocode descriptions:
CKV
current key value
CKS
current key specifier
CKL
current key length
CMPL
comparison length
MODE
positioning mode : (approximate = 0, generic = 1, exact = 2)
REVERSE indicates whether the descending direction is to be used
primary
0
next
true if the next record in sequence is to be the reference
rip
relative file insertion pointer
present
true if parameter is supplied
keyseq
file type 3 (key-sequenced and queue files)
entryseq
file type 2
relative
file type 1

Function Definitions
These functions are used in the pseudocode descriptions:
•

keyfield (record, specifier)
returns the value of the “specified” key field in the record. If the file is not key-sequenced
and specifier = 0, then a record number or record address is returned.

•

keylength (record, specifier)
returns the length of the “specified” key field in the record. If record = 0, this returns the
defined key-field length.

•

find (mode, specifier, key value, comparison length, direction)
returns the position of first record in the file according to mode, specifier, key value,
comparison length, and direction.

◦

If mode = 0 (approximate) positioning is to the first record whose key field, as designated
by the key specifier, is greater than or equal to the key value. If no such record
exists, an end-of-file indication is returned.

◦

If mode = 1 (generic), positioning is to the first record whose key field, as designated
by the key specifier, contains a value equal to key for comparison length
bytes. If no such record exists, an end-of-file indication is returned.

◦

If mode = 2 (exact), positioning is to the first record whose key field, as designated by
the key specifier, contains a value of exactly comparison length bytes and is
equal to key. If no such record exists, an end-of-file indication is returned.

Variable Definitions 183

•

•

find^next (mode, specifier, key value, comparison length, direction)
returns the position of the next record in the file according to mode, specifier, key value,
comparison length, and direction.

◦

If mode = 0 (approximate), positioning is to the next record.

◦

If mode = 1 (generic), positioning is to the next record. If the key field designated by the
key specifier does not equal key for comparison length bytes, an end-of-file
indication is returned.

◦

If mode = 2 (exact), an end-of-file indication is returned.

insert (key value, key length)
returns the position where a record is to be added, according to the specified key value and
key length. If a record already exists at the indicated position, a “duplicate record” indication
is returned. For relative and entry-sequenced files, a key value of “-1” returns the end-of-file
position and a key value of “-2” returns the position of the first available record.

Pseudocode Descriptions
These sets of pseudocode describe the behavior of the OPEN, KEYPOSITION, POSITION,
READ, READUPDATE, WRITEUPDATE, and WRITE procedures.

OPEN (FILE_OPEN_)
CKS := primary
if keyseq then CKL := CMPL := 0
else
begin
if format I file format CKL := 4
else CKL := 8;
CKV := rip := 0;
end;
MODE := approx;
next := false;
REVERSE := false;

FILE_SETKEY_, KEYPOSITION:
CKV := rip := key
if position-to-last then pad out CKV with %hFF
CKS := if present then key specifier else primary;
CKL := CMPL := if present then comparison length
else keylength (0, CKS);
MODE := if present then positioning mode else approx;
next := false;
REVERSE := reverse;

FILE_SETPOSITION_, POSITION:
CKV := rip := record specifier;
CKS := primary
if format I file format then CMPL := CKL := 4
else CMPL := CKL := 8;
MODE := approx;
next := false;
REVERSE := false;

READ:
position := if next then find^next (MODE, CKS, CKV, CMPL,
REVERSE)
184 Action of Current Key, Key Specifier, and Key Length

else find (MODE, CKS, CKV, CMPL, REVERSE);
if error then return;
record := file[position];
CKV := rip := keyfield (record, CKS);
CKL := keylength (record, CKS);
next := true;

READUPDATE:
position := find (exact, CKS, CKV, CKL, REVERSE);
if error = 1 then error := 11; if error then return;
record := file[position];

WRITEUPDATE:
position := find (exact, CKS, CKV, CKL, REVERSE);
if error = 1 then error := 11; if error then return;
if write count = 0 then
if entryseq then begin error := 21; return; end;
else delete the record
else file[position] := record;

WRITE:
if keyseq then
begin
position := insert (keyfield (record, primary),
keylength (record, primary));
if error then return;
file[keyposition] := record;
end;
if relative then
begin
if CKS then begin error := 46; return; end;
if rip <> -2 and rip <> -1 and next then rip := rip +1;
position := insert (rip, 4);
if error then return;
file[position] := record;
CKV := keyfield (record, primary);
next := true;
end;
if entryseq then
begin
if CKS then begin error := 46; return; end;
position := insert (-1,4); ! end-of-file
file[position] := record;
CKV := keyfield (record, primary);
next := true;
end;

Pseudocode Descriptions 185

Index
A
Access examples
entry-sequenced files, 130
key-sequenced files, 86
queue files, 117
relative files, 146
unstructured files, 63
Access modes, 22
Access paths
exact positioning mode, 31
generic positioning mode, 30
overview, 27
relational access, 36
accessing
updates, 166
Accessing files
entry-sequenced files, 130
key-sequenced files, 68, 85
queue files, 109
relative files, 134, 143
unstructured files, 59
Alternate keys
attributes
automatic updating, 33
null value, 33
attributes:null value, 33
automatic maintenance, 33
example, 27, 87, 90, 93, 99
file creation, 70, 123, 135
in a key-sequenced file, 33
in a relative file, 34
in an entry-sequenced file, 34
insertion-ordered, 27
overview, 31
record format, 31
Alternate-key files
automatic updating, 33
contents, 34
example of file creation, 81, 128, 140
key length, 35
key offset, 32
key specifier, 32
multiple, 34
Approximate positioning mode, 30
audit-checkpoint, 48
Audit-checkpoint compression, 48
Audited files, Errors in opening, 158
Autorefresh option, 57, 62, 143

B
Bit-map blocks in key-sequenced files, 68, 172
Block Format (1), 173
Block Format (2), 177
Block formats of structured files, 172
Block size
determining, 73, 123, 136
186 Index

index blocks, 73
relative to extent size, 45, 73, 124, 136
Block splits in key-sequenced files, 68
Block, defined, 20, 73
Buffer parameter in procedure calls, 41
Buffering
cache, 53
buffered, 53
write-through, 53
sequential block buffering
FILE_OPEN_ parameters, 55
limited use of disk process, 55
shared file access, 56
sharing buffer space, 56
BUFFERSIZE attribute, 60

C
Cache access modes
direct I/O, 56
random access, 56
sequential access, 56
system-managed access, 56
Cache access types, 53
Collating sequence, 74
Communication path errors, 160
Compaction, index, 75
COMPRESS parameter, 74
Compression, 48
Condition codes, 41
contacting Hewlett Packard Enterprise, 166
CONTROL procedure
allocating extents, 20, 58, 161
AWAITIO required with nowait I/O, 40
deallocating extents, 58
purging data, 57
write access required, 42
CREATE procedure
enabling compression, 74
setting autorefresh option, 62, 143
Creating
entry-sequenced files, 123
files, 20
key-sequenced files, 70
queue files, 107
relative files, 135
Current position relative to locks, 29
Current-key specifier definition, 27
Current-key value
key-sequenced files, 86
queue files, 116
Current-record pointer
relative files, 134, 143
unstructured files, 62
customer self repair, 167

D
Data errors, 160

DCOMPRESS parameter, 74
Deadlock, 155
Deleting data, 57
Deleting records, 86, 97, 146
Dequeuing records, 110
Device operation errors, 160
Direct-I/O cache access mode, 56
Directory, 22
Disk extent size
entry-sequenced files, 124
key-sequenced files, 73
relative files, 136
unstructured files, 60
documentation
providing feedback on, 167

E
EDIT files
how to read, 59
structure imposed by EDIT, 59
EDITREAD procedure, 59
End-of-file pointer, 134
Entry-sequenced files
access examples, 130
accessing, 130
comparison with other types, 24
creating, 123
disk extent size, 124
example of file creation, 128
examples of file creation, 124, 126
file creation examples, 124
record address, 25
record length, maximum, 123
use of alternate keys, 34
EOF pointer
encountered during sequential access, 64
key-sequenced files, 85
refreshing, 57
relative files, 134
unstructured files, 62
updating of, 62, 143
Errors
categories, 160
communication path errors, 160
data errors, 160
device operation errors, 160
extent allocation errors, 160
failure of primary application process, 161
from procedure calls, 42
messages, 160
partitioned files, 161
path errors, 160
Exclusion modes, 22
Exclusive access, 22
Extent size
entry-sequenced files, 124
key-sequenced files, 73
relative files, 136
unstructured files, 60

Extents
allocating and deallocating, 20, 58, 161
definition, 20
in file directory, 22
primary, 20
secondary, 20
size relative to block size, 45, 73, 124, 136
External declarations of procedures, 43

F
Failure of primary application process, 161
FCB, 62, 143
Field, defined, 25
File codes, 45
File control block, 143
File creation
alternate-key files, 70, 123, 135
block size
determining, 73, 123, 136
relative to extent size, 45, 73, 124, 136
block size:relative to extent size, 45
COMPRESS parameter, 74
DCOMPRESS parameter, 74
entry-sequenced files, 123
examples
alternate-key file, 81, 128, 140
entry-sequenced file, 124
entry-sequenced with alternate keys, 126
entry-sequenced, partitioned file, 128
key-sequenced file, 75
key-sequenced file with alternate keys, 77
key-sequenced, partitioned file, 82
relative file, 138
relative, partitioned file, 141
unstructured file, 61
extent size relative to block size, 45, 73, 124, 136
file codes, 45
ICOMPRESS parameter, 74
index blocks, 73
key specifier, 32
key-sequenced files
index blocks, 73
primary-key offset, 74
offset of alternate keys, 32
offset of primary key, 74
partitioned files, 123, 135
primary-key offset, 74
relative files, 135
two methods, 23
with ODDUNSTR parameter, 64
File directory, 22
File expiration dates, 52
File Format
comparison, 46
See also Format 1 and 2 Files, 45
Supported, 45
File identifiers partitioned files, 21
File loading
adding an alternate key, 162, 163
187

key-sequenced file, 162
loading a single partition, 164
reloading a single partition, 163
File locks
description of, 151
interaction with record locks, 154
unstructured files, 155
File numbers, 41
File opening
access types, 56
partitioned files, 21, 50
permanent disk file, 50
File size limits, 47
entry-sequenced files, 48
key-sequenced files, 47
relative files, 48
unstructured files, 48
File types, 20
File Utility Program see FUP
File, defined, 19
FILE_OPEN_ procedure, behavior of, 184
FILE_RENAME_ procedure
error 27 for uncompleted operations, 40
FILE_SETPOSITION_ procedure
behavior of, 184
description of, 40
error 27 for uncompleted operations, 40
unstructured files, 65
Files
creating, 20
partitioned, 20, 21
permanent, 20
structured, 20
temporary, 20
unstructured, 20
Format 1 and 2 Files
Block Format (1), 173
description of, 19
FUP
ALTER command, 62, 143
BUILDKEYRECORDS command, 162
COMPRESS parameter, 74
DCOMPRESS parameter, 74
ICOMPRESS parameter, 74
LOAD command, 162
LOADALTFILE command, 162
PURGEDATA command, 57
SET command, 74, 143
setting or altering autorefresh option, 62, 143

G
Generic locking, 152
Generic positioning mode, 30

I
ICOMPRESS parameter, 74
Index blocks, 73
Index compaction, 75
Inserting records, 146
188 Index

Insertion-ordered alternate keys, 27

K
Key
alternate, 21
definition, 20
Key specifier, 27, 32
Key-sequenced files
accessing, 68, 85
bit-map blocks, 68, 172
block splits, 68
comparison, 71, 72
comparison with other types, 24
current primary-key value, 86
disk extent size, 73
end-of-file pointer, 85
EOF pointer, 85
file creation examples, 75
index blocks, 73
primary-key offset, 74
record length, 67, 73
sequential processing, 85
structure, 67
tree structure, 68
types of access, 68
use of alternate keys, 33
KEYPOSITION procedure
behavior of, 184
entry-sequenced files, 130
error 27 for uncompleted operations, 40
use of, 27

L
Loading files, 23
LOCKFILE procedure
AWAITIO required with nowait I/O, 40
description of, 151
Locking modes, 150
LOCKREC procedure
AWAITIO required with nowait I/O, 40
description of, 152
Locks
after KEYPOSITION procedure, 86, 145
deadlock, 155
generic, 152
interaction between file and record, 154
maximum number of, 154, 156
maximum per file, 159
on whole files, 159
owner of, 156
partitioned files, 21
positioning for, 29
with sequential block-buffering, 155
with TMF, 22, 155
Locks:interaction
between file and record, 154
Logical record, defined, 19, 72

M
MAXEXTENTS attribute, 20
Multiple accessors of a file, 22

N
Next-record pointer
relative files, 134, 143
unstructured files, 62
NEXTFILENAME procedure, 40
Nowait I/O, defined, 22
Null value attribute, 33

use of file numbers and file names, 41
sequential I/O (SIO)
general characteristics, 43
Protected access, 22
PURGE procedure, 40
Purging data, 57

Q

ODDUNSTR parameter, 64
OPEN procedure
behavior of, 184
description of, 40
example, 50
sequential block buffering, 55

Queue files
access examples, 117
accessing, 107, 109
description of, 106
file creation examples, 108
primary key, 107
record format, 107
structure, 107
sync depth, 110
timestamp in primary key, 107
Queuing records, 110

P

R

Page, defined, 20
Partitioned files
creation of all partitions, 123, 135
definition, 21
differences among partitions, 21
example of file creation, 82, 128, 141
file identifiers, 21
locks, 21
number of extents, 20
opening, 21, 50
Permanent files, 50
POSITION procedure
behavior of, 184
description of, 40
error 27 for uncompleted operations, 40
unstructured files, 65
use of, 27
Positioning
in relative files, 133
in structured files, 27
Positioning modes, 29
primary extent, 20
Primary key
example, 26
in a key-sequenced file, 25
in a queue file, 107
in a relative file, 25
in an entry-sequenced file, 25
offset, 74
Procedures
file system
behavior of, 183
buffer parameter, 41
condition codes, 41
external declarations, 43
summary table, 38
tag parameter, 41
transfer count parameter, 41

Random access
entry-sequenced files, 130
key-sequenced files, 85
queue files, 107
relative files, 145
unstructured files, 65
Random cache access mode, 56
RBA
defined, 20
READ procedure
AWAITIO required with nowait I/O, 40
behavior of, 184
entry-sequenced files, 130
for queue files, 109
for sequential processing, 144
key-sequenced files, 85
queue files, 110
read access required, 42
unstructured files, 63
Read reverse, 51
Read-only access, 22
Read/write access, 22
READLOCK procedure
AWAITIO required with nowait I/O, 40
description of, 40
entry-sequenced files, 130
for sequential processing, 144
key-sequenced files, 85
queue files, 110
read access required, 42
unstructured files, 63
READLOCK procedure description of, 152
READUPDATE procedure
AWAITIO required with nowait I/O, 40
behavior of, 185
description of, 40
key-sequenced files, 85
read access required, 42

O

189

relative files, 145
unstructured files, 65
READUPDATELOCK procedure
AWAITIO required with nowait I/O, 40
description of, 40, 152
key-sequenced files, 85
queue files, 110
read access required, 42
relative files, 145
Record
definition, 19
structure, 25
Record length
key-sequenced files, 67
maximum size, 72
relative files, 133
Record locks
description of, 151
interaction with file locks, 154
unlocking, 152
unstructured files, 155
Records
deleting, 86, 97, 146
inserting, 86, 146
REFRESH procedure, 40
Refreshing file information, 62, 143
Refreshing the EOF pointer, 57
Relational access, 36
Relational processing example, 99
Relative byte address see RBA
Relative files
accessing, 134, 143
application example, 134
comparison with other types, 24
creating, 135
current-record pointer, 134, 143
disk extent size, 136
EOF pointer, 134
example of file creation, 141
examples of file creation, 138
file creation examples, 137
next-record pointer, 134, 143
positioning, 133
record length, 133
record numbers, 25, 133
structure, 133
types of access, 134
use of alternate keys, 34
remote support, 167
Removing data, 57
RENAME procedure, 40
REPOSITION procedure
description of, 40
error 27 for uncompleted operations, 40

S
SAVEPOSITION procedure, 40
Secondary extent, 20
Sector, defined, 19
190 Index

Sequential access, 63, 85, 130, 144
Sequential block buffering, 54
Sequential cache access mode, 56
Sequential cache access type, 53
SETKEY procedure, 39
SETMODE 92, 161
SETMODE procedure
description of, 40
error 27 for uncompleted operations, 40
SETMODENOWAIT procedure
AWAITIO required with nowait I/O, 40
description of, 40
error 27 for uncompleted operations, 40
SETPOSITION procedure, 39
Shared access, 22
Size limits
entry-sequenced files, 48
individual partitions, 47
key-sequenced files, 47
relative files, 48
unstructured files, 48
Structured files
block formats, 172
block size relative to extent size, 45, 73, 124, 136
comparison table, 24
definition, 20
key-sequenced file structure, 67
relative file structure, 133
support
Hewlett Packard Enterprise, 166
Sync depth, for queue files, 110
System-managed cache access mode, 56

T
Tag parameter in procedure calls, 41
Terminology, 19
Timestamp for queue file records, 107
Timestamps, 52
TMF
auditing, defined, 22
locking rules, 155
record locking, 22
Transactions locks, 155
Transfer count parameter, 41
Tree structure in key-sequenced files, 68
Types of access
key-sequenced files, 68
queue files, 107
relative files, 134

U
UNLOCKFILE procedure
AWAITIO required with nowait I/O, 40
description of, 40, 151
UNLOCKREC procedure
AWAITIO required with nowait I/O, 40
description of, 40, 152
Unstructured files
BUFFERSIZE attribute, 60

current-record pointer, 59
definition, 20
disk extent size, 60
EOF pointer, 59
file creation examples, 61
file locks, 155
next-record pointer, 59
random access, 65
record locks, 155
types of access, 59
updates
accessing, 166

V
Verification of WRITE operations, 49

W
Waited I/O, defined, 22
websites, 167
customer self repair, 167
WRITE procedure
AWAITIO required with nowait I/O, 40
behavior of, 185
description of, 40
effects on current-record pointer, 63
effects on EOF pointer, 63
effects on next-record pointer, 63
key-sequenced files, 86
queue files, 110
relative files, 146
unstructured files, 63, 66
verification, 49
write access required, 42
Write-only access, 22
WRITEUPDATE procedure
behavior of, 185
description of, 40
key-sequenced files, 85
relative files, 145
unstructured files, 65
write access required, 42
WRITEUPDATEUNLOCK procedure
AWAITIO required with nowait I/O, 40
description of, 40, 152
key-sequenced files, 85
relative files, 145
write access required, 42

191



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.4
Linearized                      : Yes
Author                          : Hewlett Packard Enterprise
Create Date                     : 2015:08:30 00:19:57Z
Keywords                        : NonStop
Modify Date                     : 2015:08:29 18:24:49-06:00
XMP Toolkit                     : Adobe XMP Core 5.2-c001 63.139439, 2010/09/27-13:37:26
Format                          : application/pdf
Title                           : Enscribe Programmer’s Guide
Creator                         : Hewlett Packard Enterprise
Producer                        : XEP 4.18 build 20100322
Trapped                         : False
Creator Tool                    : Unknown
Metadata Date                   : 2015:08:29 18:24:49-06:00
Document ID                     : uuid:a31538da-a7ec-4413-8879-7e076404c59b
Instance ID                     : uuid:be836366-3d11-43c3-8e9c-41f9a59b62bd
Page Mode                       : UseOutlines
Page Count                      : 191
EXIF Metadata provided by EXIF.tools

Navigation menu