Rename PDS members with STOW instead of asking LOCATE about them (#92) - #93
Merged
Conversation
Renaming a member was impossible, and both ways of failing lied about the
reason. On the target, with a PDS holding M1..M3:
RNTO 'IBMUSER.MBRTEST(M9)' 550 ... M9 already exists. (it did not)
RNFR 'IBMUSER.MBRTEST(NOSUCHMB)' 350 RNFR accepted. (it did not exist)
One cause: __locate() resolves the base data set name and ignores (member).
RNFR and RNTO kept the member attached and asked LOCATE, so the target check
saw the PDS and called the member "already existing", the source check passed
for members that were not there, and IDCAMS ALTER -- which renames catalogued
data sets, not directory entries -- could never have completed the operation
anyway.
Both now split the member off first:
- RNFR authorizes against the base name (a RAKF DATASET profile is held under
a data set name, so PDS(MEMBER) never matched one; only the HLQ == userid
short-circuit was covering that up), verifies the data set with __locate()
and the member with __listpd() through the new member_exists() helper.
- RNTO renames member to member with __renmem(), whose STOW return codes are
precisely the two answers LOCATE could not give: 8 for a missing source, 4
for an occupied target. Data set to data set keeps IDCAMS ALTER.
- The combinations STOW cannot express -- member to data set, data set to
member, member across two different PDSs -- get a 550 naming which of them
it was, instead of failing obscurely three steps later.
member_exists() reads the directory under the session identity, like LIST
does, so the window discipline from #79 holds.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #92.
The defect
Measured on the target with a PDS holding M1, M2, M3:
One cause behind all of it:
__locate()resolves the base data set name andignores
(member). RNFR and RNTO kept the member attached and asked LOCATE,so the "target must not exist" check saw the PDS and rejected every member of
it, the "source must exist" check passed for members that were not there, and
IDCAMS ALTER— which renames catalogued data sets, not directory entries —could not have finished the job in any case.
The same blind spot is why SIZE could not handle members (#88); there it was
__dscbdv()that choked on the member form.Change
Both handlers split the member off before doing anything else.
under a data set name, so
PDS(MEMBER)never matched one — only theHLQ == useridshort-circuit was hiding that. Existence is then checked intwo parts: the data set with
__locate(), the member with__listpd()through a new
member_exists()helper.__renmem()(clibio.h:167), whose STOWreturn codes are exactly the two answers LOCATE could not give —
8sourcemissing,
4target occupied. Both are mapped to their own 550 text.550 saying which of the three it was, rather than failing obscurely a few
steps later.
member_exists()reads the directory under the session identity, like LISTdoes, so the identity-window discipline from #79 holds — one window, opened and
closed inside the helper, no data set held across it.
What this does not change
DELEof a member keeps using IDCAMS; it works today, and__stow('D')wouldneed an open DCB the delete path does not otherwise have. Noted in #87, which
is where the "replace IDCAMS" idea now ends: its throughput premise was
measured away (0.11s median window), and for data sets there is no direct
route — libc370 uses CAMLST only for LOCATE and OBTAIN, both read-only, and the
catalog side would have to handle VSAM user catalogs.
Verification
Builds clean with
-Wall -Werror. The behaviour needs the target: afterdeploy, the transcript above must become
550 ... does not exist.for themissing member on RNFR, and a successful
250 PDS(M2) renamed to PDS(M9)forthe rename — with the member actually moved in the directory, checked through
the REST API rather than through FTPD's own listing.