1 /*  $Id: blob_storage.cpp 617414 2020-09-30 19:55:02Z saprykin $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Sergey Satskiy
27  *
28  * File Description:
29  *
30  * The functionality not directly related to blob operations
31  *
32  */
33 
34 #include <ncbi_pch.hpp>
35 #include <objtools/pubseq_gateway/impl/cassandra/blob_storage.hpp>
36 
37 #define KEYSPACE_MAPPING_CONSISTENCY    CassConsistency::CASS_CONSISTENCY_LOCAL_QUORUM
38 #define KEYSPACE_MAPPING_RETRY          5
39 
40 BEGIN_IDBLOB_SCOPE
41 
42 
FetchSatToKeyspaceMapping(const string & mapping_keyspace,shared_ptr<CCassConnection> conn,vector<tuple<string,ECassSchemaType>> & mapping,string & resolver_keyspace,ECassSchemaType resolver_schema,string & err_msg)43 bool FetchSatToKeyspaceMapping(const string &  mapping_keyspace,
44                                shared_ptr<CCassConnection>  conn,
45                                vector<tuple<string, ECassSchemaType>> &  mapping,
46                                string &  resolver_keyspace,
47                                ECassSchemaType  resolver_schema,
48                                string &  err_msg)
49 {
50     resolver_keyspace.clear();
51     mapping.clear();
52 
53     if (mapping_keyspace.empty()) {
54         err_msg = "mapping_keyspace is not specified";
55         return false;
56     }
57 
58     bool rv = false;
59     err_msg = "sat2keyspace info is empty";
60 
61     for (int i = KEYSPACE_MAPPING_RETRY; i >= 0; --i) {
62         try {
63             shared_ptr<CCassQuery>  query = conn->NewQuery();
64 
65             query->SetSQL("SELECT\n"
66                           "    sat,\n"
67                           "    keyspace_name,\n"
68                           "    schema_type\n"
69                           "FROM\n"
70                           "    " + mapping_keyspace + ".sat2keyspace", 0);
71             query->Query(KEYSPACE_MAPPING_CONSISTENCY, false, false);
72 
73             rv = true;
74             while (query->NextRow() == ar_dataready) {
75                 int32_t     sat = query->FieldGetInt32Value(0);
76                 string      name = query->FieldGetStrValue(1);
77                 ECassSchemaType schema_type = static_cast<ECassSchemaType>(query->FieldGetInt32Value(2));
78 
79                 if (schema_type <= eUnknownSchema || schema_type > eMaxSchema) {
80                     // ignoring
81                 }
82                 else if (schema_type == resolver_schema) {
83                     if (resolver_keyspace.empty()) {
84                         resolver_keyspace = name;
85                     }
86                     else {
87                         // More than one resolver keyspace
88                         err_msg = "More than one resolver keyspace in the " +
89                                   mapping_keyspace + ".sat2keyspace table";
90                         rv = false;
91                         break;
92                     }
93                 }
94                 else if (sat >= 0) {
95                     while (static_cast<int32_t>(mapping.size()) <= sat)
96                         mapping.push_back(make_tuple("", eUnknownSchema));
97                     mapping[sat] = make_tuple(name, schema_type);
98                 }
99             }
100         }
101         catch (const CCassandraException& e) {
102             if ((e.GetErrCode() == CCassandraException::eQueryTimeout || e.GetErrCode() == CCassandraException::eQueryFailedRestartable) && i > 0) {
103                 continue;
104             }
105             throw;
106 
107         }
108         break;
109     }
110 
111     if (rv && mapping.empty()) {
112         err_msg = "sat2keyspace is incomplete";
113         rv = false;
114     }
115     if (rv && resolver_keyspace.empty() && resolver_schema != eUnknownSchema) {
116         err_msg = "resolver schema is not found in sat2keyspace";
117         rv = false;
118     }
119 
120     return rv;
121 }
122 
123 
FetchSatToKeyspaceMapping(const string & mapping_keyspace,shared_ptr<CCassConnection> conn,vector<string> & mapping,ECassSchemaType mapping_schema,string & resolver_keyspace,ECassSchemaType resolver_schema,vector<pair<string,int32_t>> & bioseq_na_keyspaces,ECassSchemaType bioseq_na_schema,string & err_msg)124 bool FetchSatToKeyspaceMapping(const string &  mapping_keyspace,
125                                shared_ptr<CCassConnection>  conn,
126                                vector<string> &  mapping,
127                                ECassSchemaType  mapping_schema,
128                                string &  resolver_keyspace,
129                                ECassSchemaType  resolver_schema,
130                                vector<pair<string, int32_t>> &  bioseq_na_keyspaces,
131                                ECassSchemaType  bioseq_na_schema,
132                                string &  err_msg)
133 {
134     vector<tuple<string, ECassSchemaType>> lmapping;
135     if (FetchSatToKeyspaceMapping(mapping_keyspace, conn, lmapping, resolver_keyspace, resolver_schema, err_msg)) {
136         for (size_t sat_id = 0; sat_id < lmapping.size(); ++sat_id) {
137             ECassSchemaType  schema = get<1>(lmapping[sat_id]);
138             mapping.push_back((schema == mapping_schema ||
139                                schema == bioseq_na_schema)? get<0>(lmapping[sat_id]) : "");
140 
141             if (schema == bioseq_na_schema)
142                 bioseq_na_keyspaces.push_back(
143                         pair<string, int32_t>(get<0>(lmapping[sat_id]), sat_id));
144         }
145         return true;
146     }
147     return false;
148 }
149 
FetchMessages(const string & mapping_keyspace,shared_ptr<CCassConnection> conn,CPSGMessages & messages,string & err_msg)150 bool FetchMessages(const string &  mapping_keyspace,
151                    shared_ptr<CCassConnection>  conn,
152                    CPSGMessages &  messages,
153                    string &  err_msg)
154 {
155     if (mapping_keyspace.empty()) {
156         err_msg = "mapping_keyspace is not specified";
157         return false;
158     }
159 
160     bool rv = false;
161     err_msg = mapping_keyspace + ".messages info is empty";
162     for (int i = KEYSPACE_MAPPING_RETRY; i >= 0; --i) {
163         try {
164             shared_ptr<CCassQuery>  query = conn->NewQuery();
165             query->SetSQL("SELECT name, value FROM " + mapping_keyspace + ".messages", 0);
166             query->Query(KEYSPACE_MAPPING_CONSISTENCY, false, false);
167             while (query->NextRow() == ar_dataready) {
168                 messages.Set(
169                     query->FieldGetStrValue(0),
170                     query->FieldGetStrValueDef(1, "")
171                 );
172                 err_msg.clear();
173             }
174             rv = true;
175             break;
176         }
177         catch (const CCassandraException& e) {
178             if (
179                 (e.GetErrCode() == CCassandraException::eQueryTimeout || e.GetErrCode() == CCassandraException::eQueryFailedRestartable)
180                 && i > 0
181             ) {
182                 continue;
183             }
184             throw;
185         }
186     }
187 
188     return rv;
189 }
190 
191 
192 END_IDBLOB_SCOPE
193