1 /*  $Id: ns_db_dump.cpp 551762 2017-11-22 14:16:14Z satskyse $
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  *   NetSchedule database dumping support.
30  *
31  */
32 
33 #include <ncbi_pch.hpp>
34 
35 #include <stdlib.h>
36 #include <string.h>
37 #include "ns_db_dump.hpp"
38 #include "ns_types.hpp"
39 #include "netschedule_version.hpp"
40 
41 
42 BEGIN_NCBI_SCOPE
43 
SCommonDumpHeader()44 SCommonDumpHeader::SCommonDumpHeader() :
45     magic(kDumpMagic),
46     storage_ver_major(NETSCHEDULED_STORAGE_VERSION_MAJOR),
47     storage_ver_minor(NETSCHEDULED_STORAGE_VERSION_MINOR),
48     storage_ver_patch(NETSCHEDULED_STORAGE_VERSION_PATCH)
49 {
50     CNcbiApplication *  app = CNcbiApplication::Instance();
51     CVersionInfo        ver_info = app->GetVersion();
52 
53     server_ver_major = ver_info.GetMajor();
54     server_ver_minor = ver_info.GetMinor();
55     server_ver_patch = ver_info.GetPatchLevel();
56 }
57 
58 
SJobDumpHeader()59 SJobDumpHeader::SJobDumpHeader() :
60     common_header(),
61     job_props_fixed_size(sizeof(SJobDump)),
62     job_io_fixed_size(sizeof(SJobIODump)),
63     job_event_fixed_size(sizeof(SJobEventsDump))
64 {}
65 
66 
Write(FILE * f)67 void SJobDumpHeader::Write(FILE *  f)
68 {
69     errno = 0;
70     if (fwrite(this, sizeof(SJobDumpHeader), 1, f) != 1)
71         throw runtime_error(strerror(errno));
72 }
73 
74 
Read(FILE * f)75 int SJobDumpHeader::Read(FILE *  f)
76 {
77     size_t      bytes = fread(this, 1, sizeof(SJobDumpHeader), f);
78     if (bytes != sizeof(SJobDumpHeader)) {
79         if (bytes > 0)
80             throw runtime_error("Incomplete dump file header");
81         if (feof(f))
82             return 1;
83         if (errno != 0)
84             throw runtime_error(strerror(errno));
85         throw runtime_error("Unknown dump file header reading error");
86     }
87 
88     if (common_header.magic != kDumpMagic)
89         throw runtime_error("Dump file header magic does not match");
90     return 0;
91 }
92 
93 
SOneStructDumpHeader()94 SOneStructDumpHeader::SOneStructDumpHeader() :
95     common_header(),
96     fixed_size(0)
97 {}
98 
99 
Write(FILE * f)100 void SOneStructDumpHeader::Write(FILE *  f)
101 {
102     errno = 0;
103     if (fwrite(this, sizeof(SOneStructDumpHeader), 1, f) != 1)
104         throw runtime_error(strerror(errno));
105 }
106 
107 
Read(FILE * f)108 int SOneStructDumpHeader::Read(FILE *  f)
109 {
110     size_t      bytes = fread(this, 1, sizeof(SOneStructDumpHeader), f);
111     if (bytes != sizeof(SOneStructDumpHeader)) {
112         if (bytes > 0)
113             throw runtime_error("Incomplete dump file header");
114         if (feof(f))
115             return 1;
116         if (errno != 0)
117             throw runtime_error(strerror(errno));
118         throw runtime_error("Unknown dump file header reading error");
119     }
120 
121     if (common_header.magic != kDumpMagic)
122         throw runtime_error("Dump file header magic does not match");
123     return 0;
124 }
125 
126 
SJobDump()127 SJobDump::SJobDump()
128 {
129     memset(this, 0, sizeof(SJobDump));
130 }
131 
Write(FILE * f,const char * progress_msg)132 void SJobDump::Write(FILE *  f, const char *  progress_msg)
133 {
134     total_size = sizeof(SJobDump) + progress_msg_size;
135 
136     errno = 0;
137     if (fwrite(this, sizeof(SJobDump), 1, f) != 1)
138         throw runtime_error(strerror(errno));
139 
140     if (progress_msg_size > 0) {
141         errno = 0;
142         if (fwrite(progress_msg, progress_msg_size, 1, f) != 1)
143             throw runtime_error(strerror(errno));
144     }
145 }
146 
Read(FILE * f,size_t fixed_size_from_header,char * progress_msg)147 int SJobDump::Read(FILE *  f,
148                    size_t  fixed_size_from_header,
149                    char *  progress_msg)
150 {
151     memset(this, 0, sizeof(SJobDump));
152 
153     size_t      size_to_read = min(sizeof(SJobDump), fixed_size_from_header);
154 
155     errno = 0;
156     size_t      bytes = fread(this, 1, size_to_read, f);
157     if (bytes != size_to_read) {
158         if (bytes > 0)
159             throw runtime_error("Incomplete job record reading");
160         if (feof(f))
161             return 1;
162         if (errno != 0)
163             throw runtime_error(strerror(errno));
164         throw runtime_error("Unknown job record reading error");
165     }
166     if (fixed_size_from_header > size_to_read) {
167         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
168 
169         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
170             if (errno != 0)
171                 throw runtime_error(strerror(errno));
172             throw runtime_error("Unknown job record skipping error");
173         }
174     }
175 
176     if (client_ip_size > kMaxClientIpSize)
177         throw runtime_error("Job client ip size is more "
178                             "than max allowed");
179     if (client_sid_size > kMaxSessionIdSize)
180         throw runtime_error("Job client session id size is more "
181                             "than max allowed");
182     if (ncbi_phid_size > kMaxHitIdSize)
183         throw runtime_error("Job page hit id size is more "
184                             "than max allowed");
185     if (progress_msg_size > kNetScheduleMaxDBDataSize)
186         throw runtime_error("Job progress message size is more "
187                             "than max allowed");
188     if (progress_msg_size > 0) {
189         errno = 0;
190         bytes = fread(progress_msg, 1, progress_msg_size, f);
191         if (bytes != progress_msg_size) {
192             if (bytes > 0)
193                 throw runtime_error("Incomplete job progress message reading");
194             if (feof(f))
195                 throw runtime_error("Unexpected end of job info file. "
196                                     "Expected a progress message, got EOF");
197             if (errno != 0)
198                 throw runtime_error(strerror(errno));
199             throw runtime_error("Unknown job progress message reading error");
200         }
201     }
202 
203     if (total_size > fixed_size_from_header + progress_msg_size) {
204         size_t      bytes_to_skip = total_size -
205                                     fixed_size_from_header - progress_msg_size;
206         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
207             if (errno != 0)
208                 throw runtime_error(strerror(errno));
209             throw runtime_error("Unknown job record skipping error");
210         }
211     }
212 
213     return 0;
214 }
215 
216 
SJobIODump()217 SJobIODump::SJobIODump()
218 {
219     memset(this, 0, sizeof(SJobIODump));
220 }
221 
222 
223 // It is supposed that the input and/or output follow each instance of the
224 // structure below. The limit of the input/output is too large to have
225 // it as a member of this structure
Write(FILE * f,const char * input,const char * output)226 void SJobIODump::Write(FILE *  f, const char *  input,
227                                   const char *  output)
228 {
229     total_size = sizeof(SJobIODump) + input_size + output_size;
230 
231     errno = 0;
232     if (fwrite(this, sizeof(SJobIODump), 1, f) != 1)
233         throw runtime_error(strerror(errno));
234 
235     if (input_size > 0) {
236         errno = 0;
237         if (fwrite(input, input_size, 1, f) != 1)
238             throw runtime_error(strerror(errno));
239     }
240 
241     if (output_size > 0) {
242         errno = 0;
243         if (fwrite(output, output_size, 1, f) != 1)
244             throw runtime_error(strerror(errno));
245     }
246 }
247 
248 
Read(FILE * f,size_t fixed_size_from_header,char * input,char * output)249 int SJobIODump::Read(FILE *  f, size_t  fixed_size_from_header,
250                      char *  input, char *  output)
251 {
252     memset(this, 0, sizeof(SJobIODump));
253 
254     size_t      size_to_read = min(sizeof(SJobIODump), fixed_size_from_header);
255 
256     errno = 0;
257     size_t  bytes = fread(this, 1, size_to_read, f);
258     if (bytes != size_to_read) {
259         if (bytes > 0)
260             throw runtime_error("Incomplete job i/o record reading");
261         if (feof(f))
262             throw runtime_error("Unexpected end of job info file. "
263                                 "Expected a job i/o, got EOF");
264         if (errno != 0)
265             throw runtime_error(strerror(errno));
266         throw runtime_error("Unknown job i/o reading error");
267     }
268     if (fixed_size_from_header > size_to_read) {
269         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
270 
271         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
272             if (errno != 0)
273                 throw runtime_error(strerror(errno));
274             throw runtime_error("Unknown job i/o record skipping error");
275         }
276     }
277 
278     if (input_size > kNetScheduleMaxOverflowSize)
279         throw runtime_error("Job input size is more "
280                             "than max allowed");
281     if (input_size > 0) {
282         errno = 0;
283         bytes = fread(input, 1, input_size, f);
284         if (bytes != input_size) {
285             if (bytes > 0)
286                 throw runtime_error("Incomplete job input reading");
287             if (feof(f))
288                 throw runtime_error("Unexpected end of job info file. "
289                                     "Expected an input, got EOF");
290             if (errno != 0)
291                 throw runtime_error(strerror(errno));
292             throw runtime_error("Unknown job input reading error");
293         }
294     }
295 
296     if (output_size > kNetScheduleMaxOverflowSize)
297         throw runtime_error("Job output size is more "
298                             "than max allowed");
299     if (output_size > 0) {
300         errno = 0;
301         bytes = fread(output, 1, output_size, f);
302         if (bytes != output_size) {
303             if (bytes > 0)
304                 throw runtime_error("Incomplete job output reading");
305             if (feof(f))
306                 throw runtime_error("Unexpected end of job info file. "
307                                     "Expected an output, got EOF");
308             if (errno != 0)
309                 throw runtime_error(strerror(errno));
310             throw runtime_error("Unknown job output reading error");
311         }
312     }
313 
314     if (total_size > fixed_size_from_header + input_size + output_size) {
315         size_t      bytes_to_skip = total_size -
316                                     fixed_size_from_header -
317                                     input_size - output_size;
318         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
319             if (errno != 0)
320                 throw runtime_error(strerror(errno));
321             throw runtime_error("Unknown job i/o record skipping error");
322         }
323     }
324 
325     return 0;
326 }
327 
328 
SJobEventsDump()329 SJobEventsDump::SJobEventsDump()
330 {
331     memset(this, 0, sizeof(SJobEventsDump));
332 }
333 
Write(FILE * f,const char * client_node,const char * client_session,const char * err_msg)334 void SJobEventsDump::Write(FILE *  f, const char *  client_node,
335                                       const char *  client_session,
336                                       const char *  err_msg)
337 {
338     total_size = sizeof(SJobEventsDump) + client_node_size +
339                  client_session_size + err_msg_size;
340 
341     errno = 0;
342     if (fwrite(this, sizeof(SJobEventsDump), 1, f) != 1)
343         throw runtime_error(strerror(errno));
344 
345     if (client_node_size > 0) {
346         errno = 0;
347         if (fwrite(client_node, client_node_size, 1, f) != 1)
348             throw runtime_error(strerror(errno));
349     }
350     if (client_session_size > 0) {
351         errno = 0;
352         if (fwrite(client_session, client_session_size, 1, f) != 1)
353             throw runtime_error(strerror(errno));
354     }
355     if (err_msg_size > 0) {
356         errno = 0;
357         if (fwrite(err_msg, err_msg_size, 1, f) != 1)
358             throw runtime_error(strerror(errno));
359     }
360 }
361 
Read(FILE * f,size_t fixed_size_from_header,char * client_node,char * client_session,char * err_msg)362 int SJobEventsDump::Read(FILE *  f, size_t  fixed_size_from_header,
363                          char *  client_node,
364                          char *  client_session,
365                          char *  err_msg)
366 {
367     memset(this, 0, sizeof(SJobEventsDump));
368 
369     size_t      size_to_read = min(sizeof(SJobEventsDump),
370                                    fixed_size_from_header);
371 
372     errno = 0;
373     size_t      bytes = fread(this, 1, size_to_read, f);
374     if (bytes != size_to_read) {
375         if (bytes > 0)
376             throw runtime_error("Incomplete job event reading");
377         if (feof(f))
378             throw runtime_error("Unexpected end of job info file. "
379                                 "Expected a job event, got EOF");
380         if (errno != 0)
381             throw runtime_error(strerror(errno));
382         throw runtime_error("Unknown job event reading error");
383     }
384     if (fixed_size_from_header > size_to_read) {
385         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
386 
387         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
388             if (errno != 0)
389                 throw runtime_error(strerror(errno));
390             throw runtime_error("Unknown job event record skipping error");
391         }
392     }
393 
394     if (client_node_size > kMaxWorkerNodeIdSize)
395         throw runtime_error("Job event client node size is more "
396                             "than max allowed");
397     if (client_node_size > 0) {
398         errno = 0;
399         bytes = fread(client_node, 1, client_node_size, f);
400         if (bytes != client_node_size) {
401             if (bytes > 0)
402                 throw runtime_error("Incomplete job event client node reading");
403             if (feof(f))
404                 throw runtime_error("Unexpected end of job info file. "
405                                     "Expected a client node, got EOF");
406             if (errno != 0)
407                 throw runtime_error(strerror(errno));
408             throw runtime_error("Unknown job event client node reading error");
409         }
410     }
411 
412     if (client_session_size > kMaxWorkerNodeIdSize)
413         throw runtime_error("Job event client session size is more "
414                             "than max allowed");
415     if (client_session_size > 0) {
416         errno = 0;
417         bytes = fread(client_session, 1, client_session_size, f);
418         if (bytes != client_session_size) {
419             if (bytes > 0)
420                 throw runtime_error("Incomplete job event "
421                                     "client session reading");
422             if (feof(f))
423                 throw runtime_error("Unexpected end of job info file. "
424                                     "Expected a client session, got EOF");
425             if (errno != 0)
426                 throw runtime_error(strerror(errno));
427             throw runtime_error("Unknown job event "
428                                 "client session reading error");
429         }
430     }
431 
432     if (err_msg_size > kNetScheduleMaxDBErrSize)
433         throw runtime_error("Job event error message size is more "
434                             "than max allowed");
435     if (err_msg_size > 0) {
436         errno = 0;
437         bytes = fread(err_msg, 1, err_msg_size, f);
438         if (bytes != err_msg_size) {
439             if (bytes > 0)
440                 throw runtime_error("Incomplete job event "
441                                     "error message reading");
442             if (feof(f))
443                 throw runtime_error("Unexpected end of job info file. "
444                                     "Expected an error message, got EOF");
445             if (errno != 0)
446                 throw runtime_error(strerror(errno));
447             throw runtime_error("Unknown job event "
448                                 "error message reading error");
449         }
450     }
451 
452     if (total_size > fixed_size_from_header + client_node_size +
453                      client_session_size + err_msg_size) {
454         size_t      bytes_to_skip = total_size -
455                                     fixed_size_from_header  -
456                                     client_node_size - client_session_size -
457                                     err_msg_size;
458         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
459             if (errno != 0)
460                 throw runtime_error(strerror(errno));
461             throw runtime_error("Unknown job event record skipping error");
462         }
463     }
464 
465     return 0;
466 }
467 
468 
SAffinityDictDump()469 SAffinityDictDump::SAffinityDictDump()
470 {
471     memset(this, 0, sizeof(SAffinityDictDump));
472 }
473 
474 
Write(FILE * f)475 void SAffinityDictDump::Write(FILE *  f)
476 {
477     total_size = sizeof(SAffinityDictDump);
478 
479     errno = 0;
480     if (fwrite(this, sizeof(SAffinityDictDump), 1, f) != 1)
481         throw runtime_error(strerror(errno));
482 }
483 
Read(FILE * f,size_t fixed_size_from_header)484 int SAffinityDictDump::Read(FILE *  f, size_t  fixed_size_from_header)
485 {
486     memset(this, 0, sizeof(SAffinityDictDump));
487 
488     size_t      size_to_read = min(sizeof(SAffinityDictDump),
489                                    fixed_size_from_header);
490 
491     errno = 0;
492     size_t      bytes = fread(this, 1, size_to_read, f);
493     if (bytes != size_to_read) {
494         if (bytes > 0)
495             throw runtime_error("Incomplete affinity reading");
496         if (feof(f))
497             return 1;
498         if (errno != 0)
499             throw runtime_error(strerror(errno));
500         throw runtime_error("Unknown affinity reading error");
501     }
502 
503     if (token_size > kNetScheduleMaxDBDataSize)
504         throw runtime_error("Affinity token size is more "
505                             "than max allowed");
506 
507     if (fixed_size_from_header > size_to_read) {
508         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
509 
510         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
511             if (errno != 0)
512                 throw runtime_error(strerror(errno));
513             throw runtime_error("Unknown affinity skipping error");
514         }
515     }
516     return 0;
517 }
518 
519 
SGroupDictDump()520 SGroupDictDump::SGroupDictDump()
521 {
522     memset(this, 0, sizeof(SGroupDictDump));
523 }
524 
525 
Write(FILE * f)526 void SGroupDictDump::Write(FILE *  f)
527 {
528     total_size = sizeof(SGroupDictDump);
529 
530     errno = 0;
531     if (fwrite(this, sizeof(SGroupDictDump), 1, f) != 1)
532         throw runtime_error(strerror(errno));
533 }
534 
Read(FILE * f,size_t fixed_size_from_header)535 int SGroupDictDump::Read(FILE *  f, size_t  fixed_size_from_header)
536 {
537     memset(this, 0, sizeof(SGroupDictDump));
538 
539     size_t      size_to_read = min(sizeof(SGroupDictDump),
540                                    fixed_size_from_header);
541 
542     errno = 0;
543     size_t      bytes = fread(this, 1, size_to_read, f);
544     if (bytes != size_to_read) {
545         if (bytes > 0)
546             throw runtime_error("Incomplete job group reading");
547         if (feof(f))
548             return 1;
549         if (errno != 0)
550             throw runtime_error(strerror(errno));
551         throw runtime_error("Unknown job group reading error");
552     }
553 
554     if (token_size > kNetScheduleMaxDBDataSize)
555         throw runtime_error("Group token size is more "
556                             "than max allowed");
557 
558     if (fixed_size_from_header > size_to_read) {
559         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
560 
561         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
562             if (errno != 0)
563                 throw runtime_error(strerror(errno));
564             throw runtime_error("Unknown group skipping error");
565         }
566     }
567     return 0;
568 }
569 
570 
SQueueDescriptionDump()571 SQueueDescriptionDump::SQueueDescriptionDump()
572 {
573     memset(this, 0, sizeof(SQueueDescriptionDump));
574 }
575 
576 
Write(FILE * f)577 void SQueueDescriptionDump::Write(FILE *  f)
578 {
579     total_size = sizeof(SQueueDescriptionDump);
580 
581     errno = 0;
582     if (fwrite(this, sizeof(SQueueDescriptionDump), 1, f) != 1)
583         throw runtime_error(strerror(errno));
584 }
585 
Read(FILE * f,size_t fixed_size_from_header)586 int SQueueDescriptionDump::Read(FILE *  f, size_t  fixed_size_from_header)
587 {
588     memset(this, 0, sizeof(SQueueDescriptionDump));
589 
590     size_t      size_to_read = min(sizeof(SQueueDescriptionDump),
591                                    fixed_size_from_header);
592 
593     errno = 0;
594     size_t      bytes = fread(this, 1, size_to_read, f);
595     if (bytes != size_to_read) {
596         if (bytes > 0)
597             throw runtime_error("Incomplete queue description reading");
598         if (feof(f))
599             return 1;
600         if (errno != 0)
601             throw runtime_error(strerror(errno));
602         throw runtime_error("Unknown queue description reading error");
603     }
604 
605     if (qname_size > kMaxQueueNameSize)
606         throw runtime_error("Queue name size is more "
607                             "than max allowed");
608     if (qclass_size > kMaxQueueNameSize)
609         throw runtime_error("Queue class name size is more "
610                             "than max allowed");
611     if (program_name_size > kMaxQueueLimitsSize)
612         throw runtime_error("Program name size is more "
613                             "than max allowed");
614     if (subm_hosts_size > kMaxQueueLimitsSize)
615         throw runtime_error("Submitter hosts size is more "
616                             "than max allowed");
617     if (wnode_hosts_size > kMaxQueueLimitsSize)
618         throw runtime_error("Worker node hosts size is more "
619                             "than max allowed");
620     if (reader_hosts_size > kMaxQueueLimitsSize)
621         throw runtime_error("Reader hosts size is more "
622                             "than max allowed");
623     if (description_size > kMaxDescriptionSize)
624         throw runtime_error("Description size is more "
625                             "than max allowed");
626     if (linked_section_prefixes_size > kLinkedSectionsList)
627         throw runtime_error("Linked section prefixes size is more "
628                             "than max allowed");
629     if (linked_section_names_size > kLinkedSectionsList)
630         throw runtime_error("Linked section names size is more "
631                             "than max allowed");
632 
633     if (fixed_size_from_header > size_to_read) {
634         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
635 
636         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
637             if (errno != 0)
638                 throw runtime_error(strerror(errno));
639             throw runtime_error("Unknown queue description skipping error");
640         }
641     }
642     return 0;
643 }
644 
645 
SLinkedSectionDump()646 SLinkedSectionDump::SLinkedSectionDump()
647 {
648     memset(this, 0, sizeof(SLinkedSectionDump));
649 }
650 
651 
Write(FILE * f)652 void SLinkedSectionDump::Write(FILE *  f)
653 {
654     total_size = sizeof(SLinkedSectionDump);
655 
656     if (fwrite(this, sizeof(SLinkedSectionDump), 1, f) != 1)
657         throw runtime_error(strerror(errno));
658 }
659 
Read(FILE * f,size_t fixed_size_from_header)660 int SLinkedSectionDump::Read(FILE *  f, size_t  fixed_size_from_header)
661 {
662     memset(this, 0, sizeof(SLinkedSectionDump));
663 
664     size_t      size_to_read = min(sizeof(SLinkedSectionDump),
665                                    fixed_size_from_header);
666 
667     errno = 0;
668     size_t      bytes = fread(this, 1, size_to_read, f);
669     if (bytes != size_to_read) {
670         if (bytes > 0)
671             throw runtime_error("Incomplete linked section reading");
672         if (feof(f))
673             return 1;
674         if (errno != 0)
675             throw runtime_error(strerror(errno));
676         throw runtime_error("Unknown linked section reading error");
677     }
678 
679     if (section_size > kLinkedSectionValueNameSize)
680         throw runtime_error("Linked section name size is more "
681                             "than max allowed");
682     if (value_name_size > kLinkedSectionValueNameSize)
683         throw runtime_error("Linked section value name size is more "
684                             "than max allowed");
685     if (value_size > kLinkedSectionValueSize)
686         throw runtime_error("Linked section value size is more "
687                             "than max allowed");
688 
689     if (fixed_size_from_header > size_to_read) {
690         size_t      bytes_to_skip = fixed_size_from_header - size_to_read;
691 
692         if (fseek(f, bytes_to_skip, SEEK_CUR) != 0) {
693             if (errno != 0)
694                 throw runtime_error(strerror(errno));
695             throw runtime_error("Unknown linked section skipping error");
696         }
697     }
698     return 0;
699 }
700 
701 
702 END_NCBI_SCOPE
703