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 "row_by_row.h"
27 
28 #include <klib/log.h>
29 #include <klib/out.h>
30 #include <klib/num-gen.h>
31 #include <vdb/cursor.h>
32 #include <klib/progressbar.h>
33 
34 #include "coldefs.h"
35 #include "cmn.h"
36 
37 #include <sysalloc.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 rc_t Quitting( void );  /* because we cannot include <kapp/main.h> where it is defined! */
42 
rbr_diff_columns_iter(const col_defs * defs,const VCursor * cur_1,const VCursor * cur_2,const struct diff_ctx * dctx,const struct num_gen_iter * iter,unsigned long int * diffs)43 static rc_t rbr_diff_columns_iter( const col_defs * defs, const VCursor * cur_1, const VCursor * cur_2,
44                                    const struct diff_ctx * dctx, const struct num_gen_iter * iter,
45                                    unsigned long int *diffs )
46 {
47 	uint32_t column_count;
48 	rc_t rc = col_defs_count( defs, &column_count );
49 	if ( rc != 0 )
50 	{
51 		LOGERR ( klogInt, rc, "col_defs_count() failed" );
52 	}
53 	else
54 	{
55 		struct progressbar * progress = NULL;
56 		int64_t row_id;
57 		uint64_t rows_checked = 0;
58 		uint64_t rows_different = 0;
59 
60 		if ( dctx -> show_progress )
61 			make_progressbar( &progress, 2 );
62 
63 		while ( rc == 0 && num_gen_iterator_next( iter, &row_id, &rc ) && *diffs < dctx->max_err )
64 		{
65 			if ( rc == 0 ) rc = Quitting();    /* to be able to cancel the loop by signal */
66 			if ( rc == 0 )
67 			{
68 				bool row_equal = true;
69 
70 				uint32_t col_id;
71 				for ( col_id = 0; col_id < column_count && rc == 0; ++col_id )
72 				{
73 					col_pair * pair = VectorGet( &( defs -> cols ), col_id );
74 					if ( pair != NULL )
75 					{
76                         bool col_equal;
77                         rc = cmn_diff_column( pair, cur_1, cur_2, row_id,  &col_equal );
78                         if ( !col_equal )
79                         {
80                             row_equal = false;
81                             ( *diffs )++;
82                         }
83 					}
84 				} /* for ( col_id ... ) */
85 
86 				if ( !row_equal )
87 				{
88 					if ( rc == 0 )	rc = KOutMsg( "\n" );
89 					rows_different++;
90 				}
91 				rows_checked ++;
92 
93 				if ( progress != NULL )
94 				{
95 					uint32_t progress_value;
96 					if ( num_gen_iterator_percent( iter, 2, &progress_value ) == 0 )
97 						update_progressbar( progress, progress_value );
98 				}
99 
100 			} /* if (!Quitting) */
101 		} /* while ( num_gen_iterator_next() ) */
102 
103 		if ( rc == 0 )
104 			rc = KOutMsg( "\n%,lu rows checked ( %d columns each ), %,lu rows differ\n",
105 				rows_checked, column_count, rows_different );
106 
107 		if ( progress != NULL )
108 			destroy_progressbar( progress );
109 
110 	} /* if ( col_defs_count == 0 )*/
111 
112 	return rc;
113 }
114 
115 
rbr_diff_columns(col_defs * defs,const VTable * tab_1,const VTable * tab_2,const struct diff_ctx * dctx,unsigned long int * diffs)116 rc_t rbr_diff_columns( col_defs * defs, const VTable * tab_1, const VTable * tab_2,
117                        const struct diff_ctx * dctx, unsigned long int *diffs )
118 {
119 	const VCursor * cur_1;
120 	rc_t rc = VTableCreateCursorRead( tab_1, &cur_1 );
121 	if ( rc != 0 )
122 	{
123 		LOGERR ( klogInt, rc, "VTableCreateCursorRead( acc #1 ) failed" );
124 	}
125 	else
126 	{
127 		const VCursor * cur_2;
128 		rc = VTableCreateCursorRead( tab_2, &cur_2 );
129 		if ( rc != 0 )
130 		{
131 			LOGERR ( klogInt, rc, "VTableCreateCursorRead( acc #2 ) failed" );
132 		}
133 		else
134 		{
135 			rc = col_defs_add_to_cursor( defs, cur_1, 0 );
136 			if ( rc != 0 )
137 			{
138 				LOGERR ( klogInt, rc, "failed to add all requested columns to cursor of 1st accession" );
139 			}
140 			else
141 			{
142 				rc = col_defs_add_to_cursor( defs, cur_2, 1 );
143 				if ( rc != 0 )
144 				{
145 					LOGERR ( klogInt, rc, "failed to add all requested columns to cursor of 2nd accession" );
146 				}
147 				else
148 				{
149 					rc = VCursorOpen( cur_1 );
150 					if ( rc != 0 )
151 					{
152 						LOGERR ( klogInt, rc, "VCursorOpen( acc #1 ) failed" );
153 					}
154 					else
155 					{
156 						rc = VCursorOpen( cur_2 );
157 						if ( rc != 0 )
158 						{
159 							LOGERR ( klogInt, rc, "VCursorOpen( acc #2 ) failed" );
160 						}
161 						else
162 						{
163                             struct num_gen * rows_to_diff = NULL;
164                             rc = cmn_make_num_gen( cur_1, cur_2, 0, 0, dctx -> rows, &rows_to_diff );
165                             if ( rc == 0 && rows_to_diff != NULL )
166                             {
167                                 const struct num_gen_iter * iter = NULL;
168                                 rc = num_gen_iterator_make( rows_to_diff, &iter );
169                                 if ( rc != 0 )
170                                 {
171                                     LOGERR ( klogInt, rc, "num_gen_iterator_make() failed" );
172                                 }
173                                 else if ( iter != NULL )
174                                 {
175                                     /* *************************************************************** */
176                                     rc = rbr_diff_columns_iter( defs, cur_1, cur_2, dctx, iter, diffs );
177                                     /* *************************************************************** */
178                                     num_gen_iterator_destroy( iter );
179                                 }
180                                 num_gen_destroy( rows_to_diff );
181                             }
182 						}
183 					}
184 				}
185 			}
186 			VCursorRelease( cur_2 );
187 		}
188 		VCursorRelease( cur_1 );
189 	}
190 	return rc;
191 }
192