@@ -162,58 +162,6 @@ static int parse_footer(struct reftable_reader *r, uint8_t *footer,
162162 return err ;
163163}
164164
165- int init_reader (struct reftable_reader * r , struct reftable_block_source * source ,
166- const char * name )
167- {
168- struct reftable_block footer = { NULL };
169- struct reftable_block header = { NULL };
170- int err = 0 ;
171- uint64_t file_size = block_source_size (source );
172-
173- /* Need +1 to read type of first block. */
174- uint32_t read_size = header_size (2 ) + 1 ; /* read v2 because it's larger. */
175- memset (r , 0 , sizeof (struct reftable_reader ));
176-
177- if (read_size > file_size ) {
178- err = REFTABLE_FORMAT_ERROR ;
179- goto done ;
180- }
181-
182- err = block_source_read_block (source , & header , 0 , read_size );
183- if (err != read_size ) {
184- err = REFTABLE_IO_ERROR ;
185- goto done ;
186- }
187-
188- if (memcmp (header .data , "REFT" , 4 )) {
189- err = REFTABLE_FORMAT_ERROR ;
190- goto done ;
191- }
192- r -> version = header .data [4 ];
193- if (r -> version != 1 && r -> version != 2 ) {
194- err = REFTABLE_FORMAT_ERROR ;
195- goto done ;
196- }
197-
198- r -> size = file_size - footer_size (r -> version );
199- r -> source = * source ;
200- r -> name = xstrdup (name );
201- r -> hash_id = 0 ;
202-
203- err = block_source_read_block (source , & footer , r -> size ,
204- footer_size (r -> version ));
205- if (err != footer_size (r -> version )) {
206- err = REFTABLE_IO_ERROR ;
207- goto done ;
208- }
209-
210- err = parse_footer (r , footer .data , header .data );
211- done :
212- reftable_block_done (& footer );
213- reftable_block_done (& header );
214- return err ;
215- }
216-
217165struct table_iter {
218166 struct reftable_reader * r ;
219167 uint8_t typ ;
@@ -227,6 +175,7 @@ static int table_iter_init(struct table_iter *ti, struct reftable_reader *r)
227175{
228176 struct block_iter bi = BLOCK_ITER_INIT ;
229177 memset (ti , 0 , sizeof (* ti ));
178+ reftable_reader_incref (r );
230179 ti -> r = r ;
231180 ti -> bi = bi ;
232181 return 0 ;
@@ -314,6 +263,7 @@ static void table_iter_close(struct table_iter *ti)
314263{
315264 table_iter_block_done (ti );
316265 block_iter_close (& ti -> bi );
266+ reftable_reader_decref (ti -> r );
317267}
318268
319269static int table_iter_next_block (struct table_iter * ti )
@@ -631,31 +581,90 @@ void reftable_reader_init_log_iterator(struct reftable_reader *r,
631581 reader_init_iter (r , it , BLOCK_TYPE_LOG );
632582}
633583
634- void reader_close (struct reftable_reader * r )
584+ int reftable_reader_new (struct reftable_reader * * out ,
585+ struct reftable_block_source * source , char const * name )
635586{
636- block_source_close (& r -> source );
637- FREE_AND_NULL (r -> name );
638- }
587+ struct reftable_block footer = { 0 };
588+ struct reftable_block header = { 0 };
589+ struct reftable_reader * r ;
590+ uint64_t file_size = block_source_size (source );
591+ uint32_t read_size ;
592+ int err ;
639593
640- int reftable_new_reader (struct reftable_reader * * p ,
641- struct reftable_block_source * src , char const * name )
642- {
643- struct reftable_reader * rd = reftable_calloc (1 , sizeof (* rd ));
644- int err = init_reader (rd , src , name );
645- if (err == 0 ) {
646- * p = rd ;
647- } else {
648- block_source_close (src );
649- reftable_free (rd );
594+ REFTABLE_CALLOC_ARRAY (r , 1 );
595+
596+ /*
597+ * We need one extra byte to read the type of first block. We also
598+ * pretend to always be reading v2 of the format because it is larger.
599+ */
600+ read_size = header_size (2 ) + 1 ;
601+ if (read_size > file_size ) {
602+ err = REFTABLE_FORMAT_ERROR ;
603+ goto done ;
604+ }
605+
606+ err = block_source_read_block (source , & header , 0 , read_size );
607+ if (err != read_size ) {
608+ err = REFTABLE_IO_ERROR ;
609+ goto done ;
610+ }
611+
612+ if (memcmp (header .data , "REFT" , 4 )) {
613+ err = REFTABLE_FORMAT_ERROR ;
614+ goto done ;
615+ }
616+ r -> version = header .data [4 ];
617+ if (r -> version != 1 && r -> version != 2 ) {
618+ err = REFTABLE_FORMAT_ERROR ;
619+ goto done ;
620+ }
621+
622+ r -> size = file_size - footer_size (r -> version );
623+ r -> source = * source ;
624+ r -> name = xstrdup (name );
625+ r -> hash_id = 0 ;
626+ r -> refcount = 1 ;
627+
628+ err = block_source_read_block (source , & footer , r -> size ,
629+ footer_size (r -> version ));
630+ if (err != footer_size (r -> version )) {
631+ err = REFTABLE_IO_ERROR ;
632+ goto done ;
633+ }
634+
635+ err = parse_footer (r , footer .data , header .data );
636+ if (err )
637+ goto done ;
638+
639+ * out = r ;
640+
641+ done :
642+ reftable_block_done (& footer );
643+ reftable_block_done (& header );
644+ if (err ) {
645+ reftable_free (r );
646+ block_source_close (source );
650647 }
651648 return err ;
652649}
653650
654- void reftable_reader_free (struct reftable_reader * r )
651+ void reftable_reader_incref (struct reftable_reader * r )
652+ {
653+ if (!r -> refcount )
654+ BUG ("cannot increment ref counter of dead reader" );
655+ r -> refcount ++ ;
656+ }
657+
658+ void reftable_reader_decref (struct reftable_reader * r )
655659{
656660 if (!r )
657661 return ;
658- reader_close (r );
662+ if (!r -> refcount )
663+ BUG ("cannot decrement ref counter of dead reader" );
664+ if (-- r -> refcount )
665+ return ;
666+ block_source_close (& r -> source );
667+ FREE_AND_NULL (r -> name );
659668 reftable_free (r );
660669}
661670
@@ -786,7 +795,7 @@ int reftable_reader_print_blocks(const char *tablename)
786795 if (err < 0 )
787796 goto done ;
788797
789- err = reftable_new_reader (& r , & src , tablename );
798+ err = reftable_reader_new (& r , & src , tablename );
790799 if (err < 0 )
791800 goto done ;
792801
@@ -817,7 +826,7 @@ int reftable_reader_print_blocks(const char *tablename)
817826 }
818827
819828done :
820- reftable_reader_free (r );
829+ reftable_reader_decref (r );
821830 table_iter_close (& ti );
822831 return err ;
823832}
0 commit comments