Sam*_*m K 5 rpg rpgle ibm-midrange
我有一个要求,我需要将数组数据结构元素返回给调用程序。最初我想到使用数组数据结构(9999-最大暗淡)作为调用程序的参数。有 50 个调用程序。只有一些程序需要这个数组数据。我被要求使用临时文件(qtemp)来插入和检索。我实现了并且它工作得很好。想知道比我们迄今为止实现的更好的解决方案(需要并发)。谢谢
可能有几十种方法可以处理这个问题。一些想法:
使用临时文件。这正是 QTEMP 库所擅长的事情。您可以使用数据创建和填充文件,并知道这些数据将在作业结束时删除,或者如果您自己明确删除它们,则在之前删除。它们可以像可变长度数组一样工作,而 RPG 目前还不能很好地支持这一点。如果您尝试的话,您的并发问题可能会得到解决。RPG F-specs 和非动态 SQL 没有通过在字符串中传递文件名来选择文件的好方法,但是巧妙地使用 OVRDBF 和 DLTOVR 命令可以为主程序创建目标文件提供巧妙的方法使用唯一的名称,将其覆盖为预期的名称,然后调用第二个程序。这允许使用通用 F 规范或静态 SQL 名称编写第二个程序,但它实际上会写入覆盖的文件。
Pass a large array when calling your program. If you allocate and deallocate the space yourself, you can handle any concurrency concerns by ensuring that each called program gets its own array to write to. Some people might have concerns that this is wasteful of memory or inefficient. It is true that you will be allocating big chunks of memory that the called programs may not use, but is that such a problem on this operating system? Consider some things: parameters are usually passed by reference, not by value, so the contents of the array do not have to be blitted from one copy to another; RPG does not initialize data structures by setting them to blanks and zeros unless you specify the INZ keyword, so taking out space for a large array is just reserving space, not writing to it, and you can pass max used size as a parameter also to keep yourself from reading junk; allocating memory (an array or a userspace or maybe an IFS temp file) should all be about equally fast given the IBM i concept of a single-level store (a temp DB file probably has a little more overhead because the DB2 engine needs to create it and keep track of its fields and records). In other words, passing big chunks of memory to your subprograms might increase your total memory footprint, but it won't necessarily make your programs slow if you are smart about it.
Create a userspace object and use that as a shared memory area. I don't do this a lot because it feels more like a C technique using pointers, but it can certainly be a useful way to provide free-form space to write whatever you want. The system API's often use these userspaces to pass information out of a called program. An example of using pointers in RPG to read a userspace can be found here. You can handle concurrency by creating separate, uniquely named userspaces in QTEMP, of different sizes if you want, and pass their name and size back to the calling program for it to read. Their variable size can keep your memory footprint smaller than fixed-size arrays. If IBM chose to use them in API's as extensively as they did, it must be a good technique. You can keep the pointer code contained in one or two small sections and even clean it up by mapping a data structure onto the userspace for easier reading and writing using the BASED keyword.
You can create a callback program that delivers one data structure entry every time it is called. This may be the lowest memory method, depending on where your data is being loaded or created from. It is similar to the lazy loading used in other systems under the name of iterators or enumerators. The idea is to call a function a number of times and to get one entry each time. At no point does the whole thing need to be loaded into memory at once. The same example given above shows one way to do this technique if you look at the procedure pointer section of the code rather than the userspace section. Another way that I have tried this is to make a prototype of a data structure with three procedure pointers for the functions Current, MoveNext, and Reset. RPG makes you do more of the plumbing yourself than an IEnumerable in Microsoft.NET, but the concepts work for lazy-loading any size dataset if you are willing to write it yourself. You won't get compile-time checking, but it is not that hard to write in this style correctly once you understand the pattern. It reminds me of simulating object-oriented programming in C: set yourself some rules to follow and of course it works.
Another callback based example can be seen in how the DB2 SQL system interacts with External User Defined Table Functions (UDTF's) written in RPG or C. An example of this can be found in Birgitta Hauser's excellent article The Power of User-Defined Table Functions. I am not suggesting that you actually create a UDTF for your purpose (although that would be one legitimate, if higher overhead, solution), but instead to look at the callback mechanism that they use when calling an external program. It calls the subprogram multiple times: open (to initialize if necessary), an unrestricted number of times for each fetch until it is done, and close (to clean up and close files if necessary). Using a pattern like this is another way to pass only one data structure at a time rather than a whole array, and may be very attractive if your potential data sizes are large or unpredictable.
Hope this helps. There are probably other ways to do this that I'm not thinking of right now. Maybe someone else will chime in with them.
归档时间: |
|
查看次数: |
578 次 |
最近记录: |