-
Notifications
You must be signed in to change notification settings - Fork 447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add method sam_open_write #1055
base: develop
Are you sure you want to change the base?
Conversation
If we change |
Looks good. Maybe squash the 1st and 3rd commits together? |
Decouple htsFile::fnidx from its source and let HTSlib manage its memory. Add method sam_open_write for opening a htsFile file for writing only and setting a header to it. Add getter method hts_get_fn.
I squashed all three of them, as the second didn't make much sense by itself. |
@jmarshall so... were there any comments....? |
To continue the conversation from the previous PR #1052,
When there are lots of different sets of headers around, e.g., when implementing Having said that, I can see the point of attaching the headers to the There are two ways of opening a file for use with The proposed I would suggest instead of adding this samFile *fout = hts_open_format(filename, "w", &myfmt); // or hts_hopen etc
if (fout == NULL) { "error can't open: permission problem etc" }
if (sam_hdr_write(fout, headers) < 0) { "error headers borked or I/O error" }
…
…sam_write1(fout, NULL, b)… which keeps the handling for the distinct failure modes separate and is still only two function calls (compared to the proposed Due to the header reference counting (which needs to be verified as still correct with either form of more widespread header attaching), having (If OTOH you do go with |
@return Read-only pointer to the file's fn field. | ||
*/ | ||
HTSLIB_EXPORT | ||
const char *hts_get_fn(htsFile *fp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there other parts of the API that have …fn
in API function names? I'd rather spell it out as …filename
(and it needs to be clear what if any relationship this has to hts_set_fai_filename
).
sam.c
Outdated
const sam_hdr_t *h = hdr; | ||
if (!h) h = fp->bam_header; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clearer as
const sam_hdr_t *h = hdr? hdr : fp->bam_header;
if (h == NULL) { errno = EINVAL; return -3; }
as in particular passing NULL when no headers are attached should be an error rather than a crash 😄
vcf.c
Outdated
@@ -3295,7 +3295,8 @@ static int vcf_idx_init(htsFile *fp, bcf_hdr_t *h, int min_shift, const char *fn | |||
fp->idx = NULL; | |||
return -1; | |||
} | |||
fp->fnidx = fnidx; | |||
fp->fnidx = strdup(fnidx); | |||
if (!fp->fnidx) return -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should tear down fp->idx
like the other error path does. Ditto in bcf_idx_init
below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The top caller (test_view::main
), does the clean-up of the htsFILE
descriptor and the memory associated with its members, so calling hts_idx_destroy
here was redundant. Also, there is no other place where fp->idx
is subsequently used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No.
If fp->idx
is not NULL, then the index gets built up on the fly in bcf_write
/vcf_write
. When bcf_idx_init()
fails for any reason, it needs to tear down the fp->idx
that it has attempted to construct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well ideally the caller would inspect the return value of bcf_idx_init()
and not carry on after it failed. But as we know some callers aren't very good at doing that, it would be best to tidy everything up here. It could be made slightly easier by moving the strdup()
to before hts_idx_init()
. Both failure paths after that would need to free fp->fnidx
and set it to NULL
, but otherwise remain as they were originally.
On the whole I think I prefer the simplicity of only having to call one function. It is true that it lacks features compared to We could always add |
vcf.c
Outdated
hts_idx_destroy(fp->idx); | ||
fp->idx = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the opposite of what I suggested. What is the reason for not destroying the incompletely-setup index?
if (!h) h = fp->bam_header; | ||
if (!fp || !b) { errno = EINVAL; return -1; } | ||
const sam_hdr_t *h = hdr ? hdr : fp->bam_header; | ||
if (!h) { hts_log_error("No header available for file \"%s\"", fp->fn); return -1; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h == NULL
here is an error in the program, not a user error. So there's not much point reporting it to the user (they can't do anything about it!), but it does need to set errno
(as other error paths do).
The new method
sam_open_write
can open ahtsFile
file in writing mode only, attach a header struct (sam_hdr_t
) to it and write the header data to the disk, before any alignment data.New getter method
hts_get_fn
is used to fetch the internal file name ofhtsFile
.The index file name inside
htsFile
is now managed by HTSlib, and no longer points to an application variable.