[Info-vax] OpenVMS Development Annoyances

Stephen Hoffman seaohveh at hoffmanlabs.invalid
Tue May 7 11:30:52 EDT 2019


On 2019-05-07 05:40:55 +0000, Dave Froble said:

> 
> On Monday, May 6, 2019 at 10:51:44 AM UTC-5, Stephen Hoffman wrote:
>> 
>> On OpenVMS, itemlists shove a whole lot of complexity and overhead of 
>> the flexible API—and a whole lot of source code glue—into the user 
>> code, as part of maintaining API compatibility.
>> 
>> As for examples?  I know well how to use itemlists.  I routinely 
>> encounter and routinely write pages of source code to do a few simple 
>> system service API calls, too.
>> 
>> And the itemlist APIs can fail at even that upward-compatibility task, 
>> with fixed-length buffers being ubiquitous.  Which means a two-pass 
>> call, with added memory allocation and deallocation glue code.
>> 
>> We all always get all of our memory allocation and memory deallocation 
>> entirely right, too.  I'm not the only one that's ever made mistakes 
>> here, whether leaks or missing access checks—itemlists are really fun 
>> across mode changes.  And I know I'm not alone here with these 
>> mistakes, having fixed various leaks and itemlist parsing written by 
>> other folks.   It's forty years in and we still don't have a freaking 
>> itemlist parser-generator?  Ah well, what I'm using elsewhere 
>> eliminates this mess, and is a whole lot less glue code for callers to 
>> write.

[expurgated—deletia—clippage]

> Ok, an item list:
> 
>          Record Socket_Options             !  Socket characteristics
>                  Word    Protocol%
>                  String  Typ$=1
>                  String  AF$=1
>          End Record
> 
> 
> So, Ok, lots of definitions, but, it's done once, and put in an include 
> file.  Then any program can use the include file.
> 
>          DECLARE SOCKET_OPTIONS  SOCKOPT   !  Socket characteristics
> 
> A simple variable definition then gives one an item list.
> 
> 130     !************************************************
>          !             Create Connection Socket
>          !************************************************
> 
>          SOCKOPT::PROTOCOL% = TCPIP$C_TCP                !  Socket 
> characteristic
> s
>          SOCKOPT::TYP$ = CHR$(TCPIP$C_STREAM)
>          SOCKOPT::AF$ = CHR$(TCPIP$C_AF_INET)
> 
>          Stat% = SYS$QIOW(       ,                       !  Event flag &
>                                  CH% By Value,           !  VMS channel &
>                                  IO$_SETMODE By Value,   !  Operation &
>                                  IOSB::Stat%,            !  I/O status block &
>                                  ,                       !  AST routine &
>                                  ,                       !  AST parameter &
>                                  SOCKOPT::PROTOCOL%,     !  P1 &
>                                  ,                       !  P2 &
>                                  ,                       !  P3 &
>                                  ,                       !  P4 &
>                                  ,                       !  P5 &
>                                  )                       !  P6
> 
>          If      ( Stat% And SS$_NORMAL ) = 0%
>          Then    Call VMSERR( Stat% , E$ )
>                  E$ = "Unable to queue create connection socket - " + E$
>                  E% = -1%
>                  SaveStat% = Stat%
>                  GoTo Deassign_Channel
>          End If
> 
>          If      ( IOSB::Stat% And SS$_NORMAL ) = 0%
>          Then    Call VMSERR( IOSB::Stat% , E$ )
>                  E$ = "Unable to create connection socket - " + E$
>                  E% = -1%
>                  SaveStat% = IOSB::Stat%
>                  GoTo Deassign_Channel
>          End If
> 
> One might notice that a large part of the code is in the error 
> handling.   Sorry, nobody is going to talk me out of that.  Assume 
> nothing. Expect anything.  Prepare for anything.
> 
> Basically, one defines a RECORD / STRUCTURE.
> Then declare a variable of that RECORD / STRUCTURE.
> Set the pieces of the variable as needed.
> Call the system service.
> Handle the result.
> 
> One note, the above code was extracted from a subprogram, so arguments 
> to the subprogram are included in the code.  Could be simpler without 
> that.  IOSB is another RECORD, not included above.
> 
> Have I cluttered up c.o.v enough?


You're not seeing it, David.   I know I didn't see it.  Not until I saw 
a vendor working toward the removal of source code baggage; of removing 
boiler-plate and glue code.  Itemlists are particularly egregious here, 
though PQLs and among my most "favorite" calls 
SMG$CREATE_MENU_WITH_GREAT_API_COMPLEXITY are all certainly awaiting 
the unwary.  Are itemlists simple to code? Sure. But look at how much 
app source code is associated with a system call. In the case of 
itemlists, all that code is an OpenVMS developer pushing chunks of the 
requirements around OpenVMS-style API compatibility into the user app 
source code.  And you picked an example that doesn't have an itemlist 
structure, basically a version of a C socket options buffer.  And to be 
flexible around buffer-size changes for if (when) those requirements 
arise, there needs to be doubled system service calls and memory 
allocation and deallocation handling and that's usually app source 
code, and there quite commonly aren't those doubled calls.  When I look 
at itemlists now, all I see is piles of source code.  App source 
code—glue code—that's necessary for how OpenVMS APIs operate now and 
for the foreseeable future, unfortunately.  Gobs of code that long-time 
developers often don't notice.

The following Swift code 
https://developer.apple.com/videos/play/wwdc2018/715/ performs a DNS 
translation, creates a TLS connection to the specified host on the 
specified port (a mail server IMAP port), supports both IPv4 and IPv6, 
and handles the common errors:

// Create an outbound connection
import Network
let connection = NWConnection(host: "mail.example.com", port: .imaps, 
using: .tls)
connection.stateUpdateHandler = { (newState) in
  switch(newState) {
    case .ready:
      // Handle connection established
    case .waiting(let error):
      // Handle connection waiting for network
    case .failed(let error):
      // Handle fatal connection error
    default:
      break;
  }
}
connection.start(queue: myQueue)
...

Note that the code doesn't have to futz with records or data structures 
or socket options structures, nor with DNS, nor with TLS, nor with the 
root certificates for commercial certificates.

The Apple Network Framework is fairly new, and I've just started 
working with it.  Here's a walk-through of an Apple example from 
Objective C:

https://developer.apple.com/documentation/network/implementing_netcat_with_network_framework?language=objc 


Apple has lots of these examples posted, both accessible from the web 
and also from within the Xcode IDE environment.

Here's an example that fetches the current host name, and with an 
equivalent that'll feature itemlists on OpenVMS:

[[NSHost currentHost] localizedName];

Here's a DNS lookup:

[[NSHost hostWithName:@”www.example.com”]


ps: For folks looking to swipe some networking ideas elsewhere?  Here 
from Microsoft Windows, have a look at I/O Completion Ports.

https://docs.microsoft.com/en-us/windows/desktop/fileio/i-o-completion-ports


pps: Apple also has a habit of trying stuff and tossing out what 
doesn't work, which can be disconcerting for those of us accustomed to 
keeping problem code around forever.  VSI is going to be dragged toward 
this same replace-deprecate-and-remove approach too, though they won't 
like it. The alternative here would be worse for them and for OpenVMS. 
Ubiquitous-forever-compatibility is just not sustainable with the 
business environment VSI is presently working within.


ppps: no, I don't ever expect to see itemlists and the old APIs 
removed.  There are far too many folks that haven't adopted easier APIs 
in the decades since they've become available, and there's far too much 
code using the existing APIs.  That code will be around for many years. 
 That code will continue to be as glue-filled as it is now, and 
modified and new code will be glue-filled, if there are no better 
alternatives available.  Though I would expect to see a few specific 
cases of API changes or removals, per the "pps" above.


-- 
Pure Personal Opinion | HoffmanLabs LLC 




More information about the Info-vax mailing list