1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <config.h>
include <error.h>
include "mtio.h"
.help mtcache
.nf _________________________________________________________________________
MTCACHE -- Cache the magtape position (file and record) between file opens.
The lock file is used for permanent storage, but is only read and written
when necessary. When multiple tape files are accessed by a single task the
tape position is kept in the cache between successive MTOPEN - CLOSE file
accesses.
mt_getpos (mtname, mt)
mt_savepos (mt)
mt_sync (status)
mt_clrcache ()
SAVEPOS updates the tape descriptor in the cache; SYNC updates the cache
on disk in the lock file. SYNC is automatically called at task termination
time (including during abnormal termination), but is not normally called
when a tape file is closed.
ERROR RECOVERY is a bit tricky. If error recovery takes place the ONERROR
procedures are called first thing, before FIO cleanup takes place. That means
that SYNC will be called while the magtape channel is still open, and before
SAVEPOS has been called by ZCLSMT (which is called by fio_cleanup which is
called by the main). If an error occurs on a magtape channel we want to
record an undefined file position. We must see that SAVEPOS is called at
file open time to mark the cache for updating, causing SYNC to write an
undefined position lock file when the error occurs. ZCLSMT, when called
during error recovery, should set the position to undefined but need not
sync the cache.
The cache is invalidated at process startup time and at SYNC time in case
the user loads a new tape or runs a different magtape process while the
current process is idling between tasks. In other words, the cache is only
valid while the task using it is executing.
.endhelp ___________________________________________________________________
define SZ_CACHE MT_MAXTAPES
# MT_GETPOS -- Return the device position descriptor of a drive given its
# unit number.
procedure mt_getpos (mtname, mt)
char mtname[ARB] #I device name
int mt #I MTIO descriptor
int slot
bool streq()
include "mtcache.com"
include "mtio.com"
begin
# First look in the cache.
for (slot=1; slot <= SZ_CACHE; slot=slot+1)
if (streq (MT_LKNAME(mt), c_lkname[1,slot])) {
call amovi (c_mtdes[1,slot], MT_DEVPOS(mt), LEN_DEVPOS)
call strcpy (c_device[1,slot], MT_DEVICE(mt), SZ_DEVICE)
call strcpy (c_lkname[1,slot], MT_LKNAME(mt), SZ_LKNAME)
call strcpy (c_iodev[1,slot], MT_IODEV(mt), SZ_IODEV)
return
}
# Get the current position from the lock file, if there is one.
call mt_read_lockfile (mtname, mt)
end
# MT_SAVEPOS -- Save the current position in the cache. The entire descriptor
# is saved since most of the information therein is needed for SYNC, even
# though only a portion of the information will be used by GETPOS.
procedure mt_savepos (mt)
int mt #I MTIO descriptor
int prev, slot
bool streq(), strne()
extern mt_sync()
include "mtcache.com"
include "mtio.com"
data prev /0/
define cache_ 91
begin
# Post termination handler to sync the cache at task termination time.
call onerror (mt_sync)
# Do not update the cache if the file position is undefined.
if (MT_FILNO(mt) <= 0)
return
# Are we updating an entry already in the cache?
for (slot=1; slot <= SZ_CACHE; slot=slot+1)
if (streq (MT_LKNAME(mt), c_lkname[1,slot]))
goto cache_
# Add the entry to the cache. Resync the contents of the old slot
# if it is for a different drive and has been modified since it was
# last synced.
slot = prev + 1
if (slot > SZ_CACHE)
slot = 1
prev = slot
if (c_modified[slot] == YES && strne(MT_LKNAME(mt),c_lkname[1,slot])) {
call amovi (c_mtdes[1,slot], MT_DEVPOS(0), LEN_DEVPOS)
call strcpy (c_device[1,slot], MT_DEVICE(0), SZ_DEVICE)
call strcpy (c_lkname[1,slot], MT_LKNAME(0), SZ_LKNAME)
call strcpy (c_iodev[1,slot], MT_IODEV(0), SZ_IODEV)
call mt_update_lockfile (0)
}
cache_
call amovi (MT_DEVPOS(mt), c_mtdes[1,slot], LEN_DEVPOS)
call strcpy (MT_DEVICE(mt), c_device[1,slot], SZ_DEVICE)
call strcpy (MT_LKNAME(mt), c_lkname[1,slot], SZ_LKNAME)
call strcpy (MT_IODEV(mt), c_iodev[1,slot], SZ_IODEV)
c_modified[slot] = YES
end
# MT_SYNC -- Update all modified entries in the cache. Set the position to
# undefined (file=-1) if we are called during error recovery. We are called
# at task termination by the IRAF Main.
procedure mt_sync (status)
int status #I task termination status
int slot
include "mtcache.com"
include "mtio.com"
begin
# Update the .lok files of any active devices.
for (slot=1; slot <= SZ_CACHE; slot=slot+1) {
if (c_modified[slot] == YES) {
# If called during error recovery mark the file position undef.
if (status != OK) {
call amovi (c_mtdes[1,slot], MT_DEVPOS(0), LEN_DEVPOS)
MT_FILNO(0) = -1
MT_RECNO(0) = -1
call amovi (MT_DEVPOS(0), c_mtdes[1,slot], LEN_DEVPOS)
}
# Update the lockfile.
call amovi (c_mtdes[1,slot], MT_DEVPOS(0), LEN_DEVPOS)
call strcpy (c_device[1,slot], MT_DEVICE(0), SZ_DEVICE)
call strcpy (c_lkname[1,slot], MT_LKNAME(0), SZ_LKNAME)
call strcpy (c_iodev[1,slot], MT_IODEV(0), SZ_IODEV)
# Ignore errors if we are called during error recovery.
iferr (call mt_update_lockfile (0))
if (status == OK)
call erract (EA_ERROR)
c_modified[slot] = NO
c_device[1,slot] = EOS
}
}
# Invalidate the cache when a task terminates.
call mt_clrcache()
# If we are called during error recovery, set the file position for
# all open tapes to undefined to prevent mt_savepos from being called
# by zclsmt when the tape file is closed during error recovery.
if (status != OK)
do slot = 1, MT_MAXTAPES {
MT_FILNO(slot) = -1
MT_RECNO(slot) = -1
}
end
# MT_CLRCACHE -- Initialize the cache.
procedure mt_clrcache()
int slot
include "mtcache.com"
begin
for (slot=1; slot <= SZ_CACHE; slot=slot+1) {
c_modified[slot] = NO
c_device[1,slot] = EOS
c_lkname[1,slot] = EOS
c_iodev[1,slot] = EOS
call aclri (c_mtdes[1,slot], LEN_DEVPOS)
}
end
|