Operating System - OpenVMS
1751969 Members
5016 Online
108783 Solutions
New Discussion юеВ

Re: about $flush with pascal

 
SOLVED
Go to solution
hf.yao
Occasional Advisor

about $flush with pascal

I wanna flush to my TEXT file time to time. But found that if the text file is on another machine, the file is still empty before it is closed. Is it realy the case? how can i handle it.

I use PAS$RAB to get the rab. Here is some sample code:

FUNCTION open_file(var f:TEXT; _filename:varying [Len] of char):integer;

VAR
Vf_Status: integer;

BEGIN

OPEN (FILE_VARIABLE := f,
FILE_NAME := _filename,
HISTORY := NEW,
SHARING := READONLY,
USER_ACTION := F_Text_open,
ERROR := CONTINUE);

V_time_file_rab := PAS$RAB(f);
IF STATUS(f) <> 0 THEN
BEGIN
WRITELN (' ');
WRITELN ('ERROR Openning file: ',_filename);
open_file := 0;
END
Else
open_file:=1;
END;

begin

vl_filename:='mylog:out.dat';
vl_stat := open_file(V_IN_FILE, vl_filename);
rewrite(V_IN_FILE);
writeln(V_IN_FILE,'hello',1);
$FLUSH (V_time_file_rab^);
lib$wait(10);
.....
9 REPLIES 9
Steven Schweda
Honored Contributor
Solution

Re: about $flush with pascal

I know nothing, but ...

> [...] on another machine [...]

What does that mean? DECnet? NFS? ???

> $FLUSH (V_time_file_rab^);

Have you looked at the status value(s) which
$FLUSH returns?

http://h71000.www7.hp.com/doc/731final/4523/4523pro_027.html

RAB$V_ASY?
John Gillings
Honored Contributor

Re: about $flush with pascal

hf,
I'm also unsure what you mean by "on another machine". Some explanation might help.

I'll have a stab at "the file is still empty before it is closed"... I assume you mean when you attempt to view the file from another process you don't see any data. This is possibly to be expected.

The $FLUSH forces RMS buffers to be written to disk. Although it does update the EOF, another process which already has the file open may not see the new EOF. See RMS documentation:

"On a flush, the EOF value written to the file header is only accessible to subsequent accessors. Any process that has the file open at the time of the flush cannot access the new EOF value without some explicit action."

Another possibility is the Pascal I/O routines have their own buffers "above" the RMS buffers. $FLUSH may not have any influence on language I/O buffers. Mixing raw RMS and language RTL I/O routines doesn't necessarily work the way you expect. For full control over I/O you may need to go to pure RMS calls. You also don't say what F_Text_open does. It may be critical to explaining observed behaviour.

If your objective is to be able to read a sequential file while it's being written by a long running process, rather than using a periodic $FLUSH in the writer, I suggest you open the file with SHARING:=READWRITE and not bother with $FLUSH (or any other direct RMS actions). Let the reading process request RMS to flush the data when it wants to read it. From DCL use:

$ OPEN/APPEND/SHARE=WRITE log
$ CLOSE log

This will force a flush and update the EOF. You can then read the file (say with TYPE) up to the new EOF.

If that doesn't help, please let us know exactly what you're trying to do, and what isn't working.
A crucible of informative mistakes
hf.yao
Occasional Advisor

Re: about $flush with pascal

Hi Steven & John, thanks for your reply.
Here i brief my requirement. My server program generates log, and I need check/type the log file in another terminal. Actually the log file is on another machine connected by DECNet.

just like the program I posted, if the out.dat file is in local directory, I can surely type the file on another terminal before the program finish with close(v_in_file). But if I "define mylog RemoteNode::dir:", RemoteNode is another server connected via DecNet, when i type the out.dat it is always empty before the file is closed.
I checked the return value of $flush, always 65537 which means ok.

Here I raise another question. I also tried way to uses all routines in RMS ($create, $connect, $put, $flush, $close). Seems work.
But the question is when i output a string, how to add EOL just as writeln()? I added "\r\n", it's not the same, because when i 'EDIT' the log file, it shows 'LF CR' but a real new line. Can i $put just as same as writeln()?
Steven Schweda
Honored Contributor

Re: about $flush with pascal

> [...] I added "\r\n", it's not the same,
> [...]

That's right, it's not the same.

dire /full

Look for "Record format:".

In files with "Record format: Stream*",
records are delimited by special characters
in the data (Stream_CR: CR; Stream_LF: LF; or
Stream: CR+LF). In files with "Record
format: Variable length", byte counts are
stored for each record, and there are no
special characters in the data. Adding
"\r\n" to one of these files adds those
characters, but they do not delimit a record.
(And the editor knows that.)

I don't use $PUT enough to remember anything,
but the RMS manual says, "The Put service
inserts a record into a file", so I'd expect
$PUT to create a new record every time you
call it. I can't see your code, and I can't
see your file, so it's hard for me to guess
what anything is doing.

> Can i $put just as same as writeln()?

I know even less about what Pascal I/O does
than I do about what RMS does, but I'd guess
so.

> I checked the return value of $flush,
> always 65537 which means ok.

What about "RAB$L_STV Additional status
information"?

> "define mylog RemoteNode::dir:", [...]

I would not be amazed if DECnet affected the
way these things work. (Disappointed,
perhaps, but not amazed.)
Hein van den Heuvel
Honored Contributor

Re: about $flush with pascal

There is a lot going on here.

First, the flush works (as per status... thanks!) but the effects are slightly different from what you'd expect.
To verify, use a REAL program to open and read the file in REAL sharing mode.

Even a DCL script with $OPEN/SHARE will do.
Now READ the records in a loop. Before the $FLUSH they will NOT be there (remotely) after the the flush they will.

Tools like TYPE, SEARCH, CONVERT/SHARE all use RMS option SHR=UPI. That indicates USER PROVIDED INTERLOCK.

There are TWO main tools to really dive into this, if you care:
1) $ DEFINE FAL$LOG This will allow you to see what goes on 'over the wire'
2) ANALYZE/SYSTEM ... SHOW PROC/RMS=(FAB,RAB,BDBSUM)
This shows what is going on in memory.
In the FAB for a local file you'll see DFW = deferred write. That'l muddle the effects some.
In the FAB for the FAL process for the remote case you'll see SQO. That optimization will muddle the the result a whole lot.
In the RFA field for the RAB you see how far the $PUTs have progressed.
In the ADDR fields from the BDBSUM you can actually peek into the RMS buffer and see the records written so far.

When you change the open to "sharing := readwrite", then a simple DCL OPEN/SHARE and CLOSE will flush out the EOF information in the remote case like John desrcibes.

I suspect the the SQO (Sequential Output Only) is the cause for the somewhat odd behaviour. You may have to read up on that some.

You may want/need to keep the logfile local, and it's access remote?

Now for the easy one...

If you change the open to use "record_type :=stream", then embedded pairs in the data will become indistinguishable from multiple lines.
You can achieve that post-fact with
$ CONV/FDL="RECORD;FORMAT STREAM" embedded clean

And for a irrelevant ones...

Your example indicates a USER_ACTION without showing the code, so that could change the whole game. But it reproduces without.

And you code write to IN_file, but flushes something named TIME_file which could be indicative of a simple confusion. But again, it reproduces, so that's not the problem.

That's all the time I have now,
Cheers,
Hein
Hein van den Heuvel
Honored Contributor

Re: about $flush with pascal

'over the write' should be 'over the wire'

also, sample program I used to try some variations


Hein
--------------------------------

[inherit ('sys$library:starlet','sys$library:pascal$lib_routines')]
program get_data_and_time (input,output);

type
rab_pointer = ^rab$type;

function pas$rab (var f : [unsafe] text) : rab_pointer; extern;

var
rabp : rab_pointer;
stat : integer;
filename : varying [255] of char;
f : text;

begin
write('Enter file name >> ');
readln(filename);
writeln;

open (file_variable := f, file_name := filename, history := new, record_type :=stream, sharing := readwrite);
rabp := pas$rab (f);

rewrite(f);
writeln(f, 'hello');
write('Next ?');
readln(filename);
writeln(f, 'aap');
writeln(f, 'noot');
writeln(f, 'mies');
stat := $flush ( rabp^ );
writeln(stat, ' Done ?');
readln(filename);
end.
Hoff
Honored Contributor

Re: about $flush with pascal

Get rid of all the baggage in this design and simplify the design and write the log locally and with read-sharing enabled and let the remote users grab a copy of it from their end via DECnet or IP and this whole shared-FAL-flush-records morass disappears in a puff of greasy orange smoke.

With the local log file, the log file is also more reliably available to the Pascal code writing stuff, and the folks examining the log can use DECnet or IP to access and/or pull over copies of the log, too. And the code is simpler.

Or punt on the whole design used here and use something intended for this sort of a task, such as a tool that knows to send syslog messages into a remote syslog daemon.
hf.yao
Occasional Advisor

Re: about $flush with pascal

thanks all
Hein van den Heuvel
Honored Contributor

Re: about $flush with pascal

I wrote... "I suspect the the SQO (Sequential Output Only) is the cause for the somewhat odd behaviour. You may have to read up on that some."

The documentation for that is in the RMS REF manual under SQO. There are several paragraphs worth studying. The intro gives a strong clue:
"For OpenVMS DECnet operations, this option has an added meaning. When set for a remote file access, it indicates that file transfer mode (FTM) should be used for Get, Put, Read, and Write services. File transfer mode is a Data Access Protocol (DAP) feature that allows several records to be transferred in a
single-network I/O operation to maximize throughput for sequential access file
transfers."

Hein