1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 #include "join_results.h"
27 #include "helper.h"
28 #include <klib/vector.h>
29 #include <klib/printf.h>
30 #include <kfs/buffile.h>
31 
32 typedef struct join_printer
33 {
34     struct KFile * f;
35     uint64_t file_pos;
36 } join_printer;
37 
38 typedef rc_t ( * print_v1 )( struct join_results * self,
39                              int64_t row_id,
40                              uint32_t dst_id,
41                              uint32_t read_id,
42                              const String * name,
43                              const String * read,
44                              const String * quality );
45 
46 typedef rc_t ( * print_v2 )( struct join_results * self,
47                              int64_t row_id,
48                              uint32_t dst_id,
49                              uint32_t read_id,
50                              const String * name,
51                              const String * read_1,
52                              const String * read_2,
53                              const String * quality );
54 
55 typedef struct join_results
56 {
57     KDirectory * dir;
58     struct temp_registry * registry;
59     const char * output_base;
60     const char * accession_short;
61     struct Buf2NA * buf2na;
62     print_v1 v1_print_name_null;
63     print_v1 v1_print_name_not_null;
64     print_v2 v2_print_name_null;
65     print_v2 v2_print_name_not_null;
66     SBuffer print_buffer;   /* we have only one print_buffer... */
67     Vector printers;
68     size_t buffer_size;
69     bool print_frag_nr, print_name;
70 } join_results;
71 
destroy_join_printer(void * item,void * data)72 static void CC destroy_join_printer( void * item, void * data )
73 {
74     if ( NULL != item )
75     {
76         join_printer * p = item;
77         if ( NULL != p -> f )
78         {
79             rc_t rc = KFileRelease( p -> f );
80             if ( 0 != rc )
81             {
82                 ErrMsg( "destroy_join_printer().KFileRelease() -> %R", rc );
83             }
84         }
85         free( item );
86     }
87 }
88 
destroy_join_results(join_results * self)89 void destroy_join_results( join_results * self )
90 {
91     if ( NULL != self )
92     {
93         VectorWhack ( &self -> printers, destroy_join_printer, NULL );
94         release_SBuffer( &self -> print_buffer );
95         if ( NULL != self -> buf2na )
96         {
97             release_Buf2NA( self -> buf2na );
98         }
99         free( ( void * ) self );
100     }
101 }
102 
103 static const char * fmt_fastq_v1_no_name_no_frag_nr   = "@%s.%ld length=%u\n%S\n+%s.%ld length=%u\n%S\n";
print_v1_no_name_no_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)104 static rc_t print_v1_no_name_no_frag_nr( join_results * self,
105                                          int64_t row_id,
106                                          uint32_t dst_id,
107                                          uint32_t read_id,
108                                          const String * name,
109                                          const String * read,
110                                          const String * quality )
111 {
112     return join_results_print( self,
113                                dst_id,
114                                fmt_fastq_v1_no_name_no_frag_nr,
115                                /* READ... */
116                                self -> accession_short, row_id,
117                                read -> len, read,
118                                /* QUALITY... */
119                                self -> accession_short, row_id,
120                                quality -> len, quality );
121 }
122 
123 static const char * fmt_fastq_v1_no_name_frag_nr = "@%s.%ld/%u length=%u\n%S\n+%s.%ld/%u length=%u\n%S\n";
print_v1_no_name_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)124 static rc_t print_v1_no_name_frag_nr( join_results * self,
125                                          int64_t row_id,
126                                          uint32_t dst_id,
127                                          uint32_t read_id,
128                                          const String * name,
129                                          const String * read,
130                                          const String * quality )
131 {
132     return join_results_print( self,
133                                dst_id,
134                                fmt_fastq_v1_no_name_frag_nr,
135                                /* READ... */
136                                self -> accession_short, row_id, read_id,
137                                read -> len, read,
138                                /* QUALITY... */
139                                self -> accession_short, row_id, read_id,
140                                quality -> len, quality );
141 }
142 
143 static const char * fmt_fastq_v1_syn_name_no_frag_nr   = "@%s.%ld %ld length=%u\n%S\n+%s.%ld %ld length=%u\n%S\n";
print_v1_syn_name_no_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)144 static rc_t print_v1_syn_name_no_frag_nr( join_results * self,
145                                          int64_t row_id,
146                                          uint32_t dst_id,
147                                          uint32_t read_id,
148                                          const String * name,
149                                          const String * read,
150                                          const String * quality )
151 {
152     return join_results_print( self,
153                                dst_id,
154                                fmt_fastq_v1_syn_name_no_frag_nr,
155                                /* READ... */
156                                self -> accession_short, row_id,
157                                row_id,
158                                read -> len, read,
159                                /* QUALITY... */
160                                self -> accession_short, row_id,
161                                row_id,
162                                quality -> len, quality );
163 }
164 
165 static const char * fmt_fastq_v1_syn_name_frag_nr      = "@%s.%ld/%u %ld length=%u\n%S\n+%s.%ld/%u %ld length=%u\n%S\n";
print_v1_syn_name_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)166 static rc_t print_v1_syn_name_frag_nr( join_results * self,
167                                          int64_t row_id,
168                                          uint32_t dst_id,
169                                          uint32_t read_id,
170                                          const String * name,
171                                          const String * read,
172                                          const String * quality )
173 {
174     return join_results_print( self,
175                                dst_id,
176                                fmt_fastq_v1_syn_name_frag_nr,
177                                /* READ... */
178                                self -> accession_short, row_id, read_id,
179                                row_id,
180                                read -> len, read,
181                                /* QUALITY... */
182                                self -> accession_short, row_id, read_id,
183                                row_id,
184                                quality -> len, quality );
185 }
186 
187 static const char * fmt_fastq_v1_real_name_no_frag_nr  = "@%s.%ld %S length=%u\n%S\n+%s.%ld %S length=%u\n%S\n";
188 static const char * fmt_fastq_v1_empty_name_no_frag_nr = "@%s.%ld length=%u\n%S\n+%s.%ld length=%u\n%S\n";
print_v1_real_name_no_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)189 static rc_t print_v1_real_name_no_frag_nr( join_results * self,
190                                          int64_t row_id,
191                                          uint32_t dst_id,
192                                          uint32_t read_id,
193                                          const String * name,
194                                          const String * read,
195                                          const String * quality )
196 {
197     if ( name -> len > 0 )
198     {
199         return join_results_print( self,
200                                    dst_id,
201                                    fmt_fastq_v1_real_name_no_frag_nr,
202                                    /* READ... */
203                                    self -> accession_short, row_id,
204                                    name,
205                                    read -> len, read,
206                                    /* QUALITY... */
207                                    self -> accession_short, row_id,
208                                    name,
209                                    quality -> len, quality );
210     }
211 
212     return join_results_print( self,
213                                dst_id,
214                                fmt_fastq_v1_empty_name_no_frag_nr,
215                                /* READ... */
216                                self -> accession_short, row_id,
217                                read -> len, read,
218                                /* QUALITY... */
219                                self -> accession_short, row_id,
220                                quality -> len, quality );
221 }
222 
223 static const char * fmt_fastq_v1_real_name_frag_nr = "@%s.%ld/%u %S length=%u\n%S\n+%s.%ld/%u %S length=%u\n%S\n";
224 static const char * fmt_fastq_v1_empty_name_frag_nr = "@%s.%ld/%u length=%u\n%S\n+%s.%ld/%u length=%u\n%S\n";
print_v1_real_name_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)225 static rc_t print_v1_real_name_frag_nr( join_results * self,
226                                          int64_t row_id,
227                                          uint32_t dst_id,
228                                          uint32_t read_id,
229                                          const String * name,
230                                          const String * read,
231                                          const String * quality )
232 {
233     if ( name -> len > 0 )
234     {
235         return join_results_print( self,
236                                    dst_id,
237                                    fmt_fastq_v1_real_name_frag_nr,
238                                    /* READ... */
239                                    self -> accession_short, row_id, read_id,
240                                    name,
241                                    read -> len, read,
242                                    /* QUALITY... */
243                                    self -> accession_short, row_id, read_id,
244                                    name,
245                                    quality -> len, quality );
246     }
247 
248    return join_results_print( self,
249                                dst_id,
250                                fmt_fastq_v1_empty_name_frag_nr,
251                                /* READ... */
252                                self -> accession_short, row_id, read_id,
253                                read -> len, read,
254                                /* QUALITY... */
255                                self -> accession_short, row_id, read_id,
256                                quality -> len, quality );
257 }
258 
259 static const char * fmt_fastq_v2_no_name_no_frag_nr = "@%s.%ld length=%u\n%S%S\n+%s.%ld length=%u\n%S\n";
print_v2_no_name_no_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)260 static rc_t print_v2_no_name_no_frag_nr( join_results * self,
261                                          int64_t row_id,
262                                          uint32_t dst_id,
263                                          uint32_t read_id,
264                                          const String * name,
265                                          const String * read1,
266                                          const String * read2,
267                                          const String * quality )
268 {
269     return join_results_print( self,
270                                dst_id,
271                                fmt_fastq_v2_no_name_no_frag_nr,
272                                /* READ... */
273                                self -> accession_short, row_id,
274                                read1 -> len + read2 -> len, read1, read2,
275                                /* QUALITY... */
276                                self -> accession_short, row_id,
277                                quality -> len, quality );
278 }
279 
280 static const char * fmt_fastq_v2_no_name_frag_nr    = "@%s.%ld/%u length=%u\n%S%S\n+%s.%ld/%u %length=%u\n%S\n";
print_v2_no_name_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)281 static rc_t print_v2_no_name_frag_nr( join_results * self,
282                                          int64_t row_id,
283                                          uint32_t dst_id,
284                                          uint32_t read_id,
285                                          const String * name,
286                                          const String * read1,
287                                          const String * read2,
288                                          const String * quality )
289 {
290     return join_results_print( self,
291                                dst_id,
292                                fmt_fastq_v2_no_name_frag_nr,
293                                /* READ... */
294                                self -> accession_short, row_id, read_id,
295                                read1 -> len + read2 -> len, read1, read2,
296                                /* QUALITY... */
297                                self -> accession_short, row_id, read_id,
298                                quality -> len, quality );
299 }
300 
301 static const char * fmt_fastq_v2_syn_name_no_frag_nr = "@%s.%ld %ld length=%u\n%S%S\n+%s.%ld %ld length=%u\n%S\n";
print_v2_syn_name_no_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)302 static rc_t print_v2_syn_name_no_frag_nr( join_results * self,
303                                          int64_t row_id,
304                                          uint32_t dst_id,
305                                          uint32_t read_id,
306                                          const String * name,
307                                          const String * read1,
308                                          const String * read2,
309                                          const String * quality )
310 {
311     return join_results_print( self,
312                                dst_id,
313                                fmt_fastq_v2_syn_name_no_frag_nr,
314                                /* READ... */
315                                self -> accession_short, row_id,
316                                row_id,
317                                read1 -> len + read2 -> len, read1, read2,
318                                /* QUALITY... */
319                                self -> accession_short, row_id,
320                                row_id,
321                                quality -> len, quality );
322 }
323 
324 static const char * fmt_fastq_v2_syn_name_frag_nr    = "@%s.%ld/%u %ld length=%u\n%S%S\n+%s.%ld/%u %ld length=%u\n%S\n";
print_v2_syn_name_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)325 static rc_t print_v2_syn_name_frag_nr( join_results * self,
326                                          int64_t row_id,
327                                          uint32_t dst_id,
328                                          uint32_t read_id,
329                                          const String * name,
330                                          const String * read1,
331                                          const String * read2,
332                                          const String * quality )
333 {
334     return join_results_print( self,
335                                dst_id,
336                                fmt_fastq_v2_syn_name_frag_nr,
337                                /* READ... */
338                                self -> accession_short, row_id, read_id,
339                                row_id,
340                                read1 -> len + read2 -> len, read1, read2,
341                                /* QUALITY... */
342                                self -> accession_short, row_id, read_id,
343                                row_id,
344                                quality -> len, quality );
345 }
346 
347 static const char * fmt_fastq_v2_real_name_no_frag_nr = "@%s.%ld %S length=%u\n%S%S\n+%s.%ld %S length=%u\n%S\n";
348 static const char * fmt_fastq_v2_empty_name_no_frag_nr = "@%s.%ld length=%u\n%S%S\n+%s.%ld length=%u\n%S\n";
print_v2_real_name_no_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)349 static rc_t print_v2_real_name_no_frag_nr( join_results * self,
350                                          int64_t row_id,
351                                          uint32_t dst_id,
352                                          uint32_t read_id,
353                                          const String * name,
354                                          const String * read1,
355                                          const String * read2,
356                                          const String * quality )
357 {
358     if ( name -> len > 0 )
359     {
360         return join_results_print( self,
361                                    dst_id,
362                                    fmt_fastq_v2_real_name_no_frag_nr,
363                                    /* READ... */
364                                    self -> accession_short, row_id,
365                                    name,
366                                    read1 -> len + read2 -> len, read1, read2,
367                                    /* QUALITY... */
368                                    self -> accession_short, row_id,
369                                    name,
370                                    quality -> len, quality );
371     }
372 
373     return join_results_print( self,
374                                dst_id,
375                                fmt_fastq_v2_empty_name_no_frag_nr,
376                                /* READ... */
377                                self -> accession_short, row_id,
378                                read1 -> len + read2 -> len, read1, read2,
379                                /* QUALITY... */
380                                self -> accession_short, row_id,
381                                quality -> len, quality );
382 }
383 
384 static const char * fmt_fastq_v2_real_name_frag_nr  = "@%s.%ld/%u %S length=%u\n%S%S\n+%s.%ld/%u %S length=%u\n%S\n";
385 static const char * fmt_fastq_v2_empty_name_frag_nr = "@%s.%ld/%u length=%u\n%S%S\n+%s.%ld/%u length=%u\n%S\n";
print_v2_real_name_frag_nr(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)386 static rc_t print_v2_real_name_frag_nr( join_results * self,
387                                          int64_t row_id,
388                                          uint32_t dst_id,
389                                          uint32_t read_id,
390                                          const String * name,
391                                          const String * read1,
392                                          const String * read2,
393                                          const String * quality )
394 {
395     if ( name -> len > 0 )
396     {
397         return join_results_print( self,
398                                    dst_id,
399                                    fmt_fastq_v2_real_name_frag_nr,
400                                    /* READ... */
401                                    self -> accession_short, row_id, read_id,
402                                    name,
403                                    read1 -> len + read2 -> len, read1, read2,
404                                    /* QUALITY... */
405                                    self -> accession_short, row_id, read_id,
406                                    name,
407                                    quality -> len, quality );
408     }
409 
410     return join_results_print( self,
411                                dst_id,
412                                fmt_fastq_v2_empty_name_frag_nr,
413                                /* READ... */
414                                self -> accession_short, row_id, read_id,
415                                read1 -> len + read2 -> len, read1, read2,
416                                /* QUALITY... */
417                                self -> accession_short, row_id, read_id,
418                                quality -> len, quality );
419 }
420 
make_join_results(struct KDirectory * dir,join_results ** results,struct temp_registry * registry,const char * output_base,const char * accession_short,size_t file_buffer_size,size_t print_buffer_size,bool print_frag_nr,bool print_name,const char * filter_bases)421 rc_t make_join_results( struct KDirectory * dir,
422                         join_results ** results,
423                         struct temp_registry * registry,
424                         const char * output_base,
425                         const char * accession_short,
426                         size_t file_buffer_size,
427                         size_t print_buffer_size,
428                         bool print_frag_nr,
429                         bool print_name,
430                         const char * filter_bases )
431 {
432     rc_t rc = 0;
433     struct Buf2NA * buf2na = NULL;
434     if ( filter_bases != NULL )
435     {
436         rc = make_Buf2NA( &buf2na, 512, filter_bases );
437         if ( 0 != rc )
438         {
439             ErrMsg( "make_join_results().error creating nucstrstr-filter from ( %s ) -> %R", filter_bases, rc );
440         }
441     }
442     if ( rc == 0 )
443     {
444         join_results * p = calloc( 1, sizeof * p );
445         *results = NULL;
446         if ( NULL == p )
447         {
448             rc = RC( rcVDB, rcNoTarg, rcConstructing, rcMemory, rcExhausted );
449             ErrMsg( "make_join_results().calloc( %d ) -> %R", ( sizeof * p ), rc );
450         }
451         else
452         {
453             p -> dir = dir;
454             p -> output_base = output_base;
455             p -> accession_short = accession_short;
456             p -> buffer_size = file_buffer_size;
457             p -> registry = registry;
458             p -> print_frag_nr = print_frag_nr;
459             p -> print_name = print_name;
460             p -> buf2na = buf2na;
461 
462             /* available:
463                 print_v1_no_name_no_frag_nr()       print_v2_no_name_no_frag_nr()
464                 print_v1_no_name_frag_nr()          print_v2_no_name_frag_nr()
465                 print_v1_syn_name_no_frag_nr()      print_v2_syn_name_no_frag_nr()
466                 print_v1_syn_name_frag_nr()         print_v2_syn_name_frag_nr()
467                 print_v1_real_name_no_frag_nr()     print_v2_real_name_no_frag_nr()
468                 print_v1_real_name_frag_nr()        print_v2_real_name_frag_nr()
469             */
470             if ( print_frag_nr )
471             {
472                 if ( print_name )
473                 {
474                     p -> v1_print_name_null     = print_v1_syn_name_frag_nr;
475                     p -> v1_print_name_not_null = print_v1_real_name_frag_nr;
476                     p -> v2_print_name_null     = print_v2_syn_name_frag_nr;
477                     p -> v2_print_name_not_null = print_v2_real_name_frag_nr;
478                 }
479                 else
480                 {
481                     p -> v1_print_name_null     = print_v1_no_name_frag_nr;
482                     p -> v1_print_name_not_null = print_v1_no_name_frag_nr;
483                     p -> v2_print_name_null     = print_v2_no_name_frag_nr;
484                     p -> v2_print_name_not_null = print_v2_no_name_frag_nr;
485                 }
486             }
487             else
488             {
489                 if ( print_name )
490                 {
491                     p -> v1_print_name_null     = print_v1_syn_name_no_frag_nr;
492                     p -> v1_print_name_not_null = print_v1_real_name_no_frag_nr;
493                     p -> v2_print_name_null     = print_v2_syn_name_no_frag_nr;
494                     p -> v2_print_name_not_null = print_v2_real_name_no_frag_nr;
495                 }
496                 else
497                 {
498                     p -> v1_print_name_null     = print_v1_no_name_no_frag_nr;
499                     p -> v1_print_name_not_null = print_v1_no_name_no_frag_nr;
500                     p -> v2_print_name_null     = print_v2_no_name_no_frag_nr;
501                     p -> v2_print_name_not_null = print_v2_no_name_no_frag_nr;
502                 }
503             }
504 
505             rc = make_SBuffer( &( p -> print_buffer ), print_buffer_size ); /* helper.c */
506             if ( 0 == rc )
507             {
508                 VectorInit ( &p -> printers, 0, 4 );
509                 *results = p;
510             }
511         }
512     }
513     if ( 0 != rc && NULL != buf2na )
514     {
515         release_Buf2NA( buf2na );
516     }
517     return rc;
518 }
519 
join_results_match(join_results * self,const String * bases)520 bool join_results_match( join_results * self, const String * bases )
521 {
522     bool res = true;
523     if ( NULL != self && NULL != bases && NULL != self -> buf2na )
524     {
525         res = match_Buf2NA( self -> buf2na, bases ); /* helper.c */
526     }
527     return res;
528 }
529 
join_results_match2(struct join_results * self,const String * bases1,const String * bases2)530 bool join_results_match2( struct join_results * self, const String * bases1, const String * bases2 )
531 {
532     bool res = true;
533     if ( NULL != self && NULL != bases1 && NULL != bases2 && NULL != self -> buf2na )
534     {
535         res = ( match_Buf2NA( self -> buf2na, bases1 ) || match_Buf2NA( self -> buf2na, bases2 ) ); /* helper.c */
536     }
537     return res;
538 }
539 
make_join_printer(join_results * self,uint32_t read_id,join_printer ** printer)540 static rc_t make_join_printer( join_results * self, uint32_t read_id, join_printer ** printer )
541 {
542     char filename[ 4096 ];
543     size_t num_writ;
544 
545     rc_t rc = string_printf( filename, sizeof filename, &num_writ, "%s.%u", self -> output_base, read_id );
546     *printer = NULL;
547     if ( 0 != rc )
548     {
549         ErrMsg( "make_join_printer().string_vprintf() -> %R", rc );
550     }
551     else
552     {
553         struct KFile * f;
554         rc = KDirectoryCreateFile( self -> dir, &f, false, 0664, kcmInit, "%s", filename );
555         if ( 0 != rc )
556         {
557             ErrMsg( "make_join_printer().KDirectoryVCreateFile() -> %R", rc );
558         }
559         else
560         {
561             if ( self -> buffer_size > 0 )
562             {
563                 struct KFile * temp_file = f;
564                 rc = KBufFileMakeWrite( &temp_file, f, false, self -> buffer_size );
565                 if ( 0 != rc )
566                 {
567                     ErrMsg( "make_join_printer().KBufFileMakeWrite() -> %R", rc );
568                 }
569                 {
570                     rc_t rc2 = KFileRelease( f );
571                     if ( 0 != rc2 )
572                     {
573                         ErrMsg( "make_join_printer().KFileRelease().1 -> %R", rc2 );
574                         rc = ( 0 == rc ) ? rc2 : rc;
575                     }
576                 }
577                 f = temp_file;
578             }
579             if ( 0 == rc )
580             {
581                 join_printer * p = calloc( 1, sizeof * p );
582                 if ( NULL == p )
583                 {
584                     rc = RC( rcVDB, rcNoTarg, rcConstructing, rcMemory, rcExhausted );
585                     ErrMsg( "make_join_printer().calloc( %d ) -> %R", ( sizeof * p ), rc );
586                     {
587                         rc_t rc2 = KFileRelease( f );
588                         if ( 0 != rc2 )
589                         {
590                             ErrMsg( "make_join_printer().KFileRelease().2 -> %R", rc2 );
591                         }
592                     }
593                 }
594                 else
595                 {
596                     rc = register_temp_file( self -> registry, read_id, filename );
597                     if ( rc != 0 )
598                     {
599                         free( p );
600                         {
601                             rc_t rc2 = KFileRelease( f );
602                             if ( 0 != rc2 )
603                             {
604                                 ErrMsg( "make_join_printer().KFileRelease().3 -> %R", rc2 );
605                             }
606                         }
607                     }
608                     else
609                     {
610                         p -> f = f;
611                         *printer = p;
612                     }
613                 }
614             }
615         }
616     }
617     return rc;
618 }
619 
join_results_print(struct join_results * self,uint32_t read_id,const char * fmt,...)620 rc_t join_results_print( struct join_results * self, uint32_t read_id, const char * fmt, ... )
621 {
622     rc_t rc = 0;
623     if ( NULL == self )
624     {
625         rc = RC( rcVDB, rcNoTarg, rcWriting, rcSelf, rcNull );
626         ErrMsg( "join_results_print() -> %R", rc );
627     }
628     else if ( NULL == fmt )
629     {
630         rc = RC( rcVDB, rcNoTarg, rcWriting, rcParam, rcNull );
631         ErrMsg( "join_results_print() -> %R", rc );
632     }
633     else
634     {
635         join_printer * p = VectorGet ( &self -> printers, read_id );
636         if ( NULL == p )
637         {
638             rc = make_join_printer( self, read_id, &p );
639             if ( 0 == rc )
640             {
641                 rc = VectorSet ( &self -> printers, read_id, p );
642                 if ( 0 != rc )
643                 {
644                     destroy_join_printer( p, NULL );
645                 }
646             }
647         }
648 
649         if ( 0 == rc && NULL != p )
650         {
651             bool done = false;
652             uint32_t cnt = 4;
653 
654             while ( 0 == rc && !done && cnt-- > 0 )
655             {
656                 va_list args;
657                 va_start ( args, fmt );
658                 rc = print_to_SBufferV( & self -> print_buffer, fmt, args );
659                 /* do not print failed rc, because it is used to increase the buffer */
660                 va_end ( args );
661 
662                 done = ( 0 == rc );
663                 if ( !done )
664                 {
665                     rc = try_to_enlarge_SBuffer( & self -> print_buffer, rc );
666                 }
667             }
668 
669             if ( 0 != rc )
670             {
671                 ErrMsg( "join_results_print().failed to enlarge buffer -> %R", rc );
672             }
673             else
674             {
675                 size_t num_writ, to_write;
676                 to_write = self -> print_buffer . S . size;
677                 const char * src = self -> print_buffer . S . addr;
678                 rc = KFileWriteAll( p -> f, p -> file_pos, src, to_write, &num_writ );
679                 if ( 0 != rc )
680                 {
681                     ErrMsg( "join_results_print().KFileWriteAll( at %lu ) -> %R", p -> file_pos, rc );
682                 }
683                 else if ( num_writ != to_write )
684                 {
685                     rc = RC( rcVDB, rcNoTarg, rcWriting, rcFormat, rcInvalid );
686                     ErrMsg( "join_results_print().KFileWriteAll( at %lu ) ( %d vs %d ) -> %R", p -> file_pos, to_write, num_writ, rc );
687                 }
688                 else
689                 {
690                     p -> file_pos += num_writ;
691                 }
692             }
693         }
694     }
695     return rc;
696 }
697 
join_results_print_fastq_v1(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read,const String * quality)698 rc_t join_results_print_fastq_v1( join_results * self,
699                                   int64_t row_id,
700                                   uint32_t dst_id,
701                                   uint32_t read_id,
702                                   const String * name,
703                                   const String * read,
704                                   const String * quality )
705 {
706     if ( NULL == name )
707     {
708         return self -> v1_print_name_null( self, row_id, dst_id, read_id, name, read, quality );
709     }
710     return self -> v1_print_name_not_null( self, row_id, dst_id, read_id, name, read, quality );
711 }
712 
join_results_print_fastq_v2(join_results * self,int64_t row_id,uint32_t dst_id,uint32_t read_id,const String * name,const String * read1,const String * read2,const String * quality)713 rc_t join_results_print_fastq_v2( join_results * self,
714                                   int64_t row_id,
715                                   uint32_t dst_id,
716                                   uint32_t read_id,
717                                   const String * name,
718                                   const String * read1,
719                                   const String * read2,
720                                   const String * quality )
721 {
722     if ( NULL == name )
723     {
724         return self -> v2_print_name_null( self, row_id, dst_id, read_id, name, read1, read2, quality );
725     }
726     return self -> v2_print_name_not_null( self, row_id, dst_id, read_id, name, read1, read2, quality );
727 }
728