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