<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://try-as400.pocnet.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Greenfive</id>
	<title>Try-AS/400 - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://try-as400.pocnet.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Greenfive"/>
	<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/wiki/Special:Contributions/Greenfive"/>
	<updated>2026-07-05T20:39:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Porting_C-Source_to_OS/400&amp;diff=1708</id>
		<title>Porting C-Source to OS/400</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Porting_C-Source_to_OS/400&amp;diff=1708"/>
		<updated>2026-04-28T21:55:17Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FIXME|Complete with Links to all necessary Books.}}&lt;br /&gt;
Because of the &#039;&#039;uncommon&#039;&#039; file handling, name length and character constraints, porting is already a mostly manual task.&amp;lt;ref&amp;gt;It&#039;s possible to use stream files in IFS as compiler input, but compiled objects have to be put into a &#039;&#039;QSYS.LIB&#039;&#039;, library. So, the file name restrictions apply anyway. The line length problem is mostly gone, though.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most often, the real challenge is to manually put together a &#039;&#039;config.h&#039;&#039; file. Since there&#039;s no capable UNIX shell environment, &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt; is no option.&amp;lt;ref&amp;gt;With V4R5, IBM claims to have implemented the C90 standard in Compiler and C-Library. I did not yet find a readymade &#039;&#039;config.h&#039;&#039; with all statements needed for a C90 environment.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These are definitions for integers, being used often. This can be put e.&amp;amp;thinsp;g. into a separate header file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef __stdint_h                                                                                   &lt;br /&gt;
typedef unsigned long long int uint64_t;                                                             &lt;br /&gt;
typedef unsigned int uint32_t;                                                                       &lt;br /&gt;
typedef unsigned short int uint16_t;                                                                 &lt;br /&gt;
typedef unsigned char uint8_t;                                                                       &lt;br /&gt;
#define __stdint_h 1                                                                                 &lt;br /&gt;
#endif                                                                                               &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039; The IMPI (CISC) C compiler in V3R2 and earlier doesn&#039;t know &amp;lt;tt&amp;gt;long long&amp;lt;/tt&amp;gt;, it&#039;s 32 bits only.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Preparations for QSYS.LIB ==&lt;br /&gt;
Preparations are mostly done on UNIX/Linux side. This is required to make the older V4R5 compiler happy. Newer compilers might be more forgiving.&lt;br /&gt;
&lt;br /&gt;
# Convert to native line endings for your platform, if the source files don&#039;t match.&lt;br /&gt;
# Convert Tabs to spaces:&amp;lt;ref&amp;gt;Tabs appear in SEU as only one blank. This makes source indentation hardly visible.&amp;lt;/ref&amp;gt;&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;for FILE in *.c *.h; do cp ${FILE} ${FILE}~; expand -i -t4 &amp;lt; ${FILE}~ &amp;gt; ${FILE}; done&amp;lt;/code&amp;gt;&lt;br /&gt;
# Find out longest line in all C- and H-Files.&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;wc -L *.c |sort -rn |head&amp;lt;/code&amp;gt;&lt;br /&gt;
# Eliminate too long lines by wrapping. This is easily done with &amp;lt;code&amp;gt;set colorcolumn=80&amp;lt;/code&amp;gt; in &#039;&#039;vim&#039;&#039;, and scrolling through the files with a wide window. &amp;lt;ref&amp;gt;Wider than 80 chars, that is.&amp;lt;/ref&amp;gt;&lt;br /&gt;
# Find C++-style comments and convert to proper C comments.&lt;br /&gt;
# Find function definitions which should be inlined, remove the word &amp;quot;inline&amp;quot; from the definition, and add a hint for the preprocessor/compiler that a function should be inlined before the function definition: &amp;lt;code&amp;gt;#pragma inline (&#039;&#039;functionname&#039;&#039;)&amp;lt;/code&amp;gt;&lt;br /&gt;
# Find and remove text following &amp;lt;code&amp;gt;#endif&amp;lt;/code&amp;gt; preprocessor statements in the same line (thought as comment).&lt;br /&gt;
# Create (at least) &#039;&#039;&#039;two&#039;&#039;&#039; appropriate SRCPF with matching maximum line lengths through the RCDLEN parameter for CRTSRCPF:&lt;br /&gt;
## One (or more) for C-Files (&#039;&#039;may&#039;&#039; be named &#039;&#039;QCSRC&#039;&#039;),&amp;lt;ref&amp;gt;It could be clever to create one PF per subdirectory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
## One for H-Files (&#039;&#039;&#039;must&#039;&#039;&#039; be named &#039;&#039;H&#039;&#039;).&lt;br /&gt;
# Upload.&lt;br /&gt;
## If the file names are already shorter than 10 Characters (excluding file extension), just upload to a SRC PF:&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;for FILE in *.c; do echo -n &amp;quot;put ${FILE} MYLIB/QCSRC.&amp;quot;; basename ${FILE} .c; done |ftp as400&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;Automatic login and switching to ASCII mode is done though a &#039;&#039;~/.netrc&#039;&#039;-file.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;FTP ASCII takes care to convert ASCII to EBCDIC.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
## If the file names are longer, you&#039;ll have considerable fun to come up with shorter names. Possibly &#039;&#039;grep&#039;&#039; through, and replace names in all text files if you needed to shorten a &#039;&#039;.h&#039;&#039; name. Finally, put together a text file with appropriate &#039;&#039;put&#039;&#039; commands, and hope for the best.&lt;br /&gt;
# Change file type to &#039;&#039;C&#039;&#039;:&amp;lt;br&amp;gt;&amp;lt;code&amp;gt;for FILE in *.c; do echo &amp;quot;quote rcmd CHGPFM FILE(MYLIB/QCSRC) MBR($(basename ${FILE} .c)) SRCTYPE(C)&amp;quot;; done |ftp as400&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;This is a good example how to exploit the ftp server&#039;s ability to call CL commands as a replacement for &#039;&#039;rcmd&#039;&#039;.&amp;lt;/ref&amp;gt; Note: You&#039;ll need to do this for header files, also!&lt;br /&gt;
&lt;br /&gt;
The precompiler searches private includes in &#039;&#039;*LIBL/H&#039;&#039;, without the &#039;&#039;.h&#039;&#039;-Extension.&lt;br /&gt;
&lt;br /&gt;
== Compile Cycle ==&lt;br /&gt;
Compile object files as follows:&lt;br /&gt;
 CRTCMOD MODULE(MYLIB/MAIN) SRCFILE(MYLIB/QCSRC) DEFINE(DEF1 DEF2=1) OPTION(*LOGMSG) OUTPUT(*PRINT)&lt;br /&gt;
* Add &amp;lt;code&amp;gt;SYSIFCOPT(*IFSIO *IFS64IO)&amp;lt;/code&amp;gt; to the compiler parameters if the code contains &amp;lt;code&amp;gt;fopen()&amp;lt;/code&amp;gt; calls.&lt;br /&gt;
* If you added &amp;lt;code&amp;gt;#pragma inline (&#039;&#039;functionname&#039;&#039;)&amp;lt;/code&amp;gt; to the code, add &amp;lt;code&amp;gt;INLINE(*ON)&amp;lt;/code&amp;gt; to the compiler parameters&lt;br /&gt;
&lt;br /&gt;
If compilation fails, output will go into a spooled file in the configured output queue. This is the most tedious task.&lt;br /&gt;
# Compile,&lt;br /&gt;
# check output,&lt;br /&gt;
# fix problems,&lt;br /&gt;
# &amp;lt;code&amp;gt;goto 1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If all object modules have been created, you can then link them to a &#039;&#039;*PGM&#039;&#039; object as follows:&lt;br /&gt;
 CRTPGM PGM(MYLIB/MYPG) MODULE(MYLIB/*ALL) ENTMOD(*PGM) ACTGRP(*NEW) DETAIL(*BASIC)&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Programming]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Features_that_separate_the_AS/400_from_common_computer_systems&amp;diff=1707</id>
		<title>Features that separate the AS/400 from common computer systems</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Features_that_separate_the_AS/400_from_common_computer_systems&amp;diff=1707"/>
		<updated>2026-04-16T15:31:24Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo + style&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The AS/400 as a whole of Soft- and Hardware has a bunch of unique features as advertised by IBM:&lt;br /&gt;
* High Level Machine,&lt;br /&gt;
* Object Orientation,&lt;br /&gt;
* Single Level Storage,&lt;br /&gt;
* Hierarchy of Microprocessors,&lt;br /&gt;
* Operating System: OS/400.&lt;br /&gt;
&lt;br /&gt;
These are nicely explained in the video linked [[#Weblinks|below]].&lt;br /&gt;
&lt;br /&gt;
Reviewed in 2022, some are still relevant, some are no longer. Additionally, I&#039;ll highlight features that I think are unique compared to common platforms, and not listed above.&lt;br /&gt;
&lt;br /&gt;
== Split OS ==&lt;br /&gt;
OS/400 may be seen as split in half.&amp;lt;ref&amp;gt;Not necessarily evenly sized halves.&amp;lt;/ref&amp;gt; An good deal of it (about 1&amp;amp;thinsp;GiB with V4) is called &#039;&#039;System Licensed Internal Code&#039;&#039; (SLIC) and handles hardware dependent stuff. This includes features like multiple processors with dedicated memory just for I/O tasks.&amp;lt;ref&amp;gt;This may be seen as a technical borrowing from the mainframe world within IBM. This technique is called &#039;&#039;Channel&#039;&#039; there.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Above the SLIC is the OS/400 and its components system administrators and users usually see and deal with. This is called [[wikipedia:Control Program Facility|CPF]]&amp;lt;ref&amp;gt;Control Program Facility&amp;lt;/ref&amp;gt;, a leftover from the AS/400’s ancestor, the System/38.&lt;br /&gt;
&lt;br /&gt;
== Byte Code ==&lt;br /&gt;
Compilers don&#039;t output CPU native byte code but kind of intermediate code, for example like Java does. This makes compiled programs surprisingly large in size but enables an unprecedented backwards compatibility on binary level.&lt;br /&gt;
&lt;br /&gt;
Binary programs copied to a newer machine with different processor technology can just be started like on the old platform. The start will take a few moments in that the SLIC recognizes missing CPU native code, compiles the intermediate byte code and adds the result to the program object. After that, the program is started and runs as native code on a possibly completely different CPU architecture.&lt;br /&gt;
&lt;br /&gt;
IBM exploited this possibility when they switched the hardware from a custom 48-Bit CISC CPU architecture&amp;lt;ref&amp;gt;Derived from the CPUs in IBM Mainframes of the 1980s era.&amp;lt;/ref&amp;gt; to the PowerPC AS architecture in the mid-1990s. In later incarnations, there have been some restrictions regarding this feature, requiring applications compiled with &#039;&#039;obervability&#039;&#039; turned on.&lt;br /&gt;
&lt;br /&gt;
== Backwards Compatibility ==&lt;br /&gt;
IBM has a long history building platforms that span a multi-decade backward compatibility at binary level. The AS/400 is no exception. Programs compiled on earlier platforms and/or versions can be transferred to a newer machine and usually run without hassle.&amp;lt;br /&amp;gt;&lt;br /&gt;
Source code written with older releases of OS/400 usually compiles without any changes on newer platforms.&lt;br /&gt;
&lt;br /&gt;
These features aren&#039;t of much interest on the first look, but they enable one to develop an application on an older system and run it on newer platforms. This could be seen as a base requirement for more free and Open Source Software: It&#039;s easier to acquire an older machine.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, transferring stuff from newer systems to older ones isn&#039;t that easy. The &#039;&#039;Savlib&#039;&#039; command writes stuff into a pre-created Save-File and records the release string of OS/400 where it was run. It is possible to set pre-set different values but the newer the utilized OS version, the newer the oldest possible compatibility level. V4R5 permits V3R2 as oldest release and select V4 releases.&amp;lt;br /&amp;gt;&lt;br /&gt;
Transfers from old to new systems are painless, though.&lt;br /&gt;
&lt;br /&gt;
== Single Level Storage ==&lt;br /&gt;
Since it&#039;s first incarnations the AS/400 creates a virtual 128&amp;amp;thinsp;Bit address space for the upper OS layer and application programs. &amp;lt;ref&amp;gt;When looking a bit closer, the addresses are split into a 64&amp;amp;thinsp;Bit actual &#039;&#039;address component&#039;&#039; and a 64&amp;amp;thinsp;Bit numbered &#039;&#039;object type&#039;&#039;. So, the claim of a 128&amp;amp;thinsp;Bit address space aren&#039;t exactly wrong, but also not exactly right.&amp;lt;/ref&amp;gt; This comprises physical memory and hard disk space.&lt;br /&gt;
&lt;br /&gt;
A hard disk may be seen as a giant memory area mmap&#039;ed into the address space of upper layer OS components. Swapping and Paging isn&#039;t done on the application layer as most conventional systems do, but on the address layer. Applications simply request contents from addresses and the layer below the OS called SLIC takes care of shuffling the data into RAM, should a page fault occur. Thus, page faults can occur also for data, not only for executables.&lt;br /&gt;
&lt;br /&gt;
This concept also explains why the AS/400 platform lacks a conventional File System on it&#039;s disks. Since disks are essentially memory mapped into virtual memory space, everything visible is just an object at an address with certain properties. This allows to easily share these objects between requesting entities.&lt;br /&gt;
&lt;br /&gt;
The advantage of this approach is the ability to do very fast context switches (if no or only a few page faults occur).&amp;lt;ref&amp;gt;According to Frank Soltis as written in his Books &#039;&#039;Inside the AS/400&#039;&#039;, and &#039;&#039;Fortress Rochester&#039;&#039;.&amp;lt;/ref&amp;gt; This is the reason why even older machines with 100&amp;amp;thinsp;% loaded CPU still have an astonishing fast response time when compared with common platforms of that era. If disk accesses are necessary for a context switch to take place, there&#039;s no notable speed difference to common platforms, though.&lt;br /&gt;
&lt;br /&gt;
=== Disk Allocations ===&lt;br /&gt;
The usual way the system allocates space on secondary storage (aka: hard disks) is to spread objects over as many disks as possible. In modern RAID terminology, this is referred to as &#039;&#039;spindles&#039;&#039; (from the stack of rotating platters&#039; axis), while IBM AS/400 documentation refers to the same concept as &#039;&#039;disk arms&#039;&#039;: The actuator moving the read/write heads over the desired cylinder — a set of tracks — on the rotating platters.&amp;lt;ref&amp;gt;Once, disks with two actuators have been built, but these have been a development on the fringes and quickly vanished from the market.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This spreading of data has the same advantages and disadvantages as RAID 0:&lt;br /&gt;
* with increasing count of disk arms, the chance that a given data block is located on an idle drive increases and thus decreases latency through exploiting parallelism: the more applications run, the more data can be picked up from individual disks, the more overall processing work can be done.&lt;br /&gt;
* since data is located in the system just once, the failure of (at least) one disk has hard to predict ramifications. Objects become &#039;&#039;damaged&#039;&#039; because parts of them are no longer accessible.&amp;lt;ref&amp;gt;The necessity of a solid, and &#039;&#039;&#039;tested&#039;&#039;&#039; backup and restore concept is self-explanatory, but also emphasized in IBM documentation.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From early on, the concept of a dedicated I/O processor allowed for easy implementation of &#039;&#039;data mirroring&#039;&#039;, to compensate for data loss because of a malfunctioning disk drive through redundancy.&lt;br /&gt;
&lt;br /&gt;
Later, the well-known RAID-Levels have been made available through the availability of dedicated storage controllers.&lt;br /&gt;
&lt;br /&gt;
=== Memory Pools ===&lt;br /&gt;
The described concept of the platform relying on paging as primary means to bring in data and code into the faster main memory for actual processing has some implications on main memory constrained machines. Once, RAM was extraordinarily expensive. Without precautions, it was easily possible to start many programs at the same time, each one competing for presence in RAM. When seriously overwhelmed with concurrent requests, this situation leads to [[wikipedia:Thrashing (computer science)|Thrashing]], a situation where the machine is completely busy with paging activity, but does no useful work anymore because of competing tasks.&lt;br /&gt;
&lt;br /&gt;
OS/400 introduced the concept of memory pools for that purpose. A memory pool mainly has these attributes:&lt;br /&gt;
* Size,&lt;br /&gt;
* Shared or Private,&lt;br /&gt;
* Maximum Activity Level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Pool&#039;&#039; can be more or less translated to &#039;&#039;RAM Cache&#039;&#039;: What&#039;s already in the pool&#039;s memory is &#039;&#039;cached&#039;&#039;, because it mustn&#039;t be handled by the paging logic.&lt;br /&gt;
&lt;br /&gt;
==== Pool Size ====&lt;br /&gt;
The &#039;&#039;Size&#039;&#039; of a memory pool is just how much RAM is set aside for applications being directed to run in this pool. More RAM means more cache and less disk activity for shoveling work into RAM.&lt;br /&gt;
&lt;br /&gt;
==== Shared or Private Pool ====&lt;br /&gt;
&#039;&#039;Shared pools&#039;&#039; allow more than one group of applications to utilize a memory pool, while &#039;&#039;private pools&#039;&#039; are reserved for just one group. See &#039;&#039;Subsystems&#039;&#039; below for the explanation of this grouping. This brings in another consideration: The more pools one creates, the more unused memory is left over from excess memory partitioning. &amp;lt;ref&amp;gt;OS/400 has a function called &#039;&#039;performance adjustment&#039;&#039;. This function periodically checks paging activity and adjusts memory allocations between pools, as well as the pool&#039;s activity levels.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Maximum Activity Level ====&lt;br /&gt;
The &#039;&#039;Maximum Activity Level&#039;&#039; of a memory pool is the overall count of applications which are eligible to actively &#039;&#039;run&#039;&#039; in a given pool in parallel. This eligible count only considers applications which require actual access to the CPU, but not &#039;&#039;sleeping&#039;&#039; ones, waiting for some application-external event. This setting reduces competition for memory amongst applications within that pool. But at the same time — to a lesser extent — overall competition for main memory, system-wide.&lt;br /&gt;
&lt;br /&gt;
==== Pool Summary ====&lt;br /&gt;
It is important to consider that this competition for RAM is not limited to actual code being in main memory, but also for data. Heavy paging can be quite normal for a batch job reading through a huge database file, and only a minor brake on other applications running. As long as the application code stays in main memory, that application can run again as soon as more data arrives in main memory to be processed. Because batch applications (ideally) use a different memory pool than interactive applications, there is no competition for main memory for these two application &#039;&#039;classes&#039;&#039; being confined in their respective pools.&amp;lt;ref&amp;gt;There &#039;&#039;is&#039;&#039; a certain degree of competition for disk I/O, though. As long as both pools need to access data on a common set of disks, I/O latency for both pools will go up, and response time for interactive applications will degrade. Again, this latency increase should happen most often for paging of data, not application code.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Many Books have been written about &#039;&#039;performance tuning&#039;&#039; the AS/400 system. As you can see, there are many aspects to consider which values of these settings lead to the sweet spot of a machine doing maximum (batch) work while minimally affecting interactive users. Dynamic scenarios have been described where interactive users are not considered at non-office hours, giving batch jobs more memory and thus allowing faster processing.&lt;br /&gt;
&lt;br /&gt;
In current reality, there are two groups of users, and both of them rarely need to consider the points outlined above:&lt;br /&gt;
* Hobbyists are most often the sole users of a system. Thus, overall system activity levels are low — most often, the machine idles.&lt;br /&gt;
* Professional users with current systems have RAM in abundance. In addition, the increasing ubiquity of solid state storage with its intrinsic lack of mechanical positioning latency boosts I/O throughput.&lt;br /&gt;
&lt;br /&gt;
For both groups, the directions given in the [[Post-Install Optimizations]] article gives an almost perfect starting point for the self-adjustment of the system itself to balance into a good partitioning of RAM into existing shared pools.&lt;br /&gt;
&lt;br /&gt;
==== Expert Cache ====&lt;br /&gt;
In short, this is a setting of a pool where the system itself decides the block size of data being read from disk and put into memory. Without this, transferred blocks are of a fixed size, thus increasing processing overhead. &amp;lt;code&amp;gt;CHGSHRPOOL PAGING(*CALC)&amp;lt;/code&amp;gt; switches Expert Cache on for a given pool. On the other hand, smaller data transfers decrease the wait time until some other disk access can be satisfied.&amp;lt;br /&amp;gt;&lt;br /&gt;
Usually the recommended setting is &#039;&#039;enabled&#039;&#039;. Allow the system to adjust itself. Note: The default setting is &#039;&#039;disabled&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Subsystems ===&lt;br /&gt;
A subsystem is a way to group application programs. Subsystems are defined by a subsystem definition object. This object allows for many attributes to be set, to prepare the desired run-time environment. See [[Subsystems]] for a more in-depth illustration about the underlying concept.&lt;br /&gt;
&lt;br /&gt;
=== Running Application Programs: Activation and Activation Groups ===&lt;br /&gt;
Since programs are already existent as objects in the single level store memory space, there&#039;s no need to load them from disk as common OS&#039; need(ed) to do. To actually run such an application program needs some housekeeping, though. Commonly a program needs a [[wikipedia:Stack-based memory allocation|Stack]] and a [[wikipedia:Memory_management#Dynamic_memory_allocation|Heap]] for variables and other internal data structures to be able to run. The AS/400 is no different in this case, although this stuff is buried very deep into the LIC&#039;s innards.&lt;br /&gt;
&lt;br /&gt;
Actually starting a program to be run on an AS/400 is called &#039;&#039;activation&#039;&#039;. This task creates necessary storage as outlined above and adds the program to to the job scheduling queue. This is also necessary to provide a properly isolated environment when multiple users start the same application.&lt;br /&gt;
&lt;br /&gt;
Completely different compared to common platforms, it&#039;s possible to &#039;&#039;share&#039;&#039; some of this space between programs. This shared space is called an &#039;&#039;activation group&#039;&#039;. That is, while creating a new program (by compiling and linking), one can tell the compiler/linker if the program is to be run in&lt;br /&gt;
* the default activation group, that contains most of the OS,&lt;br /&gt;
* the caller&#039;s activation group, to allow a more dynamic approach, or&lt;br /&gt;
* a new activation group that is to be created for every instance the program has,&lt;br /&gt;
* a common activation group with a programmer specified name.&lt;br /&gt;
&lt;br /&gt;
As long as any program of any activation group is activated, so is the activation group. Data structures will be destroyed only when the last program terminates, or &#039;&#039;the job ends&#039;&#039;, &amp;lt;ref&amp;gt;A job is defined as work that needs to be done by the system. Work can be done by a single program or mutiple.&amp;lt;/ref&amp;gt; or when a group is explicitly deallocated with the RCLACTGRP program. For details see weblinks.&lt;br /&gt;
&lt;br /&gt;
Sharing an activation group shares (amongst other data):&lt;br /&gt;
* Static variables,&lt;br /&gt;
* Open files and file pointer positions,&lt;br /&gt;
* and more…&lt;br /&gt;
&lt;br /&gt;
There&#039;s a certain intersection of functionality between a common activation group and &amp;lt;code&amp;gt;fork()&amp;lt;/code&amp;gt;ing an application on Linux/Unix platforms. Even if it is not exactly the same but maybe it gives you an idea.&amp;lt;br /&amp;gt;&lt;br /&gt;
On OS/400, programs to share an activation group must exist as separate objects while on Linux/Unix all code is either linked to a monolithic program or uses additional code with the aid of &#039;&#039;shared libraries&#039;&#039;.&amp;lt;ref&amp;gt;A concept that &#039;&#039;also&#039;&#039; exists on the AS/400. There, they are called &#039;&#039;service programs&#039;&#039;.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Standardized UI ==&lt;br /&gt;
The whole UI revolves mainly around forms and menus, accompanied by static text. The layouts of these screens are somewhat standardized. AS/400 screens are very recognizable because of this.&lt;br /&gt;
&lt;br /&gt;
See also: [[About Green Screens and mouse-clickable UIs]].&lt;br /&gt;
&lt;br /&gt;
== Predictable Command Naming ==&lt;br /&gt;
For experienced users who won&#039;t repeatedly navigate though nested menus, commands may be entered on the command line instead of menu numbers. These commands consist of two or more parts, built of abbreviated english words. Abbreviations often take place by omitting vowels and shortening the result to less or equal four characters. The first one being a &#039;&#039;verb&#039;&#039; and the second one a &#039;&#039;subject&#039;&#039;, optionally followed by more building blocks.&lt;br /&gt;
&lt;br /&gt;
A few examples may illustrate the previous statements:&lt;br /&gt;
; wrksplf&lt;br /&gt;
: Work with Spooled Files&lt;br /&gt;
; chgmsgq&lt;br /&gt;
: Change Message Queue Properties&lt;br /&gt;
; crtdspf&lt;br /&gt;
: Create Display File&lt;br /&gt;
; dltf&lt;br /&gt;
: Delete File&lt;br /&gt;
; dspmsg&lt;br /&gt;
: Display Messages (from Message Queue)&lt;br /&gt;
&lt;br /&gt;
See also [[wikipedia:IBM i Control Language|IBM i Control Language]] and [[CL Tricks]].&lt;br /&gt;
&lt;br /&gt;
== Outstanding Reliability ==&lt;br /&gt;
Software is a complex thing built by humans. Humans make errors. Thus, Software contains errors. This is an inevitable fact.&lt;br /&gt;
&lt;br /&gt;
IBM managed to make OS/400 not bug free but caught most problems that lead to a complete crash of the operating system. There may be edge cases that are usually hard to spot.&lt;br /&gt;
&lt;br /&gt;
Also, IBM built multiple measures against &#039;&#039;defective sectors on hard disks being catastrophic&#039;&#039; into the OS from early on. Since there is no classical file system, most often, read errors only affect one or more objects that can be easily restored from backup.&amp;lt;ref&amp;gt;You don&#039;t have a backup? Own fault! No backup, no pity.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reliability is &#039;&#039;&#039;not&#039;&#039;&#039; the same as availability. Some tasks can only be done when OS/400 is running in a restricted state.&amp;lt;ref&amp;gt;In Unix this would be called Single User Mode, with not much more than &#039;&#039;init&#039;&#039; and a root-shell running.&amp;lt;/ref&amp;gt; This includes but is not limited to a full system backup or certain hardware failure recovery procedures.&lt;br /&gt;
&lt;br /&gt;
== Rapid Development ==&lt;br /&gt;
OS/400 comes with a set of tools and supportive facilities within the OS to ease development of application programs. Usually, development comprises of:&lt;br /&gt;
* Definition and creation of database tables, display forms and printer output,&lt;br /&gt;
* Writing code that references these files and shovels data just by issuing proper READ and WRITE (among other) requests to these files.&lt;br /&gt;
&lt;br /&gt;
The mentioned files are typed in a format called &#039;&#039;Data Definition Specifications&#039;&#039; or &#039;&#039;DDS&#039;&#039;. It provides data field definitions, field definition references between files, arbitrary placement of static text (not for database files) and a multitude of flags for content to be shaped to fit for the desired presentation.&amp;lt;br /&amp;gt;&lt;br /&gt;
The &#039;&#039;Screen Design Agent&#039;&#039; program (&amp;lt;code&amp;gt;strsda&amp;lt;/code&amp;gt;) provides a pseudo-[[wikipedia:WYSIWYG|WYSIWYG]]-interface for creating screen forms and menus.&amp;lt;br /&amp;gt;&lt;br /&gt;
The &#039;&#039;Report Layout Utility&#039;&#039; program (&amp;lt;code&amp;gt;strrlu&amp;lt;/code&amp;gt;) provides a pseudo-WYSIWYG-interface for creating layouts for printer output files.&lt;br /&gt;
&lt;br /&gt;
Actual programming can be done in RPG, COBOL, and C/C++. Output of the compilers (called &#039;&#039;modules&#039;&#039;) created by any of these languages can be linked together to create an actual program object or a shared library (&#039;&#039;service program&#039;&#039;). Any language may call functions of any other language as long as parameters have been defined to be compatible.&lt;br /&gt;
&lt;br /&gt;
The compilable CL &amp;quot;shell&amp;quot;-script language and REXX-Interpreter help in easing traditional automation tasks on the command line level.&lt;br /&gt;
&lt;br /&gt;
Programming is done within the &#039;&#039;Program Development Manager&#039;&#039; collection of programs (&amp;lt;code&amp;gt;strpdm&amp;lt;/code&amp;gt;). The most used component is the &#039;&#039;Work with File Members&#039;&#039; application, &amp;lt;code&amp;gt;wrkmbrpdm&amp;lt;/code&amp;gt;, to list source code physical file content. This in turn calls the &#039;&#039;Source Entry Utility&#039;&#039; (&#039;&#039;SEU&#039;&#039;) with the appropriate parameters for actual code writing/editing with the desired existing or new file member.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;SEU&#039;&#039; provides a linetype-aware form for RPG and DDS, easing the matching of the appropriate columnns. It can be invoked as usual: With &amp;lt;code&amp;gt;F4&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
See also: [[How to program an Application]]&lt;br /&gt;
&lt;br /&gt;
=== Times they are a changin&#039; ===&lt;br /&gt;
Today, development tasks are most often done on Windows PCs, with IBM provided tools, that pull a local copy of a source file to edit.&lt;br /&gt;
&lt;br /&gt;
Also, since the late 1990&#039;s, IBM has been trying to establish Java as &#039;&#039;the&#039;&#039; language of choice, along with helper programs for shifting away from the old fashioned character based applications (&#039;&#039;green screen&#039;&#039;) to a pure web-browser based way of user&#039;s interaction with the system.&lt;br /&gt;
&lt;br /&gt;
Also, &#039;&#039;&#039;the&#039;&#039;&#039; AS/400 Language, RPG, has been enhanced and modernised slowly but constantly. While most examples in this collection of knowledge are based on &#039;&#039;ILE RPG IV&#039;&#039;, newer OS releases were accompanied by compilers allowing to escape the punched card appeal of RPG more and more. V5 introduced the possibility to write actual code (not definition statements, though) in a free form, while with some V7 all parts of a RPG program may be written without being forced to write statements at a certain position within a line. This generates a load of syntactical changes to be learned.&lt;br /&gt;
&lt;br /&gt;
Examples of positional code are slowly vanishing from Internet Websites. Looking up how to do stuff in positional code is getting increasingly difficult. Asking around in mailing lists for positional code examples sometimes yield unhelpful and cynic comments.&amp;lt;br /&amp;gt;&lt;br /&gt;
Still, many companies have old to very old code to be maintained that predates compilers allowing free syntax. Providing mainly positional RPG examples is supposed to help understanding this old way of writing RPG, while examples for newer techniques are easily found with an internet search engine of choice.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [https://www.youtube.com/watch?v=5pY6Xxptp9A IBM AS/400 The Best Architecture In The World 1992], Video at YouTube.&lt;br /&gt;
* [https://www.mcpressonline.com/programming/rpg/introduction-to-ile-rpg-activation-groups Introduction to ILE RPG Activation Groups], McPress online.&lt;br /&gt;
* [https://www.mcpressonline.com/operating-systems/ibm-i-os400-i5os/i5os-v6r1-upgrade-now-or-later i5/OS V6R1: Upgrade Now or Later?], MC Press Online, with some background information regarding code observability.&lt;br /&gt;
* [https://www.itjungle.com/2020/11/23/frank-soltis-discusses-a-possible-future-for-single-level-storage/ Frank Soltis Discusses A Possible Future for Single-Level Storage], IT Jungle, also explaining the benefits of SLS for task switching.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Basic Knowledge]]&lt;br /&gt;
[[Category: Musings]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Filesystems_and_Files_on_the_AS/400&amp;diff=1699</id>
		<title>Filesystems and Files on the AS/400</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Filesystems_and_Files_on_the_AS/400&amp;diff=1699"/>
		<updated>2026-04-14T14:15:00Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FIXME|&lt;br /&gt;
* Add Chapter how to create physical and logical files,&lt;br /&gt;
* Move explanations to access paths to a programming article?}}&lt;br /&gt;
Since the AS/400 has been designed as a business helper machine, its processing capabilities mainly cover structured data with comparatively small record sizes. With the ongoing evolution of OS/400, more functionality was added by IBM that weakens this concise definition, though. On the other hand, the same added functionality improves ease of data storage for, and data exchange with other platforms.&lt;br /&gt;
&lt;br /&gt;
== Different approaches of data storage and processing ==&lt;br /&gt;
Structured data can be processed most efficiently when the underlying logical and physical facilities support this approach natively instead of mimicking.&lt;br /&gt;
&lt;br /&gt;
By comparison, most platforms outside the world of mainframes and minicomputers, as they were once known, operate on byte streams. Byte streams don&#039;t have any natural structure visible from outside. That is, without analyzing the content of the stream at any given moment, there is no chance to map the current byte position into any logical structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
This is somewhat similar to the differences between data transmission in an asynchronous manner (such as the RS-232 protocol specifies) versus synchronous. With asynchronous transfers, data payload has to be enriched with additional information to enable processing logic to chop the continuous stream of data into pieces to enable processing facilities to work on them in a structured way.&lt;br /&gt;
&lt;br /&gt;
Most, if not all data is based on some structure, though. The simplest structure is a blob of data of a given size, usually named a &#039;&#039;block&#039;&#039;. When looking closely, conversion from, and to byte streams from and to blocks takes place on many levels:&lt;br /&gt;
* Storage of data on hard disks or in solid state memory in blocks of 512&amp;amp;thinsp;Bytes or 4&amp;amp;thinsp;[[wikipedia:Kibibyte|KiB]],&lt;br /&gt;
* Paging and Swapping activity of virtual memory systems also takes place in blocks instead of streams,&lt;br /&gt;
* Data Transfer over todays networks is done in pieces called &#039;&#039;frames&#039;&#039;.&amp;lt;ref&amp;gt;To be precise, this isn&#039;t done to ease or enable record oriented processing but to enable sharing of physical media (like cables) between many participants of the network.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a higher level of a file&#039;s content definition, more elaborated structuring of stream-based data can be found:&lt;br /&gt;
* Pixel-oriented picture files include a header that dynamically defines the format of the data that follows,&lt;br /&gt;
* Movie files are defined by different kinds of data blocks: To save space, many frames are only saved as differences to the picture before,&amp;lt;ref&amp;gt;From time to time, a key frame contains a complete picture to compensate for data loss, that can happen for many reasons.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Todays most used text processing software internally uses [[wikipedia:XML|XML]] to give seemingly unstructured data a structure,&lt;br /&gt;
* Application Program Files also are structured in a way that permits the operating system to efficiently load and execute the contained code,&lt;br /&gt;
* Even plain text files have a structure: They contain of words, sentences, and paragraphs.&lt;br /&gt;
&lt;br /&gt;
The mapping of structured data into byte streams leverages processing speed with flexibility to store arbitrary complex data structures into very simple data structures on disk. Today, the processing overhead of mapping byte streams into records (blocks) or more elaborated data structures is almost nullified by cheap availability of sheer processing power.&lt;br /&gt;
&lt;br /&gt;
=== Storage Overhead ===&lt;br /&gt;
However, mapping byte streams into logical blocks of information often creates &#039;&#039;storage overhead&#039;&#039;. For example, a plain text file with the word &#039;Hello&#039; uses only 5&amp;amp;thinsp;Bytes of actual data&amp;lt;ref&amp;gt;Counted as ASCII, or SBCS as named in the AS/400-World.&amp;lt;/ref&amp;gt; (sometimes followed by implicit end of line marker(s)), the file occupies at least 512&amp;amp;thinsp;Bytes data, since this is the minimum block size on usual hard disks. If the file is expanded to exactly 512&amp;amp;thinsp;Bytes by adding more text, the overhead is zero. Adding just one character starts the continuation of data in the next disk block and again occupies the whole block of that 511&amp;amp;thinsp;Bytes are wasted.&amp;lt;br /&amp;gt;&lt;br /&gt;
This overhead might be negligible when looking at todays file sizes. But, every OS utilizes configuration files, that usually are small and fit the above description perfectly. &#039;&#039;/etc/hosts&#039;&#039; may be 680&amp;amp;thinsp;Bytes long on a given system, that makes up 344&amp;amp;thinsp;Bytes wasted space, according to the above calculation.&amp;lt;ref&amp;gt;Actually, with todays partition sizes, Linux uses 4&amp;amp;thinsp;KiB blocks, not 512&amp;amp;thinsp;Bytes. This raises the overhead of said &#039;&#039;/etc/hosts&#039;&#039; to 3416&amp;amp;thinsp;Bytes.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Today, this storage overhead is also almost nullified by cheap availability of gigantic hard disk storage capacity.&lt;br /&gt;
&lt;br /&gt;
=== Latency ===&lt;br /&gt;
Considering the above description, it&#039;s easily observable that actual data is scattered across a greater area of a given hard disk with many holes in between, compared to all files concatenated to one big blob. This increases latency, because the disk&#039;s head assembly must move more often to access a certain block on the physical media.&lt;br /&gt;
&lt;br /&gt;
Today, I/O latencies are nullified by cheap availability of solid state memory “disks”.&lt;br /&gt;
&lt;br /&gt;
== AS/400 IFS ==&lt;br /&gt;
Early incarnations of the AS/400 had no facilities to save or process byte-based &#039;&#039;stream files&#039;&#039;. There only was the possibility to create files with a fixed record structure. With the introduction of the &#039;&#039;integrated file system&#039;&#039; in OS/400 Version 3, saving and processing of byte stream files has been made possible. The classical record oriented file system was in turn named &#039;&#039;QSYS.LIB&#039;&#039;-file system and looks like a classical Unix mount point, when looking with applications being aware of the IFS, such as &#039;&#039;qsh&#039;&#039;, the minimal UNIX like shell. The rest of the filesystems allow to store stream files.&amp;lt;br /&amp;gt;&lt;br /&gt;
Up to today, &#039;&#039;QSYS.LIB&#039;&#039; is still the most important file system on AS/400&#039;s because most part of the OS is stored there, as well as configuration database files and, of course application specific database files.&lt;br /&gt;
&lt;br /&gt;
This &#039;&#039;IFS&#039;&#039; is not the same as file systems in Linux or other common operating systems. There, one or more disks are &#039;&#039;partitioned&#039;&#039;: Space from one disk split into slices of usable space by software. To make use of the space available in this partitions, a &#039;&#039;file system&#039;&#039; has to be created. That is, database-like structures for the mapping of files to disk blocks are written into any given partition space. The space available for the creation of files on any given file system is thus fixed to the size of the partition, minus overhead, minus space needed for the aforementioned data structures. Multiple filesystems have been conceived over decades with a determined set of features, so it&#039;s possible to use different file systems to match the different storage needs of different types of files.&lt;br /&gt;
&lt;br /&gt;
On the other side, the IFS of the AS/400 is a purely &#039;&#039;logical structure&#039;&#039; that allocates disk blocks as requested by the operating system. If a record oriented file in the classical &#039;&#039;QSYS.LIB&#039;&#039;-filesystem is filled with data, disk blocks are filled with this data and are thus no longer available for storage. If someone transfers a picture file to the AS/400&#039;s &#039;&#039;/QOpenSys&#039;&#039;-Filesystem, disk-blocks are allocated for that data and also cannot be allocated for storage. There is no static assignment for these different file systems to partitions or disk blocks.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stuff saved in file systems on the AS/400 is usually referred to as &#039;&#039;objects&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== AS/400 files ==&lt;br /&gt;
The AS/400 file handling shares a common heritage of file handling found in IBM mainframes (MVS or z/OS partitioned data sets). An AS/400 &#039;&#039;file&#039;&#039; defines at least the record length. All &#039;&#039;members&#039;&#039; of these file share this maximum length and thus are constrained to this length.&amp;lt;br&amp;gt;&lt;br /&gt;
In addition, an &#039;&#039;externally defined file&#039;&#039; can be more strict than an MVS PDS, by not only enforcing a record length, but also an actual field layout and -content over this record.&amp;lt;br&amp;gt;&amp;lt;ref&amp;gt;The term &#039;&#039;external&#039;&#039; is greatly misleading here, because the file definition is &#039;&#039;external&#039;&#039; to the &#039;&#039;program&#039;&#039; using that file. Indeed, the field layout is &#039;&#039;internal&#039;&#039; to the file object.&amp;lt;/ref&amp;gt;&lt;br /&gt;
This can be roughly compared to a directory on Linux or (better) a tar file, where one may only add TIFF image data with a common horizontal pixel count.&amp;lt;ref&amp;gt;This is fairly unpractical in computing as we know it.&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
For example, by creating a &#039;&#039;source file&#039;&#039; on an AS/400, one defines a &#039;&#039;file&#039;&#039; with a certain record length.&amp;lt;ref&amp;gt;92&amp;amp;thinsp;Bytes by default.&amp;lt;/ref&amp;gt; One may use this &#039;&#039;file&#039;&#039;, create &#039;&#039;members&#039;&#039; and add program source code to these members at will, but it&#039;s not possible to add data with any line longer than 92 characters into any member of that file.&lt;br /&gt;
&lt;br /&gt;
=== File Types ===&lt;br /&gt;
Basically there are four types of files found in any AS/400&#039;s classical &#039;&#039;QSYS.LIB&#039;&#039; filesystem:&lt;br /&gt;
* &#039;&#039;&#039;Source Files&#039;&#039;&#039; are &#039;&#039;physical files&#039;&#039;, aka &#039;&#039;database files&#039;&#039; with at least two fields per record:&lt;br /&gt;
** Line of Text, primarily to hold program code to be compiled,&lt;br /&gt;
** Timestamp, records the last change of that particular line.&amp;lt;ref&amp;gt;SEU shows these timestamps on the very far right of it&#039;s display.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Physical Files&#039;&#039;&#039; are again database files but with a user defined record length and field format.&lt;br /&gt;
* &#039;&#039;&#039;Logical Files&#039;&#039;&#039; are files that reference one or more physical files, but do not contain any data. LFs can be compared to the SQL terms:&lt;br /&gt;
** &#039;&#039;view&#039;&#039;: Show only a subset of fields of PF,&lt;br /&gt;
** &#039;&#039;join&#039;&#039;: Show a superset of fields of more than one PF,&lt;br /&gt;
** &#039;&#039;index&#039;&#039;: Apply different indexes, and thus record sorting.&lt;br /&gt;
: In addition, restrictions about which records to select or omit from the PF can be added.&lt;br /&gt;
* &#039;&#039;&#039;Other Files&#039;&#039;&#039; that appear as type &#039;&#039;*FILE&#039;&#039; in output listings that include, but are not limited to&lt;br /&gt;
** &#039;&#039;Display Files&#039;&#039; that map data to positions on the screen and enable user interaction to this forms,&lt;br /&gt;
** &#039;&#039;Printer Files&#039;&#039; that map data to positions on a virtual sheet of paper for later printer output,&lt;br /&gt;
** &#039;&#039;Inter Communication Facility Files&#039;&#039; who provide an easy way for application programs to talk to other programs on the same or remote AS/400&#039;s,&lt;br /&gt;
** &#039;&#039;Save files&#039;&#039; that provide roughly the same functionality as tar files on Linux, enabling bundling of files (objects) of different types into one self-contained archive, for easier transmission to other systems for re-extracting or permanent storage.&lt;br /&gt;
&lt;br /&gt;
Handling of these files will be explained in separate articles.&lt;br /&gt;
&lt;br /&gt;
==== A word on physical and logical (database) files ====&lt;br /&gt;
The main usage of logical files is to provide different &#039;&#039;access paths&#039;&#039; compared to the linked physical file to read data. An access path is just one or more [[wikipedia:Database index|database index(es)]] created for one or more fields of a given physical file.&lt;br /&gt;
&lt;br /&gt;
When accessing database files through the classical READ(P)(E)-API-Calls, there&#039;s no possibility to sort a result set dynamically as it&#039;s easily done with [[wikipedia:SQL|SQL]]. There&#039;s not even a result set. There&#039;s just kind of a &#039;&#039;file pointer&#039;&#039; that points to the last read row, and the order in that the rows are retrieved by subsequent READs (that increment this file pointer) are determined by the access path(s).&amp;lt;br /&amp;gt;&lt;br /&gt;
Keep in mind that this handling of structured data stems from a time period when computers had only a tiny fraction of today&#039;s processing power&amp;lt;ref&amp;gt;Processing as in &#039;&#039;Read from disk — Modify — Write to disk&#039;&#039;.&amp;lt;/ref&amp;gt; and storage capacity.&lt;br /&gt;
&lt;br /&gt;
Considering the clear positioning of the AS/400 as &#039;&#039;database machine&#039;&#039; by IBM, and adding the fact that the precursor to SQL was created in the early 1970s by IBM employees, SQL might have been available on the AS/400 from it&#039;s first release.&amp;lt;br /&amp;gt;&lt;br /&gt;
On older machines, SQL proves to be painfully slow, especially when dealing with huge database tables. Since the SQL engine dynamically adds database indexes as needed when processing queries, getting data out of a table can be really slow when such a temporary index must be created in advance.&lt;br /&gt;
&lt;br /&gt;
On the other side, utilizing the legacy API-Calls to retrieve and process random records with CHAIN-READ from multi-GiB-sized database tables is surprisingly quick on old machines for many reasons.&lt;br /&gt;
&lt;br /&gt;
This somewhat restricted API call interface explains why data handling within applications on the AS/400 feel so fundamentally different compared to what we&#039;re used to.&lt;br /&gt;
&lt;br /&gt;
Most common platforms utilize SQL:&lt;br /&gt;
* The user is providing (part of) a query string, the database picks matching rows and&lt;br /&gt;
* the application delivers a limited view of the whole database content back to the user.&lt;br /&gt;
** The user may easily change sorting of the result records to be based on any single field by usually clicking on the respective table header field in the application&#039;s UI,&lt;br /&gt;
* the user may finally select the desired record for further processing.&lt;br /&gt;
&lt;br /&gt;
AS/400 applications usually…&lt;br /&gt;
* provide a complete list view&amp;lt;ref&amp;gt;These lists are called &#039;&#039;subfiles&#039;&#039;.&amp;lt;/ref&amp;gt; of the entire database content, with a fixed sort order. The user may either scroll to the desired record, or type part of a search string in a designated input line and press &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt;.&lt;br /&gt;
* The application reloads the list view after CHAINing (placing the &#039;&#039;file pointer&#039;&#039;) to the first record matching (part of) the search string&amp;lt;ref&amp;gt;To be precise, the search string is matched against the &#039;&#039;&#039;start&#039;&#039;&#039; of the respective strings in the key field. It&#039;s not a &amp;lt;code&amp;gt;… LIKE &#039;%FOOBAR%&#039;&amp;lt;/code&amp;gt;-matching that is simply not possible with the legacy API.&amp;lt;/ref&amp;gt;. The rest of the list is filled with subsequent READs until the list is full or [[wikipedia:End-of-file|EOF]] is reached.&lt;br /&gt;
** Skillful programming techniques allow the user to freely scroll forward and backward from the record retrieved in the previous step.&lt;br /&gt;
* The user may finally select the desired record for further processing.&lt;br /&gt;
&lt;br /&gt;
Programs don&#039;t need to maintain the list programmatically xor allocate memory for loading the whole database. Details will be explained in the articles about programming.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Basic Knowledge]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Using_NFS-based_image_catalogs_for_backups&amp;diff=1697</id>
		<title>Using NFS-based image catalogs for backups</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Using_NFS-based_image_catalogs_for_backups&amp;diff=1697"/>
		<updated>2026-04-05T20:42:33Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Using NFS-based image catalogs for backups&#039;&#039;&#039; is an alternative and inexpensive way to use OS provided facilities for backups. If a single tape drive would suffice for a given backup scenario, but is not viable because the machine is located in a remote location, NFS-based image catalogs might be worth considering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039; The procedures outlined below have been tested on IBM i 7.2 and 7.3. V4R5 definitely has no support for image catalogs.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pro:&lt;br /&gt;
* No temporary local data,&lt;br /&gt;
** No local I/Os due to data to be backed up being copied into the backup images,&lt;br /&gt;
* No unnecessary transfers of image files bloated to the maximum size to the final file destination.&lt;br /&gt;
&lt;br /&gt;
Con:&lt;br /&gt;
* Full restores require a D-mode manual IPL from the last &#039;&#039;Save 21&#039;&#039;. This can be handled through copying that image to the HMC or VIOS storage, so it can be tied to an emulated optical drive. Depending on the image size, this simply might not fit onto the available space, or takes unacceptably long to be copied. It should be possible to import the NFS exported backup directory to VIOS as an installation image collection to spare the lengthy copy, but this has not yet been tested.&lt;br /&gt;
&lt;br /&gt;
== Configuring the service tools adapter on IBM i ==&lt;br /&gt;
On IBM i, you need to establish a &#039;&#039;service tools adapter&#039;&#039;. This is a virtual network IOA which is just added to the LPAR and otherwise not referenced in the OS with a line description. Configuration of this adapter is done in DST.&amp;lt;ref&amp;gt;Configuration in SST is also possible, but the menu item numbers and labels are slightly different.&amp;lt;/ref&amp;gt;:&lt;br /&gt;
* &amp;lt;tt&amp;gt;5. Service tools device IDs&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* &amp;lt;tt&amp;gt;F13&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* Select one of the adapters shown with &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;.&amp;lt;ref&amp;gt;We recommend the one with the numerically higher &#039;&#039;Resource Name&#039;&#039;. This is a purely cosmetic decision.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Enter the IP configuration,&lt;br /&gt;
* &amp;lt;tt&amp;gt;F7&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* &amp;lt;tt&amp;gt;F17&amp;lt;/tt&amp;gt;; Ping to this address from another machine connected to the network should now work.&lt;br /&gt;
&lt;br /&gt;
NFS traffic for image catalogs exclusively runs through this adapter, being managed by SLIC. The &amp;quot;upper layer&amp;quot; OS components are not involved. Access to NFS catalogs is working in restricted mode, with TCP/IP being unavailable.&lt;br /&gt;
&lt;br /&gt;
== Configuring the NFS-Server ==&lt;br /&gt;
This setup guide assumes a Linux based NFS server as backup destination.&lt;br /&gt;
* Install NFS server,&lt;br /&gt;
* configure NFS server by editing &#039;&#039;/etc/exports&#039;&#039;,&lt;br /&gt;
* reload configuration by running &amp;lt;code&amp;gt;exportfs -ra&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example entry:&lt;br /&gt;
 /backups/i-backups 192.168.0.10/32(rw,no_root_squash,no_subtree_check,async)&lt;br /&gt;
&lt;br /&gt;
192.168.0.10 is the address you gave to the service tools adapter in the previous step. This assures that only that IP address can actually access backup images.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;image catalog&#039;&#039; is in fact a simple ASCII text file. It&lt;br /&gt;
* must be named &#039;&#039;VOLUME_LIST&#039;&#039;,&lt;br /&gt;
* has one entry per optical image in the same directory,&lt;br /&gt;
* optionally has a blank and the letter &#039;&#039;W&#039;&#039; to mark the respective image as writeable,&lt;br /&gt;
* cannot be managed through the usual image catalog commands on IBM i.&lt;br /&gt;
&lt;br /&gt;
Example entry:&lt;br /&gt;
 20250528-1.udf W&lt;br /&gt;
&lt;br /&gt;
Using sparse files as images works and is highly recommended. It saves time and unneeded I/O to create the images compared to creating preallocated images filled to the brim with zero bytes. Such files can be created with&lt;br /&gt;
 truncate -s 4G /backups/i-backups/20250528-1.udf&lt;br /&gt;
&lt;br /&gt;
This quickly creates a file with initially 0 Bytes in size, with a maximum size of 4&amp;amp;thinsp;GiB. The suffix &#039;&#039;-1&#039;&#039; designates this file as a differential backup to the last full save.&lt;br /&gt;
&lt;br /&gt;
You can use this example shell script to create images with &#039;&#039;cron&#039;&#039; on Linux before the backup job runs on IBM i:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=shell&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
  &lt;br /&gt;
TODAY=&amp;quot;$(date &#039;+%Y%m%d&#039;)&amp;quot;&lt;br /&gt;
SIZE=&amp;quot;4G&amp;quot;&lt;br /&gt;
DIR=&amp;quot;/backups/i-backups&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -f &amp;quot;${DIR}&amp;quot;/&amp;quot;${TODAY}&amp;quot;-1.udf ]; then&lt;br /&gt;
        truncate -s &amp;quot;${SIZE}&amp;quot; &amp;quot;${DIR}&amp;quot;/&amp;quot;${TODAY}&amp;quot;-1.udf&lt;br /&gt;
&lt;br /&gt;
        if [ ! -f &amp;quot;${DIR}&amp;quot;/VOLUME_LIST ]; then&lt;br /&gt;
                echo &amp;quot;${TODAY}-1.udf W&amp;quot; &amp;gt; &amp;quot;${DIR}&amp;quot;/VOLUME_LIST&lt;br /&gt;
        else&lt;br /&gt;
                sed -i &amp;quot;1i ${TODAY}-1.udf W&amp;quot; &amp;quot;${DIR}&amp;quot;/VOLUME_LIST&lt;br /&gt;
        fi&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
You can name it &#039;&#039;create-imgclge-daily&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The image catalog logic on IBM i automatically loads the first entry in &#039;&#039;VOLUME_LIST&#039;&#039;. Hence the shown script inserts new images at the beginning of the file.&lt;br /&gt;
&lt;br /&gt;
== Configuring IBM i ==&lt;br /&gt;
With remote, NFS-based image catalogs, an image catalog is tied to a device file. We create the device &#039;&#039;optbkup01&#039;&#039; for that purpose:&lt;br /&gt;
 crtdevopt devd(optbkup01) online(*no) rsrcname(*vrt) lclintneta(*srvlan) rmtintneta(&#039;192.168.0.11&#039;) netimgdir(&#039;/backups/i-backups&#039;)&lt;br /&gt;
&lt;br /&gt;
192.168.0.11 is the IP address of the NFS server.&lt;br /&gt;
&lt;br /&gt;
Next, we can vary on the device:&lt;br /&gt;
 vrycfg cfgobj(optbkup01) cfgtype(*dev) status(*on)&lt;br /&gt;
&lt;br /&gt;
Finally, we can look at the catalog entries:&lt;br /&gt;
 wrkimgclge imgclg(*dev) dev(optbkup01)&lt;br /&gt;
&lt;br /&gt;
Always make sure that you vary off the device after usage, so changes to &#039;&#039;VOLUME_LIST&#039;&#039; will be recognized at next vary on.&lt;br /&gt;
&lt;br /&gt;
== Differential saves ==&lt;br /&gt;
Running an incremental save basically runs these steps:&lt;br /&gt;
&lt;br /&gt;
* Create new image, and update &#039;&#039;VOLUME_LIST&#039;&#039; on the NFS server&lt;br /&gt;
* Vary on the backup device, and initialize the automatically attached first image&lt;br /&gt;
* &#039;&#039;savchgobj&#039;&#039; — Back up changed objects from user libraries since the last full backup&lt;br /&gt;
* &#039;&#039;savcfg&#039;&#039; — Back up configuration objects&lt;br /&gt;
* &#039;&#039;savsecdta&#039;&#039; — Back up user and access list objects&lt;br /&gt;
* &#039;&#039;savdlo&#039;&#039; — Back up Document Library Objects (DOS 8-character compatibility file system)&lt;br /&gt;
* &#039;&#039;sav&#039;&#039; — Back up IFS&lt;br /&gt;
* vary off the backup device&lt;br /&gt;
&lt;br /&gt;
The following CL program automates these steps:&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
   PGM        /* Save Changed Stuff to an Image Catalog.            */&lt;br /&gt;
   DCL        VAR(&amp;amp;OPTDRV) TYPE(*CHAR) LEN(10) VALUE(OPTBKUP01)&lt;br /&gt;
   DCL        VAR(&amp;amp;TODAY) TYPE(*CHAR) LEN(6)&lt;br /&gt;
   DCL        VAR(&amp;amp;OPTDAT) TYPE(*CHAR) LEN(10)&lt;br /&gt;
/* Vary on and initialize with current date.                        */&lt;br /&gt;
   RTVSYSVAL  SYSVAL(QDATE) RTNVAR(&amp;amp;TODAY)&lt;br /&gt;
   CVTDAT     DATE(&amp;amp;TODAY) TOVAR(&amp;amp;OPTDAT) TOFMT(*YMD) +&lt;br /&gt;
                TOSEP(*NONE)&lt;br /&gt;
   VRYCFG     CFGOBJ(&amp;amp;OPTDRV) CFGTYPE(*DEV) STATUS(*ON)&lt;br /&gt;
   DLYJOB     DLY(15)&lt;br /&gt;
   INZOPT     DEV(&amp;amp;OPTDRV) NEWVOL(&amp;amp;OPTDAT) MEDFMT(*UDF) +&lt;br /&gt;
              VOL(*MOUNTED) CHECK(*NO) THRESHOLD(*CALC)&lt;br /&gt;
/* Actually save.                                                   */&lt;br /&gt;
   SAVCHGOBJ  OBJ(*ALL) LIB(*ALLUSR) DEV(&amp;amp;OPTDRV) +&lt;br /&gt;
                OBJJRN(*YES) VOL(&amp;amp;OPTDAT) ENDOPT(*LEAVE) +&lt;br /&gt;
                UPDHST(*NO) PRECHK(*NO) SAVACT(*SYNCLIB) +&lt;br /&gt;
                SAVACTWAIT(30) DTACPR(*LOW) +&lt;br /&gt;
                OMITLIB(SAVRST) OUTPUT(*PRINT)&lt;br /&gt;
   MONMSG     MSGID(CPF3774 CPF3778 CPF9845)&lt;br /&gt;
   MONMSG     MSGID(CPF3794) EXEC(GOTO CMDLBL(SENDMSG))&lt;br /&gt;
   SAVCFG     DEV(&amp;amp;OPTDRV) ENDOPT(*LEAVE) DTACPR(*LOW) +&lt;br /&gt;
                OUTPUT(*PRINT)&lt;br /&gt;
   SAVSECDTA  DEV(&amp;amp;OPTDRV) ENDOPT(*LEAVE) DTACPR(*LOW) +&lt;br /&gt;
                OUTPUT(*PRINT)&lt;br /&gt;
   SAVDLO     DLO(*CHG) DEV(&amp;amp;OPTDRV) ENDOPT(*LEAVE) +&lt;br /&gt;
                OUTPUT(*PRINT) DTACPR(*LOW)&lt;br /&gt;
   MONMSG     MSGID(CPF906B)&lt;br /&gt;
   MONMSG     MSGID(CPF6772) EXEC(GOTO CMDLBL(SENDMSG))&lt;br /&gt;
   SAV        DEV((&#039;/QSYS.LIB/&#039; *CAT &amp;amp;OPTDRV *TCAT +&lt;br /&gt;
                &#039;.DEVD&#039;)) OBJ((&#039;/*&#039;) (&#039;/QSYS.LIB&#039; *OMIT) +&lt;br /&gt;
                (&#039;/QDLS&#039; *OMIT) (&#039;/QNTC&#039; *OMIT) +&lt;br /&gt;
                (&#039;/QFileSvr.400&#039; *OMIT)) OUTPUT(*PRINT) +&lt;br /&gt;
                CHGPERIOD(*LASTSAVE) UPDHST(*NO) DTACPR(*LOW)&lt;br /&gt;
   MONMSG     MSGID(CPF3837 CPD37C3 CPFA09E CPD384E)&lt;br /&gt;
   MONMSG     MSGID(CPF6772) EXEC(GOTO CMDLBL(SENDMSG))&lt;br /&gt;
   GOTO       CMDLBL(END)&lt;br /&gt;
   SENDMSG:&lt;br /&gt;
   SNDMSG     MSG(&#039;Fehler aufgetreten: Sicherungsabbruch.&#039;) +&lt;br /&gt;
                TOUSR(QSYSOPR)&lt;br /&gt;
   END:&lt;br /&gt;
   DLYJOB     DLY(15)&lt;br /&gt;
/* Close device file properly                                       */&lt;br /&gt;
   VRYCFG     CFGOBJ(&amp;amp;OPTDRV) CFGTYPE(*DEV) STATUS(*OFF)&lt;br /&gt;
   ENDPGM&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This CL code can be saved into e.&amp;amp;thinsp;g. &#039;&#039;qgpl/qclsrc.sav2imgclg&#039;&#039;, compiled, and run through &#039;&#039;wrkjobscde&#039;&#039; after the cronjob above has created the new images.&lt;br /&gt;
&lt;br /&gt;
== Full saves ==&lt;br /&gt;
These are also called &#039;&#039;Save 21&#039;&#039;, because it is run through item 21 in the &#039;&#039;save&#039;&#039; menu. The procedure is very much akin to incremental saves, but there are no individual calls to the various save programs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
   PGM        /* Vary on and inzopt optbkup01.                      */&lt;br /&gt;
   DCL        VAR(&amp;amp;OPTDRV) TYPE(*CHAR) LEN(10) VALUE(OPTBKUP01)&lt;br /&gt;
   DCL        VAR(&amp;amp;TODAY) TYPE(*CHAR) LEN(6)&lt;br /&gt;
   DCL        VAR(&amp;amp;OPTDAT) TYPE(*CHAR) LEN(10)&lt;br /&gt;
/* Vary on and initialize with current date.                        */&lt;br /&gt;
   RTVSYSVAL  SYSVAL(QDATE) RTNVAR(&amp;amp;TODAY)&lt;br /&gt;
   CVTDAT     DATE(&amp;amp;TODAY) TOVAR(&amp;amp;OPTDAT) TOFMT(*YMD) +&lt;br /&gt;
                TOSEP(*NONE)&lt;br /&gt;
   VRYCFG     CFGOBJ(&amp;amp;OPTDRV) CFGTYPE(*DEV) STATUS(*ON)&lt;br /&gt;
   DLYJOB     DLY(15)&lt;br /&gt;
   INZOPT     DEV(&amp;amp;OPTDRV) NEWVOL(&amp;amp;OPTDAT) MEDFMT(*UDF) +&lt;br /&gt;
              VOL(*MOUNTED) CHECK(*NO) THRESHOLD(*CALC)&lt;br /&gt;
   MONMSG     MSGID(OPT1330) EXEC(GOTO CMDLBL(SENDMSG))&lt;br /&gt;
   GOTO       CMDLBL(END)&lt;br /&gt;
   SENDMSG:&lt;br /&gt;
   SNDMSG     MSG(&#039;Fehler aufgetreten: Abbruch.&#039;) +&lt;br /&gt;
                TOUSR(QSYSOPR)&lt;br /&gt;
   END:&lt;br /&gt;
   ENDPGM&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This CL code can be saved into e.&amp;amp;thinsp;g. &#039;&#039;qgpl/qclsrc.prepsav21&#039;&#039;, compiled, and run manually after the you manually have created the new full save image.&lt;br /&gt;
&lt;br /&gt;
Since Save 21 is an inherently manual process, four steps are necessary:&lt;br /&gt;
* Create the new full save image, and an appropriate entry in &#039;&#039;VOLUME_LIST&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=shell&amp;gt;&lt;br /&gt;
truncate -s 20G /backups/i-backups/$(date &#039;+%Y%m%d&#039;)-0.udf&lt;br /&gt;
sed -i &amp;quot;1i $(date &#039;+%Y%m%d&#039;)-0.udf W&amp;quot; /backups/i-backups/VOLUME_LIST&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Vary on, initialize the image by running &#039;&#039;prepsav21&#039;&#039; shown above.&lt;br /&gt;
* &amp;lt;tt&amp;gt;go save&amp;lt;/tt&amp;gt;, type 21 and press return.&lt;br /&gt;
* After completion, vary off the device.&lt;br /&gt;
 vrycfg cfgobj(optbkup01) cfgtype(*dev) status(*off) &lt;br /&gt;
&lt;br /&gt;
Always make sure that you vary off the device after usage, so changes to &#039;&#039;VOLUME_LIST&#039;&#039; will be recognized at next vary on.&lt;br /&gt;
&lt;br /&gt;
== Single-file restore ==&lt;br /&gt;
* Vary on image catalog:&lt;br /&gt;
 vrycfg cfgobj(optbkup01) cfgtype(*dev) status(*on)&lt;br /&gt;
&lt;br /&gt;
* If necessary, select backup image (by date), and load:&lt;br /&gt;
 wrkimgclge imgclg(*dev) dev(optinst01)&lt;br /&gt;
&lt;br /&gt;
* For each backed up library, a file with the same name as the library was created in the respective image.&amp;lt;br&amp;gt;To see what&#039;s in it:&lt;br /&gt;
 dspopt vol(250417) data(*savrst) path(&#039;/mylib&#039;)&lt;br /&gt;
&lt;br /&gt;
* Since &#039;&#039;savchgobj&#039;&#039; is used for backup, &#039;&#039;rstobj&#039;&#039; must be used for restoration, e.&amp;amp;thinsp;g.:&lt;br /&gt;
 rstobj obj(*all) savlib(mylib) dev(optbkup01) endopt(*leave) mbropt(*all) rstlib(savrst) output(*print) optfile(&#039;/mylib&#039;)&lt;br /&gt;
&lt;br /&gt;
* Vary off the image catalog:&amp;lt;ref&amp;gt;If this is not done, the subsequent automatic incremental backup will fail.&amp;lt;/ref&amp;gt;&lt;br /&gt;
 vrycfg cfgobj(optbkup01) cfgtype(*dev) status(*off)&lt;br /&gt;
&lt;br /&gt;
== Pitfalls ==&lt;br /&gt;
* &#039;&#039;VOLUME_LIST&#039;&#039; is referenced only when varying on the optical device on IBM i. Changes to the file while the device is varied on are not recognized.&lt;br /&gt;
* Each file referenced in &#039;&#039;VOLUME_LIST&#039;&#039; &#039;&#039;&#039;must&#039;&#039;&#039; exist. If not the whole image catalog will behave erratic. &#039;&#039;Inzopt&#039;&#039; will fail with error code &amp;lt;code&amp;gt;OPT1300&amp;lt;/code&amp;gt;. On the other hand, the directory &#039;&#039;may&#039;&#039; contain files not being referenced in the image catalog. These are invisible to the image catalog logic.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ls -l&amp;lt;/tt&amp;gt; on the NFS server always shows the maximum allocatable size of the images. If you want to know the actually used size, use &amp;lt;tt&amp;gt;du&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [https://www.ibm.com/docs/en/i/7.3?topic=recovery-recovering-your-system Recovering your system], IBM.com&lt;br /&gt;
* [https://www.ibm.com/support/pages/ibm-i-save-and-restore-using-virtual-optical-images-nfs-server IBM i save and restore using virtual optical images on an NFS server], IBM.com&lt;br /&gt;
* [https://archive.midrange.com/midrange-l/202012/msg00377.html Image Catalog over NFS], discussion on midrange.com&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: System Administration‏‎]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Keeping_your_machine_clean&amp;diff=1695</id>
		<title>Keeping your machine clean</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Keeping_your_machine_clean&amp;diff=1695"/>
		<updated>2026-04-05T15:45:21Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;OS/400 has a lot of facilities to keep your machine running smoothly without doing anything sysadmin related. I want to not only keep the machine running smoothly, but keep it clean und uncluttered by unnecessary data. Thus I sign on as &#039;&#039;QSECOFR&#039;&#039; on a daily basis and check/clean the following:&lt;br /&gt;
&lt;br /&gt;
* Output queues (&amp;lt;code&amp;gt;WRKOUTQ&amp;lt;/code&amp;gt;), purging job logs and other output no longer relevant.&lt;br /&gt;
* Messages (&amp;lt;code&amp;gt;DSPMSG&amp;lt;/code&amp;gt;) for the users &#039;&#039;QSYSOPR&#039;&#039;, &#039;&#039;QTCP&#039;&#039;, &#039;&#039;QPGMR&#039;&#039;. These get purged by the system cleanup jobs eventually, but retain some messages. To keep overview about more or less important things happening, I want at least have a look at new messages appearing in &#039;&#039;QSYSOPR&#039;&#039;s message queue.&lt;br /&gt;
* Alerts (&amp;lt;code&amp;gt;WRKALR&amp;lt;/code&amp;gt;) are a more persistent, and visible way for the system to record possibly important messages, which might be easily overseen by just (loosely over)looking routinely over the &#039;&#039;QSYSOPR&#039;&#039; messages.&lt;br /&gt;
* Problems (&amp;lt;code&amp;gt;WRKPRB&amp;lt;/code&amp;gt;) are the next step to alerts. Some things on the system trigger all three: Messages, Alerts, and Problem entries.&lt;br /&gt;
&lt;br /&gt;
[[Category: System Administration]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Tape_Drives_on_old_AS/400&amp;diff=1694</id>
		<title>Tape Drives on old AS/400</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Tape_Drives_on_old_AS/400&amp;diff=1694"/>
		<updated>2026-04-05T15:25:33Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed another typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The QIC drives contained in many older machines are often defective, or it&#039;s expensive to impossible to get actual tapes for these drives. Sometimes, stock tape drives can be used also. This article documents which combination of machine, OS release, and drive has been tested so far.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note&#039;&#039;&#039;: The mentioned drives have been used to &#039;&#039;&#039;replace&#039;&#039;&#039; an existing internal drive, being connected to the internal SCSI bus. Some machines have hidden SCSI ports. Using those will fail to terminate the SCSI bus properly, with accompanying problems for the connected devices to transfer data.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Drive&lt;br /&gt;
!Server/OS&lt;br /&gt;
!Tasks tested&lt;br /&gt;
!Remark&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ddffdd;&amp;quot;&lt;br /&gt;
|HP DDS-1/2/3&lt;br /&gt;
|9401-150/V4R5&lt;br /&gt;
|Save/Restore/BMR&amp;lt;ref&amp;gt;&#039;&#039;B&#039;&#039;are &#039;&#039;M&#039;&#039;etal &#039;&#039;R&#039;&#039;estore, IPL from tape and restore of the entire system.&amp;lt;/ref&amp;gt;&lt;br /&gt;
|DIP-Switches set to default.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ddffdd;&amp;quot;&lt;br /&gt;
|HP DLTVS 80&amp;lt;ref&amp;gt;&#039;&#039;&#039;Caution!&#039;&#039;&#039; Protect the controller board of the drive with a piece of carton or other insulating material. The EMI prevention springs of the case will scratch components from the board otherwise.&amp;lt;/ref&amp;gt;&lt;br /&gt;
|9406-S20/V4R4 + 2726 SCSI RAID-Controller&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|SCSI-Error logged at IPL time.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ddffdd;&amp;quot;&lt;br /&gt;
|Dell LTO2&amp;lt;ref&amp;gt;Reported by third party.&amp;lt;/ref&amp;gt;&lt;br /&gt;
|9406-170 V4&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffffdd;&amp;quot;&lt;br /&gt;
|Conner CDT20004R-S&lt;br /&gt;
|9401-150/V4R5&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|DIP-Switches set to default.&amp;lt;br /&amp;gt;SCSI errors are logged for every initial access.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffffdd;&amp;quot;&lt;br /&gt;
|HP LTO1&lt;br /&gt;
|9406-800/V5R4 + 2757 SCSI RAID-Controller&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|SCSI-Errors logged at IPL time, and for every initial access.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffffdd;&amp;quot;&lt;br /&gt;
|Quantum DLT4000&lt;br /&gt;
|9401-150/V4R5&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|SCSI-Error 63A09210&amp;lt;ref&amp;gt;Illegal or unsupported tape unit response.&amp;lt;/ref&amp;gt; logged at IPL time, and for each access.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffdddd;&amp;quot;&lt;br /&gt;
|HP DDS-1/2/3&lt;br /&gt;
|9402-400/V4R2&lt;br /&gt;
|None.&lt;br /&gt;
|DIP-Switches set to default.&amp;lt;br /&amp;gt;Drive not recognised in DST.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffdddd;&amp;quot;&lt;br /&gt;
|HP DDS-1/2/3&lt;br /&gt;
|9401-P03/V3R2&lt;br /&gt;
|None.&lt;br /&gt;
|DIP-Switches set to default.&amp;lt;br /&amp;gt;Drive not recognised in DST.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Color legend:&lt;br /&gt;
{|class=&amp;quot;wikitable&lt;br /&gt;
|style=&amp;quot;align:center; background-color:#ddffdd;&amp;quot;|Green is for &#039;&#039;works without or with just minor errors&#039;&#039;.&lt;br /&gt;
|style=&amp;quot;align:center; background-color:#ffffdd;&amp;quot;|Yellow is for &#039;&#039;works, but with errors&#039;&#039;.&lt;br /&gt;
|style=&amp;quot;align:center; background-color:#ffdddd;&amp;quot;|Red is for &#039;&#039;does not work&#039;&#039;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Please see the &#039;&#039;Remarks&#039;&#039; column for further details.&lt;br /&gt;
&lt;br /&gt;
== A Word on HP DDS drives ==&lt;br /&gt;
[[File:Dds-roller.jpg|thumb|right|Paper-Sheet type cleaning roller (red arrow)]]&lt;br /&gt;
All those drives feature an automatic head cleaning mechanism.&lt;br /&gt;
&lt;br /&gt;
Certain (newer?) models have kind of a roller made from tiny raspy paper sheets, which is momentarily pressed to the rotating head drum via a solenoid. Other (older?) drive models feature a foam roller instead of these paper sheet cleaners. The foam has over the years degraded into bitumen foam. Once it made contact with the head from a test run, you&#039;ll have with that sticky substance forcing the tape being pulled out of the cartridge and winding around the drum in very high speed. A lot of work to undo.&lt;br /&gt;
&lt;br /&gt;
For these drives, &#039;&#039;&#039;it&#039;s crucial to prevent the foam roller to make contact with the head before you do any testing&#039;&#039;&#039;!&lt;br /&gt;
* by physically removing the foam residue from the roller; denatured alcohol helps in cleaning.&lt;br /&gt;
* by unplugging the power plug to the coil.&lt;br /&gt;
* by removing that cleaning assembly completely.&lt;br /&gt;
&lt;br /&gt;
I have two drives running without being able to clean automatically for years. They tend to more often ask for a cleaning tape, though. And once in a while, I remove the drives and clean the drum assembly by hand, with the tip of a soft cloth soaked with denatured alcohol.&lt;br /&gt;
&lt;br /&gt;
I have not yet found a reliable way of determining which DDS1 and 2 drive models are &amp;quot;safe&amp;quot; and which are not. I have not yet had a DDS3 drive out of four with that foam roller.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Tape device related system reference codes]]&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Hardware Configuration Guide‏‎]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Tape_Drives_on_old_AS/400&amp;diff=1693</id>
		<title>Tape Drives on old AS/400</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Tape_Drives_on_old_AS/400&amp;diff=1693"/>
		<updated>2026-04-05T15:25:03Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The QIC drives contained in many older machines are often defective, or it&#039;s expensive to impossible to get actual tapes for these drives. Sometimes, stock tape drives can be used also. This article documents which combination of machine, OS release, and drive has been tested so far.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Note&#039;&#039;&#039;: The mentioned drives have been used to &#039;&#039;&#039;replace&#039;&#039;&#039; an existing internal drive, being connected to the internal SCSI bus. Some machines have hidden SCSI ports. Using those will fail to terminate the SCSI bus properly, with accompanying problems for the connected devices to transfer data.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Drive&lt;br /&gt;
!Server/OS&lt;br /&gt;
!Tasks tested&lt;br /&gt;
!Remark&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ddffdd;&amp;quot;&lt;br /&gt;
|HP DDS-1/2/3&lt;br /&gt;
|9401-150/V4R5&lt;br /&gt;
|Save/Restore/BMR&amp;lt;ref&amp;gt;&#039;&#039;B&#039;&#039;are &#039;&#039;M&#039;&#039;etal &#039;&#039;R&#039;&#039;estore, IPL from tape and restore of the entire system.&amp;lt;/ref&amp;gt;&lt;br /&gt;
|DIP-Switches set to default.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ddffdd;&amp;quot;&lt;br /&gt;
|HP DLTVS 80&amp;lt;ref&amp;gt;&#039;&#039;&#039;Caution!&#039;&#039;&#039; Protect the controller board of the drive with a piece of carton or other insulating material. The EMI prevention springs of the case will scratch components from the board otherwise.&amp;lt;/ref&amp;gt;&lt;br /&gt;
|9406-S20/V4R4 + 2726 SCSI RAID-Controller&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|SCSI-Error logged at IPL time.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ddffdd;&amp;quot;&lt;br /&gt;
|Dell LTO2&amp;lt;ref&amp;gt;Reported by third party.&amp;lt;/ref&amp;gt;&lt;br /&gt;
|9406-170 V4&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffffdd;&amp;quot;&lt;br /&gt;
|Conner CDT20004R-S&lt;br /&gt;
|9401-150/V4R5&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|DIP-Switches set to default.&amp;lt;br /&amp;gt;SCSI errors are logged for every initial access.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffffdd;&amp;quot;&lt;br /&gt;
|HP LTO1&lt;br /&gt;
|9406-800/V5R4 + 2757 SCSI RAID-Controller&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|SCSI-Errors logged at IPL time, and for every initial access.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffffdd;&amp;quot;&lt;br /&gt;
|Quantum DLT4000&lt;br /&gt;
|9401-150/V4R5&lt;br /&gt;
|Save/Restore&lt;br /&gt;
|SCSI-Error 63A09210&amp;lt;ref&amp;gt;Illegal or unsupported tape unit response.&amp;lt;/ref&amp;gt; logged at IPL time, and for each access.&amp;lt;br /&amp;gt;Works otherwise.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffdddd;&amp;quot;&lt;br /&gt;
|HP DDS-1/2/3&lt;br /&gt;
|9402-400/V4R2&lt;br /&gt;
|None.&lt;br /&gt;
|DIP-Switches set to default.&amp;lt;br /&amp;gt;Drive not recognised in DST.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top; background-color:#ffdddd;&amp;quot;&lt;br /&gt;
|HP DDS-1/2/3&lt;br /&gt;
|9401-P03/V3R2&lt;br /&gt;
|None.&lt;br /&gt;
|DIP-Switches set to default.&amp;lt;br /&amp;gt;Drive not recognised in DST.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Color legend:&lt;br /&gt;
{|class=&amp;quot;wikitable&lt;br /&gt;
|style=&amp;quot;align:center; background-color:#ddffdd;&amp;quot;|Green is for &#039;&#039;works without or with just minor errors&#039;&#039;.&lt;br /&gt;
|style=&amp;quot;align:center; background-color:#ffffdd;&amp;quot;|Yellow is for &#039;&#039;works, but with errors&#039;&#039;.&lt;br /&gt;
|style=&amp;quot;align:center; background-color:#ffdddd;&amp;quot;|Red is for &#039;&#039;does not work&#039;&#039;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Please see the &#039;&#039;Remarks&#039;&#039; column for further details.&lt;br /&gt;
&lt;br /&gt;
== A Word on HP DDS drives ==&lt;br /&gt;
[[File:Dds-roller.jpg|thumb|right|Paper-Sheet type cleaning roller (red arrow)]]&lt;br /&gt;
All those drives feature an automatic head cleaning mechanism.&lt;br /&gt;
&lt;br /&gt;
Certain (newer?) models have kind of a roller made from tiny raspy paper sheets, which is momentarily pressed to the rotating head drum via a solenoid. Other (older?) drive models feature a foam roller instead of these paper sheet cleaners. The foam has over the years degraded into bitumen foam. Once it made contact with the head from a test run, you&#039;ll have with that sticky substance forcing the tape being pulled out of the cartridge and winding around the drum in very high speed. A lot of work to undo.&lt;br /&gt;
&lt;br /&gt;
For these drives, &#039;&#039;&#039;it&#039;s crucial to prevent the foam roller to make contact with the head before you do any testing&#039;&#039;&#039;!&lt;br /&gt;
* by physically removing the foam residue from the roller; denatured alcohol helps in cleaning.&lt;br /&gt;
* by unplugging the power plug to the coil.&lt;br /&gt;
* by removing that cleaning assembly completely.&lt;br /&gt;
&lt;br /&gt;
I have two drives running without being able to clean automatically for years. They tend to more often ask for a cleaning tape, though. And once in a while, I remove the drives and clean the drum assembly by hand, with the tip of a soft cloth soaked with denatured Alcohol.&lt;br /&gt;
&lt;br /&gt;
I have not yet found a reliable way of determining which DDS1 and 2 drive models are &amp;quot;safe&amp;quot; and which are not. I have not yet had a DDS3 drive out of four with that foam roller.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Tape device related system reference codes]]&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Hardware Configuration Guide‏‎]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=How_to_program_an_Application&amp;diff=1692</id>
		<title>How to program an Application</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=How_to_program_an_Application&amp;diff=1692"/>
		<updated>2026-04-04T10:38:53Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FIXME|Finish article.}}&lt;br /&gt;
Getting started on programming the AS/400 isn&#039;t hard. According to Frank Soltis, the most effective way to get a machine sold is to actually bring an AS/400 along to the future customer, and show an C&#039;&#039;x&#039;&#039;O in a one hour crash course how to code a simple &#039;&#039;business application&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Well, something an arbitrary business buffoon can do, you can do, too. Since the usual [[wikipedia:&amp;quot;Hello, World!&amp;quot; program|Hello World]] is just too lame, let&#039;s start with an actually usable example: A simple address book application.&lt;br /&gt;
&lt;br /&gt;
== Components of a typical Program ==&lt;br /&gt;
Since we&#039;re talking about a database machine, the first we need to know is how to create &#039;&#039;Database Tables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Editing Database Content is usually done in screen &#039;&#039;forms&#039;&#039;. These are called &#039;&#039;Display Files&#039;&#039;. So, let&#039;s also learn how to create Display Files in the next turn.&lt;br /&gt;
&lt;br /&gt;
Finally, there must be a program for handling key presses from the user and coping with the I/O of database- and display files.&lt;br /&gt;
&lt;br /&gt;
Optionally, there can be more files to support additional functions in a program. Printer files allow for formatted output (tabular report) to a printer. InterSystem Communication Files allow for Record-I/O to other programs on the local or a remote host. We will not dig into these, for now.&lt;br /&gt;
&lt;br /&gt;
=== Programming Languages ===&lt;br /&gt;
Available on a full install of an older OS/400 are compilers for&lt;br /&gt;
* [[wikipedia:C (programming language)|C]]/[[wikipedia:C++|C++]],&lt;br /&gt;
* [[wikipedia:COBOL|COBOL]],&lt;br /&gt;
* [[wikipedia:IBM i Control Language|CL]], the equivalent of batch/shell scripts,&lt;br /&gt;
* [[wikipedia:Java (programming language)|Java]],&lt;br /&gt;
* [[wikipedia:IBM RPG|RPG]],&amp;lt;ref&amp;gt;Report Program Generator.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and interpreters for&lt;br /&gt;
* [[wikipedia:Rexx|REXX]], a scripting language derived from the mainframe world.&lt;br /&gt;
&lt;br /&gt;
RPG and COBOL are available in two flavors: [[wikipedia:Integrated Language Environment|ILE]] and [https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/ilec/opmdesc.htm OPM]. See linked explanations for details.&lt;br /&gt;
&lt;br /&gt;
It makes no sense to utilize OPM compilers for new projects. It&#039;s best you save space and deinstall these as well as the &#039;&#039;*PRV&#039;&#039; variants, that generate code for the immediately previous OS release. We&#039;ll solely focus on ILE since it has (amongst others) the advantage of linking (binding) compiled object code from different languages together to form a program.&lt;br /&gt;
&lt;br /&gt;
The IBM website features [https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzahg/rzahglanguages.htm extensive documentation] for each language.&lt;br /&gt;
&lt;br /&gt;
== A Word on Editors ==&lt;br /&gt;
If you are familiar with &#039;&#039;vi&#039;&#039; or &#039;&#039;vim&#039;&#039; on Unix-like platforms, learning SEU will be an easy task. You may alternatively utilize an editor of your choice on the platform of your choice.&amp;lt;ref&amp;gt;Windows Notepad is &#039;&#039;&#039;not&#039;&#039;&#039; a proper editor. It&#039;s sufficient for notes, though. Hence the name.&amp;lt;/ref&amp;gt; To help you chose, we&#039;ll take a closer look on the pros and cons of each solution.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Editor&lt;br /&gt;
!Pro&lt;br /&gt;
!Con&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|&#039;&#039;&#039;SEU on OS/400&#039;&#039;&#039;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Built-in contextual support for certain file types and kind of lines with precise column requirements.&amp;lt;br /&amp;gt;Editing is done in an implicit array of blanks in permanent overwrite mode for easier placement of characters in proper position.&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Can display only a few lines of code, that reduces clarity and thus forces a lot of scrolling.&amp;lt;br /&amp;gt;Uniform colouring of code is increasingly uncommon and makes it even more difficult to keep an overview.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|&#039;&#039;&#039;Other on other platforms&#039;&#039;&#039;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Familiar operation and UI.&amp;lt;br /&amp;gt;Easy content duplication with clearly visible text range selection, and copy-paste.&amp;lt;br /&amp;gt;Possibility to create custom rules for syntax highlighting.&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Cumbersome handling: After every change that should result in a compile run, changed files have to be transferred back in some way.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Killer-Feature of SEU is the extensive contextual support it provides for RPG and DDS, and partly for COBOL. For beginners, it&#039;s much easier to utilize this helpful function often until some knowledge, routine and working programs as copy-source have been established.&lt;br /&gt;
&lt;br /&gt;
=== Vim ===&lt;br /&gt;
Vim is most often the editor of choice for seasoned Text-UI aficionados. Since &#039;&#039;vim&#039;&#039; is able to open files on remote-locations via URL notation, you can perfectly use it for editing on the fly from any platform vim is available for. There are even extensions for [https://github.com/kaimoku/vim-syntax-for-i syntax-highlighting] of common code.&amp;lt;ref&amp;gt;No longer working with vim 8.&amp;lt;/ref&amp;gt; Automation of login can be done via [http://www.mavetju.org/unix/netrc.php &#039;&#039;~/.netrc&#039;&#039; file]:&lt;br /&gt;
&lt;br /&gt;
* Create/edit your &#039;&#039;~/.vimrc&#039;&#039; to switch to ASCII mode on start, add:&lt;br /&gt;
 let g:netrw_ftpmode=&amp;quot;ascii&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Create/edit your &#039;&#039;~/.netrc&#039;&#039; to have credentials ready, add:&lt;br /&gt;
 machine my-machine-name&lt;br /&gt;
 login myuser&lt;br /&gt;
 password mypassword&lt;br /&gt;
 macdef init&lt;br /&gt;
  ascii&lt;br /&gt;
 &lt;br /&gt;
Important: The file &#039;&#039;&#039;must&#039;&#039;&#039;&lt;br /&gt;
* end with a blank line,&lt;br /&gt;
* set &amp;lt;code&amp;gt;chmod 600 ~/.netrc&amp;lt;/code&amp;gt;, otherwise the &#039;&#039;ftp&#039;&#039; command refuses to use it.&lt;br /&gt;
&lt;br /&gt;
* Edit files giving vim the remote URL:&lt;br /&gt;
 vim &amp;lt;nowiki&amp;gt;ftp://my-machine-name/mylib/mysrcpf.mymember&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this toolset, you can develop with a tall &#039;&#039;vim&#039;&#039; window on your desktop machine, klick on a 5250-session to compile and maybe have a second 5250 session open for running the program.&lt;br /&gt;
&amp;lt;gallery class=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
File:Vim-screen-dspf-dds.png|Vim showing 91 lines of DDS&lt;br /&gt;
File:Vim-screen-rpgle.png|Vim showing 91 lines of RPG IV positional code&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Preparation ==&lt;br /&gt;
As you probably know from your experience with common systems, it&#039;s considered bad habit to work with administrative rights all of the time. I recommend [[Creating a User Account]] for you to properly work without accidentally doing harm to the system. &#039;&#039;Sign in&#039;&#039; as this user now. This gives you a subset of menu items in the &#039;&#039;main&#039;&#039; menu and makes your own Library your &#039;&#039;current library&#039;&#039;. For now, consider this almost the same thing as using the &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt; command of a shell to make a directory your current one.&lt;br /&gt;
&lt;br /&gt;
As outlined in [[Filesystems and Files on the AS/400#File Types|File Types]], we&#039;ll need to create a file to hold source code. Let&#039;s do that and make the maximum line length a bit larger for more flexibility.&amp;lt;ref&amp;gt;IBM delivers ready made, empty source files in the QGPL-Library. Every class of file has it&#039;s own source file, such as QCLSRC for CL source code. I consider this confusing: Working on multiple files is more cumbersome than working on multiple members of one file. The files in a member could be marked as a given type of content. The only drawback is that one must use distinct names on members. The QSYS.LIB-Filesystem can hold files with the same &#039;&#039;name&#039;&#039; as long as they have distinct &#039;&#039;types&#039;&#039;.&amp;lt;/ref&amp;gt;&lt;br /&gt;
 CRTSRCPF FILE(SOURCES) RCDLEN(112)&lt;br /&gt;
&lt;br /&gt;
The white text in the status line will show you that the file has been created.&lt;br /&gt;
&lt;br /&gt;
== Working with Members in Files ==&lt;br /&gt;
The easiest way to edit members of source files is to utilize part of the &#039;&#039;Program Development Manager&#039;&#039;.&lt;br /&gt;
 WRKMBRPDM FILE(SOURCES)&lt;br /&gt;
&lt;br /&gt;
You&#039;ll be presented with a screen form to handle members. Press &amp;lt;code&amp;gt;F6&amp;lt;/code&amp;gt; to show the &#039;&#039;Start SEU&#039;&#039;&amp;lt;ref&amp;gt;Source Entry Utility.&amp;lt;/ref&amp;gt; screen. Fill out the two first fields:&lt;br /&gt;
* SRCMBR is &#039;&#039;addrpf&#039;&#039; (for addresses physical file),&lt;br /&gt;
* TYPE is &#039;&#039;pf&#039;&#039; for physical file.&lt;br /&gt;
&lt;br /&gt;
Press &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt; to start SEU and present an empty file.&lt;br /&gt;
&lt;br /&gt;
== Coding the Database Table ==&lt;br /&gt;
We&#039;re going to code the description of a database file, that is the traditional way to create database files in OS/400.&amp;lt;ref&amp;gt;Database files can also be created with the interactive SQL facility, though. But one can&#039;t derive a textual description from a SQL created database file.&amp;lt;/ref&amp;gt; The &#039;&#039;language&#039;&#039; for the statements is called &#039;&#039;DDS&#039;&#039;&amp;lt;ref&amp;gt;Data Description Statements.&amp;lt;/ref&amp;gt; that is not a line oriented description like HTML. The position of statements within one line are also important.&amp;lt;ref&amp;gt;This stems from old times when punch cards were used for programming stuff. Since compatibility is mandatory, IBM extended DDS from time to time with new keywords, but left the previous stuff alone.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For an address book, let&#039;s assume the following fields are of primary interest:&lt;br /&gt;
* Name,&lt;br /&gt;
* First Name,&lt;br /&gt;
* Birthday,&lt;br /&gt;
* Street and Number,&lt;br /&gt;
* ZIP Code and City Name,&lt;br /&gt;
* Phone Number,&lt;br /&gt;
* Cellular Phone Number,&lt;br /&gt;
* E-Mail Address.&lt;br /&gt;
&lt;br /&gt;
Plain DDS Code looks like this:&lt;br /&gt;
      A                                      UNIQUE&lt;br /&gt;
      A          R ADDRTBL&lt;br /&gt;
      A            NAME          48A&lt;br /&gt;
      A            FIRSTNAME     48A&lt;br /&gt;
      A            BIRTHDAY        L&lt;br /&gt;
      A            STREETNUM     48A&lt;br /&gt;
      A            ZIPCITY       48A&lt;br /&gt;
      A            PHONE         48A         ALWNULL&lt;br /&gt;
      A            CELLPHONE     48A         ALWNULL&lt;br /&gt;
      A            EMAIL         48A         ALWNULL&lt;br /&gt;
      A          K NAME&lt;br /&gt;
      A          K FIRSTNAME&lt;br /&gt;
      A          K BIRTHDAY&lt;br /&gt;
&lt;br /&gt;
To understand a bit better, I&#039;ll elaborate.&lt;br /&gt;
&lt;br /&gt;
As you can see, everything is written in upper case. To be honest, I don&#039;t know if a file with lower case characters in any place but comments is compilable.&lt;br /&gt;
&lt;br /&gt;
Every line starts with an &#039;&#039;A&#039;&#039; in the 6th place of a line. The first five once were reserved for optional line numbering but I&#039;ve seen no examples where this is actually done.&lt;br /&gt;
&lt;br /&gt;
The first line denotes that this file may not have duplicate values in key fields (coded later).&lt;br /&gt;
&lt;br /&gt;
The second line names this &#039;&#039;record format&#039;&#039;. This should be different from the file name. If not, you&#039;ll earn compiler warnings: In the actual program, when working with that file, it&#039;s ambiguous if you refer to the file name or the record format. For that reason, I name record formats for physical files with the suffix &#039;&#039;tbl&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Physical Files must have exactly one record format.&lt;br /&gt;
&lt;br /&gt;
The next few lines define the fields of the database file. I don&#039;t want getting unnecessary initial complexity, so I defined all fields as ch&#039;&#039;&#039;a&#039;&#039;&#039;racter with static 48 places.&amp;lt;ref&amp;gt;The AS/400 database knows about &#039;&#039;varchar&#039;&#039; field, but the handling in the code later would be really clumsy. So I refrain from that for now. Not used places are automatically filled with blanks.&amp;lt;/ref&amp;gt; The &#039;&#039;Birthday&#039;&#039;-field is the only exception, that is defined as a date field.&lt;br /&gt;
&lt;br /&gt;
Some fields may be left empty. To save space, these may be NULL, that is not the same as &#039;&#039;empty&#039;&#039;. Therefore they are defined with an additional parameter &#039;&#039;alwnull&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
NULL fields permit fields of records to utilize no space at all, but need special attention in the code. This isn&#039;t as clumsy as coping with &#039;&#039;varlen&#039;&#039; strings, though.&lt;br /&gt;
&lt;br /&gt;
The last three lines denote &#039;&#039;key fields&#039;&#039;. When reading records, they&#039;ll be retrieved in key order (ascending by default). According to the first line, entries must be &#039;&#039;unique&#039;&#039; over all key fields. So you may not have more than one entry named Fred Flintstone born on 1989-08-20. This is a somewhat crude way to prevent duplicates.&amp;lt;ref&amp;gt;If Fred has more than one place to live, the right way to handle that would be to create a second table that lists every possible street address for a given Tuple Name—First Name—Birthday. Of course we might introduce entry IDs to keep the address table small. As said, I want to keep complexity low.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After saving the member, one may type &#039;&#039;14&#039;&#039; into the field of the &#039;&#039;wrkmbrpdm&#039;&#039; members list to instruct it to compile the file with default values to the default location that is your current library.&lt;br /&gt;
&lt;br /&gt;
=== A Word about the Compilation of Objects ===&lt;br /&gt;
Compilation per default takes place as background (batch) job that is more friendly to other tasks running in interactive mode but it&#039;s a bit clumsy to handle. One needs to look into the session&#039;s [[Messages and Message Queues|message queue]] to see if the compilation succeeded or failed, to be followed by a look into the [[Spooled Files and Output Queues|spooled file]], searching the verbose compiler output for possible culprits.&amp;lt;br /&amp;gt;&lt;br /&gt;
One may press &amp;lt;code&amp;gt;F18&amp;lt;/code&amp;gt; in the &#039;&#039;wrkmbrpdm&#039;&#039; screen to access another screen with user based defaults. The third option must be set to &#039;&#039;N&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Editing Source Files using Eclipse and FTP]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [https://www.pocnet.net/computer/fallout/ Helper Programs] for the Fallout Role Playing Game Series&lt;br /&gt;
* [https://github.com/PoC-dev/as400-sfltemplates Templates] for easy development of one-database-table maintenance programs&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Programming]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=Filesystems_and_Files_on_the_AS/400&amp;diff=1691</id>
		<title>Filesystems and Files on the AS/400</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=Filesystems_and_Files_on_the_AS/400&amp;diff=1691"/>
		<updated>2026-03-18T17:58:04Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo, fixed grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FIXME|&lt;br /&gt;
* Add Chapter how to create physical and logical files,&lt;br /&gt;
* Move explanations to access paths to a programming article?}}&lt;br /&gt;
Since the AS/400 has been designed as a business helper machine, its processing capabilities mainly cover structured data with comparatively small record sizes. With the ongoing evolution of OS/400, more functionality was added by IBM that weakens this concise definition, though. On the other hand, the same added functionality improves ease of data storage for, and data exchange with other platforms.&lt;br /&gt;
&lt;br /&gt;
== Different approaches of data storage and processing ==&lt;br /&gt;
Structured data can be processed most efficiently when the underlying logical and physical facilities support this approach natively instead of mimicking.&lt;br /&gt;
&lt;br /&gt;
By comparison, most platforms outside the world of mainframes and minicomputers, as they were once known, operate on byte streams. Byte streams don&#039;t have any natural structure visible from outside. That is, without analyzing the content of the stream at any given moment, there is no chance to map the current byte position into any logical structure.&amp;lt;br /&amp;gt;&lt;br /&gt;
This is somewhat similar to the differences between data transmission in an asynchronous manner (such as the RS-232 protocol specifies) versus synchronous. With asynchronous transfers, data payload has to be enriched with additional information to enable processing logic to chop the continuous stream of data into pieces to enable processing facilities to work on them in a structured way.&lt;br /&gt;
&lt;br /&gt;
Most, if not all data is based on some structure, though. The simplest structure is a blob of data of a given size, usually named a &#039;&#039;block&#039;&#039;. When looking closely, conversion from, and to byte streams from and to blocks takes place on many levels:&lt;br /&gt;
* Storage of data on hard disks or in solid state memory in blocks of 512&amp;amp;thinsp;Bytes or 4&amp;amp;thinsp;[[wikipedia:Kibibyte|KiB]],&lt;br /&gt;
* Paging and Swapping activity of virtual memory systems also takes place in blocks instead of streams,&lt;br /&gt;
* Data Transfer over todays networks is done in pieces called &#039;&#039;frames&#039;&#039;.&amp;lt;ref&amp;gt;To be precise, this isn&#039;t done to ease or enable record oriented processing but to enable sharing of physical media (like cables) between many participants of the network.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On a higher level of a file&#039;s content definition, more elaborated structuring of stream-based data can be found:&lt;br /&gt;
* Pixel-oriented picture files include a header that dynamically defines the format of the data that follows,&lt;br /&gt;
* Movie files are defined by different kinds of data blocks: To save space, many frames are only saved as differences to the picture before,&amp;lt;ref&amp;gt;From time to time, a key frame contains a complete picture to compensate for data loss, that can happen for many reasons.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Todays most used text processing software internally uses [[wikipedia:XML|XML]] to give seemingly unstructured data a structure,&lt;br /&gt;
* Application Program Files also are structured in a way that permits the operating system to efficiently load and execute the contained code,&lt;br /&gt;
* Even plain text files have a structure: They contain of words, sentences, and paragraphs.&lt;br /&gt;
&lt;br /&gt;
The mapping of structured data into byte streams leverages processing speed with flexibility to store arbitrary complex data structures into very simple data structures on disk. Today, the processing overhead of mapping byte streams into records (blocks) or more elaborated data structures is almost nullified by cheap availability of sheer processing power.&lt;br /&gt;
&lt;br /&gt;
=== Storage Overhead ===&lt;br /&gt;
However, mapping byte streams into logical blocks of information often creates &#039;&#039;storage overhead&#039;&#039;. For example, a plain text file with the word &#039;Hello&#039; uses only 5&amp;amp;thinsp;Bytes of actual data&amp;lt;ref&amp;gt;Counted as ASCII, or SBCS as named in the AS/400-World.&amp;lt;/ref&amp;gt; (sometimes followed by implicit end of line marker(s)), the file occupies at least 512&amp;amp;thinsp;Bytes data, since this is the minimum block size on usual hard disks. If the file is expanded to exactly 512&amp;amp;thinsp;Bytes by adding more text, the overhead is zero. Adding just one character starts the continuation of data in the next disk block and again occupies the whole block of that 511&amp;amp;thinsp;Bytes are wasted.&amp;lt;br /&amp;gt;&lt;br /&gt;
This overhead might be negligible when looking at todays file sizes. But, every OS utilizes configuration files, that usually are small and fit the above description perfectly. &#039;&#039;/etc/hosts&#039;&#039; may be 680&amp;amp;thinsp;Bytes long on a given system, that makes up 344&amp;amp;thinsp;Bytes wasted space, according to the above calculation.&amp;lt;ref&amp;gt;Actually, with todays partition sizes, Linux uses 4&amp;amp;thinsp;KiB blocks, not 512&amp;amp;thinsp;Bytes. This raises the overhead of said &#039;&#039;/etc/hosts&#039;&#039; to 3416&amp;amp;thinsp;Bytes.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Today, this storage overhead is also almost nullified by cheap availability of gigantic hard disk storage capacity.&lt;br /&gt;
&lt;br /&gt;
=== Latency ===&lt;br /&gt;
Considering the above description, it&#039;s easily observable that actual data is scattered across a greater area of a given hard disk with many holes in between, compared to all files concatenated to one big blob. This increases latency, because the disk&#039;s head assembly must move more often to access a certain block on the physical media.&lt;br /&gt;
&lt;br /&gt;
Today, I/O latencies are nullified by cheap availability of solid state memory “disks”.&lt;br /&gt;
&lt;br /&gt;
== AS/400 IFS ==&lt;br /&gt;
Early incarnations of the AS/400 had no facilities to save or process byte-based &#039;&#039;stream files&#039;&#039;. There only was the possibility to create files with a fixed record structure. With the introduction of the &#039;&#039;integrated file system&#039;&#039; in OS/400 Version 3, saving and processing of byte stream files has been made possible. The classical record oriented file system was in turn named &#039;&#039;QSYS.LIB&#039;&#039;-file system and looks like a classical Unix mount point, when looking with applications being aware of the IFS, such as &#039;&#039;qsh&#039;&#039;, the minimal UNIX like shell. The rest of the filesystems allow to store stream files.&amp;lt;br /&amp;gt;&lt;br /&gt;
Up to today, &#039;&#039;QSYS.LIB&#039;&#039; is still the most important file system on AS/400&#039;s because most part of the OS is stored there, as well as configuration database files and, of course application specific database files.&lt;br /&gt;
&lt;br /&gt;
This &#039;&#039;IFS&#039;&#039; is not the same as file systems in Linux or other common operating systems. There, one or more disks are &#039;&#039;partitioned&#039;&#039;: Space from one disk split into slices of usable space by software. To make use of the space available in this partitions, a &#039;&#039;file system&#039;&#039; has to be created. That is, database-like structures for the mapping of files to disk blocks are written into any given partition space. The space available for the creation of files on any given file system is thus fixed to the size of the partition, minus overhead, minus space needed for the aforementioned data structures. Multiple filesystems have been conceived over decades with a determined set of features, so it&#039;s possible to use different file systems to match the different storage needs of different types of files.&lt;br /&gt;
&lt;br /&gt;
On the other side, the IFS of the AS/400 is a purely &#039;&#039;logical structure&#039;&#039; that allocates disk blocks as requested by the operating system. If a record oriented file in the classical &#039;&#039;QSYS.LIB&#039;&#039;-filesystem is filled with data, disk blocks are filled with this data and are thus no longer available for storage. If someone transfers a picture file to the AS/400&#039;s &#039;&#039;/QOpenSys&#039;&#039;-Filesystem, disk-blocks are allocated for that data and also cannot be allocated for storage. There is no static assignment for these different file systems to partitions or disk blocks.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Stuff saved in file systems on the AS/400 is usually referred to as &#039;&#039;objects&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== AS/400 files ==&lt;br /&gt;
The AS/400 file handling shares a common heritage of file handling found in IBM mainframes (MVS or z/OS partitioned data sets). An AS/400 &#039;&#039;file&#039;&#039; defines at least the record length. All &#039;&#039;members&#039;&#039; of these file share this maximum length and thus are constrained to this length.&amp;lt;br&amp;gt;&lt;br /&gt;
In addition, an &#039;&#039;externally defined file&#039;&#039; can be more strict than an MVS PDS, by not only enforcing a record length, but also an actual field layout and -content over this record.&amp;lt;br&amp;gt;&amp;lt;ref&amp;gt;The term &#039;&#039;external&#039;&#039; is greatly misleading here, because the file definition is &#039;&#039;external&#039;&#039; to the &#039;&#039;program&#039;&#039; using that file. Indeed, the field layout is &#039;&#039;internal&#039;&#039; to the file object.&amp;lt;/ref&amp;gt;&lt;br /&gt;
This can be roughly compared to a directory on Linux or (better) a tar file, where one may only add TIFF image data with a common horizontal pixel count.&amp;lt;ref&amp;gt;This is fairly unpractical in computing as we know it.&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
For example, by creating a &#039;&#039;source file&#039;&#039; on an AS/400, one defines a &#039;&#039;file&#039;&#039; with a certain record length.&amp;lt;ref&amp;gt;92&amp;amp;thinsp;Bytes by default.&amp;lt;/ref&amp;gt; One may use this &#039;&#039;file&#039;&#039;, create &#039;&#039;members&#039;&#039; and add program source code to these members at will, but it&#039;s not possible to add data with any line longer than 92 characters into any member of that file.&lt;br /&gt;
&lt;br /&gt;
=== File Types ===&lt;br /&gt;
Basically there are four types of files found in any AS/400&#039;s classical &#039;&#039;QSYS.LIB&#039;&#039; filesystem:&lt;br /&gt;
* &#039;&#039;&#039;Source Files&#039;&#039;&#039; are &#039;&#039;physical files&#039;&#039;, aka &#039;&#039;database files&#039;&#039; with at least two fields per record:&lt;br /&gt;
** Line of Text, primarily to hold program code to be compiled,&lt;br /&gt;
** Timestamp, records the last change of that particular line.&amp;lt;ref&amp;gt;SEU shows these timestamps on the very far right of it&#039;s display.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Physical Files&#039;&#039;&#039; are again database files but with a user defined record length and field format.&lt;br /&gt;
* &#039;&#039;&#039;Logical Files&#039;&#039;&#039; are files that reference one or more physical files, but do not contain any data. LFs can be compared to the SQL terms:&lt;br /&gt;
** &#039;&#039;view&#039;&#039;: Show only a subset of fields of PF,&lt;br /&gt;
** &#039;&#039;join&#039;&#039;: Show a superset of fields of more than one PF,&lt;br /&gt;
** &#039;&#039;index&#039;&#039;: Apply different indexes, and thus record sorting.&lt;br /&gt;
: In addition, restrictions about which records to select or omit from the PF can be added.&lt;br /&gt;
* &#039;&#039;&#039;Other Files&#039;&#039;&#039; that appear as type &#039;&#039;*FILE&#039;&#039; in output listings that include, but are not limited to&lt;br /&gt;
** &#039;&#039;Display Files&#039;&#039; that map data to positions on the screen and enable user interaction to this forms,&lt;br /&gt;
** &#039;&#039;Printer Files&#039;&#039; that map data to positions on a virtual sheet of paper for later printer output,&lt;br /&gt;
** &#039;&#039;Inter Communication Facility Files&#039;&#039; who provide an easy way for application programs to talk to other programs on the same or remote AS/400&#039;s,&lt;br /&gt;
** &#039;&#039;Save files&#039;&#039; that provide roughly the same functionality as tar files on Linux, enabling bundling of files (objects) of different types into one self-contained archive, for easier transmission to other systems for re-extracting or permanent storage.&lt;br /&gt;
&lt;br /&gt;
Handling of these files will be explained in separate articles.&lt;br /&gt;
&lt;br /&gt;
==== A word on physical and logical (database) files ====&lt;br /&gt;
The main usage of logical files is to provide different &#039;&#039;access paths&#039;&#039; compared to the linked physical file to read data. An access path is just one or more [[wikipedia:Database index|database index(es)]] created for one or more fields of a given physical file.&lt;br /&gt;
&lt;br /&gt;
When accessing database files through the classical READ(P)(E)-API-Calls, there&#039;s no possibility to sort a result set dynamically as it&#039;s easily done with [[wikipedia:SQL|SQL]]. There&#039;s not even a result set. There&#039;s just kind of a &#039;&#039;file pointer&#039;&#039; that points to the last read row, and the order in that the rows are retrieved by subsequent READs (that increment this file pointer) are determined by the access path(s).&amp;lt;br /&amp;gt;&lt;br /&gt;
Keep in mind that this handling of structured data stems from a time period when computers had only a tiny fraction of today&#039;s processing power&amp;lt;ref&amp;gt;Processing as in &#039;&#039;Read from disk — Modify — Write to disk&#039;&#039;.&amp;lt;/ref&amp;gt; and storage capacity.&lt;br /&gt;
&lt;br /&gt;
Considering the clear positioning of the AS/400 as &#039;&#039;database machine&#039;&#039; by IBM, and adding the fact that the precursor to SQL was created in the early 1970s by IBM employees, SQL might have been available on the AS/400 from it&#039;s first release.&amp;lt;br /&amp;gt;&lt;br /&gt;
On older machines, SQL proves to be painfully slow, especially when dealing with huge database tables. Since the SQL engine dynamically adds database indexes as needed when processing queries, getting data out of a table can be really slow when such a temporary index must be created in advance.&lt;br /&gt;
&lt;br /&gt;
On the other side, utilizing the legacy API-Calls to retrieve and process random records with CHAIN-READ from multi-GiB-sized database tables is surprisingly quick on old machines for many reasons.&lt;br /&gt;
&lt;br /&gt;
This somewhat restricted API call interface explains why data handling within applications on the AS/400 feel so fundamentally different compared to what we&#039;re used to.&lt;br /&gt;
&lt;br /&gt;
Most common platforms utilize SQL:&lt;br /&gt;
* The user is providing (part of) a query string, the database picks matching rows and&lt;br /&gt;
* the application delivers a limited view of the whole database content back to the user.&lt;br /&gt;
** The user may easily change sorting of the result records to be based on any single field by usually clicking on the respective table header field in the application&#039;s UI,&lt;br /&gt;
* the user may finally select the desired record for further processing.&lt;br /&gt;
&lt;br /&gt;
AS/400 applications usually…&lt;br /&gt;
* provide a complete list view&amp;lt;ref&amp;gt;These lists are called &#039;&#039;subfiles&#039;&#039;.&amp;lt;/ref&amp;gt; of the entire database content, with a fixed sort order. The user may either scroll to the desired record, or type part of a search string in a designated input line and press &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt;.&lt;br /&gt;
* The application reloads the list view after CHAINing (placing the &#039;&#039;file pointer&#039;&#039;) to the first record matching (part of) the search string&amp;lt;ref&amp;gt;To be precise, the search string is matched against the &#039;&#039;&#039;start&#039;&#039;&#039; of the respective strings in the key field. It&#039;s not a &amp;lt;code&amp;gt;… LIKE &#039;%FOOBAR%&#039;&amp;lt;/code&amp;gt;-matching that is simply not possible with the legacy API.&amp;lt;/ref&amp;gt;. The rest of the list is filled with subsequent READs until the list is full or [[wikipedia:End-of-file|EOF]] is reached.&lt;br /&gt;
** Skillful programming techniques allow the user to freely scroll forward and backward from the record retrieved in the last step.&lt;br /&gt;
* The user may finally select the desired record for further processing.&lt;br /&gt;
&lt;br /&gt;
Programs don&#039;t need to maintain the list programmatically xor allocate memory for loading the whole database. Details will be explained in the articles about programming.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Basic Knowledge]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=5250_colors_and_display_attributes&amp;diff=1525</id>
		<title>5250 colors and display attributes</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=5250_colors_and_display_attributes&amp;diff=1525"/>
		<updated>2025-07-09T13:55:34Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The IBM &#039;&#039;&#039;5250&#039;&#039;&#039; data stream was devised in the 1970&#039;s. Color was not thought of, even if color displays were well known for a long time from TV. After the later introduction of color displays for computer terminal screens, already established &#039;&#039;&#039;display attributes&#039;&#039;&#039; were reused for indicating which color something on the screen should have.&lt;br /&gt;
&lt;br /&gt;
Display attributes are encoded in a single, otherwise invisible screen position directly preceding the screen element(s) the attribute is applied to.&amp;lt;ref&amp;gt;The DDS logic takes care to switch off set attributes after a screen element&#039;s end.&amp;lt;/ref&amp;gt; This &#039;&#039;attribute byte&#039;&#039; can be modified with the DDS keywords &amp;lt;tt&amp;gt;COLOR&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DSPATR&amp;lt;/tt&amp;gt; and indicators. Since indicators are limited in count, conditionally applying many attributes to many screen objects can quickly exhaust the number of available indicators for a given screen (record format).&amp;lt;ref&amp;gt;It should be noted that in a subfile, each record has an independent set of indicators.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attributes ==&lt;br /&gt;
The basic display attributes are specified as follows. Counted from right to left (LSB to MSB)!&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Bit&lt;br /&gt;
!Attribute (DSPATR-Name)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|0&lt;br /&gt;
|Reverse Image (RI)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|1&lt;br /&gt;
|High Intensity (HI)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|2&lt;br /&gt;
|Underline (UL)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|3&lt;br /&gt;
|Blink (BL)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|4&lt;br /&gt;
|Column separator (CS)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|5&lt;br /&gt;
|Always 1&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|6&lt;br /&gt;
|Always 0&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;right&amp;quot;|7&lt;br /&gt;
|Protect (PR)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Attribute to color mapping ==&lt;br /&gt;
As stated, color was introduced later. Hence, display attribute bits have been reused for setting color:&lt;br /&gt;
* Blink = Red&lt;br /&gt;
* Column separator = Turquoise (cyan)&lt;br /&gt;
* High intensity = White&lt;br /&gt;
&lt;br /&gt;
Further colors can be displayed by combining bits 1, 3, and 4:&lt;br /&gt;
* Blink, column separator = Pink (magenta)&lt;br /&gt;
* Blink, column separator, high intensity = Blue&lt;br /&gt;
* Column separator, high intensity = Yellow&lt;br /&gt;
&lt;br /&gt;
Normally, you don&#039;t need to memorize all of that, but just use the DDS &amp;lt;tt&amp;gt;COLOR(xxx)&amp;lt;/tt&amp;gt; keyword to enable the available colors:&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Desired color&lt;br /&gt;
!DDS &amp;lt;tt&amp;gt;COLOR&amp;lt;/tt&amp;gt; statement&lt;br /&gt;
!equivalent DDS &amp;lt;tt&amp;gt;DSPATR&amp;lt;/tt&amp;gt; statement&lt;br /&gt;
|-&lt;br /&gt;
|Black&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(ND)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|White&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(WHT)&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(HI)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Red&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(RED)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(BL)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Green&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(GRN)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|Blue&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(BLU)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(BL CS HI)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Yellow&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(YLW)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(CS HI)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Pink (magenta)&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(PNK)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(BL CS)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Turquoise (cyan)&lt;br /&gt;
|&amp;lt;tt&amp;gt;COLOR(TRQ)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;DSPATR(CS)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
All but black can be combined with the Reverse Video (&amp;lt;tt&amp;gt;RI&amp;lt;/tt&amp;gt;) attribute to have black letters on colored background.&amp;lt;ref&amp;gt;This should be used sparsely, because it&#039;s very eye straining.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on the settings of the used color display terminal or emulator, attributes and color might be shown concurrently. This is most apparent when setting the color of an input capable field to cyan, and the result not only is cyan, but also &#039;&#039;looks ugly&#039;&#039;, due to column separators being displayed. Most display terminals or emulators have a configuration setting to only show colors and not apply attributes.&amp;lt;ref&amp;gt;Due to reusing of attribute bits, changing this setting disables the display of attributes globally. You can&#039;t then display one field with e.&amp;amp;thinsp;g. column separators. Instead, the field is then colored cyan.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Table of valid attribute byte values ==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Hex&lt;br /&gt;
!Binary&lt;br /&gt;
!Color&lt;br /&gt;
!Attribute(s)&lt;br /&gt;
!Screen appearance&lt;br /&gt;
|-&lt;br /&gt;
|0x20&lt;br /&gt;
|0b00100000&lt;br /&gt;
|GRN &lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|Green&lt;br /&gt;
|-&lt;br /&gt;
|0x21&lt;br /&gt;
|0b00100001&lt;br /&gt;
|GRN &lt;br /&gt;
|RI &lt;br /&gt;
|Green, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x22&lt;br /&gt;
|0b00100010&lt;br /&gt;
|WHT &lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|White&lt;br /&gt;
|-&lt;br /&gt;
|0x23&lt;br /&gt;
|0b00100011&lt;br /&gt;
|WHT &lt;br /&gt;
|RI &lt;br /&gt;
|White, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x24&lt;br /&gt;
|0b00100100&lt;br /&gt;
|GRN &lt;br /&gt;
|UL &lt;br /&gt;
|Green, underline&lt;br /&gt;
|-&lt;br /&gt;
|0x25&lt;br /&gt;
|0b00100101&lt;br /&gt;
|GRN &lt;br /&gt;
|UL RI &lt;br /&gt;
|Green, underline, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x26&lt;br /&gt;
|0b00100110&lt;br /&gt;
|WHT &lt;br /&gt;
|UL &lt;br /&gt;
|White, underline&lt;br /&gt;
|-&lt;br /&gt;
|0x27&lt;br /&gt;
|0b00100111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND &lt;br /&gt;
|Nondisplay&lt;br /&gt;
|-&lt;br /&gt;
|0x28&lt;br /&gt;
|0b00101000&lt;br /&gt;
|RED &lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|Red&lt;br /&gt;
|-&lt;br /&gt;
|0x29&lt;br /&gt;
|0b00101001&lt;br /&gt;
|RED &lt;br /&gt;
|RI &lt;br /&gt;
|Red, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x2a&lt;br /&gt;
|0b00101010&lt;br /&gt;
|RED &lt;br /&gt;
|HI &lt;br /&gt;
|Red, high intensity&lt;br /&gt;
|-&lt;br /&gt;
|0x2b&lt;br /&gt;
|0b00101011&lt;br /&gt;
|RED &lt;br /&gt;
|HI RI &lt;br /&gt;
|Red, reverse image, high intensity&lt;br /&gt;
|-&lt;br /&gt;
|0x2c&lt;br /&gt;
|0b00101100&lt;br /&gt;
|RED &lt;br /&gt;
|UL &lt;br /&gt;
|Red, underline&lt;br /&gt;
|-&lt;br /&gt;
|0x2d&lt;br /&gt;
|0b00101101&lt;br /&gt;
|RED &lt;br /&gt;
|UL RI &lt;br /&gt;
|Red, unline, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x2e&lt;br /&gt;
|0b00101110&lt;br /&gt;
|RED &lt;br /&gt;
|UL BL &lt;br /&gt;
|Red, underline, blink&lt;br /&gt;
|-&lt;br /&gt;
|0x2f&lt;br /&gt;
|0b00101111&lt;br /&gt;
|RED&lt;br /&gt;
|ND &lt;br /&gt;
|Nondisplay&lt;br /&gt;
|-&lt;br /&gt;
|0x30&lt;br /&gt;
|0b00110000&lt;br /&gt;
|TRQ &lt;br /&gt;
|CS &lt;br /&gt;
|Turquoise, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0x31&lt;br /&gt;
|0b00110001&lt;br /&gt;
|TRQ &lt;br /&gt;
|CS RI &lt;br /&gt;
|Turquoise, column separator, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x32&lt;br /&gt;
|0b00110010&lt;br /&gt;
|YLW &lt;br /&gt;
|CS &lt;br /&gt;
|Yellow, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0x33&lt;br /&gt;
|0b00110011&lt;br /&gt;
|WHT &lt;br /&gt;
|RI CS &lt;br /&gt;
|White, reverse image, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0x34&lt;br /&gt;
|0b00110100&lt;br /&gt;
|TRQ &lt;br /&gt;
|UL CS &lt;br /&gt;
|Turquoise, underline, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0x35&lt;br /&gt;
|0b00110101&lt;br /&gt;
|TRQ &lt;br /&gt;
|UL RI CS &lt;br /&gt;
|Turquoise, underline, reverse image, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0x36&lt;br /&gt;
|0b00110110&lt;br /&gt;
|YLW &lt;br /&gt;
|UL CS &lt;br /&gt;
|Yellow, underline, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0x37&lt;br /&gt;
|0b00110111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND &lt;br /&gt;
|Nondisplay&lt;br /&gt;
|-&lt;br /&gt;
|0x38&lt;br /&gt;
|0b00111000&lt;br /&gt;
|PNK &lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|Pink&lt;br /&gt;
|-&lt;br /&gt;
|0x39&lt;br /&gt;
|0b00111001&lt;br /&gt;
|PNK &lt;br /&gt;
|RI &lt;br /&gt;
|Pink, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x3a&lt;br /&gt;
|0b00111010&lt;br /&gt;
|BLU &lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|Blue&lt;br /&gt;
|-&lt;br /&gt;
|0x3b&lt;br /&gt;
|0b00111011&lt;br /&gt;
|BLU &lt;br /&gt;
|RI &lt;br /&gt;
|Blue, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x3c&lt;br /&gt;
|0b00111100&lt;br /&gt;
|PNK &lt;br /&gt;
|UL &lt;br /&gt;
|Pink, underline&lt;br /&gt;
|-&lt;br /&gt;
|0x3d&lt;br /&gt;
|0b00111101&lt;br /&gt;
|PNK &lt;br /&gt;
|UL RI &lt;br /&gt;
|Pink, underline, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0x3e&lt;br /&gt;
|0b00111110&lt;br /&gt;
|BLU &lt;br /&gt;
|UL &lt;br /&gt;
|Blue, underline&lt;br /&gt;
|-&lt;br /&gt;
|0x3f&lt;br /&gt;
|0b00111111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND &lt;br /&gt;
|Nondisplay&lt;br /&gt;
|-&lt;br /&gt;
|0xa0&lt;br /&gt;
|0b10100000&lt;br /&gt;
|GRN &lt;br /&gt;
|PR &lt;br /&gt;
|Green, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xa1&lt;br /&gt;
|0b10100001&lt;br /&gt;
|GRN &lt;br /&gt;
|PR RI &lt;br /&gt;
|Green, protected, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xa2&lt;br /&gt;
|0b10100010&lt;br /&gt;
|WHT &lt;br /&gt;
|PR &lt;br /&gt;
|White, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xa3&lt;br /&gt;
|0b10100011&lt;br /&gt;
|WHT &lt;br /&gt;
|PR RI &lt;br /&gt;
|White, protected, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xa4&lt;br /&gt;
|0b10100100&lt;br /&gt;
|GRN &lt;br /&gt;
|PR UL &lt;br /&gt;
|Green, protected, underline&lt;br /&gt;
|-&lt;br /&gt;
|0xa5&lt;br /&gt;
|0b10100101&lt;br /&gt;
|GRN &lt;br /&gt;
|PR UL RI &lt;br /&gt;
|Green, protected, underline, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xa6&lt;br /&gt;
|0b10100110&lt;br /&gt;
|WHT &lt;br /&gt;
|PR UL &lt;br /&gt;
|White, protected, underline&lt;br /&gt;
|-&lt;br /&gt;
|0xa7&lt;br /&gt;
|0b10100111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND PR &lt;br /&gt;
|Nondisplay, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xa8&lt;br /&gt;
|0b10101000&lt;br /&gt;
|RED &lt;br /&gt;
|PR &lt;br /&gt;
|Red, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xa9&lt;br /&gt;
|0b10101001&lt;br /&gt;
|RED &lt;br /&gt;
|PR RI &lt;br /&gt;
|Red, protected, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xaa&lt;br /&gt;
|0b10101010&lt;br /&gt;
|RED &lt;br /&gt;
|PR HI &lt;br /&gt;
|Red, protected, high intensity&lt;br /&gt;
|-&lt;br /&gt;
|0xab&lt;br /&gt;
|0b10101011&lt;br /&gt;
|RED &lt;br /&gt;
|PR HI RI &lt;br /&gt;
|Red, protected, reverse image, high intensity&lt;br /&gt;
|-&lt;br /&gt;
|0xac&lt;br /&gt;
|0b10101100&lt;br /&gt;
|RED &lt;br /&gt;
|PR UL &lt;br /&gt;
|Red, protected, underline&lt;br /&gt;
|-&lt;br /&gt;
|0xad&lt;br /&gt;
|0b10101101&lt;br /&gt;
|RED &lt;br /&gt;
|PR UL RI &lt;br /&gt;
|Red, protected, unline, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xae&lt;br /&gt;
|0b10101110&lt;br /&gt;
|RED &lt;br /&gt;
|PR UL BL &lt;br /&gt;
|Red, protected, underline, blink&lt;br /&gt;
|-&lt;br /&gt;
|0xaf&lt;br /&gt;
|0b10101111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND PR &lt;br /&gt;
|Nondisplay, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xb0&lt;br /&gt;
|0b10110000&lt;br /&gt;
|TRQ &lt;br /&gt;
|PR CS &lt;br /&gt;
|Turquoise, protected, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0xb1&lt;br /&gt;
|0b10110001&lt;br /&gt;
|TRQ &lt;br /&gt;
|PR CS RI &lt;br /&gt;
|Turquoise, protected, column separator, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xb2&lt;br /&gt;
|0b10110010&lt;br /&gt;
|YLW &lt;br /&gt;
|PR CS &lt;br /&gt;
|Yellow, protected, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0xb3&lt;br /&gt;
|0b10110011&lt;br /&gt;
|WHT &lt;br /&gt;
|PR RI CS &lt;br /&gt;
|White, protected, reverse image, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0xb4&lt;br /&gt;
|0b10110100&lt;br /&gt;
|TRQ &lt;br /&gt;
|PR UL CS &lt;br /&gt;
|Turquoise, protected, underline, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0xb5&lt;br /&gt;
|0b10110101&lt;br /&gt;
|TRQ &lt;br /&gt;
|PR UL RI CS &lt;br /&gt;
|Turquoise, protected, underline, reverse image, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0xb6&lt;br /&gt;
|0b10110110&lt;br /&gt;
|YLW &lt;br /&gt;
|PR UL CS &lt;br /&gt;
|Yellow, protected, underline, column separator&lt;br /&gt;
|-&lt;br /&gt;
|0xb7&lt;br /&gt;
|0b10110111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND PR &lt;br /&gt;
|Nondisplay, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xb8&lt;br /&gt;
|0b10111000&lt;br /&gt;
|PNK &lt;br /&gt;
|PR &lt;br /&gt;
|Pink, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xb9&lt;br /&gt;
|0b10111001&lt;br /&gt;
|PNK &lt;br /&gt;
|PR RI &lt;br /&gt;
|Pink, protected, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xba&lt;br /&gt;
|0b10111010&lt;br /&gt;
|BLU &lt;br /&gt;
|PR &lt;br /&gt;
|Blue, protected&lt;br /&gt;
|-&lt;br /&gt;
|0xbb&lt;br /&gt;
|0b10111011&lt;br /&gt;
|BLU &lt;br /&gt;
|PR RI &lt;br /&gt;
|Blue, protected, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xbc&lt;br /&gt;
|0b10111100&lt;br /&gt;
|PNK &lt;br /&gt;
|PR UL &lt;br /&gt;
|Pink, protected, underline&lt;br /&gt;
|-&lt;br /&gt;
|0xbd&lt;br /&gt;
|0b10111101&lt;br /&gt;
|PNK &lt;br /&gt;
|PR UL RI &lt;br /&gt;
|Pink, protected, underline, reverse image&lt;br /&gt;
|-&lt;br /&gt;
|0xbe&lt;br /&gt;
|0b10111110&lt;br /&gt;
|BLU &lt;br /&gt;
|PR UL &lt;br /&gt;
|Blue, protected, underline&lt;br /&gt;
|-&lt;br /&gt;
|0xbf&lt;br /&gt;
|0b10111111&lt;br /&gt;
|&amp;amp;nbsp;&lt;br /&gt;
|ND PR &lt;br /&gt;
|Nondisplay, protected&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Arithmetics of attributes ===&lt;br /&gt;
Because the meaning of attributes or color is well defined, many lines of  &amp;lt;tt&amp;gt;IF&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SELECT&amp;lt;/tt&amp;gt; statements in RPG can possibly be substituted by simple arithmetics, like additions and bit operations.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
Base value is always 0x20.&lt;br /&gt;
* To have a field displayed in reverse image, add 1,&lt;br /&gt;
* to have a field displayed in red, add 8,&lt;br /&gt;
* etc.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [https://www.ibm.com/docs/en/i/7.6.0?topic=80-color-color-keyword-display-files COLOR (Color) keyword for display files], IBM DDS reference&lt;br /&gt;
* [https://www.ibm.com/docs/en/i/7.6.0?topic=80-dspatr-display-attribute-keyword-display-files DSPATR (Display Attribute) keyword for display files], IBM DDS reference&lt;br /&gt;
* [[wikipedia:IBM 5250|IBM 5250]], Wikipedia&lt;br /&gt;
* [https://www.rpgpgm.com/2013/10/condition-display-fields-without.html Condition display fields without indicators], rpmpgm.com&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Programming]]&lt;br /&gt;
[[Category: System Internals]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
	<entry>
		<id>http://try-as400.pocnet.net/index.php?title=How_to_program_an_Application&amp;diff=1431</id>
		<title>How to program an Application</title>
		<link rel="alternate" type="text/html" href="http://try-as400.pocnet.net/index.php?title=How_to_program_an_Application&amp;diff=1431"/>
		<updated>2024-02-08T18:44:17Z</updated>

		<summary type="html">&lt;p&gt;Greenfive: fixed typos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FIXME|Finish article.}}&lt;br /&gt;
Getting started on programming the AS/400 isn&#039;t hard. According to Frank Soltis, the most effective way to get a machine sold is to actually bring an AS/400 along to the future customer, and show an C&#039;&#039;x&#039;&#039;O in a one hour crash course how to code a simple &#039;&#039;business application&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Well, something an arbitrary business buffoon can do, you can do, too. Since the usual [[wikipedia:&amp;quot;Hello, World!&amp;quot; program|Hello World]] is just too lame, let&#039;s start with an actually usable example: A simple address book application.&lt;br /&gt;
&lt;br /&gt;
== Components of a typical Program ==&lt;br /&gt;
Since we&#039;re talking about a database machine, the first we need to know is how to create &#039;&#039;Database Tables&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Editing Database Content is usually done in screen &#039;&#039;forms&#039;&#039;. These are called &#039;&#039;Display Files&#039;&#039;. So, let&#039;s also learn how to create Display Files in the next turn.&lt;br /&gt;
&lt;br /&gt;
Finally, there must be a program for handling key presses from the user and coping with the I/O of database- and display files.&lt;br /&gt;
&lt;br /&gt;
Optionally, there can be more files to support additional functions in a program. Printer files allow for formatted output (tabular report) to a printer. InterSystem Communication Files allow for Record-I/O to other programs on the local or a remote host. We will not dig into these, for now.&lt;br /&gt;
&lt;br /&gt;
=== Programming Languages ===&lt;br /&gt;
Available on a full install of an older OS/400 are compilers for&lt;br /&gt;
* [[wikipedia:C (programming language)|C]]/[[wikipedia:C++|C++]],&lt;br /&gt;
* [[wikipedia:COBOL|COBOL]],&lt;br /&gt;
* [[wikipedia:IBM i Control Language|CL]], the equivalent of batch/shell scripts,&lt;br /&gt;
* [[wikipedia:Java (programming language)|Java]],&lt;br /&gt;
* [[wikipedia:IBM RPG|RPG]],&amp;lt;ref&amp;gt;Report Program Generator.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and interpreters for&lt;br /&gt;
* [[wikipedia:Rexx|REXX]], a scripting language derived from the mainframe world.&lt;br /&gt;
&lt;br /&gt;
RPG and COBOL are available in two flavors: [[wikipedia:Integrated Language Environment|ILE]] and [https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/ilec/opmdesc.htm OPM]. See linked explanations for details.&lt;br /&gt;
&lt;br /&gt;
It makes no sense to utilize OPM compilers for new projects. It&#039;s best you save space and deinstall these as well as the &#039;&#039;*PRV&#039;&#039; variants, that generate code for the immediately previous OS release. We&#039;ll solely focus on ILE since it has (amongst others) the advantage of linking (binding) compiled object code from different languages together to form a program.&lt;br /&gt;
&lt;br /&gt;
The IBM website features [https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzahg/rzahglanguages.htm extensive documentation] for each language.&lt;br /&gt;
&lt;br /&gt;
== A Word on Editors ==&lt;br /&gt;
If you are familiar with &#039;&#039;vi&#039;&#039; or &#039;&#039;vim&#039;&#039; on Unix-like platforms, learning SEU will be an easy task. You may alternatively utilize an editor of your choice on the platform of your choice.&amp;lt;ref&amp;gt;Windows Notepad is &#039;&#039;&#039;not&#039;&#039;&#039; a proper editor. It&#039;s sufficient for notes, though. Hence the name.&amp;lt;/ref&amp;gt; To help you chose, we&#039;ll take a closer look on the pros and cons of each solution.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Editor&lt;br /&gt;
!Pro&lt;br /&gt;
!Con&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|&#039;&#039;&#039;SEU on OS/400&#039;&#039;&#039;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Built-in contextual support for many file types and kind of lines with precise column requirements.&amp;lt;br /&amp;gt;Editing is done in an implicit array of blanks in permanent overwrite mode for easier placement of characters in proper position.&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Can display only a few lines of code, that reduces clarity and thus forces a lot of scrolling.&amp;lt;br /&amp;gt;Uniform colouring of code is increasingly uncommon and makes it even more difficult to keep an overview.&lt;br /&gt;
|-&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|&#039;&#039;&#039;Other on other platforms&#039;&#039;&#039;&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Familiar operation and UI.&amp;lt;br /&amp;gt;Easy content duplication with clearly visible text range selection, and copy-paste.&amp;lt;br /&amp;gt;Possibility to create custom rules for syntax highlighting.&lt;br /&gt;
|valign=&amp;quot;top&amp;quot;|Cumbersome handling: After every change that should result in a compile run, changed files have to be transferred back in some way.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Killer-Feature of SEU is the extensive contextual support it provides for RPG and DDS, and partly for COBOL. For beginners, it&#039;s much easier to utilize this helpful function often until some knowledge, routine and working programs as copy-source have been established.&lt;br /&gt;
&lt;br /&gt;
=== Vim ===&lt;br /&gt;
Vim is most often the editor of choice for seasoned Text-UI affictionados. Since &#039;&#039;vim&#039;&#039; is able to open files on remote-locations via URL notation, you can perfectly use it for editing on the fly from any platform vim is available for. There are even extensions for [https://github.com/kaimoku/vim-syntax-for-i syntax-highlighting] of common code.&amp;lt;ref&amp;gt;No longer working with vim 8.&amp;lt;/ref&amp;gt; Automation of login can be done via [http://www.mavetju.org/unix/netrc.php &#039;&#039;~/.netrc&#039;&#039; file]:&lt;br /&gt;
&lt;br /&gt;
* Create/edit your &#039;&#039;~/.vimrc&#039;&#039; to switch to ASCII mode on start, add:&lt;br /&gt;
 let g:netrw_ftpmode=&amp;quot;ascii&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* Create/edit your &#039;&#039;~/.netrc&#039;&#039; to have credentials ready, add:&lt;br /&gt;
 machine my-machine-name&lt;br /&gt;
 login myuser&lt;br /&gt;
 password mypassword&lt;br /&gt;
 macdef init&lt;br /&gt;
  ascii&lt;br /&gt;
 &lt;br /&gt;
Important: The file &#039;&#039;&#039;must&#039;&#039;&#039; end with a blank line! Do a &amp;lt;code&amp;gt;chmod 600 ~/.netrc&amp;lt;/code&amp;gt; for some more security.&lt;br /&gt;
&lt;br /&gt;
* Edit files giving vim the remote URL:&lt;br /&gt;
 vim &amp;lt;nowiki&amp;gt;ftp://my-machine-name/mylib/mysrcpf.mymember&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this toolset, you can develop with a tall &#039;&#039;vim&#039;&#039; window on your desktop machine, klick on a 5250-session to compile and maybe have a second 5250 session open for running the program.&lt;br /&gt;
&amp;lt;gallery class=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
File:Vim-screen-dspf-dds.png|Vim showing 91 lines of DDS&lt;br /&gt;
File:Vim-screen-rpgle.png|Vim showing 91 lines of RPG IV positional code&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Preparation ==&lt;br /&gt;
As you probably know from your experience with common systems, it&#039;s considered bad habit to work with administrative rights all of the time. I recommend [[Creating a User Account]] for you to properly work without accidentally doing harm to the system. &#039;&#039;Sign in&#039;&#039; as this user now. This gives you a subset of menu items in the &#039;&#039;main&#039;&#039; menu and makes your own Library your &#039;&#039;current library&#039;&#039;. For now, consider this almost the same thing as using the &amp;lt;code&amp;gt;cd&amp;lt;/code&amp;gt; command of a shell to make a directory your current one.&lt;br /&gt;
&lt;br /&gt;
As outlined in [[Filesystems and Files on the AS/400#File Types|File Types]], we&#039;ll need to create a file to hold source code. Let&#039;s do that and make the maximum line length a bit larger for more flexibility.&amp;lt;ref&amp;gt;IBM delivers ready made, empty source files in the QGPL-Library. Every class of file has it&#039;s own source file, such as QCLSRC for CL source code. I consider this confusing: Working on multiple files is more cumbersome than working on multiple members of one file. The files in a member could be marked as a given type of content. The only drawback is that one must use distinct names on members. The QSYS.LIB-Filesystem can hold files with the same &#039;&#039;name&#039;&#039; as long as they have distinct &#039;&#039;types&#039;&#039;.&amp;lt;/ref&amp;gt;&lt;br /&gt;
 CRTSRCPF FILE(SOURCES) RCDLEN(112)&lt;br /&gt;
&lt;br /&gt;
The white text in the status line will show you that the file has been created.&lt;br /&gt;
&lt;br /&gt;
== Working with Members in Files ==&lt;br /&gt;
The easiest way to edit members of source files is to utilize part of the &#039;&#039;Program Development Manager&#039;&#039;.&lt;br /&gt;
 WRKMBRPDM FILE(SOURCES)&lt;br /&gt;
&lt;br /&gt;
You&#039;ll be presented with a screen form to handle members. Press &amp;lt;code&amp;gt;F6&amp;lt;/code&amp;gt; to show the &#039;&#039;Start SEU&#039;&#039;&amp;lt;ref&amp;gt;Source Entry Utility.&amp;lt;/ref&amp;gt; screen. Fill out the two first fields:&lt;br /&gt;
* SRCMBR is &#039;&#039;addrpf&#039;&#039; (for addresses physical file),&lt;br /&gt;
* TYPE is &#039;&#039;pf&#039;&#039; for physical file.&lt;br /&gt;
&lt;br /&gt;
Press &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt; to start SEU and present an empty file.&lt;br /&gt;
&lt;br /&gt;
== Coding the Database Table ==&lt;br /&gt;
We&#039;re going to code the description of a database file, that is the traditional way to create database files in OS/400.&amp;lt;ref&amp;gt;Database files can also be created with the interactive SQL facility, though. But one can&#039;t derive a textual description from a SQL created database file.&amp;lt;/ref&amp;gt; The &#039;&#039;language&#039;&#039; for the statements is called &#039;&#039;DDS&#039;&#039;&amp;lt;ref&amp;gt;Data Description Statements.&amp;lt;/ref&amp;gt; that is not a line oriented description like HTML. The position of statements within one line are also important.&amp;lt;ref&amp;gt;This stems from old times when punch cards were used for programming stuff. Since compatibility is mandatory, IBM extended DDS from time to time with new keywords, but left the previous stuff alone.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For an address book, let&#039;s assume the following fields are of primary interest:&lt;br /&gt;
* Name,&lt;br /&gt;
* First Name,&lt;br /&gt;
* Birthday,&lt;br /&gt;
* Street and Number,&lt;br /&gt;
* ZIP Code and City Name,&lt;br /&gt;
* Phone Number,&lt;br /&gt;
* Cellular Phone Number,&lt;br /&gt;
* E-Mail Address.&lt;br /&gt;
&lt;br /&gt;
Plain DDS Code looks like this:&lt;br /&gt;
      A                                      UNIQUE&lt;br /&gt;
      A          R ADDRTBL&lt;br /&gt;
      A            NAME          48A&lt;br /&gt;
      A            FIRSTNAME     48A&lt;br /&gt;
      A            BIRTHDAY        L&lt;br /&gt;
      A            STREETNUM     48A&lt;br /&gt;
      A            ZIPCITY       48A&lt;br /&gt;
      A            PHONE         48A         ALWNULL&lt;br /&gt;
      A            CELLPHONE     48A         ALWNULL&lt;br /&gt;
      A            EMAIL         48A         ALWNULL&lt;br /&gt;
      A          K NAME&lt;br /&gt;
      A          K FIRSTNAME&lt;br /&gt;
      A          K BIRTHDAY&lt;br /&gt;
&lt;br /&gt;
To understand a bit better, I&#039;ll elaborate.&lt;br /&gt;
&lt;br /&gt;
As you can see, everything is written in upper case. To be honest, I don&#039;t know if a file with lower case characters in any place but comments is compilable.&lt;br /&gt;
&lt;br /&gt;
Every line starts with an &#039;&#039;A&#039;&#039; in the 6th place of a line. The first five once were reserved for optional line numbering but I&#039;ve seen no examples where this is actually done.&lt;br /&gt;
&lt;br /&gt;
The first line denotes that this file may not have duplicate values in key fields (coded later).&lt;br /&gt;
&lt;br /&gt;
The second line names this &#039;&#039;record format&#039;&#039;. This should be different from the file name. If not, you&#039;ll earn compiler warnings: In the actual program, when working with that file, it&#039;s ambiguous if you refer to the file name or the record format. For that reason, I name record formats for physical files with the suffix &#039;&#039;tbl&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Physical Files must have exactly one record format.&lt;br /&gt;
&lt;br /&gt;
The next few lines define the fields of the database file. I don&#039;t want getting unnecessary initial complexity, so I defined all fields as ch&#039;&#039;&#039;a&#039;&#039;&#039;racter with static 48 places.&amp;lt;ref&amp;gt;The AS/400 database knows about &#039;&#039;varchar&#039;&#039; field, but the handling in the code later would be really clumsy. So I refrain from that for now. Not used places are automatically filled with blanks.&amp;lt;/ref&amp;gt; The &#039;&#039;Birthday&#039;&#039;-field is the only exception, that is defined as a date field.&lt;br /&gt;
&lt;br /&gt;
Some fields may be left empty. To save space, these may be NULL, that is not the same as &#039;&#039;empty&#039;&#039;. Therefore they are defined with an additional parameter &#039;&#039;alwnull&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
NULL fields permit fields of records to utilize no space at all, but need special attention in the code. This isn&#039;t as clumsy as coping with &#039;&#039;varlen&#039;&#039; strings, though.&lt;br /&gt;
&lt;br /&gt;
The last three lines denote &#039;&#039;key fields&#039;&#039;. When reading records, they&#039;ll be retrieved in key order (ascending by default). According to the first line, entries must be &#039;&#039;unique&#039;&#039; over all key fields. So you may not have more than one entry named Fred Flintstone born on 1989-08-20. This is a somewhat crude way to prevent duplicates.&amp;lt;ref&amp;gt;If Fred has more than one place to live, the right way to handle that would be to create a second table that lists every possible street address for a given Tuple Name—First Name—Birthday. Of course we might introduce entry IDs to keep the address table small. As said, I want to keep complexity low.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After saving the member, one may type &#039;&#039;14&#039;&#039; into the field of the &#039;&#039;wrkmbrpdm&#039;&#039; members list to instruct it to compile the file with default values to the default location that is your current library.&lt;br /&gt;
&lt;br /&gt;
=== A Word about the Compilation of Objects ===&lt;br /&gt;
Compilation per default takes place as background (batch) job that is more friendly to other tasks running in interactive mode but it&#039;s a bit clumsy to handle. One needs to look into the session&#039;s [[Messages and Message Queues|message queue]] to see if the compilation succeeded or failed, to be followed by a look into the [[Spooled Files and Output Queues|spooled file]], searching the verbose compiler output for possible culprits.&amp;lt;br /&amp;gt;&lt;br /&gt;
One may press &amp;lt;code&amp;gt;F18&amp;lt;/code&amp;gt; in the &#039;&#039;wrkmbrpdm&#039;&#039; screen to access another screen with user based defaults. The third option must be set to &#039;&#039;N&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Editing Source Files using Eclipse and FTP]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [https://www.pocnet.net/computer/fallout/ Helper Programs] for the Fallout Role Playing Game Series&lt;br /&gt;
* [https://github.com/PoC-dev/as400-sfltemplates Templates] for easy development of one-database-table maintenance programs&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Programming]]&lt;/div&gt;</summary>
		<author><name>Greenfive</name></author>
	</entry>
</feed>