1 /*  $Id: psgs_request.cpp 629837 2021-04-22 12:47:49Z ivanov $
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  */
31 #include <ncbi_pch.hpp>
32 
33 #include <corelib/ncbistr.hpp>
34 
35 #include "psgs_request.hpp"
36 
37 USING_NCBI_SCOPE;
38 
39 static atomic<bool>     s_RequestIdLock(false);
40 static size_t           s_NextRequestId = 0;
41 
42 
GetNextRequestId(void)43 size_t  GetNextRequestId(void)
44 {
45     while (s_RequestIdLock.exchange(true)) {}   // acquire lock
46     auto request_id = ++s_NextRequestId;
47     s_RequestIdLock = false;                    // release lock
48     return request_id;
49 }
50 
51 
CPSGS_Request()52 CPSGS_Request::CPSGS_Request() :
53     m_RequestId(0)
54 {}
55 
56 
CPSGS_Request(unique_ptr<SPSGS_RequestBase> req,CRef<CRequestContext> request_context)57 CPSGS_Request::CPSGS_Request(unique_ptr<SPSGS_RequestBase> req,
58                              CRef<CRequestContext>  request_context) :
59     m_Request(move(req)),
60     m_RequestContext(request_context),
61     m_RequestId(GetNextRequestId())
62 {}
63 
64 
GetRequestType(void) const65 CPSGS_Request::EPSGS_Type  CPSGS_Request::GetRequestType(void) const
66 {
67     if (m_Request)
68         return m_Request->GetRequestType();
69     return ePSGS_UnknownRequest;
70 }
71 
72 
73 // Provides the original request context
GetRequestContext(void)74 CRef<CRequestContext>  CPSGS_Request::GetRequestContext(void)
75 {
76     return m_RequestContext;
77 }
78 
79 
80 // Sets the cloned request context so that many threads can produce messages
SetRequestContext(void)81 void CPSGS_Request::SetRequestContext(void)
82 {
83     if (m_RequestContext.NotNull()) {
84         CDiagContext::SetRequestContext(m_RequestContext->Clone());
85         CDiagContext::GetRequestContext().SetReadOnly(false);
86     }
87 }
88 
89 
GetStartTimestamp(void) const90 TPSGS_HighResolutionTimePoint CPSGS_Request::GetStartTimestamp(void) const
91 {
92     if (m_Request)
93         return m_Request->GetStartTimestamp();
94 
95     NCBI_THROW(CPubseqGatewayException, eLogic,
96                "User request is not initialized");
97 }
98 
99 
NeedTrace(void)100 bool CPSGS_Request::NeedTrace(void)
101 {
102     if (m_Request)
103         return m_Request->GetTrace() == SPSGS_RequestBase::ePSGS_WithTracing;
104 
105     NCBI_THROW(CPubseqGatewayException, eLogic,
106                "User request is not initialized");
107 }
108 
109 
GetName(void) const110 string CPSGS_Request::GetName(void) const
111 {
112     if (m_Request)
113         return m_Request->GetName();
114     return "unknown (request is not initialized)";
115 }
116 
117 
Serialize(void) const118 CJsonNode CPSGS_Request::Serialize(void) const
119 {
120     if (m_Request)
121         return m_Request->Serialize();
122 
123     CJsonNode       json(CJsonNode::NewObjectNode());
124     json.SetString("name", GetName());
125     return json;
126 }
127 
128 
x_RequestTypeToString(EPSGS_Type type) const129 string CPSGS_Request::x_RequestTypeToString(EPSGS_Type  type) const
130 {
131     switch (type) {
132         case ePSGS_ResolveRequest:
133             return "ResolveRequest";
134         case ePSGS_BlobBySeqIdRequest:
135             return "BlobBySeqIdRequest";
136         case ePSGS_BlobBySatSatKeyRequest:
137             return "BlobBySatSatKeyRequest";
138         case ePSGS_AnnotationRequest:
139             return "AnnotationRequest";
140         case ePSGS_TSEChunkRequest:
141             return "TSEChunkRequest";
142         case ePSGS_UnknownRequest:
143             return "UnknownRequest";
144         default:
145             break;
146     }
147     return "???";
148 }
149 
150 
Serialize(void) const151 CJsonNode SPSGS_ResolveRequest::Serialize(void) const
152 {
153     CJsonNode       json(CJsonNode::NewObjectNode());
154 
155     json.SetString("name", GetName());
156     json.SetString("seq id", m_SeqId);
157     json.SetInteger("seq id type", m_SeqIdType);
158     json.SetBoolean("trace", m_Trace);
159     json.SetInteger("include data flags", m_IncludeDataFlags);
160     json.SetInteger("output format", m_OutputFormat);
161     json.SetBoolean("use cache", m_UseCache);
162     json.SetInteger("subst option", m_AccSubstOption);
163     return json;
164 }
165 
166 
Serialize(void) const167 CJsonNode SPSGS_BlobBySeqIdRequest::Serialize(void) const
168 {
169     CJsonNode       json(CJsonNode::NewObjectNode());
170 
171     json.SetString("name", GetName());
172     json.SetString("seq id", m_SeqId);
173     json.SetInteger("seq id type", m_SeqIdType);
174     json.SetInteger("tse option", m_TSEOption);
175     json.SetBoolean("use cache", m_UseCache);
176     json.SetString("client id", m_ClientId);
177     json.SetBoolean("trace", m_Trace);
178     json.SetInteger("subst option", m_AccSubstOption);
179 
180     CJsonNode   exclude_blobs(CJsonNode::NewArrayNode());
181     for (const auto &  blob_id : m_ExcludeBlobs) {
182         exclude_blobs.AppendString(blob_id);
183     }
184     json.SetByKey("exclude blobs", exclude_blobs);
185 
186     return json;
187 }
188 
189 
Serialize(void) const190 CJsonNode SPSGS_BlobBySatSatKeyRequest::Serialize(void) const
191 {
192     CJsonNode       json(CJsonNode::NewObjectNode());
193 
194     json.SetString("name", GetName());
195     json.SetString("blob id", m_BlobId.GetId());
196     json.SetInteger("tse option", m_TSEOption);
197     json.SetBoolean("use cache", m_UseCache);
198     json.SetString("client id", m_ClientId);
199     json.SetBoolean("trace", m_Trace);
200     json.SetInteger("last modified", m_LastModified);
201     return json;
202 }
203 
204 
Serialize(void) const205 CJsonNode SPSGS_AnnotRequest::Serialize(void) const
206 {
207     CJsonNode       json(CJsonNode::NewObjectNode());
208 
209     json.SetString("name", GetName());
210     json.SetString("seq id", m_SeqId);
211     json.SetInteger("seq id type", m_SeqIdType);
212     json.SetBoolean("trace", m_Trace);
213     json.SetBoolean("use cache", m_UseCache);
214     json.SetInteger("tse option", m_TSEOption);
215 
216     CJsonNode   names(CJsonNode::NewArrayNode());
217     for (const auto &  name : m_Names) {
218         names.AppendString(name);
219     }
220     json.SetByKey("names", names);
221 
222     return json;
223 }
224 
225 
226 // If the name has already been processed then it returns a priority of
227 // the processor which did it.
228 // If the name is new to the list then returns kUnknownPriority
229 // The highest priority will be stored together with the name.
230 TProcessorPriority
RegisterProcessedName(TProcessorPriority priority,const string & name)231 SPSGS_AnnotRequest::RegisterProcessedName(TProcessorPriority  priority,
232                                           const string &  name)
233 {
234     TProcessorPriority      ret = kUnknownPriority;
235 
236     while (m_Lock.exchange(true)) {}        // acquire lock
237 
238     for (auto &  item : m_Processed) {
239         if (item.second == name) {
240             ret = item.first;
241             item.first = max(item.first, priority);
242             break;
243         }
244     }
245 
246     if (ret == kUnknownPriority) {
247         // Not found => add
248         m_Processed.push_back(make_pair(priority, name));
249     }
250 
251     m_Lock = false;                         // release lock
252     return ret;
253 }
254 
255 
256 TProcessorPriority
RegisterBioseqInfo(TProcessorPriority priority)257 SPSGS_AnnotRequest::RegisterBioseqInfo(TProcessorPriority  priority)
258 {
259     while (m_Lock.exchange(true)) {}        // acquire lock
260     TProcessorPriority      ret = m_ProcessedBioseqInfo;
261     m_ProcessedBioseqInfo = max(m_ProcessedBioseqInfo, priority);
262     m_Lock = false;                         // release lock
263     return ret;
264 }
265 
266 
267 // The names could be processed by the other processors which priority is
268 // higher (or equal) than the given. Those names should not be provided.
269 vector<string>
GetNotProcessedName(TProcessorPriority priority)270 SPSGS_AnnotRequest::GetNotProcessedName(TProcessorPriority  priority)
271 {
272     vector<string>      ret = m_Names;
273 
274     while (m_Lock.exchange(true)) {}        // acquire lock
275     for (const auto &  item : m_Processed) {
276         if (item.first >= priority) {
277             auto    it = find(ret.begin(), ret.end(), item.second);
278             if (it != ret.end()) {
279                 ret.erase(it);
280             }
281         }
282     }
283     m_Lock = false;                         // release lock
284     return ret;
285 }
286 
287 
288 vector<pair<TProcessorPriority, string>>
GetProcessedNames(void) const289 SPSGS_AnnotRequest::GetProcessedNames(void) const
290 {
291     while (m_Lock.exchange(true)) {}        // acquire lock
292     auto    ret = m_Processed;
293     m_Lock = false;                         // release lock
294     return ret;
295 }
296 
297 
Serialize(void) const298 CJsonNode SPSGS_TSEChunkRequest::Serialize(void) const
299 {
300     CJsonNode       json(CJsonNode::NewObjectNode());
301 
302     json.SetString("name", GetName());
303     json.SetInteger("id2 chunk", m_Id2Chunk);
304     json.SetString("id2 info", m_Id2Info);
305     json.SetBoolean("use cache", m_UseCache);
306     json.SetBoolean("trace", m_Trace);
307     return json;
308 }
309 
310