SEPTEMBER 1993 VOLUME 5 NUMBER 9
INDEX
If I look closely at my plate of developer food, I've got questions. I've still got the same four
basic food groups: tools, addressing, optimizing and portability across platforms. I've got
technological and philosophical issues about how much of each food group constitutes a "good"
diet. I'd hate to find out that my two extra helpings of optimizers actually added poundage to my
code.
Maybe I should check into a "code control clinic" to determine which group has the best trained
staff and to make sure that my multi-vendor solutions are nutritionally balanced.
Is there a staff doctor or nutritionist available 24 x 7 for support therapy? And what about
cholesterol? Am I unknowingly clogging my bus lines and making my CPU-heart beat erratically?
Where do I exercise?
But that is this week. Next week, I'll probably be multimedia-ing my existing source using both
digital audio and full-motion video into some sort of PLD (Programmable Logic Dance), so that I
can play back a meeting in my hotel room or office in full 3-D sensaround detail.
I'm planning on being hungry! I may not even care which food group I pick from as long as it tastes
good. I just hope my metabolism can handle whatever load I give it. This could lead to a whole
new world of meaning for "Slim, Trim, Coding Machine."
Happy_Programming!
Mad Poarch
Director
Developer Support/Service
New Lock Mechanism for NetWare Btrieve v6.10b
Btrieve is Novell's complete key-indexed record management system designed for
high-performance data handling and improved programming productivity. Btrieve allows your
application to retrieve, insert, update, or delete records either by key value or by sequential or
random access methods.
NetWare Btrieve is the server-based implementation of Novell's tried-and-tested record manager.
It is implemented as an NLM for NetWare 3.x and 4.x. This article discusses a new design feature
of NetWare Btrieve v6.10b, specifically: concurrency inside concurrent transactions and lock
sharing with multiple cursors.
Novell has added two significant enhancements to NetWare Btrieve (NLM) v6.10b:
- Record-level locking within concurrent transactions
- Lock sharing with multiple cursors.
In the earlier releases of NetWare Btrieve, record locking inside a concurrent transaction
was converted to page-level locking. In the new release a true record-level lock is used. Also,
with previous releases, multiple cursors in the same file within the same application could block
one another.
In NetWare Btrieve v6.10b, the same record can be locked by different cursors on behalf of the
same client within a single application. In this article, multiple cursors in an application refers to
cursors belonging to a single client within that application. (A "single-client" application is one
that uses the BTRV function call and all Btrieve requests are only executed on behalf of that client.
A "multiple- client" application is an application that uses the BTRVID function call and Btrieve
calls are executed on behalf of the individual client whose ID is specified in the BTRVID function
call.)
For simplicity, this article refers to new and old implementations to distinguish between different
revisions. The "old implementation" refers to NetWare Btrieve v6.0, v6.0a-d, v6.10 and v6.10a;
and the "new implementation" refers to NetWare Btrieve v6.10b and above.
Characteristics Common to All Versions
In all versions of NetWare Btrieve, any Insert, Update, or Delete operation within a
concurrent transaction locks the data pages and any index pages modified for the duration of that
concurrent transaction. So, if a record is updated within a concurrent transaction, the second user
is unable to update or delete other records that either reside on that data page or use the same
index page.
In addition, "simple reads," or reads operations without any lock bias, within a concurrent
transaction will not lock the corresponding data and index pages.
Finally, record locks are owned (controlled) by the cursor, or positioning within a file. If a file is
opened multiple times by a single client within an application using different position blocks, each
position block contains independent positioning information within that file. Individual position
blocks are referred to as cursors. If a NetWare Btrieve client has multiple cursors for a particular
file, specific record locks obtained by one cursor cannot be released by another cursor.
New Characteristics: Record Locking inside Concurrent Transactions
The first difference between the old and new implementations is record locking within
concurrent transactions. In the old implementation, the locking inside a transaction took place at the
page level. The new implementation provides more concurrency by allowing true record-level
locking. An explicit record lock (set by adding a bias to the Get and Step operations or Begin
Transaction) does not lock the corresponding data page; it only locks that particular record. To
demonstrate this, examine the examples at left. In each of the examples, Record 1 and Record 2
reside on the same data page.
In Figure 1, User B receives status 84 (Record In Use) on the Read operation using old revisions
because User A's Read+Lock has locked the data page. In the new implementation, since the page
is not locked by User A, User B successfully reads Record 2; both users are able to read and lock
their respective records. Later, after User A updates record 1, the page is implicitly locked with
either implementation. User B must wait until User A aborts or ends that transaction before
continuing with the update.
FIGURE 1: Explicit record lock within concurrent transaction
USER A | USER B
==============================|=============================
Begin Concurrent Transaction |
------------------------------|-----------------------------
| Begin Concurrent Transaction
------------------------------|-----------------------------
Read+Lock Record 1 |
(page locked with old |
implementation, |
not locked w/ new) |
------------------------------|-----------------------------
| Read+Lock Record 2
| (status with old imple-
| mentation status 0 w/new)
------------------------------|-----------------------------
Update Record 1 |
(page locked implicitly |
w/ either implementation) |
------------------------------|-----------------------------
| Update Record 2
| (USER B w/ either
| implementation)
==============================|=============================
END of FIGURE 1
Successful locking of a record (inside or outside of a transaction) guarantees that no other
client (not to be confused with "no other cursor") may update or delete that record. In other words,
when a user performs an update or delete operation on a record which he has previously locked,
he will eventually succeed unless a deadlock situation is detected. A deadlock occurs if two
clients are waiting for each other to release a resource which is locked by the other. If a user
obtains a lock on a record and the corresponding data page or index page is locked implicitly by
another client in a concurrent transaction, waiting for the data page to be released will produce a
deadlock situation. Then, Btrieve will return status 78 (Deadlock Detected).
In the example in Figure 1, User B waits until User A aborts or ends the transaction. However, in
the example in Figure 2, Btrieve detects a deadlock; User B is waiting for User A to release
Record 1 while User A is waiting for the data page to be released in order to execute the update.
FIGURE 2: Record locking in deadlock situation
USER A | USER B | STATUS
========================|==========================|========
Begin Concurrent Trans. | | 0
------------------------|--------------------------|--------
Read+Lock Record 1 | | 0
------------------------|--------------------------|--------
| Begin Concurrent Trans. | 0
------------------------|--------------------------|--------
| Read+Lock Record 2 | 0
------------------------|--------------------------|--------
| Update Record 2 | 0
------------------------|--------------------------|--------
| Read+Wait Lock Record 1 | USER B
| | waits
------------------------|--------------------------|--------
Update Record 1 | | 78
========================|==========================|========
END of FIGURE 2
Lock Sharing with Multiple Cursors
In the new implementation, if a client of an application opens the same file multiple times,
the locks issued by different cursors within the same application do not block each other. In the
previous implementation, cursors were treated as completely independent clients. Thus, if a record
was locked by one cursor, the second cursor of the same client would not be able to obtain a lock
on the same record. As mentioned previously, cursors in the new implementation do not block each
other from locking the same record, but they are still independent in the sense that they cannot
explicitly unlock (using the Unlock operation) the records that were locked by the other cursors. In
Figure 3, with the new implementation, Cursor 1 and Cursor 2 can lock the same record, but the
update by Cursor 1 fails with status 80 (Conflict Error).
FIGURE 3: Lock-sharing with multiple cursors (Case 1)
USER A/ | USER A/ | STATUS | STATUS
CURSOR 1 | CURSOR 2 | (New) | (Old)
====================|=====================|=========|========
Read+Lock Record 1 | | 0 | 0
--------------------|---------------------|---------|--------
| Read+Lock Record 1 | 0 | 84
--------------------|---------------------|---------|--------
| Update Record 1 | 0 | N/A
--------------------|---------------------|---------|--------
Update Record 1 | | 80 | 0
====================|=====================|=========|========
END of FIGURE 3
This status is returned because Cursor 2 has already updated the record and Cursor 1 must
re-read the record before updating it. In the old implementation, the application will never reach
this point and will receive status 84 on the read by the second cursor.
Thus, in the new implementation, after Cursor 1 has read a record with a lock, Cursor 2 can update
or delete the record regardless of whether Cursor 2 has locked the record (see Figure 4). Cursor 1
will not receive an status 80 until it tries to delete or update that record. In the old implementation,
Cursor 2 would receive a status 84 on a read if a lock bias is used or a status 84 on an Update
operation if regular read without any lock bias is used.
FIGURE 4: Lock sharing with multiple cursors (Case 2)
USER A/ | USER A/ | STATUS | STATUS
CURSOR 1 | CURSOR 2 | (New) | (Old)
====================|=====================|=========|========
Read+Lock Record 1 | | 0 | 0
--------------------|---------------------|---------|--------
| Read Record 1 | 0 | 0
--------------------|---------------------|---------|--------
| Update Record 1 | 0 | 84
--------------------|---------------------|---------|--------
Update Record 1 | | 80 | 0
====================|=====================|=========|========
END of FIGURE 4
With multiple cursors inside a concurrent transaction, locks obtained on a cursor before
the application starts a concurrent transaction are automatically released when the cursor becomes
an active participant of that transaction. A cursor becomes an active participant of a concurrent
transaction if a lock is requested or if an insert, delete, or update operation is executed with that
cursor. This situation is shown in Figure 5.
FIGURE 5: Multiple cursors within a concurrent transaction
USER A/ |USER A/ |USER B | STATUS
CURSOR 1 | CURSOR 2 | |
=================|==================|=================|=======
Read+Lock Rec.1 | | | 0
-----------------|------------------|-----------------|-------
| Read+Lock Rec.1 | | 0
-----------------|------------------|-----------------|-------
| | Read+Lock Rec.1 | 84
-----------------|------------------|-----------------|-------
Begin Concurrent | | | 0
Transaction. | | |
-----------------|------------------|-----------------|-------
Read+Lock Rec.1 | | | 0
-----------------|------------------|-----------------|-------
| | Read+Lock Rec.1 | 84
-----------------|------------------|-----------------|-------
End Transaction | | | 0
-----------------|------------------|-----------------|-------
| | Read+Lock Rec.1 | 84
-----------------|------------------|-----------------|-------
| Update Record 1 | | 0
-----------------|------------------|-----------------|-------
| | Read+Lock Rec.1 | 0
=================|==================|=================|=======
END of FIGURE 5
Notice that all locks in Figure 5 are single, no-wait locks. The transaction does not have
any affect on the inactive cursors. In other words, locks obtained before the transaction are still
maintained after ending or aborting the transaction for inactive cursors.
This article has discussed two major issues with the new Btrieve locking mechanism. First, more
concurrency is achieved by allowing record-level locking inside concurrent transactions. Second,
the ability to share locks between multiple cursors held by one client on the same file in an
application has been added.
NetWare Btrieve v6.10b is now available on NetWire at no charge to U.S. and international
customers. The following files are located in Library 7 and have been compressed using PKZIP:
- BTR61.EXE (707K) - software files
- BTR61M.EXE (128K) - ASCII manual
At 9600 baud, downloading the files takes about 30 minutes. If you wish to receive the
product on diskette, call 1-800- UPDATE1 (domestic customers) or 317-364-7276 (international
customers) and order the product for US$49.95 plus shipping and handling. You may also place
orders by fax by calling 317-364-0787.
The NetWare Btrieve v6.1x Developer's Kit Supplement is available to registered members of the
Novell Professional Developers' Program.
What's in the Box? Novell's NLM Certification Kit
The NLM Certification kit was developed by Novell Labs to ensure that NLM-based
products meet Novell's criteria for "well-behaved" NetWare applications. This kit contains all the
tools and information needed to perform the same tests Novell Labs applies to third-party products
submitted for certification.
The NLM Certification Kit now contains a new test tool, NControl, that was developed by the
Novell Provo System Test Group. This kit is included as a component of the NLM SDK. This
article presents a brief overview of the functionality of this testing kit.
Automation Tools
The NLM Certification Kit includes several utilities and tools to automate the testing
procedure.
NControl
NControl is an automated testing tool designed to test DOS, Windows, OS/2, and NLM
applications developed for use with NetWare. It is an excellent tool for testing applications with
user interfaces. It replaces the MASTER.NLM that was previously included with the NLM Testing
Kit. NControl has all the functionality of MASTER.NLM, with additional features, so you can use
the same test suites that were used with MASTER.NLM. NControl is also shipped with the Yes,
NetWare Tested and Approved Software Test Kit from Novell Labs.
NControl offers a record mode that captures keyboard or mouse input and automatically creates a
test program (written in C language). It also has a playback mode that executes the test program
and logs the results. The test programs created by NControl can be compiled and used as
generated, or can be customized to support more specific testing. A set of APIs are included to
assist you in customizing your test programs.
An NControl record session creates C source code to play back a set of keystrokes and mouse
operations, and to check the playback results against reference results. The compiled code is the
test playback program.
The test programs generated with NControl create a master process that controls and verifies the
execution of a slave workstation. Under DOS, the slave and master processes must run on separate
machines. In the graphical environment, the master process controls the workstation using
messages and APIs and can control the workstation on which it is running. During playback,
discrepancies are written to an error log and the status of the playback is written to a general log
file.
The text-based applications check playback results by taking a snapshot of the screen during the
record session and comparing the playback screen results to the snapshot. In the graphical
environment, the state and attributes of the window are included in the source code, and the
window state and attributes must match during playback. Bitmaps in the graphical environment
may also be used to check the playback.
NetWare Job Server
Job Server (JSERVER.NLM) is a script driven tool designed to automate software testing
environments so that NetWare users, groups, and trustee rights can be duplicated easily on
different servers. Job Server can also control the sequence of loading automated test NLMs (i.e.,
NControl script NLMs), including the number of times a sequence is repeated. Job Server runs as
an NLM and uses NetWare's QMS (Queue Management System). Once loaded, Job Server
attaches to a server as a job server account and services assigned job queues.
The DO_REC Utility
DO_REC is a simple DOS utility for recording keystrokes used when executing DOS
applications. The keystrokes recorded by DO_REC are placed in a key file and may be played
back using DO_PLAY. Up to 512 keystrokes may be recorded in each DO_REC session.
DO_REC can only record keystrokes of a single application. It cannot perform any logical
branching based on the state of the application being executed or screen contents. An example of
using DO_REC would be:
DO_REC syscon syskeys
where syscon is the program whose keystroke sequences will be stored in the file syskeys.
The DO_PLAY Utility
DO_PLAY is a DOS utility which replays the keystrokes recorded by DO_REC. An
example of using DO_REC would be:
DO_PLAY syscon syskeys
The keystrokes are fed to the application at the rate of about three per second (one keystroke every
five clock ticks).
Verification Utilities
The purpose of verification utilities is to provide you with the statistics of behavior testing.
The utilities do not perform any test but rather provide information about behavior testing being
performed.
Procedure Coverage Logger (PCL)
The Procedure Coverage Logger (PCL), is used to verify that the exercising procedure of a
product provides adequate coverage of the functions declared in the source code.
If PCL reports that your exercising procedure executes less than 100% of the declared functions,
you know that your exercising procedure is inadequate. On the other hand, if PCL reports that all of
the functions have been executed, then you know that your exercising procedure is adequate.
Using the PCL utility in the NLM testing process, you are able to:
- Dynamically monitor which public symbols have been called
- Dynamically track how often selected sections are called
- Dynamically monitor all NetWare resources used by your product
- Generate ASCII text reports
- Can simultaneously monitor several NLMs without affecting the performance of the NLMs
being monitored
- Automatically monitor NLMs auto-loaded or spawned by your NLM, provided the NLMs
have the necessary debugging information (NetWare 4.x only).
The Procedure Coverage Logger consists of a single NLM, called PCL.NLM. Tutorials are
also provided in the NLM Certification Kit to demonstrate the functionality of PCL.
Monitoring Utilities
The NLM Certification Kit provides utilities to monitor the behavior of your NLM.
The Sentry Utility
A key requirement of "well-behaved" NLMs is that they frequently relinquish the control of
the CPU. The Sentry Utility (SENTRY.NLM) monitors the length of the time taken by all execution
threads of the file server. Once Sentry has started to monitor a set of execution threads, it
automatically monitors any new threads that are created, and retains the information of any thread
that is destroyed.
The Protect Utility
The Protect Utility (PROTECT.NLM) monitors all memory accesses from NLMs loaded
via PROTECT.NLM. If an NLM accesses any memory that the Protect Utility considers
suspicious, it stops the execution of that NLM and reports the instance on the screen.
PROTECT.NLM can be used to verify that an NLM meets the requirement forbidding illegal
memory accesses. Right now, PROTECT.NLM only supports NetWare 3.11.
The Starver Utility
The Starver utility (STARVER.NLM) is used to monitor memory allocation requests made
by NLMs, and to selectively refuse them. This allows you to monitor the behavior of your NLM in
scarce memory conditions and determine how your product handles situations where it can not get
the memory it needs for proper operations.
User Activity Simulators
The following utilities simulate the activity of several users on the workstations and relieve
the necessity of actually placing human users on the network to simulate certain test conditions:
- DO_BTRV (DO_BTRV.EXE)
DO_BTRV simulates the Btrieve record management of several network database users. It
creates a database with two different indices, fills it with over 1900 records, performs various
sorts and queries, and then deletes it.
- DO_PRINT (DO_PRINT.EXE)
This utility simulates the file printing requests of as many as 40 individual users. It generates
a specified number of ASCII text files, and sends them to the network's print services. The user
instructions for DO_PRINT include directions for building a mock-printer; a device allowing you
to fully exercise print services on a network without the need for a physical printer or paper.
- DO_FILE (DO_FILE.EXE)
DO_FILE simulates the network file activity of dozens of network users. It creates a file,
copies 4Kb into it, closes it, locks it, unlocks it, and performs various other file oriented task on it
several times a second.
Miscellaneous Utilities
Five more utility NLMs bring additional functionality to the NLM Certification Kit.
The MemMap NLM
The MemMap NLM (MEMMAP.NLM) displays the addresses of the code and the data
area of each NLM loaded on the file server. This utility, in conjunction with PROTECT.NLM, is
useful in determining whether memory access reported by Protect as suspicious is really illegal or
not. For example, Protect might report a memory access as illegal, but by looking at that address
you discover that the address belongs to the data area of another NLM in the same product.
The Sets NLM
The Sets NLM (SETS.NLM) gives a menu driven interface for altering the system
parameters for the NetWare Operating System. The same functionality can also be achieved with
the system console command, "Set." This NLM is useful for performing behavior testing of NLMs.
(SETS.NLM supports NetWare 3.x only. SERVMEM.NLM is included for 4.x NLMs)
The Mod NLM
This NLM (MOD.NLM) generates a report on all the modules loaded on the file server.
This report contains the same information that is displayed by the system console command
"modules."
The ReadBind NLM
The ReadBind NLM provides a menu-driven method of examining the contents of the file
server's bindery. This utility is useful in verifying the bindery objects used and created by an
application.
The Spawn Trap NLM
Spawn Trap (SPWNTRAP.NLM) is a work-around utility for testing NLMs that spawn
other NLMS (in NetWare 3.1x). Normally, calls to spawnlp or spawnvp cause other NLMs to be
loaded programatically. However, this feature prevents some NLM testing tools (PCL in NetWare
3.1x environment) from monitoring behavior of the spawned NLMs. When Spawn Trap is loaded
before a test session, it intercepts attempts by one NLM to spawn another, and allows the user to
manually load the spawned NLM. Then, you can load the spawned NLMs through one of the
testing utilities. In the NetWare 4.x environment, SPWNTRAP.NLM is not needed since, in that
environment, PCL can detect the behavior of spawned NLMs that have the needed debugging
information.
The NLM Certification Kit is a valuable collection of utilities and tools to test your NLM, even if
you do not plan to certify it. If you do plan to have your NLM certified by Novell, contact Novell
Labs at 1-800-453-1267 x5544 or 1-801- 429-5544. When your product passes Novell's testing
process, it will be authorized to display the "YES! NetWare Tested & Approved NLM"
certification mark.
NOVDEV: New Developer Area on CompuServe
Novell is pleased to announce the unveiling of the new Novell developer area on
CompuServe. This area, called NOVDEV, will provide common services for all Novell
developers creating applications with Novell development tools.
This area provides an exclusive developer interface for support, patches, periodicals and product
information, as well as information on all of the programs and services provided for members of
the Novell Professional Developers' Program.
Why Make a New Area?
Many times in the past, Novell developers have found it necessary to search through several
forums in several different areas in order to find information or resolve a development problem.
At times, this process could be frustrating.
Over time, the complexity increased as Novell's product line increased and additional services
were introduced. For example, Developer Support was provided though several sections on
NOVC as well as sections of the Developer Relations forum, while patches were posted to the
NOVFILES forum.
After analyzing this situation, the forums were reorganized to make life easier for the Novell
customer by providing a central point for developer services, support and information. Whether
you would like to join the a Novell Developer Program, ask a technical support question, find out
about a new SDK, or look up a technical article from a past issue of Novell Professional
Developer Bullets, all of this information is here at your fingertips.
New NOVDEV Area Layout
Once you type "GO NOVDEV" at the CompuServe "!" prompt, you will see a main menu
corresponding to the map in Figure 6. The menu contains several options that are available from
the NOVDEV main menu. The general layout of the new NOVDEV area is shown in Figure 6.
FIGURE 6: Layout of new NOVDEV area
NOVDEV
|
|----------|----------|---|-------|-----------|---------|
| | | | | |
| NDEVREL | Files/Patches | NetWire
NDEVSUPP NDEVINFO Novell
| | |
| | |
General Business General Business Bullets
Btrieve Btrieve White Papers
NetWare SQL NetWare SQL Other tech. pubs
NetWare Client SDK NetWare Client SDK
NetWare Server SDK NetWare Server SDK
Macintosh SDKs Macintosh SDKs
Communication SDKs Communication SDKs
To be assigned To be assigned
Personal NW SDK Personal NW SDK
AppWare Found. SDK AppWare Found. SDK
LAN WorkPlace SDK LAN WorkPlace SDK
Telephony SDK Telephony SDK
Visual AppBuilder Visual AppBuilder
END of FIGURE 6
NDEVSUPP: The Developer Support Forum
NDEVSUPP, the new Developer Support forum, is where Novell developers post technical
questions or answers and voice concerns about Novell development products. NDEVSUPP is
divided into sections for each of the Novell development tools. As Novell continues to expand its
product line, additional sections will be added.
NDEVINFO: The Developer Support Forum
NDEVINFO is a forum dedicated to pre-sales information on the Novell development tools.
Like the Developer Support forum, NDEVINFO is divided into sections for each of the tools.
NDEVREL: The Developer Relations Forum
Many developers will recognize the name "NOVDEV" from past experience and may
wonder what has happened to the original NOVDEV. The forum that was formerly named
NOVDEV has been renamed NDEVREL. The existing sections of this forum will be changed to
accommodate the new Developer Support (NDEVSUPP) and Product Information (NDEVINFO)
forums.
Note: Because the new, all-encompassing developer forum reuses the name NOVDEV, be aware
that all script files written to target the old Developer Relations forum will now access the new
main developer forum.
Other Services & Information
NOVDEV also has sections for publications of interest to application developers like
Novell Professional Developer Bullets, Novell white papers and other technical publications. In
addition, NOVDEV includes a section for example code and patches.
Novell is committed to providing quality support, services and programs for developers. The new
NOVDEV area will enhance and streamline the services and support provided to the Novell
developer community.
The Basics of Using Visual AppBuilder
AppWare's Visual AppBuilder raises the level of application development beyond coding
altogether, enabling programmers and non-programmers alike to create professional software with
unprecedented speed and ease.
This article provides an overview of Visual AppBuilder and explains the basics of building
applications with this valuable 5GL tool.
Overview of Visual AppBuilder
Visual AppBuilder provides a 5GL-level development environment that is tightly integrated
with the AppWare environment. Visual AppBuilder allows applications to be constructed by
selecting, manipulating, and connecting on- screen icons.
These icons represent the building blocks of the application and are known as objects and
functions in Visual AppBuilder. Objects and their associated functions make up the ALMs
(AppWare Loadable Modules) in the AppWare development environment.
The range of applications Visual AppBuilder users can create is limited only by the range of
ALMs available. By purchasing the ALM SDK, developers can use 3GL development tools to
produce a variety of ALMs that can plug directly into Visual AppBuilder. Likewise, Novell is
also committed to developing additional ALMs to be used in Visual AppBuilder. Because ALMs
hide the inherent complexity of their code behind on-screen icons, Visual AppBuilder is ideal for
corporate and vertical business application developers.
Currently, Visual AppBuilder provides a comprehensive library of robust, high-level objects and
functions that facilitate application development, without significant sacrifices in either
performance or functionality.
Using these objects is an order of magnitude less complicated than developing them -something
that cannot be said of objects in more conventional object-oriented programming environments. In
other words, you don't need to know anything about how it works at the code level to use a Visual
AppBuilder object.
Visual AppBuilder ALM Libraries
The Visual AppBuilder ALM Library for Microsoft Windows currently consists of
approximately 40 high-level objects and hundreds of high-level functions divided among several
object sets.
The first of these is the Visual AppBuilder Essentials, a core set of objects and functions
supporting various aspects of the Microsoft Windows graphical user interface (GUI), such as
menus, lists, buttons, and windows, as well as traditional programming features such as loops,
subroutines, and arrays -all structured to be usable by non-programmers. The Visual AppBuilder
Essentials ALM set is included with Visual AppBuilder.
Other object sets address specialized areas of application development. The Visual AppBuilder
Database ALM set consists of five objects for building robust, multiuser, relational databases. The
Database ALM set supports unlimited indexing, unlimited relations, virtually unlimited record
size, and unlimited data types, enabling users to store most other objects. ASCII file import/export,
multi-column tabular display/printing, and international sorting are also supported.
Future ALM sets in development include:
- Visual AppBuilder Multimedia - a multi-media set for dynamic, frame-based color
animation, CD audio, digitized sound, and movies.
- Visual AppBuilder Communications - a three-object set for modem and serial connection,
file transfer, and terminal emulation.
Other ALM sets under development include sets for Dynamic Data Exchange, OLE, serial
communications, NetWare services, client-server databases, and imaging.
To create your own object sets (ALMs) for use in the Visual AppBuilder environment, you
can use the ALM SDK and lower- level tools such as Borland C++, Microsoft C++, and Turbo
Pascal for Windows.
Visual AppBuilder Objects
A Visual AppBuilder object is a self-contained, reusable program building block containing
both the data and the code your computer needs to manage that data. You use a Text object, for
example, to store and display textual data. Graphics are displayed in Picture objects, lists in List
objects, and so on. Most Visual AppBuilder objects represent application features that you'll
recognize immediately.
For example, the Window object enables your application to display and operate windows. In
this and most other cases, there's a one-to-one correspondence between a typical application
feature (like a window) and a Visual AppBuilder object (such as a Windows object). Thus, a
Database object would handle all the low-level database operations for indexing, record
searching, retrieval, etc. The Table object would do the same for multicolumn tables.
You don't need to be a programmer to know how to use a Visual AppBuilder object. Nor do
you need to know a lot about the inner workings of DOS, Windows or Macintosh. In fact, the code
that makes a Visual AppBuilder object work is invisible. You'll never see a line of it. To use an
object, all you need to know is how to use the application feature that the object represents.
Building An Application Using Visual AppBuilder
To start Visual AppBuilder, you simply double-click on the Visual AppBuilder icon in
Windows. Once you are in Visual AppBuilder, the first step in building your applications is to
create a project. This project will contain your application "code."
Although much easier to create and understand, a project is like the source code file a
programmer creates in C or Pascal. After you have finished constructing your project, you compile
it and create an icon for it. By double-clicking on that icon, you launch your application.
Although all this sounds pretty simple, you also need to know that a project is made up of one
or more reusable sub- projects or subjects, each devoted to a different aspect of your application.
Some subjects are so basic in nature that you'll reuse them over and over.
For instance, your application may create a basic menu bar subject containing File and Edit
menus. You will need a subject like this in just about every application. Other subjects may be
very specific in nature--the sort of thing you may never need to reuse.
General or specific, subjects let you compartmentalize your program and isolate segments that
are reusable from those that are not. Every project must contain at least one subject.
The Object & Function Palette
After you have created the project and one subject, you can begin building your application
using the Visual AppBuilder Object & Function Palette. This palette displays alphabetical lists of
objects and functions for use in Visual AppBuilder.
The Pallette has three scrollable compartments:
- Objects are displayed in the left compartment of the Object & Function Palette.
Examples of objects that are provided with Visual AppBuilder include List, Menu, Menu Bar,
Loop, Keyboard, Cursor, File, Database, etc.
- Functions are displayed to the right of the objects in the center compartment of the Palette.
The functions displayed in the center compartment depend on which function category is selected.
- Function categories are listed in the right compartment of the Object & Function Palette.
These categories generally relate to an object type.
When you want to use an object of a particular type in your application, you drag its icon
from the Object & Function Palette into the object list. Visual AppBuilder then creates a copy or
instance of that object type in your project. The objects you use in a subject reside in the object
groups that you can freely locate within the subject window. Once an object has been copied into
the object list, it can be named and edited. Note that every subject has one object list.
Associating Objects and Functions
Before objects can be useful, the computer must know what you want your application to do
with them. For example, you may want to open or close a window, enter or delete a record in a
database, etc. Each object file therefore comes with a set of functions that you use to control
exactly how the object is to operate in your application.
The Window object, to take an example, includes the functions Open Window and Close
Window. You use these functions to open and close windows in your application. If your window
contains editable text fields, then you might have occasion to use Text functions such as Append
Return, Concatenate, Find-Replace, and so on. There are also File Operations and General
functions not associated with any specific object.
Unlike objects, functions contain no information and interact with objects. A Visual
AppBuilder function performs a single high-level operation. High-level means that the Visual
AppBuilder user is shielded from the complicated, operating system-level programming that
actually makes the function work.
To select a function, you simply highlight that function and then drag it from the Palette onto
the subject's worksheet.
Creating Signal Flows and Function Chains
You indicate that an object calls a function by dragging a line between the object and a
function. This line is called a signal flow. Each object has its own set of signals, which reflect
occurrences or events that affect the object.
For example, the Text object notes when you change or edit its content, tab into or out of it,
type too many characters, or press the Enter key. Signals are issued for each of these occurrences.
Functions, like objects, issue signals that you can use to call other functions. By clicking on a
particular function and dragging a line to another function, you create a function chain. Function
chains are initially triggered by the object to which they are connected. In addition, functions, like
objects, may issue more than one signal.
Through the use of different signals, one function may call several different function chains
that extend from the function like branches of a tree. Each of these branches represents a path along
which your function may proceed.
Defining an Object as an Input or Output Parameter
Functions by definition operate on objects. The object (or objects) that a function does
something to are its parameters. Parameters come in two varieties: inputs and outputs.
To define an object as an input parameter, you simply click the label above the function and
drag a line from the label to the object in the object list. When you activate one of the labels above
the function icon, you are specifying that the object specified in that label can be passed as an input
parameter to that function.
Parameter Type Checking
One of the unique features of Visual AppBuilder is its built in parameter type checking. In
Visual AppBuilder, input and output parameters expect or produce certain types of information, in
the form of objects. Parameter type checking ensures that you connect only appropriate types of
objects to function inputs and outputs.
To prevent you from mistakenly connecting the wrong kind of object parameter to a function
input, Visual AppBuilder uses type checking. Type checking works by not allowing you to draw a
line between a function label and an improper object type or between incompatible function
outputs and inputs.
Type checking, then, limits the sort of parameters you can pass to and from a function. In some
cases, type checking may limit the choice of object types to one. However, many function inputs
and outputs do accept more than one type of object connection.
For example, certain functions have inputs and outputs that will accept any type of object. For
these functions, there is effectively no type checking, and the input and output parameter types are
therefore said to be "global" in nature.
Sharing and Aliasing Objects Between Subjects
In Visual AppBuilder, you use lines (signal flows) to link functions to objects and to other
functions. This methodology works fine within a subject, but it can't be used between subjects,
since each is its own separate window and lines can't be drawn across window boundaries.
Fortunately, there is a way around this dilemma.
When a function or object in Subject A needs to reference an object in Subject B, you create a
surrogate or alias for the object in Subject B and put it into Subject A. Objects and functions in
Subject A work with the alias just as they would with the original, which still resides in Subject B.
Object aliases are, therefore, the links that hold various subjects together.
An object alias is not a copy of the original object, but a representative of it that you can use
as if it were the original. The difference between a copy and an alias is easily illustrated in an
example. Suppose that you're working on a project that contains two subjects: one devoted to a
menu bar and its constituents, and another concerned with windows. While the responsibilities of
the two subjects are generally distinct, there could possibly be some interaction between them.
Now, suppose that at runtime when you choose a menu item, you want to open a dialog
window. To program this, you would drag an Open Window function into your work area and
attach (draw a line) between the Open Window function and the menu item in the menu bar subject.
Next, you would specify the window to open as the input parameter to the Open Window function.
Since that window is in the Windows subject, you would create an alias of it in the menu bar
subject and pass the alias to the Open Window function.
If, on the other hand, you were to copy the dialog Window object, paste the copy into the
menu bar subject, and pass this to the Open Window function, then the menu item would open an
exact duplicate of the dialog, but not the dialog you want.
Both functions and objects face this dilemma when communicating with objects in another
subject. An object can "see" only those objects resident in its subject. If, for example, your Menu
Bar object is in one subject and its Menu objects are in others, the Menu objects will not appear in
the Menu Bar's editing dialog. So, you will not be able to add the Menu objects to the Menu Bar.
If, on the other hand, you create aliases of your Menus in the Menu Bar's subject, then the
Menu Bar will "see" and display them in the editing dialog. You can then add them to the Menu
Bar just like ordinary Menu objects.
Most of your objects will not need to be aliased. Those that do may be aliased more than
once, perhaps in multiple subjects. So, it is useful to have a quick way to get to them when you
need to make an alias. To make quick access possible, you first identify the object you want to
alias and share it. Once shared, an object can be aliased in any subject within your project. Shared
objects are distinguished from other objects by their boldface titles.
Debugging and Compiling
After designing your application in Visual AppBuilder, the final step is to debug and
compile the application you have designed.
Debugging is the process of running your application with an interpreter (the interpreter is
intrinsic to Visual AppBuilder) to see if there are any bugs in the application. The interpreter lets
you run through the application one step at a time. The advantage of using an interpreter is that you
can find exactly where in the application an error occurs. Knowing this, you can then address the
problem and try again.
When you run in the interpreter, Visual AppBuilder actually creates and launches a temporary
application. When you exit the interpreter, the temporary application file is automatically deleted.
An additional feature in Visual AppBuilder aids in the debugging process even before running
in the interpreter. This feature is the ability to check selected projects, subjects, and objects for
errors. You can use this feature by inserting stops (pauses) along suspected problem function
chains in your application before running the interpreter. As the interpreter runs through your
application, it pauses at each stop and waits for you to select "Continue" from the Project menu.
If an error occurs between stops, then you know that the problematic functions are to be found
after the first stop and before the second. By inserting additional stops, you can narrow down the
problem even further. Although you can't edit an object, you may make other changes to your
project while it pauses. These changes will not be reflected until you exit the interpreter and run
the application again.
Stops are for you to use as needed. You probably won't want to install them the first time you
debug your application, but they are a valuable aid in debugging applications that don't run
correctly.
When you are finished designing and debugging a project, you can compile it into a
double-clickable application. All of your subjects, objects, functions, and function chains are
merged into one program.
To compile a project, you simply choose Create Application from the Visual AppBuilder
Project Menu and specify a file name for your application. To create an icon for your application,
you choose Edit Icon from the Visual AppBuilder Project menu and use an icon editor to draw the
icon.
The icon editor displays a "fat-bits" icon editing box. The view is enlarged to make your
editing easier. Each square or bit in the fat-bits editor represents a single pixel in the icon. To
draw the icon, you first select from a series of colors. An Import button also lets you import an
icon (.ICO) file.
Distributing Your Application
When distributing your application, you will need to copy the application file (*.EXE) file
itself and the DLL file for each type of object used inside the application. You will deposit the
DLL files in a directory that is in a common search path so that your built application can easily
find them as it runs. You may, in fact, install the DLL files on a network server, so that several
users can simultaneously run off of one set of object code files.
Porting Your Application to and From the Macintosh
For developers who want to port their Windows application developed using Visual
AppBuilder for Windows to the Macintosh environment, a new technology is provided that allows
you to do just that. This new technology is known as Universal Program Structure File (UPSF).
UPSF allows projects created in Visual AppBuilder for Windows to be ported to operate on
Macintosh computers.
In order for a project to be ported, the objects and functions it uses must be available on both
platforms. Currently, the Essentials and Database object sets are available on both platforms.
Windows versions of object sets currently available only for Macintosh are in development.
UPSF is a file specification similar in concept to an Adobe Postscript file. Many different
printers and typesetters understand postscript files. Likewise, the Macintosh and Windows
versions of Visual AppBuilder speak a common language in UPSF.
In the future, Novell will be announcing new versions of Visual AppBuilder for several
additional platforms, making your existing and new Visual AppBuilder applications portable to
those platforms.
For More Information
For more information on Visual AppBuilder, call 1-800-NETWARE. Visual AppBuilder is
scheduled to be available to Novell developers in October 1993 through the Novell Professional
Developers' Program.
Problem With Domain (NLM SDK v3.0)
The version of DOMAIN.NLM included with NetWare 4.01 can trigger a server crash in
the following situation: if you attempt to enter the debugger using the keyboard sequence (ALT,
ALT, SHIFT, ESC), and domain is running, and control of the CPU belongs to an NLM running in
the protected domain when you enter the debugger, the server will crash. This situation does not
present a problem for end users, but could definitely affect Novell developers debugging NLMs.
This situation has been addressed by Novell Engineering. A new version of DOMAIN.NLM
has been posted on Novell's NOVDEV CompuServe forum (Library 6, DOMAIN.ZIP, 8/9/93).
stat() Fails on 254th Attempt (NetWare Client SDK v1.00c)
The stat() function in the versions of CLIB associated with NetWare 4.00 and 4.01 fails on
the 254th attempt against a remote file server. The function returns a completion code of -1 and
errno is set to 11, indicating that it is out of directory handles.
This failure will be prevented in a future CLIB release. Until then, use the access() function if
stat() is being used to check for the existence of a file. Otherwise, use opendir() and readir() to
return file information.
Creating 32-bit OS/2 Applications (NetWare Client SDK v1.0d)
Creating 32-bit OS/2 applications with the NetWare Client SDK and either IBM's CSET/2
compiler or the Borland OS/2 Compiler requires that you thunk the header files to perform the
appropriate pointer conversion for the APIs. The #include file, NWCALDEF.H, documents this
procedure. The format of the declarations in the header files unfortunately is not consistent, so you
must modify 70+ files, rather than NWCALDEF.H alone.
The thunked headers for the NetWare Client SDK are posted on NetWire in NOVDEV forum
(Library 6, THUNK.ZIP). You must activate the thunking in a manner similar to the thunked files in
the C Interface for OS/2 (i.e., using the #define IS32BIT and #define BCPP -or CSET2).
Additional information appeared in the February 1993 issue of Bullets.
NetWare SQL Index Optimization Changes (NetWare SQL v3.0)
NetWare SQL v3.0 performs index optimization somewhat differently than previous
versions. When using a restriction such as:
WHERE fld1 =
AND fld2 =
NetWare SQL first looks for a segmented index where the first two segments are "fld1" and "fld2"
(in any order). If such an index does not exist, it will check for an index where the first segment is
either "fld1" or "fld2."
Suppose there is an index on "fld1," and a separate index on "fld2." Previous versions of
NetWare SQL would choose to optimize on the index with "fld1" as its first segment, since this is
the first restriction in the query. However, NetWare SQL v3.0 optimizes on whichever index is
defined first in the table. So, if "fld2" is the fourth index defined in the table, and "fld1" is the fifth
index, NetWare SQL optimizes the query using the index on "fld2."
In some cases, it may be more desirable for NetWare SQL to choose one index over the other,
depending on the number of duplicate values that exist in each of the indexes. One option is to
rebuild the table so that the preferred index is declared first. However, this option does not give
users control in their SQL statements to determine the optimization. This can be done by rewriting
the restriction so that the preferred indexed field uses an equal restriction. For example, the
restriction above could be rewritten as:
WHERE fld1 =
AND fld2 <=
AND fld2 >=
NetWare SQL attempts to optimize equal restrictions first, and if no appropriate indexes exist, then
it attempts to optimize other types of restrictions. So, this example would result in NetWare SQL
optimizing on an index on "fld1" instead of "fld2."
A second option is to add an ORDER BY clause to the statement specifying the indexed field
to be used. NetWare SQL always attempts to optimize the ORDER BY clause before optimizing
restrictions.
Status 0xF2 on SPXInitialize() in Standard Mode (NetWare Client SDK v1.0d)
A call to SPXInitialize() in Windows running in standard mode will return a completion
code of 0xF2 (no DOS memory) when more than 60 ECBs are specified as the maximum number
of ECBs on the function call.
TBMI2.COM must be loaded before Windows 3.1 only if running in standard mode and
IPX/SPX communication applications will be run. However, TBMI2 defaults to allocating 60 data
ECBs. The NetWare C Interface for Windows documentation states that, if TBMI2 is configured
for less than the number of needed ECBs, a status 0xFE will be returned. Actually, when the
NetWare Client SDK makes a request for an ECB, it cannot distinguish between an "out of DOS
memory" state and an "out of configured ECBs" state. Because of this, an 0xF2 (no DOS memory)
will be returned in both cases.
To configure TBMI2 for more than 60 data ECBs, create a configuration file containing the
following line:
DATA ECB COUNT = n
where n equals the number of ECBs for TBMI2 to allocate.
If you name the configuration file TBMI2.CFG, TBMI2 will be loaded before Windows as
follows for the configuration option to take effect:
TBMI2 /C=TBMI2.CFG
With this configuration, SPXInitialize() can be called with more than 60 ECBs. However, if this
data ECB value is set too high and exceeds the lower DOS memory limit for that machine, an 0xF2
status will also be returned; the machine actually has no DOS memory available.
The NetWare C Interface for Windows v1.3 documentation (p. 1- 12 through 1-14) provides
more information on the "DATA ECB COUNT" configuration option, as well as other
configuration options for TBMI2. These configuration options are not documented in the NetWare
Client SDK v1.0d documentation.
Service Query Responses for Windows and DOS (NetWare Client SDK v1.0d) (NetWare C
Interface for Windows v1.3) (NetWare C Interface for DOS v1.2)
General Service Queries (GSQs) from Windows or DOS targets return Nearest Service
Responses. This fact is unimportant unless you filter the packets coming back. MacIPX does filter
these packets, and does not see the Service Responses to GSQs. Furthermore, the Service
Response replies to a broadcast address, thus causing one response to come back to the querying
machine multiple times depending on routing.
The situation results from a problem with the AdvertiseService() function included with the
NetWare C Interface for Windows and NetWare C Interface for DOS. In the function,
RespondToLocalQuery(), it does not test so see if the query is "general" or "nearest." The
response packet is initialized to respond back with a packet type of 4 (nearest) for all responses.
Also, the response ECB immediate address field is initialized to -1 (all 0xFF values) and never
set to the address from which the query originated.
To resolve this situation, you must modify the source file, advertis.c (included with the
NetWare C Interface Kits). Using the NetWare C Interface for Windows, for example, you could
replace the RespondToLocalQuery() function with the code in Figure 13.
FIGURE 7: Replacement for RespondToLocalQuery()
void far pascal RespondToLocalQuery2()
{
int transTime;
if (!((instStructPtr + availSlot)->listenECB.completionCode))
{
if((instStructPtr + availSlot)->querySAP.serverType ==
thisServerType)
{
while((instStructPtr + availSlot)->responseSAP.theECB.inUseFlag)
{
IPXRelinquishControl();
IPXYield();
}
/* reply back to the address that the SAPquery came from */
memmove((instStructPtr+availSlot)->responseSAP.packet.destination.
network,
(instStructPtr+availSlot)->querySAP.source.network,12);
/* respond back directly, rather than broadcast(this way you won't
** get N=1 responses, where n=number routers) */
IPXGetLocalTarget(TaskID,
(BYTE FAR *)(instStructPtr+availSlot)->
responseSAP.packet.destination.network,
(BYTE FAR *)(instStructPtr+availSlot)->
responseSAP.theECB.immediateAddress, &transTime);
/* if the query is general, respond back general
** (default response is RESPOND_IS_PACKET #def'd to 4) */
if ( (instStructPtr+availSlot)->querySAP.queryType == 0x0100 )
(instStructPtr+availSlot)->responseSAP.packet.SAPPacketType =
IntSwap(2);
IPXSendPacket(TaskID, &(instStructPtr+availSlot)->
responseSAP.theECB);
} // END - if this is our server
} // END - if we got the ECB ok
IPXListenForPacket( TaskID, (ECB far *)&(instStructPtr + availSlot)->
listenECB);
} // END = ResponseToLocalQuery2
END of FIGURE 7
Rather than using the IPXGetLocalTarget() in an ESR, you could also copy the immediate
address field from the Query ECB into the Response ECB for a faster (though not guaranteed)
response. The modified source files are available on NetWire (NOVLIB, section 9, SAPFIX.ZIP)
and are also posted on AppleLink in the Third Parties area for MacIPX users.
Microsoft QuickBasic & Btrieve Status 76 (Btrieve for DOS v5.10a)
Btrieve applications compiled with Microsoft QuickBasic may return a BASIC run-time
error 76 (Path Not Found) when run on peer-to-peer networks. The error occurs when executing
the OPEN "NUL" statement in applications that use fielded variables rather than type structures.
To resolve this error, change each OPEN "NUL" statement to:
OPEN "\DEV\NUL".
By default, Microsoft QuickBasic appends path names to files opened with the OPEN statement.
The \DEV\ added to the OPEN statement prevents Microsoft QuickBasic from assigning a file path
to the device and enables the statement to succeed.
NetBIOS for OS2 & DOS Mutually Exclusive (NetWare OS/2 SDK v2.0)
The use of NetBIOS under OS/2 involves loading NETBIOS.SYS and NBDAEMON.EXE.
These drivers take over the NetBIOS interrupt 0x5A. When using NetBIOS in a DOS VDM, the
NETBIOS.EXE TSR is loaded, which then attempts to take over int 0x5A. The OS/2 Requester
v2.0 Manual incorrectly describes the steps necessary to run NetBIOS from a VDM as follows:
- Make sure the NetWare Requester in installed with Novell NetBIOS and Virtual
DOS Session support.
- Install the NETBIOS.EXE TSR.
This procedure causes the VDM to lock up, although the operating system still runs and
other sessions are not affected.
DOS NetBIOS may be loaded only if the OS/2 NetBIOS statements in the workstation
config.sys are "commented out." Doing so provides support for NetBIOS under one DOS VDM
only. Multiple Global DOS NetBIOS sessions are possible through the use of the files
LANVDD.SYS and LANPDD.SYS, which virtualize NetBIOS through NETBIOS.OS2. These files
are available in either Extended Services or LAN Services.
DOS NetBIOS and OS/2 NetBIOS are available through the IBM multiple protocol stack
extender for OS/2, which in turn is included as a part of IBM's NTS/2 product.
Btrieve Overwrites Key Buffer with Status 22 (NetWare Btrieve (NLM) v6.00)
Btrieve will overwrite the Key Buffer parameter on a Get Equal (5) operation if a status 22
(Data Buffer Length Too Short) is returned. NetWare Btrieve (NLM) v6.x and the Btrieve v5.x
client versions overwrite the Key Buffer parameter with extraneous characters on a Get Equal (5)
operation if a status 22 (Data Buffer Length Too Short) is returned from the call. This situation
occurs only if the data buffer length specified is less than the offset and length of the key specified
in the Key Number parameter.
This situation occurs because the return key value is extracted from the data buffer itself. An
incomplete Data Buffer results in an incomplete (thus invalid) key value.
Status 22 is an informative status code indicating that there is more data in the record than
Btrieve was able to return. When using variable-length records, many developers intentionally set
the Data Buffer Length parameter to a number that is less than needed to return the entire record.
Doing so can improve performance by preventing a variable- page read when only the fixed-length
data is needed. This is an acceptable method of data retrieval. The Key Buffer overwrite problem
described above only occurs if the Data Buffer Length parameter specified is shorter than the
fixed- length portion of the record, and specifically the offset of the key specified in the Key
Number parameter.
Registering Console Commands Requires Stable Console Process (Network C for NLMs
v2.00)
The RegisterConsoleCommand() function may fail when used in an NLM that is autoloaded
from AUTOEXEC.NCF. RegisterConsoleCommand() requires the console interpreter to be fully
loaded and initialized before it can be used, but it does not check for such conditions.
If an NLM that makes this call must be autoloaded, it must provide a long enough delay for the
console to become fully stable before the call is made. The exact length of this required delay
depends on the specific hardware and system configuration.
Obtaining NetWare Print Queue IDs (NetWare Client SDK v1.0d)
]The documentation for the NetWare Client SDK incorrectly describes
NWGetPrinterQueueID(): it is actually an NLM API. The underlying NCP denotes the API as
being server-based. On a client workstation it will return a Queue ID of 0.
To obtain the Queue ID for a captured device on a workstation, call NWGetCaptureFlags().
This API returns a structure called NWCAPTURE_FLAGSRO that contains a queueID field
containing the queue ID.
Closing TLI Endpoints & "Time-Outs" (NetWare Client SDK v1.0d)
When you attempt to connect to a non-listening node, the following scenario results in a
"time-out," when a cancellation of the request was expected.
- t_connect() (in non-blocking) is called against a non-listening node (or bad
address).
- t_close() waits until t_connect() completes its "time-out" process. Once t_connect() does
"time-out," t_close() completes successfully.
Loading Brequest from Login Scripts (NetWare Btrieve (NLM) v6.00d)
When loading BREQUEST.EXE from a NetWare login script, the TSR fragments memory,
so it appears to take 200K of space. This memory loss is attributed to the fact that the LOGIN
program is still in memory when the TSR is loaded. It gets trapped between whatever was in
memory prior to logging in (most likely the network shell) and the newly loaded TSR.
To avoid this situation, do not load TSRs from login scripts. If you need to load any TSRs at
login time, use the "EXIT" statement in a login script to call a DOS batch file. Batch files can load
the TSRs without this memory penalty.
Ensuring Btrieve Transaction Recovery (Btrieve for DOS v5.10a)
The documentation for Btrieve for DOS v5.10a states that, when using Btrieve in a
networked environment, all users who start Btrieve with a "/T" option should specify the same
physical location for the transaction control file. This rule ensures that, when a data file is shared
by two workstations, both of the stations will be able to recover from a server failure during an
End Transaction (20) operation, regardless of which station is recovered first.
This rule should be applied, but it is not foolproof. The full logical path of the data files used
in a transaction are stored in the transaction control file. If the first station to start Btrieve after a
server failure does not have the same logical mappings to the files as the station that was
processing an End Transaction operation during server failure, Btrieve will not be able to access
the files described in the transaction file and will report the error "Unable to access Btrieve file
for transaction recovery."
To insure transaction recovery after a server failure, all stations should share the same transaction
file (/T), and should also access the data files with the same logical mappings.
File Cache Buffer Size (Network C for NLMs v2.0(e))
If a file server is configured for 4096-byte cache buffers, the NetWare API
AllocNonMovableCacheMemory() returns multiples of a block size larger than 4096 bytes.
Under NetWare 3.11 a 4096-byte cache buffer actually has 124 bytes of overhead associated
with it. So, although 4096 bytes of each block is usable, each block is actually 4220 bytes long.
When a block is moved from the file cache buffers to the non-movable memory pool and then
allocated, only 16 bytes of memory are required for overhead for each allocation.
Therefore, if a single block of memory is allocated the usable storage will be:
4220 (block) - 16 (overhead) = 4204
If more than one block is allocated the total allocated and usable memory is equal to:
(number of blocks * 4220) - 16
SAP Service Queries From OS/2 (NetWare OS/2 SDK v2.0)
Issuing a SAP (Service Advertise Protocol) Service Query from OS/2 will not return all of
the responses to the application through IPXReceive().
If you use IPXSend() and IPXReceive() with the NW OS/2 Requester v2.01 or less to get a
list of advertising services, a number of the responses (possibly up to 50) are dropped because the
IPX/LSL interface is unable to handle large quantities of incoming packets at one time.
The most reliable solution in this situation is to use the NetWare Bindery to locate services.
In peer-to-peer cases, or where dependency on a NetWare server is undesirable, there are two
potential solutions:
- To issue the GSQs inside a loop, building an internal exclusion list of respondents
for each query, until a sufficient number of responses have come back. This solutions relies on the
fact that the servers will not respond in the same order every time and is therefore not dependable.
- Run a background process that monitors the advertisements on the SAP socket and records
the services to a file or a shared memory area. This is similar to what DOSNP does to find Named
Pipe servers for SQL.
Error in Attach_LU Call with CPI-C (NetWare LU6.2 Tools v1.4)
While loading CPI-C from NetWare 3270 LAN Workstation for Windows v1.2, an error in
the Attach_LU call or a "CPI-C Application Subsystem Error" may occur if the LU Local Address
is improperly configured. In this case, NetWare for SAA does not recognize the dependent LU
address in the "LU_LOCAL_ADDRESS" field, or it does not recognize it as an LU 6.2 address.
To prevent the error, make the "LU_LOCAL_ADDRESS" field match the address of a
dependent type of LU 6.2 address in the NetWare for SAA database. Also, call CSRESTART after
the service profile is modified in CSCON to place the changes in effect. Error code "0x00000501"
is also returned at 20th byte in the Attach_LU call in the protocol boundary trace.
IBM LAN Server Reports Sharing Violation with Btrieve (Btrieve for DOS v5.10a)
IBM LAN Server reports a "Sharing Violation" when an application issues a Close (1)
operation on a Btrieve file if at least two stations have a data file open and have both modified the
data file.
The error occurs when Btrieve for DOS performs its Close test to determine if it is the last
instance accessing the data file. During the Close operation, Btrieve tries to open the preimage file
in exclusive mode. If the Open operation succeeds, then Btrieve knows that this is the last handle
to the data file and can erase the preimage file. Unlike DOS, LAN Server interprets this test as a
critical error.
To prevent this "Sharing Violation" error from occurring, load Btrieve with a "/O." This load
parameter tells Btrieve to override the critical error handler so that Btrieve handles critical errors
instead of the operating system.
NWDSLogout() & SMS APIs (NLM SDK for NetWare 4.0 v1.0c)
The NWDSlogout() and NWSMTSReleaseTargetServer() interfere with each other in the
NetWare 4.0 environment. If the SMS (Storage Management System) services are used in
conjunction with the NetWare 4.0 CLIB APIs, they may interfere with each other.
In particular, NWDSlogout() and NWSMTSReleaseTargetServer() fail when used together.
When used together, in either order, the second call always fails. In addition, the active connection
for the second call remains allocated.
This situation has been resolved in NetWare 4.01.
Volume Info for Large Volumes (NetWare Client SDK v1.0d)
NWGetVolumeInfoWithHandle() and NWGetVolumeInfoWithNumber() return, among other
things, available blocks and total blocks for a volume. They return them as type NWNUMBER,
which is a 16-bit quantity. This type poses a problem when these calls are used on a large volume,
since large volumes could conceivably have more than 65,535 blocks.
The call NWGetDirSpaceInfo() returns these values as NWNUM_BLOCKS, which is a
32-bit quantity. Use this call instead of the NWGetVolumeInfo..() calls mentioned above to ensure
the information returned is correct for large volumes.
Btrieve Clients & SHARE.EXE (Btrieve for DOS v5.10a)
SHARE.EXE needs to be loaded on Btrieve for DOS and Btrieve for Windows client
workstations under the following conditions:
- If your application accesses the files that reside on your hard disk and applies any
record locks, whether single or multiple.
- If your application uses multiple cursors (multiple position blocks) to access the same file
on the hard disk.
DOS, by default (and without the NetWare shell), provides no locks at all; that is, INT
21H, function 5CH, is a "NOP." To support locking on local disks, DOS provides SHARE.EXE.
In order for Btrieve to be able to lock records on a local disk, SHARE.EXE must be loaded.
SHARE, by default, allows up to 20 concurrent locks. To increase locks, use the SHARE "L"
command line parameter. The "F" parameter may have to be used to make SHARE allocate more
work space if many files are locked, or if the files are in "deep" subdirectories, (for example,
c:\path1\path2...\path6\FILE.EXT.
Invalid Window Handle in NetWare Applications (NetWare Client SDK v1.0x)
Applications using the NetWare C Interface for Windows v1.3 function IPXYield() will
cause an invalid window to be reported if the debug version of Windows 3.1 is running. The
message is reported because IPXYield() uses a null window handle. This condition does not affect
the functionality of the call, but it does cause the debugger to report an error. This situation also
occurs with the following NetWare C Interface for Windows functions that use IPXYield()
internally:
- BeginDiagnostics()
- EndDiagnostics()
- IPXCancelEvent()
- PSAttachToPrintServer()
- QueryServices()
- ShutdownSAP()
- StartSendingPacketsTimed()
GetDiskUtilization() usedBlocks Parameter (NetWare C Interface for DOS v1.2)
The usedBlocks value returned by GetDiskUtilization() is incorrect due to a problem with
the NetWare C Interface for DOS source code. The wrong area of the NCP reply packet is being
returned.
To resolve this situation, modify the line in DISKUTIL.C:
*usedBlocks = *(LONG *)
&receivePacket[4];
to read:
*usedBlocks = *(LONG *)
&receivePacket[6];
and recompile the module. The correct number of used blocks is then returned and the usedBlocks
parameter does not need to be swapped.
Fast Answers to Common Questions
NetWare 3.11
Q - Sometimes when an NLM is loaded, the amount of "Total Server Work Memory"
that is displayed in MONITOR.NLM decreases by a multiple of 16 bytes. Are small amounts of
memory being lost when NLMs are loaded?
A - No, this decrease is a result of the method MONITOR.NLM uses to calculate the
amount of memory. No memory is actually being lost. The Non-Movable Cache, Movable Cache,
and File Cache totals reflect the total allocated memory, including the overhead involved in
managing these pools. The totals for Permanent and Alloc, however, only reflect memory that is
usable by an application and do not take into account the overhead involved in managing the
memory.
Therefore, any time an NLM needs more memory and the server is required to move memory
from File Cache Buffers to the Permanent pool, a full buffer (overhead and all) is removed from
the File Cache total and the amount of usable memory added to the Permanent total is 16 bytes
smaller, since 16 bytes are required for overhead.
NetWare Client SDK
Tip When a Windows application calls the the Service Advertise Protocol
(SAP) services, ShutDownSap(), after advertising, SAP Services will not be discontinued.
The "SAPping" process will continue until you actually exit from Windows.
Tip NWGetFileConnectionID() returns 0x89FD when it is used under NETx,
but the call works fine under VLM. This call is not supported under NETx. To be able to use
NWGetFileConnectionID(), the workstation must be running VLM.
NetWare C Interface for Windows
Q - How does VIPX handle ECBs (Event Control Blocks) internally?
A - When you call IPXListenForPacket(), VIPX adds the client ECB to a list of listen
ECBs for the socket. When a GetECB request is issued from the LAN driver, VIPX checks its list
of listen ECBs for that socket. If there is an ECB available, VIPX allocates a global ECB and then
copies the local client ECB to the global ECB. The global ECB is then submitted to the LAN
driver.
When a packet is received, the LAN driver fills the global ECB with the received packet. It
then calls the ServiceEvents routine to service the Event Service Routine (ESR) corresponding to
the ECB. This ESR is the service events callback used by VIPX. VIPX copies the contents of the
global ECB into the local client ECB. VIPX then determines whether the currently running virtual
machine (VM) is the owner of the local client ECB. If it is, the ESR is called immediately.
Otherwise, VIPX schedules the owner VM to run. When the VM that owns the local client ECB is
running, the ESR is called.
Btrieve
Tip When you perform an Insert (2) operation on a file containing an
auto-increment key, if the value of the auto-increment key is set to zero, on return from the operation,
Btrieve will update the data buffer to the new assigned auto-increment value for the record.
When you issue an Extended Insert (40) operation to insert multiple records with a single call
to Btrieve, if the data file contains an auto-increment key, the multiple records in the data buffer
will be updated with the auto-increment value, as well.
Tip If a data file is flagged "H" (hidden), NetWare Btrieve (NLM) cannot open
the file. NetWare Btrieve (NLM) returns a status 12 (File Not Found), but Btrieve for DOS v5.10a
is able to open data files that are hidden.
Currently, there is no solution for this inconsistency between the two Btrieve products.
Network C for NLMs
Tip If you are using WATCOM C/C++32 to create a C++ NLM, you must
include the header files in the \NOVH directory first, and then include the header files in the
\WATCOM\H directory. For example, if you had installed the tools in C:\WATCOM, you would
set the environment variable as follows:
set INCLUDE=C:\WATCOM\NOVH;
C:\WATCOM\H
You still need to include the regular \H directory because all the C++ headers are located there
(the header files are not duplicated in the \NOVH directory).
Novell FAX ON DEMAND Service
Q - How can I obtain the latest product information and press releases from Novell?
A - Novell customers who have access to a touch-tone telephone and a fax machine can
now request faxes of customer success stories, current press releases or specific product
information from Novell's new Fax on Demand (FOD) service by calling 1-800-NETWARE
(1-800- 638-9273) or 1-801-429-5588.
Product information on the FOD system includes the latest specifications on each of Novell's
products including: NetWare 4.01 and the NetWare Branch Office Solutions.
Developer information is still available through the Novell Developer Relations Automated
Fax System (see "Current Patches for Novell Development Tools" for details).
Available Novell Developer Education Courses
Novell Developer Education offers several courses for developers who use Novell's
development & database tools, including NetWare SQL, Btrieve, Xtrieve PLUS, and the NetWare
Client APIs.
904 - Btrieve: An Overview
905 - Programming with Btrieve
907 - Xtrieve PLUS
911 - NetWare Database Administrator
912 - Programming with NetWare SQL
930 - Developing NetWare Loadable Modules (NLMs)
940 - NetWare Programming: Basic Services
945 - NetWare Programming: Protocol Support
To obtain information on pricing, location, scheduling, & course content for classes held in the US,
call 1-800-233- 3382, 1-801-429-5508 or 1-800-NETWARE. For information on classes outside
of the US, contact your local Novell office.
The latest NetWare drivers, example code for NetWare API development tools, OS/2 requester
patches, and patches for Novell's database products are available on Novell's NetWire forum on
CompuServe. New information is first stored in NOVLIB library 1, and moved to library 7 after a
period of 30 days. If you do not have access to CompuServe, request these files from Novell's
Developer Support Group at 1-800-NETWARE (1-800-638-9273) or 1-801-429-5588.
When calling, be ready to provide a shipping address, disk preference (5.25", 3.5", HD, or
DD) and, if you prefer overnight delivery, your company's Federal Express account number. If you
do not provide a Federal Express account number, the patch disk will be sent to you via regular
mail.
Novell Professional Developers' Program members can obtain updated NetWare API SDK
components from Novell's NOVDEV forum on CompuServe. For more information on Novell
developer programs contact Novell at 1-800-NETWARE (1-800-638-9273) or 1-801-429-5588.
Novell Developer Relations Automated Fax System
A document describing available patches and other files and their location on CompuServe is
available through Novell Developer Relations Automated Fax System (AFS). This system can
provide you other useful information as well.
To use the AFS, call 1-800-RED-WORD (1-800-733-9673) or 512- 794-1796 from a touch-tone
phone. Then, choose the option for the Automated Fax System, select the documents you wish to
receive, and supply your fax number (the fax number to which you want the document(s) sent).
Document #7805 describes the patches. Document #1 lists all other documents available through
the Automated Fax System. Up to five documents can be requested per call.
Developer Support
Developers in the U.S. and Canada may contact Novell Developer Support via telephone, fax,
BBS or electronic mail via CompuServe, MHS or the Internet. Voice
For both presales and postsales support, call Novell Developer Support between 8:00 a.m. and
5:00 p.m. Mountain Time at 1-801-429-5588. Many calls to Novell Developer Support are
passed to a software support engineer immediately. Calls to Novell Developer Support generally
will be acknowledged or answered within four hours.
Fax
If you prefer, you may contact Novell Developer Support via fax at 1-801-429-2990. Faxed
questions are acknowledged or answered within 24 hours.
Developer BBS
If you do not have access to either CompuServe or the Internet, send test cases to our BBS. Set
your communication software to N-8-1 and call 1-801-429-5836. E-mail:
CompuServe
Post your messages in the appropriate section addressed to Novell at 76701,171. These messages
will receive a response within 24 hours.
E-mail: MHS
You may direct your questions and comments to Novell Developer Support via Novell's Message
Handling Service E-mail facility. Address your messages to devsup@novell. These messages will
receive a response within 24 hours.
E-mail: Internet (SMTP)
An alternative method of contacting Novell Developer Support is through the Internet E-mail
system. Send your messages to devsup@novell.com. These messages will receive a response
within 24 hours.
NetWire on CompuServe
Novell's NetWire forum is open to all registered CompuServe subscribers. Through the
NDEVSUP forum, professional developers writing applications with Novell development tools
can gain access to information specific to Novell development. Support, patches, periodicals and
product information, as well as information on all of the programs and services provided for
Novell developers are accessible through this forum. Post your messages in the appropriate
section addressed to Novell at 76701,171. Technical questions will be acknowledged or
answered by Novell Developer Support within 24 hours.
Novell Products and SDKs
Novell products on the "Currently Shipping Developer Products" list (see page 15 of this
issue), including the Red Box Products, are available to Novell Professional Developer's Program
members. Call 1-800-RED-WORD (1-800-733-9673) or 1-303-894-4135 to order these products
or to receive additional information. To order other Red Box Products not listed, contact your
local Novell office or Novell Authorized Reseller. Novell Labs
For information on Novell Labs development tools, education classes and product certification, in
the U.S. and Canada call 1-800-453-1267 ext. 5544 or 1-801-429-5544, or call your local Novell
office (see back cover of this issue).
Novell Developer Relations
Novell Professional Developers or those wishing to become members may contact Novell
Developer Relations via telephone, fax, or electronic mail via Compuserve, MHS or the Internet.
Voice
For general information or questions on Novell Developer Relations programs, in the U.S.
or Canada call 1-800-RED-WORD (1-800-733-9673). All others call 1-801-429-5281. Fax
If you prefer, you may contact Novell Developer Relations via fax at 1-801-429-7207.
NetWire on CompuServe
Novell's NetWire forum is open to all registered Compuserve subscribers. Through the
NDEVREL forum, Novell Professional Developer's Program-related issues or general questions
may be posted. Through the NDEVINFO forum, customers who do not have products may post
pre-sales product information questions on all Novell SDKs. E-mail: MHS or Internet
(SMTP)
You may direct your questions and comments to Novell Developer Relations via Novell's
Message Handling Service E-mail facility. Address your messages to devprog@novell.com. Use
the same address when going through the Internet E-mail system.
Publisher: Mad Poarch
Editor: Kirk R. Humphries
Design: Creative Services, Provo
Articles: Drake Backman, Neda Eslami, Holly Roff, Glenn Stephens, and Aslam Tejani
Contributors: Linda Anderson, Vitek Boruvka, Jack Gumaer, Clint McVey, Raj Perubhatla, Matt
Pinsonneault, Bob Quinlan, Randy Reddy, Vicki L. Smith, Aslam Tejani, Howard Thamm, and
Brenda Wallace
Special thanks to the Developer Support, Development, Developer Relations, Product Marketing,
and Marketing Communications staff who contributed time and valuable input.
(c) 1993 Novell, Inc. All rights reserved.
Novell, the N design, NetWare, Btrieve, XQL, LAN WorkPlace, NetWare Name Services and
LANalyzer are registered trademarks; NetWare Loadable Module, NLM, NetWare Global
Messaging, Global MHS, NetWare MHS, NetWare System Calls for DOS, NetWare Runtime,
NetWare SQL, NetWare Btrieve, NetWare C Interface for DOS, NetWare System Interface
Technical Overview, NetWare RPC, NetWare RPC 386, NetWare LU6.2, Report Executive,
NetWare Asynchronous Communication Services (NACS), NetWare Asynchronous Services
Interface (NASI), NetWare Management System, NetWare 3270 LAN Workstation, Xtrieve PLUS,
Novell Labs, IPX, and MacIPX are trademarks; and NetWire and Professional Developers'
Program are service marks of Novell, Inc. IBM and OS/2 are registered trademarks, and NetBIOS
and SAA are trademarks of International Business Machines Corporation. Microsoft is a
registered trademark, and Windows and Microsoft QuickBasic are trademarks of Microsoft
Corporation. AppleLink and Macintosh are registered trademarks of Apple Computer, Inc.
CompuServe is a registered trademark of CompuServe Corporation. Sun Microsystems and NFS
are registered trademarks and TI-RPC is a trademark of Sun Microsystems, Inc. UNIX is a
trademark of UNIX Systems Laboratories, Inc. in the USA and other countries. UNIX Systems
Laboratories is a wholly-owned subsidiary of Novell, Inc. WATCOM is a registered trademarks
of WATCOM Systems, Inc.
|