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 
27 #include "sra-sort.h"
28 #include "db-pair.h"
29 #include "ctx.h"
30 #include "caps.h"
31 #include "mem.h"
32 #include "except.h"
33 #include "status.h"
34 
35 #include <sra/sraschema.h>
36 #include <vdb/manager.h>
37 #include <vdb/schema.h>
38 #include <vdb/database.h>
39 #include <vdb/table.h>
40 #include <kfg/config.h>
41 #include <klib/text.h>
42 #include <klib/rc.h>
43 
44 #include <string.h>
45 
46 
47 FILE_ENTRY ( run );
48 
49 static
typename_to_config_path(const char * in,char * out)50 void typename_to_config_path ( const char *in, char *out )
51 {
52     bool end;
53     uint32_t i;
54 
55     for ( end = false, i = 0; ! end; ++ i )
56     {
57         switch ( out [ i ] = in [ i ] )
58         {
59         case ':':
60             out [ i ] = '/';
61             break;
62         case ' ':
63         case '#':
64             out [ i ] = 0;
65         case 0:
66             end = true;
67             return;
68         }
69     }
70 }
71 
72 static
map_typename_builtin(const ctx_t * ctx,const char * sub_node,const char * in,char * out,char * schema_src,size_t size)73 bool map_typename_builtin ( const ctx_t *ctx, const char *sub_node, const char *in, char *out, char *schema_src, size_t size )
74 {
75     FUNC_ENTRY ( ctx );
76 
77     size_t copied;
78 
79 #define ALIGN_EVIDENCE_MAP "NCBI:align:db:alignment_evidence_sorted"
80 #define ALIGN_UNSORTED_MAP "NCBI:align:db:alignment_sorted"
81 #define ALIGN_SRC          "align/align.vschema"
82 
83     if ( strcmp ( out, "NCBI/align/db/alignment_evidence" ) == 0 )
84         copied = string_copy ( out, size, ALIGN_EVIDENCE_MAP, sizeof ALIGN_EVIDENCE_MAP - 1 );
85     else if ( strcmp ( out, "NCBI/align/db/alignment_unsorted" ) == 0 )
86         copied = string_copy ( out, size, ALIGN_UNSORTED_MAP, sizeof ALIGN_UNSORTED_MAP - 1 );
87     else
88     {
89         strcpy ( out, in );
90         schema_src [ 0 ] = 0;
91         return false;
92     }
93 
94     if ( copied != size )
95     {
96         out [ copied ] = 0;
97         copied = string_copy ( schema_src, size, ALIGN_SRC, sizeof ALIGN_SRC - 1 );
98     }
99 
100     if ( copied == size )
101     {
102         rc_t rc = RC ( rcExe, rcType, rcCopying, rcBuffer, rcInsufficient );
103         INTERNAL_ERROR ( rc, "failed to copy a built-in constant" );
104         strcpy ( out, in );
105         schema_src [ 0 ] = 0;
106         return false;
107     }
108 
109 #undef ALIGN_EVIDENCE_MAP
110 #undef ALIGN_UNSORTED_MAP
111 #undef ALIGN_SRC
112 
113     schema_src [ copied ] = 0;
114     return true;
115 }
116 
117 static
map_typename(const ctx_t * ctx,const char * sub_node,const char * in,char * out,char * schema_src,size_t size)118 bool map_typename ( const ctx_t *ctx, const char *sub_node, const char *in, char *out, char *schema_src, size_t size )
119 {
120     FUNC_ENTRY ( ctx );
121 
122     rc_t rc;
123     const KConfigNode *n;
124     size_t num_read, remaining;
125 
126     typename_to_config_path ( in, out );
127 
128     rc = KConfigOpenNodeRead ( ctx -> caps -> cfg, & n, "sra-sort/%s/%s", sub_node, out );
129     if ( rc != 0 )
130         return map_typename_builtin ( ctx, sub_node, in, out, schema_src, size );
131 
132     rc = KConfigNodeRead ( n, 0, out, size - 1, & num_read, & remaining );
133     if ( rc != 0 )
134         ERROR ( rc, "KConfigNodeRead failed" );
135     else if ( remaining != 0 )
136     {
137         rc = RC ( rcExe, rcNode, rcReading, rcBuffer, rcInsufficient );
138         ERROR ( rc, "type map of '%s' is too long", in );
139     }
140     else
141     {
142         out [ num_read ] = 0;
143         typename_to_config_path ( out, schema_src );
144 
145         KConfigNodeRelease ( n );
146         rc = KConfigOpenNodeRead ( ctx -> caps -> cfg, & n, "sra-sort/schema-src/%s", schema_src );
147         if ( rc != 0 )
148             ERROR ( rc, "KConfigOpenNodeRead - failed to find entry 'sra-sort/schema-src/%s'", schema_src );
149         else
150         {
151             rc = KConfigNodeRead ( n, 0, schema_src, size - 1, & num_read, & remaining );
152             if ( rc != 0 )
153                 ERROR ( rc, "KConfigNodeRead failed" );
154             else if ( remaining != 0 )
155             {
156                 rc = RC ( rcExe, rcNode, rcReading, rcBuffer, rcInsufficient );
157                 ERROR ( rc, "type map of '%s' is too long", in );
158             }
159             else
160             {
161                 schema_src [ num_read ] = 0;
162             }
163         }
164     }
165 
166     KConfigNodeRelease ( n );
167     return true;
168 }
169 
170 static
map_schema_types(TypeParams * type,const ctx_t * ctx,const VSchema * src_schema)171 VSchema *map_schema_types ( TypeParams *type, const ctx_t *ctx, const VSchema *src_schema )
172 {
173     FUNC_ENTRY ( ctx );
174 
175     bool mapped;
176     char schema_src [ 256 ];
177     assert ( sizeof schema_src == sizeof type -> dst_type );
178 
179     TRY ( mapped = map_typename ( ctx, "out-map", type -> src_type, type -> dst_type, schema_src, sizeof schema_src ) )
180     {
181         rc_t rc;
182         VSchema *dst_schema;
183 
184         if ( ! mapped )
185         {
186             type -> view_type [ 0 ] = 0;
187             rc = VSchemaAddRef ( src_schema );
188             if ( rc != 0 )
189                 ERROR ( rc, "VSchemaAddRef failed" );
190             return ( VSchema* ) src_schema;
191         }
192 
193         rc = VDBManagerMakeSchema ( ctx -> caps -> vdb, & dst_schema );
194         if ( rc != 0 )
195             ERROR ( rc, "VDBManagerMakeSchema failed" );
196         else
197         {
198             rc = VSchemaParseFile ( dst_schema, "%s", schema_src );
199             if ( rc != 0 )
200                 ERROR ( rc, "VSchemaParseFile failed adding file '%s' for destination", src_schema );
201             else
202             {
203                 TRY ( mapped = map_typename ( ctx, "view-map", type -> src_type, type -> view_type, schema_src, sizeof schema_src ) )
204                 {
205                     if ( ! mapped )
206                     {
207                         type -> view_type [ 0 ] = 0;
208                         return dst_schema;
209                     }
210 
211                     rc = VSchemaParseFile ( dst_schema, "%s", schema_src );
212                     if ( rc == 0 )
213                         return dst_schema;
214 
215                     ERROR ( rc, "VSchemaParseFile failed adding file '%s' for view", src_schema );
216                 }
217             }
218 
219             VSchemaRelease ( dst_schema );
220         }
221     }
222 
223     return NULL;
224 }
225 
226 /* open_db
227  *  called from run
228  *  determines the type of schema
229  *  opens output object
230  *  dispatches to the appropriate handler
231  */
232 static
open_db(const ctx_t * ctx,const VDatabase ** srcp)233 void open_db ( const ctx_t *ctx, const VDatabase **srcp )
234 {
235     FUNC_ENTRY ( ctx );
236 
237     const VDatabase *src = *srcp;
238 
239     const VSchema *src_schema;
240     rc_t rc = VDatabaseOpenSchema ( src, & src_schema );
241     if ( rc != 0 )
242         ERROR ( rc, "VDatabaseOpenSchema failed" );
243     else
244     {
245         TypeParams type;
246         rc = VDatabaseTypespec ( src, type . src_type, sizeof type . src_type );
247         if ( rc != 0 )
248             ERROR ( rc, "failed to obtain database typespec" );
249         else
250         {
251             VSchema *dst_schema;
252 
253             /* map input type to output type */
254             TRY ( dst_schema = map_schema_types ( & type, ctx, src_schema ) )
255             {
256                 const Tool *tp = ctx -> caps -> tool;
257 
258                 /* if view was remapped, reopen the database */
259                 if ( type . view_type [ 0 ] != 0 )
260                 {
261                     VSchemaRelease ( src_schema );
262                     rc = VSchemaAddRef ( dst_schema );
263                     if ( rc != 0 )
264                     {
265                         ERROR ( rc, "VSchemaAddRef failed" );
266                         src_schema = NULL;
267                     }
268                     else
269                     {
270                         src_schema = dst_schema;
271                         VDatabaseRelease ( src );
272                         rc = VDBManagerOpenDBRead ( ctx -> caps -> vdb, srcp, src_schema, "%s", tp -> src_path );
273                         if ( rc != 0 )
274                             ERROR ( rc, "VDBManagerOpenDBRead failed reopening db '%s'", tp -> src_path );
275                         src = *srcp;
276                     }
277                 }
278 
279                 if ( ! FAILED () )
280                 {
281                     VDatabase *dst;
282                     rc = VDBManagerCreateDB ( ctx -> caps -> vdb, & dst, dst_schema,
283                                               type . dst_type, tp -> db . cmode, "%s", tp -> dst_path );
284                     if ( rc != 0 )
285                         ERROR ( rc, "VDBManagerCreateDB failed to create '%s' with type '%s'", tp -> dst_path, type . dst_type );
286                     else
287                     {
288                         rc = VDatabaseColumnCreateParams ( dst, tp -> col . cmode, tp -> col . checksum, tp -> col . pgsize );
289                         if ( rc != 0 )
290                             ERROR ( rc, "VDatabaseColumnCreateParams: failed to set column create params on db '%s'", tp -> dst_path );
291                         else
292                         {
293                             DbPair *pb;
294 
295                             /* TBD - this has to be fixed to use proper stuff */
296                             const char *name = strrchr ( tp -> src_path, '/' );
297                             if ( name ++ == NULL )
298                                 name = tp -> src_path;
299 
300                             TRY ( pb = DbPairMake ( ctx, src, dst, name ) )
301                             {
302                                 DbPairRun ( pb, ctx );
303                                 DbPairRelease ( pb, ctx );
304                             }
305                         }
306 
307                         rc = VDatabaseRelease ( dst );
308                         if ( rc != 0 )
309                             ERROR ( rc, "VDatabaseRelease failed on '%s'", tp -> dst_path );
310                     }
311                 }
312 
313                 VSchemaRelease ( dst_schema );
314             }
315         }
316 
317         VSchemaRelease ( src_schema );
318     }
319 }
320 
321 
322 /* open_tbl
323  *  called from run
324  *  determines the type of schema
325  *  opens output object
326  *  dispatches to the appropriate handler
327  */
328 static
open_tbl(const ctx_t * ctx,const VTable ** tblp)329 void open_tbl ( const ctx_t *ctx, const VTable **tblp )
330 {
331     FUNC_ENTRY ( ctx );
332 
333     rc_t rc = RC ( rcExe, rcFunction, rcExecuting, rcFunction, rcUnsupported );
334     ERROR ( rc, "unimplemented function" );
335 }
336 
337 /* run
338  *  called from KMain
339  *  determines the type of object being copied/sorted
340  *  opens input object
341  *  dispatches to the appropriate handler
342  */
run(const ctx_t * ctx)343 void run ( const ctx_t *ctx )
344 {
345     FUNC_ENTRY ( ctx );
346 
347     VDBManager *mgr = ctx -> caps -> vdb;
348     const Tool *tp = ctx -> caps -> tool;
349 
350     const VDatabase *db;
351     rc_t rc = VDBManagerOpenDBRead ( mgr, & db, NULL, "%s", tp -> src_path );
352     if ( rc == 0 )
353     {
354         open_db ( ctx, & db );
355         VDatabaseRelease ( db );
356     }
357     else
358     {
359         const VTable *tbl;
360         rc_t rc2 = VDBManagerOpenTableRead ( mgr, & tbl, NULL, "%s", tp -> src_path );
361         if ( rc2 == 0 )
362         {
363             rc = 0;
364             open_tbl ( ctx, & tbl );
365             VTableRelease ( tbl );
366         }
367         else
368         {
369             VSchema *sra_dflt;
370             rc2 = VDBManagerMakeSRASchema ( mgr, & sra_dflt );
371             if ( rc2 == 0 )
372             {
373                 rc2 = VDBManagerOpenTableRead ( mgr, & tbl, sra_dflt, "%s", tp -> src_path );
374                 if ( rc2 == 0 )
375                 {
376                     rc = 0;
377                     open_tbl ( ctx, & tbl );
378                     VTableRelease ( tbl );
379                 }
380 
381                 VSchemaRelease ( sra_dflt );
382             }
383         }
384     }
385 
386     if ( rc != 0 )
387         ERROR ( rc, "failed to open object '%s'", tp -> src_path );
388 }
389