1 /* $Id: pubseq_gateway_utils.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 #include <objects/seqloc/Seq_id.hpp>
35
36 #include "pubseq_gateway_utils.hpp"
37 #include "psgs_request.hpp"
38 #include "psgs_reply.hpp"
39
40 USING_NCBI_SCOPE;
41 USING_SCOPE(objects);
42
43
44 // see CXX-10728
45 // Need to replace the found accession with the seq_ids found accession
46 EPSGS_AccessionAdjustmentResult
AdjustAccession(shared_ptr<CPSGS_Request> request,shared_ptr<CPSGS_Reply> reply)47 SBioseqResolution::AdjustAccession(shared_ptr<CPSGS_Request> request,
48 shared_ptr<CPSGS_Reply> reply)
49 {
50 if (m_AdjustmentTried)
51 return m_AccessionAdjustmentResult;
52 m_AdjustmentTried = true;
53
54 if (m_ResolutionResult != ePSGS_BioseqDB && m_ResolutionResult != ePSGS_BioseqCache) {
55 m_AdjustmentError = "BIOSEQ_INFO accession adjustment logic error. The "
56 "data are not ready for adjustments.";
57 m_AccessionAdjustmentResult = ePSGS_LogicError;
58 return m_AccessionAdjustmentResult;
59 }
60
61 auto seq_id_type = m_BioseqInfo.GetSeqIdType();
62 if (m_BioseqInfo.GetVersion() > 0 && seq_id_type != CSeq_id::e_Gi) {
63 if (request->NeedTrace())
64 reply->SendTrace("No need to adjust accession",
65 request->GetStartTimestamp());
66
67 m_AccessionAdjustmentResult = ePSGS_NotRequired;
68 return m_AccessionAdjustmentResult;
69 }
70
71 auto & seq_ids = m_BioseqInfo.GetSeqIds();
72 for (const auto & seq_id : seq_ids) {
73 if (get<0>(seq_id) == CSeq_id::e_Gi) {
74 string orig_accession = m_BioseqInfo.GetAccession();
75 auto orig_seq_id_type = m_BioseqInfo.GetSeqIdType();
76
77 m_BioseqInfo.SetAccession(get<1>(seq_id));
78 m_BioseqInfo.SetSeqIdType(CSeq_id::e_Gi);
79
80 seq_ids.erase(seq_id);
81 if (orig_seq_id_type != CSeq_id::e_Gi)
82 seq_ids.insert(make_tuple(orig_seq_id_type, orig_accession));
83
84 if (request->NeedTrace())
85 reply->SendTrace("Accession adjusted with Gi",
86 request->GetStartTimestamp());
87
88 m_AccessionAdjustmentResult = ePSGS_AdjustedWithGi;
89 return m_AccessionAdjustmentResult;
90 }
91 }
92
93 if (seq_ids.empty()) {
94 m_AdjustmentError = "BIOSEQ_INFO data inconsistency. Accession " +
95 m_BioseqInfo.GetAccession() + " needs to be "
96 "adjusted but the seq_ids list is empty.";
97 m_AccessionAdjustmentResult = ePSGS_SeqIdsEmpty;
98 return m_AccessionAdjustmentResult;
99 }
100
101 // Adjusted with any
102 string orig_accession = m_BioseqInfo.GetAccession();
103 auto orig_seq_id_type = m_BioseqInfo.GetSeqIdType();
104
105 auto first_seq_id = seq_ids.begin();
106 m_BioseqInfo.SetAccession(get<1>(*first_seq_id));
107 m_BioseqInfo.SetSeqIdType(get<0>(*first_seq_id));
108
109 seq_ids.erase(*first_seq_id);
110 if (orig_seq_id_type != CSeq_id::e_Gi)
111 seq_ids.insert(make_tuple(orig_seq_id_type, orig_accession));
112
113 if (request->NeedTrace())
114 reply->SendTrace("Accession adjusted with type " +
115 to_string(m_BioseqInfo.GetSeqIdType()) +
116 " (first from the seq_ids list)",
117 request->GetStartTimestamp());
118
119 m_AccessionAdjustmentResult = ePSGS_AdjustedWithAny;
120 return m_AccessionAdjustmentResult;
121 }
122
123
124
125 static string s_ProtocolPrefix = "\n\nPSG-Reply-Chunk: ";
126
127 // Names
128 static string s_ItemId = "item_id=";
129 static string s_ItemType = "item_type=";
130 static string s_ChunkType = "chunk_type=";
131 static string s_Size = "size=";
132 static string s_BlobChunk = "blob_chunk=";
133 static string s_NChunks = "n_chunks=";
134 static string s_Status = "status=";
135 static string s_Code = "code=";
136 static string s_Severity = "severity=";
137 static string s_BlobId = "blob_id=";
138 static string s_Fmt = "fmt=";
139 static string s_NA = "na=";
140 static string s_Reason = "reason=";
141 static string s_NChunksOne = "n_chunks=1";
142 static string s_ProcessorId = "processor_id=";
143 static string s_Id2Chunk = "id2_chunk=";
144 static string s_Id2Info = "id2_info=";
145 static string s_LastModified = "last_modified=";
146
147 // Fixed values
148 static string s_BioseqInfo = "bioseq_info";
149 static string s_BlobProp = "blob_prop";
150 static string s_Data = "data";
151 static string s_Reply = "reply";
152 static string s_Blob = "blob";
153 static string s_Meta = "meta";
154 static string s_Message = "message";
155 static string s_Protobuf = "protobuf";
156 static string s_Json = "json";
157 static string s_BioseqNA = "bioseq_na";
158 static string s_Excluded = "excluded";
159 static string s_InProgress = "inprogress";
160 static string s_Sent = "sent";
161 static string s_Processor = "processor";
162 static string s_PublicComment = "public_comment";
163
164 // Combinations
165 static string s_AndSize = "&" + s_Size;
166 static string s_AndStatus = "&" + s_Status;
167 static string s_AndCode = "&" + s_Code;
168 static string s_AndSeverity = "&" + s_Severity;
169 static string s_AndNChunks = "&" + s_NChunks;
170 static string s_AndBlobId = "&" + s_BlobId;
171 static string s_AndBlobChunk = "&" + s_BlobChunk;
172 static string s_AndNChunksOne = "&" + s_NChunksOne;
173 static string s_AndReason = "&" + s_Reason;
174 static string s_AndNA = "&" + s_NA;
175 static string s_BioseqInfoItem = s_ItemType + s_BioseqInfo;
176 static string s_AndBioseqInfoItem = "&" + s_BioseqInfoItem;
177 static string s_BlobPropItem = s_ItemType + s_BlobProp;
178 static string s_AndBlobPropItem = "&" + s_BlobPropItem;
179 static string s_BioseqNAItem = s_ItemType + s_BioseqNA;
180 static string s_AndBioseqNAItem = "&" + s_BioseqNAItem;
181 static string s_BlobItem = s_ItemType + s_Blob;
182 static string s_AndBlobItem = "&" + s_BlobItem;
183 static string s_ReplyItem = s_ItemType + s_Reply;
184 static string s_AndReplyItem = "&" + s_ReplyItem;
185 static string s_ProcessorItem = s_ItemType + s_Processor;
186 static string s_PublicCommentItem = s_ItemType + s_PublicComment;
187 static string s_AndProcessorItem = "&" + s_ProcessorItem;
188 static string s_AndPublicCommentItem = "&" + s_PublicCommentItem;
189 static string s_AndProcessorId = "&" + s_ProcessorId;
190 static string s_AndId2Chunk = "&" + s_Id2Chunk;
191 static string s_AndId2Info = "&" + s_Id2Info;
192 static string s_AndLastModified = "&" + s_LastModified;
193
194 static string s_DataChunk = s_ChunkType + s_Data;
195 static string s_AndDataChunk = "&" + s_DataChunk;
196 static string s_MetaChunk = s_ChunkType + s_Meta;
197 static string s_AndMetaChunk = "&" + s_MetaChunk;
198 static string s_MessageChunk = s_ChunkType + s_Message;
199 static string s_AndMessageChunk = "&" + s_MessageChunk;
200 static string s_FmtJson = s_Fmt + s_Json;
201 static string s_AndFmtJson = "&" + s_FmtJson;
202 static string s_FmtProtobuf = s_Fmt + s_Protobuf;
203 static string s_AndFmtProtobuf = "&" + s_FmtProtobuf;
204
205 static string s_ReplyBegin = s_ProtocolPrefix + s_ItemId;
206 static string s_ReplyCompletionFixedPart = s_ReplyBegin + "0&" +
207 s_ReplyItem + "&" +
208 s_MetaChunk + "&" + s_NChunks;
209
210
SeverityToLowerString(EDiagSev severity)211 static string SeverityToLowerString(EDiagSev severity)
212 {
213 string severity_as_string = CNcbiDiag::SeverityName(severity);
214 NStr::ToLower(severity_as_string);
215 return severity_as_string;
216 }
217
218
SkipReasonToString(EPSGS_BlobSkipReason skip_reason)219 static string SkipReasonToString(EPSGS_BlobSkipReason skip_reason)
220 {
221 switch (skip_reason) {
222 case ePSGS_BlobExcluded:
223 return s_Excluded;
224 case ePSGS_BlobInProgress:
225 return s_InProgress;
226 case ePSGS_BlobSent:
227 return s_Sent;
228 }
229 return "UnknownSkipReason";
230 }
231
232
GetBioseqInfoHeader(size_t item_id,const string & processor_id,size_t bioseq_info_size,SPSGS_ResolveRequest::EPSGS_OutputFormat output_format)233 string GetBioseqInfoHeader(size_t item_id,
234 const string & processor_id,
235 size_t bioseq_info_size,
236 SPSGS_ResolveRequest::EPSGS_OutputFormat output_format)
237 {
238 // E.g. PSG-Reply-Chunk: item_id=1&processor_id=get+blob+proc&item_type=bioseq_info&chunk_type=data&size=450&fmt=protobuf
239 string reply(s_ReplyBegin);
240
241 reply.append(to_string(item_id))
242 .append(s_AndProcessorId)
243 .append(NStr::URLEncode(processor_id))
244 .append(s_AndBioseqInfoItem)
245 .append(s_AndDataChunk)
246 .append(s_AndSize)
247 .append(to_string(bioseq_info_size));
248 if (output_format == SPSGS_ResolveRequest::ePSGS_JsonFormat)
249 reply.append(s_AndFmtJson);
250 else
251 reply.append(s_AndFmtProtobuf);
252 return reply.append(1, '\n');
253 }
254
255
GetBioseqMessageHeader(size_t item_id,const string & processor_id,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)256 string GetBioseqMessageHeader(size_t item_id,
257 const string & processor_id,
258 size_t msg_size,
259 CRequestStatus::ECode status,
260 int code,
261 EDiagSev severity)
262 {
263 string reply(s_ReplyBegin);
264
265 return reply.append(to_string(item_id))
266 .append(s_AndProcessorId)
267 .append(NStr::URLEncode(processor_id))
268 .append(s_AndBioseqInfoItem)
269 .append(s_AndMessageChunk)
270 .append(s_AndSize)
271 .append(to_string(msg_size))
272 .append(s_AndStatus)
273 .append(to_string(static_cast<int>(status)))
274 .append(s_AndCode)
275 .append(to_string(code))
276 .append(s_AndSeverity)
277 .append(SeverityToLowerString(severity))
278 .append(1, '\n');
279 }
280
281
GetBioseqCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)282 string GetBioseqCompletionHeader(size_t item_id,
283 const string & processor_id,
284 size_t chunk_count)
285 {
286 // E.g. PSG-Reply-Chunk: item_id=1&processor_id=get+blob+proc&item_type=bioseq_info&chunk_type=meta&n_chunks=1
287 string reply(s_ReplyBegin);
288
289 return reply.append(to_string(item_id))
290 .append(s_AndProcessorId)
291 .append(NStr::URLEncode(processor_id))
292 .append(s_AndBioseqInfoItem)
293 .append(s_AndMetaChunk)
294 .append(s_AndNChunks)
295 .append(to_string(chunk_count))
296 .append(1, '\n');
297 }
298
299
GetBlobPropHeader(size_t item_id,const string & processor_id,const string & blob_id,size_t blob_prop_size,CBlobRecord::TTimestamp last_modified)300 string GetBlobPropHeader(size_t item_id,
301 const string & processor_id,
302 const string & blob_id,
303 size_t blob_prop_size,
304 CBlobRecord::TTimestamp last_modified)
305 {
306 string reply(s_ReplyBegin);
307
308 string last_modified_part;
309 if (last_modified != -1)
310 last_modified_part.append(s_AndLastModified)
311 .append(to_string(last_modified));
312
313 return reply.append(to_string(item_id))
314 .append(s_AndProcessorId)
315 .append(NStr::URLEncode(processor_id))
316 .append(s_AndBlobPropItem)
317 .append(s_AndDataChunk)
318 .append(s_AndSize)
319 .append(to_string(blob_prop_size))
320 .append(s_AndBlobId)
321 .append(blob_id)
322 .append(last_modified_part)
323 .append(1, '\n');
324 }
325
GetTSEBlobPropHeader(size_t item_id,const string & processor_id,int64_t id2_chunk,const string & id2_info,size_t blob_prop_size)326 string GetTSEBlobPropHeader(size_t item_id,
327 const string & processor_id,
328 int64_t id2_chunk,
329 const string & id2_info,
330 size_t blob_prop_size)
331 {
332 // E.g. PSG-Reply-Chunk: item_id=2&processor_id=get+blob+proc&item_type=blob_prop&chunk_type=data&size=550
333 string reply(s_ReplyBegin);
334
335 return reply.append(to_string(item_id))
336 .append(s_AndProcessorId)
337 .append(NStr::URLEncode(processor_id))
338 .append(s_AndBlobPropItem)
339 .append(s_AndDataChunk)
340 .append(s_AndSize)
341 .append(to_string(blob_prop_size))
342 .append(s_AndId2Chunk)
343 .append(to_string(id2_chunk))
344 .append(s_AndId2Info)
345 .append(id2_info)
346 .append(1, '\n');
347 }
348
349
GetBlobPropMessageHeader(size_t item_id,const string & processor_id,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)350 string GetBlobPropMessageHeader(size_t item_id,
351 const string & processor_id,
352 size_t msg_size,
353 CRequestStatus::ECode status,
354 int code,
355 EDiagSev severity)
356 {
357 string reply(s_ReplyBegin);
358
359 return reply.append(to_string(item_id))
360 .append(s_AndProcessorId)
361 .append(NStr::URLEncode(processor_id))
362 .append(s_AndBlobPropItem)
363 .append(s_AndMessageChunk)
364 .append(s_AndSize)
365 .append(to_string(msg_size))
366 .append(s_AndStatus)
367 .append(to_string(static_cast<int>(status)))
368 .append(s_AndCode)
369 .append(to_string(code))
370 .append(s_AndSeverity)
371 .append(SeverityToLowerString(severity))
372 .append(1, '\n');
373 }
374
375
GetTSEBlobPropMessageHeader(size_t item_id,const string & processor_id,int64_t id2_chunk,const string & id2_info,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)376 string GetTSEBlobPropMessageHeader(size_t item_id,
377 const string & processor_id,
378 int64_t id2_chunk,
379 const string & id2_info,
380 size_t msg_size,
381 CRequestStatus::ECode status,
382 int code,
383 EDiagSev severity)
384 {
385 string reply(s_ReplyBegin);
386
387 return reply.append(to_string(item_id))
388 .append(s_AndProcessorId)
389 .append(NStr::URLEncode(processor_id))
390 .append(s_AndId2Chunk)
391 .append(to_string(id2_chunk))
392 .append(s_AndId2Info)
393 .append(id2_info)
394 .append(s_AndBlobPropItem)
395 .append(s_AndMessageChunk)
396 .append(s_AndSize)
397 .append(to_string(msg_size))
398 .append(s_AndStatus)
399 .append(to_string(static_cast<int>(status)))
400 .append(s_AndCode)
401 .append(to_string(code))
402 .append(s_AndSeverity)
403 .append(SeverityToLowerString(severity))
404 .append(1, '\n');
405 }
406
GetBlobPropCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)407 string GetBlobPropCompletionHeader(size_t item_id,
408 const string & processor_id,
409 size_t chunk_count)
410 {
411 string reply(s_ReplyBegin);
412
413 return reply.append(to_string(item_id))
414 .append(s_AndProcessorId)
415 .append(NStr::URLEncode(processor_id))
416 .append(s_AndBlobPropItem)
417 .append(s_AndMetaChunk)
418 .append(s_AndNChunks)
419 .append(to_string(chunk_count))
420 .append(1, '\n');
421 }
422
423
GetTSEBlobPropCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)424 string GetTSEBlobPropCompletionHeader(size_t item_id,
425 const string & processor_id,
426 size_t chunk_count)
427 {
428 string reply(s_ReplyBegin);
429
430 return reply.append(to_string(item_id))
431 .append(s_AndProcessorId)
432 .append(NStr::URLEncode(processor_id))
433 .append(s_AndBlobPropItem)
434 .append(s_AndMetaChunk)
435 .append(s_AndNChunks)
436 .append(to_string(chunk_count))
437 .append(1, '\n');
438 }
439
440
GetBlobChunkHeader(size_t item_id,const string & processor_id,const string & blob_id,size_t chunk_size,size_t chunk_number,CBlobRecord::TTimestamp last_modified)441 string GetBlobChunkHeader(size_t item_id,
442 const string & processor_id,
443 const string & blob_id,
444 size_t chunk_size,
445 size_t chunk_number,
446 CBlobRecord::TTimestamp last_modified)
447 {
448 // E.g. PSG-Reply-Chunk: item_id=3&processor_id=get+blob+proc&item_type=blob&chunk_type=data&size=2345&blob_id=333.444&blob_chunk=37
449 string reply(s_ReplyBegin);
450
451 string last_modified_part;
452 if (last_modified != -1)
453 last_modified_part.append(s_AndLastModified)
454 .append(to_string(last_modified));
455
456 return reply.append(to_string(item_id))
457 .append(s_AndProcessorId)
458 .append(NStr::URLEncode(processor_id))
459 .append(s_AndBlobItem)
460 .append(s_AndDataChunk)
461 .append(s_AndSize)
462 .append(to_string(chunk_size))
463 .append(s_AndBlobId)
464 .append(blob_id)
465 .append(last_modified_part)
466 .append(s_AndBlobChunk)
467 .append(to_string(chunk_number))
468 .append(1, '\n');
469 }
470
471
GetTSEBlobChunkHeader(size_t item_id,const string & processor_id,size_t chunk_size,size_t chunk_number,int64_t id2_chunk,const string & id2_info)472 string GetTSEBlobChunkHeader(size_t item_id,
473 const string & processor_id,
474 size_t chunk_size,
475 size_t chunk_number,
476 int64_t id2_chunk,
477 const string & id2_info)
478 {
479 // E.g. PSG-Reply-Chunk:
480 // item_id=3&processor_id=get+blob+proc&item_type=blob&chunk_type=data&size=2345&id2_chunk=11&id2_info=33.44.55&blob_chunk=37
481 string reply(s_ReplyBegin);
482
483 return reply.append(to_string(item_id))
484 .append(s_AndProcessorId)
485 .append(NStr::URLEncode(processor_id))
486 .append(s_AndBlobItem)
487 .append(s_AndDataChunk)
488 .append(s_AndSize)
489 .append(to_string(chunk_size))
490 .append(s_AndBlobChunk)
491 .append(to_string(chunk_number))
492 .append(s_AndId2Chunk)
493 .append(to_string(id2_chunk))
494 .append(s_AndId2Info)
495 .append(id2_info)
496 .append(1, '\n');
497 }
498
499
GetBlobExcludeHeader(size_t item_id,const string & processor_id,const string & blob_id,EPSGS_BlobSkipReason skip_reason,CBlobRecord::TTimestamp last_modified)500 string GetBlobExcludeHeader(size_t item_id,
501 const string & processor_id,
502 const string & blob_id,
503 EPSGS_BlobSkipReason skip_reason,
504 CBlobRecord::TTimestamp last_modified)
505 {
506 // E.g. PSG-Reply-Chunk: item_id=5&processor_id=get+blob+proc&item_type=blob&chunk_type=meta&blob_id=555.666&n_chunks=1&reason={excluded,inprogress,sent}
507 string reply(s_ReplyBegin);
508
509 string last_modified_part;
510 if (last_modified != -1)
511 last_modified_part.append(s_AndLastModified)
512 .append(to_string(last_modified));
513
514 return reply.append(to_string(item_id))
515 .append(s_AndProcessorId)
516 .append(NStr::URLEncode(processor_id))
517 .append(s_AndBlobItem)
518 .append(s_AndMetaChunk)
519 .append(s_AndBlobId)
520 .append(blob_id)
521 .append(last_modified_part)
522 .append(s_AndNChunksOne)
523 .append(s_AndReason)
524 .append(SkipReasonToString(skip_reason))
525 .append(1, '\n');
526 }
527
528
GetTSEBlobExcludeHeader(size_t item_id,const string & processor_id,int64_t id2_chunk,const string & id2_info,EPSGS_BlobSkipReason skip_reason)529 string GetTSEBlobExcludeHeader(size_t item_id,
530 const string & processor_id,
531 int64_t id2_chunk,
532 const string & id2_info,
533 EPSGS_BlobSkipReason skip_reason)
534 {
535 string reply(s_ReplyBegin);
536
537 return reply.append(to_string(item_id))
538 .append(s_AndProcessorId)
539 .append(NStr::URLEncode(processor_id))
540 .append(s_AndId2Chunk)
541 .append(to_string(id2_chunk))
542 .append(s_AndId2Info)
543 .append(id2_info)
544 .append(s_AndBlobItem)
545 .append(s_AndMetaChunk)
546 .append(s_AndNChunksOne)
547 .append(s_AndReason)
548 .append(SkipReasonToString(skip_reason))
549 .append(1, '\n');
550 }
551
552
GetBlobCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)553 string GetBlobCompletionHeader(size_t item_id,
554 const string & processor_id,
555 size_t chunk_count)
556 {
557 // E.g. PSG-Reply-Chunk: item_id=4&processor_id=get+blob+proc&item_type=blob&chunk_type=meta&n_chunks=100
558 string reply(s_ReplyBegin);
559
560 return reply.append(to_string(item_id))
561 .append(s_AndProcessorId)
562 .append(NStr::URLEncode(processor_id))
563 .append(s_AndBlobItem)
564 .append(s_AndMetaChunk)
565 .append(s_AndNChunks)
566 .append(to_string(chunk_count))
567 .append(1, '\n');
568 }
569
570
GetTSEBlobCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)571 string GetTSEBlobCompletionHeader(size_t item_id,
572 const string & processor_id,
573 size_t chunk_count)
574 {
575 // E.g. PSG-Reply-Chunk:
576 // item_id=4&processor_id=get+blob+proc&item_type=blob&chunk_type=meta&n_chunks=100
577 string reply(s_ReplyBegin);
578
579 return reply.append(to_string(item_id))
580 .append(s_AndProcessorId)
581 .append(NStr::URLEncode(processor_id))
582 .append(s_AndBlobItem)
583 .append(s_AndMetaChunk)
584 .append(s_AndNChunks)
585 .append(to_string(chunk_count))
586 .append(1, '\n');
587
588 }
589
590
GetBlobMessageHeader(size_t item_id,const string & processor_id,const string & blob_id,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity,CBlobRecord::TTimestamp last_modified)591 string GetBlobMessageHeader(size_t item_id,
592 const string & processor_id,
593 const string & blob_id,
594 size_t msg_size,
595 CRequestStatus::ECode status,
596 int code,
597 EDiagSev severity,
598 CBlobRecord::TTimestamp last_modified)
599 {
600 // E.g. PSG-Reply-Chunk: item_id=3&processor_id=get+blob+proc&item_type=blob&chunk_type=message&size=22&blob_id=333.444&status=404&code=5&severity=critical
601 string reply(s_ReplyBegin);
602
603 string last_modified_part;
604 if (last_modified != -1)
605 last_modified_part.append(s_AndLastModified)
606 .append(to_string(last_modified));
607
608 return reply.append(to_string(item_id))
609 .append(s_AndProcessorId)
610 .append(NStr::URLEncode(processor_id))
611 .append(s_AndBlobItem)
612 .append(s_AndMessageChunk)
613 .append(s_AndSize)
614 .append(to_string(msg_size))
615 .append(s_AndBlobId)
616 .append(blob_id)
617 .append(last_modified_part)
618 .append(s_AndStatus)
619 .append(to_string(static_cast<int>(status)))
620 .append(s_AndCode)
621 .append(to_string(code))
622 .append(s_AndSeverity)
623 .append(SeverityToLowerString(severity))
624 .append(1, '\n');
625 }
626
627
GetTSEBlobMessageHeader(size_t item_id,const string & processor_id,int64_t id2_chunk,const string & id2_info,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)628 string GetTSEBlobMessageHeader(size_t item_id,
629 const string & processor_id,
630 int64_t id2_chunk,
631 const string & id2_info,
632 size_t msg_size,
633 CRequestStatus::ECode status,
634 int code,
635 EDiagSev severity)
636 {
637 string reply(s_ReplyBegin);
638
639 return reply.append(to_string(item_id))
640 .append(s_AndProcessorId)
641 .append(NStr::URLEncode(processor_id))
642 .append(s_AndBlobItem)
643 .append(s_AndMessageChunk)
644 .append(s_AndSize)
645 .append(to_string(msg_size))
646 .append(s_AndId2Chunk)
647 .append(to_string(id2_chunk))
648 .append(s_AndId2Info)
649 .append(id2_info)
650 .append(s_AndStatus)
651 .append(to_string(static_cast<int>(status)))
652 .append(s_AndCode)
653 .append(to_string(code))
654 .append(s_AndSeverity)
655 .append(SeverityToLowerString(severity))
656 .append(1, '\n');
657 }
658
659
GetReplyCompletionHeader(size_t chunk_count)660 string GetReplyCompletionHeader(size_t chunk_count)
661 {
662 // E.g. PSG-Reply-Chunk: item_id=0&item_type=reply&chunk_type=meta&n_chunks=153
663 string reply(s_ReplyCompletionFixedPart);
664
665 return reply.append(to_string(chunk_count))
666 .append(1, '\n');
667 }
668
669
GetReplyMessageHeader(size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)670 string GetReplyMessageHeader(size_t msg_size,
671 CRequestStatus::ECode status,
672 int code,
673 EDiagSev severity)
674 {
675 // E.g. PSG-Reply-Chunk: item_id=0&item_type=reply&chunk_type=message&size=22&status=404&code=5&severity=critical
676 string reply(s_ReplyBegin);
677
678 return reply.append(1, '0')
679 .append(s_AndReplyItem)
680 .append(s_AndMessageChunk)
681 .append(s_AndSize)
682 .append(to_string(msg_size))
683 .append(s_AndStatus)
684 .append(to_string(static_cast<int>(status)))
685 .append(s_AndCode)
686 .append(to_string(code))
687 .append(s_AndSeverity)
688 .append(SeverityToLowerString(severity))
689 .append(1, '\n');
690 }
691
692
GetNamedAnnotationHeader(size_t item_id,const string & processor_id,const string & annot_name,size_t annotation_size)693 string GetNamedAnnotationHeader(size_t item_id,
694 const string & processor_id,
695 const string & annot_name,
696 size_t annotation_size)
697 {
698 // E.g. PSG-Reply-Chunk: item_id=1&processor_id=get+blob+proc&item_type=bioseq_na&chunk_type=data&size=150&na=NA000111.1
699 string reply(s_ReplyBegin);
700
701 return reply.append(to_string(item_id))
702 .append(s_AndProcessorId)
703 .append(NStr::URLEncode(processor_id))
704 .append(s_AndBioseqNAItem)
705 .append(s_AndDataChunk)
706 .append(s_AndSize)
707 .append(to_string(annotation_size))
708 .append(s_AndNA)
709 .append(annot_name)
710 .append(1, '\n');
711 }
712
713
GetNamedAnnotationMessageHeader(size_t item_id,const string & processor_id,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)714 string GetNamedAnnotationMessageHeader(size_t item_id,
715 const string & processor_id,
716 size_t msg_size,
717 CRequestStatus::ECode status,
718 int code,
719 EDiagSev severity)
720 {
721 // E.g. PSG-Reply-Chunk: item_id=5&processor_id=get+blob+proc&item_type=reply&chunk_type=message&size=22&status=404&code=5&severity=critical
722
723 string reply(s_ReplyBegin);
724
725 return reply.append(to_string(item_id))
726 .append(s_AndProcessorId)
727 .append(NStr::URLEncode(processor_id))
728 .append(s_AndBioseqNAItem)
729 .append(s_AndMessageChunk)
730 .append(s_AndSize)
731 .append(to_string(msg_size))
732 .append(s_AndStatus)
733 .append(to_string(static_cast<int>(status)))
734 .append(s_AndCode)
735 .append(to_string(code))
736 .append(s_AndSeverity)
737 .append(SeverityToLowerString(severity))
738 .append(1, '\n');
739 }
740
741
GetNamedAnnotationMessageCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)742 string GetNamedAnnotationMessageCompletionHeader(size_t item_id,
743 const string & processor_id,
744 size_t chunk_count)
745 {
746 string reply(s_ReplyBegin);
747
748 return reply.append(to_string(item_id))
749 .append(s_AndProcessorId)
750 .append(NStr::URLEncode(processor_id))
751 .append(s_AndBioseqNAItem)
752 .append(s_AndMetaChunk)
753 .append(s_AndNChunks)
754 .append(to_string(chunk_count))
755 .append(1, '\n');
756 }
757
758
GetNamedAnnotationCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)759 string GetNamedAnnotationCompletionHeader(size_t item_id,
760 const string & processor_id,
761 size_t chunk_count)
762 {
763 string reply(s_ReplyBegin);
764
765 return reply.append(to_string(item_id))
766 .append(s_AndProcessorId)
767 .append(NStr::URLEncode(processor_id))
768 .append(s_AndBioseqNAItem)
769 .append(s_AndMetaChunk)
770 .append(s_AndNChunks)
771 .append(to_string(chunk_count))
772 .append(1, '\n');
773 }
774
775
GetProcessorMessageHeader(size_t item_id,const string & processor_id,size_t msg_size,CRequestStatus::ECode status,int code,EDiagSev severity)776 string GetProcessorMessageHeader(size_t item_id,
777 const string & processor_id,
778 size_t msg_size,
779 CRequestStatus::ECode status,
780 int code,
781 EDiagSev severity)
782 {
783 string reply(s_ReplyBegin);
784
785 return reply.append(to_string(item_id))
786 .append(s_AndProcessorId)
787 .append(NStr::URLEncode(processor_id))
788 .append(s_AndProcessorItem)
789 .append(s_AndMessageChunk)
790 .append(s_AndSize)
791 .append(to_string(msg_size))
792 .append(s_AndStatus)
793 .append(to_string(static_cast<int>(status)))
794 .append(s_AndCode)
795 .append(to_string(code))
796 .append(s_AndSeverity)
797 .append(SeverityToLowerString(severity))
798 .append(1, '\n');
799 }
800
801
GetProcessorMessageCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)802 string GetProcessorMessageCompletionHeader(size_t item_id,
803 const string & processor_id,
804 size_t chunk_count)
805 {
806 string reply(s_ReplyBegin);
807
808 return reply.append(to_string(item_id))
809 .append(s_AndProcessorId)
810 .append(NStr::URLEncode(processor_id))
811 .append(s_AndProcessorItem)
812 .append(s_AndMetaChunk)
813 .append(s_AndNChunks)
814 .append(to_string(chunk_count))
815 .append(1, '\n');
816 }
817
818
GetPublicCommentHeader(size_t item_id,const string & processor_id,const string & blob_id,CBlobRecord::TTimestamp last_modified,size_t msg_size)819 string GetPublicCommentHeader(size_t item_id,
820 const string & processor_id,
821 const string & blob_id,
822 CBlobRecord::TTimestamp last_modified,
823 size_t msg_size)
824 {
825 string reply(s_ReplyBegin);
826
827 return reply.append(to_string(item_id))
828 .append(s_AndProcessorId)
829 .append(NStr::URLEncode(processor_id))
830 .append(s_AndPublicCommentItem)
831 .append(s_AndDataChunk)
832 .append(s_AndBlobId)
833 .append(blob_id)
834 .append(s_AndLastModified)
835 .append(to_string(last_modified))
836 .append(s_AndSize)
837 .append(to_string(msg_size))
838 .append(1, '\n');
839 }
840
841
GetPublicCommentHeader(size_t item_id,const string & processor_id,int64_t id2_chunk,const string & id2_info,size_t msg_size)842 string GetPublicCommentHeader(size_t item_id,
843 const string & processor_id,
844 int64_t id2_chunk,
845 const string & id2_info,
846 size_t msg_size)
847 {
848 string reply(s_ReplyBegin);
849
850 return reply.append(to_string(item_id))
851 .append(s_AndProcessorId)
852 .append(NStr::URLEncode(processor_id))
853 .append(s_AndPublicCommentItem)
854 .append(s_AndDataChunk)
855 .append(s_AndId2Chunk)
856 .append(to_string(id2_chunk))
857 .append(s_AndId2Info)
858 .append(id2_info)
859 .append(s_AndSize)
860 .append(to_string(msg_size))
861 .append(1, '\n');
862
863 }
864
865
GetPublicCommentCompletionHeader(size_t item_id,const string & processor_id,size_t chunk_count)866 string GetPublicCommentCompletionHeader(size_t item_id,
867 const string & processor_id,
868 size_t chunk_count)
869 {
870 string reply(s_ReplyBegin);
871
872 return reply.append(to_string(item_id))
873 .append(s_AndProcessorId)
874 .append(NStr::URLEncode(processor_id))
875 .append(s_AndPublicCommentItem)
876 .append(s_AndMetaChunk)
877 .append(s_AndNChunks)
878 .append(to_string(chunk_count))
879 .append(1, '\n');
880 }
881
882
883
884 extern bool g_Log;
885
886
887 // If the thread had no context set => the context need to be reset.
888 // The client IP address is set only for non default context.
CRequestContextResetter()889 CRequestContextResetter::CRequestContextResetter() :
890 m_NeedReset(!CDiagContext::GetRequestContext().IsSetClientIP())
891 {}
892
~CRequestContextResetter()893 CRequestContextResetter::~CRequestContextResetter()
894 {
895 if (g_Log && m_NeedReset) {
896 CDiagContext::SetRequestContext(NULL);
897 }
898 }
899
900
FormatPreciseTime(const chrono::system_clock::time_point & t_point)901 string FormatPreciseTime(const chrono::system_clock::time_point & t_point)
902 {
903 std::time_t t = chrono::system_clock::to_time_t(t_point);
904 chrono::milliseconds t_ms = chrono::duration_cast<chrono::milliseconds>
905 (t_point.time_since_epoch());
906
907 struct tm local_time;
908 localtime_r(&t, &local_time);
909
910 char buffer[64];
911 size_t char_count = strftime(buffer, 64,
912 "%Y-%m-%d %H:%M:%S",
913 &local_time);
914 sprintf(&buffer[char_count], ".%03ld", t_ms.count() % 1000);
915 return buffer;
916 }
917
918
919
920 static map<EPSGS_StartupDataState, string> s_CassStartupDataStateMsg =
921 { {ePSGS_NoCassConnection, "Cassandra DB connection is not established"},
922 {ePSGS_NoValidCassMapping, "Cassandra DB mapping configuration is invalid"},
923 {ePSGS_NoCassCache, "LMDB cache is not initialized"},
924 {ePSGS_StartupDataOK, "Cassandra DB mapping data are OK"} };
GetCassStartupDataStateMessage(EPSGS_StartupDataState state)925 string GetCassStartupDataStateMessage(EPSGS_StartupDataState state)
926 {
927 return s_CassStartupDataStateMsg[state];
928 }
929
930