1 /* $Id: nst_database.cpp 515877 2016-10-06 14:29:20Z 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 * Author: Sergey Satskiy
27 *
28 */
29
30 #include <ncbi_pch.hpp>
31
32 #include <corelib/ncbistd.hpp>
33 #include <corelib/resource_info.hpp>
34 #include <connect/services/json_over_uttp.hpp>
35 #include <connect/services/netstorage.hpp>
36 #include "nst_database.hpp"
37 #include "nst_exception.hpp"
38 #include "nst_application.hpp"
39 #include "nst_server.hpp"
40 #include "nst_clients.hpp"
41 #include "nst_config.hpp"
42 #include "nst_perf_logging.hpp"
43 #include "nst_constants.hpp"
44
45
46 BEGIN_NCBI_SCOPE
47
48
CNSTDatabase(CNetStorageServer * server)49 CNSTDatabase::CNSTDatabase(CNetStorageServer * server)
50 : m_Server(server), m_Db(NULL), m_Connected(false),
51 m_RestoreConnectionThread(NULL),
52 m_SPTimeout(default_execute_sp_timeout)
53 {
54 // true: this is initialization time
55 x_CreateDatabase(true);
56 try {
57 m_RestoreConnectionThread.Reset(new CNSTDBConnectionThread(
58 m_Connected, m_Db,
59 this, m_DbLock));
60 m_RestoreConnectionThread->Run();
61 } catch (...) {
62 if (m_Db != NULL)
63 delete m_Db;
64 throw;
65 }
66
67 // It might be that the DB has not been created because the database
68 // password could not be decrypted. In this case we need to try again every
69 // 100 seconds. These tries are made in the restore connection thread so
70 // let's wake it up here.
71 if (m_Db == NULL)
72 m_RestoreConnectionThread->Wakeup();
73 }
74
75
InitialConnect(void)76 void CNSTDatabase::InitialConnect(void)
77 {
78 if (m_Db != NULL && !m_Connected) {
79 try {
80 m_Db->Connect();
81 m_Connected = true;
82 } catch (const CException & ex) {
83 m_Server->RegisterAlert(eDBConnect, "DB connection error: " +
84 string(ex.what()));
85 ERR_POST(ex);
86 m_RestoreConnectionThread->Wakeup();
87 } catch (const exception & ex) {
88 m_Server->RegisterAlert(eDBConnect, "DB connection error: " +
89 string(ex.what()));
90 ERR_POST("Exception while connecting to the database: " <<
91 ex.what());
92 m_RestoreConnectionThread->Wakeup();
93 } catch (...) {
94 m_Server->RegisterAlert(eDBConnect, "Unknown DB connection error");
95 ERR_POST("Unknown exception while connecting to the database");
96 m_RestoreConnectionThread->Wakeup();
97 }
98 }
99 }
100
101
~CNSTDatabase(void)102 CNSTDatabase::~CNSTDatabase(void)
103 {
104 m_RestoreConnectionThread->Stop();
105 m_RestoreConnectionThread->Join();
106 m_RestoreConnectionThread.Reset(0);
107
108 if (m_Db != NULL) {
109 if (m_Connected)
110 m_Db->Close();
111 delete m_Db;
112 }
113 }
114
115
116 CJsonNode
SetParameters(const IRegistry & reg)117 CNSTDatabase::SetParameters(const IRegistry & reg)
118 {
119 // The only parameter which could be changed is a SP execution timeout
120 double current_timeout = m_SPTimeout.GetAsDouble();
121 double new_timeout = reg.GetDouble("database",
122 "execute_sp_timeout",
123 default_execute_sp_timeout,
124 0, IRegistry::eReturn);
125 if (current_timeout == new_timeout)
126 return CJsonNode::NewNullNode();
127
128 CJsonNode diff = CJsonNode::NewObjectNode();
129 CJsonNode values = CJsonNode::NewObjectNode();
130
131 values.SetByKey("Old", CJsonNode::NewDoubleNode(current_timeout));
132 values.SetByKey("New", CJsonNode::NewDoubleNode(new_timeout));
133 diff.SetByKey("execute_sp_timeout", values);
134
135 CFastMutexGuard lock(m_SPTimeoutMutex);
136 m_SPTimeout.Set(new_timeout);
137 return diff;
138 }
139
140
141 int
ExecSP_CreateClient(const string & client,Int8 & client_id)142 CNSTDatabase::ExecSP_CreateClient(const string & client, Int8 & client_id)
143 {
144 const string proc_name = "CreateClient";
145 CNSTPreciseTime start = CNSTPreciseTime::Current();
146 try {
147 x_PreCheckConnection();
148
149 int status;
150 try {
151 CDatabase db = m_Db->Clone();
152 CQuery query = db.NewQuery();
153
154 client_id = k_UndefinedClientID;
155 query.SetParameter("@client_name", client);
156 query.SetOutputParameter("@client_id", eSDB_Int8);
157
158 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
159 query.VerifyDone();
160 status = x_CheckStatus(query, proc_name);
161
162 if (status == kSPStatusOK)
163 client_id = query.GetParameter("@client_id").AsInt8();
164 else
165 client_id = k_UndefinedClientID;
166
167 g_DoPerfLogging("MS_SQL_" + proc_name,
168 CNSTPreciseTime::Current() - start,
169 CRequestStatus::e200_Ok);
170 return status;
171 } catch (const std::exception & ex) {
172 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
173 x_PostCheckConnection();
174 throw;
175 } catch (...) {
176 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
177 x_PostCheckConnection();
178 throw;
179 }
180 } catch (...) {
181 g_DoPerfLogging("MS_SQL_" + proc_name,
182 CNSTPreciseTime::Current() - start,
183 CRequestStatus::e500_InternalServerError);
184 throw;
185 }
186 }
187
188
189 int
ExecSP_CreateUser(const CNSTUserID & user,Int8 & user_id)190 CNSTDatabase::ExecSP_CreateUser(const CNSTUserID & user, Int8 & user_id)
191 {
192 const string proc_name = "CreateUser";
193 CNSTPreciseTime start = CNSTPreciseTime::Current();
194 try {
195 x_PreCheckConnection();
196
197 int status;
198 try {
199 CDatabase db = m_Db->Clone();
200 CQuery query = db.NewQuery();
201
202 user_id = k_UndefinedUserID;
203 query.SetParameter("@user_name", user.GetName());
204 query.SetParameter("@user_namespace", user.GetNamespace());
205 query.SetOutputParameter("@user_id", eSDB_Int8);
206
207 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
208 query.VerifyDone();
209 status = x_CheckStatus(query, proc_name);
210
211 if (status == kSPStatusOK)
212 user_id = query.GetParameter("@user_id").AsInt8();
213 else
214 user_id = k_UndefinedUserID;
215
216 g_DoPerfLogging("MS_SQL_" + proc_name,
217 CNSTPreciseTime::Current() - start,
218 CRequestStatus::e200_Ok);
219 return status;
220 } catch (const std::exception & ex) {
221 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
222 x_PostCheckConnection();
223 throw;
224 } catch (...) {
225 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
226 x_PostCheckConnection();
227 throw;
228 }
229 } catch (...) {
230 g_DoPerfLogging("MS_SQL_" + proc_name,
231 CNSTPreciseTime::Current() - start,
232 CRequestStatus::e500_InternalServerError);
233 throw;
234 }
235 }
236
237
238 int
ExecSP_CreateObjectWithClientID(const string & object_key,const string & object_loc,Int8 size,Int8 client_id,Int8 user_id,const TNSTDBValue<CTimeSpan> ttl,bool & size_was_null)239 CNSTDatabase::ExecSP_CreateObjectWithClientID(
240 const string & object_key,
241 const string & object_loc, Int8 size,
242 Int8 client_id, Int8 user_id,
243 const TNSTDBValue<CTimeSpan> ttl,
244 bool & size_was_null)
245 {
246 // To avoid extending the list of resources in applog_perf
247 // two names are used: actual DB proc and how it looks in applog_perf
248 const string proc_name = "CreateObjectWithClientID_v2";
249 const string proc_name_for_perf_log = "CreateObjectWithClientID";
250 CNSTPreciseTime start = CNSTPreciseTime::Current();
251 try {
252 x_PreCheckConnection();
253
254 int status;
255 try {
256 CNetStorageObjectLoc object_loc_struct(
257 m_Server->GetCompoundIDPool(),
258 object_loc);
259 CDatabase db = m_Db->Clone();
260 CQuery query = db.NewQuery();
261
262 query.SetParameter("@object_key", object_key);
263 query.SetParameter("@object_create_tm",
264 object_loc_struct.GetCreationTime());
265 query.SetParameter("@object_loc", object_loc);
266 query.SetParameter("@object_size", size);
267 query.SetParameter("@client_id", client_id);
268 query.SetParameter("@user_id", user_id);
269 query.SetOutputParameter("@size_was_null", eSDB_Int4);
270
271 if (ttl.m_IsNull)
272 query.SetNullParameter("@object_expiration", eSDB_DateTime);
273 else
274 query.SetParameter("@object_expiration",
275 CTime(CTime::eCurrent) + ttl.m_Value);
276
277 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
278 query.VerifyDone();
279
280 status = x_CheckStatus(query, proc_name);
281 g_DoPerfLogging("MS_SQL_" + proc_name_for_perf_log,
282 CNSTPreciseTime::Current() - start,
283 CRequestStatus::e200_Ok);
284
285 if (status == kSPStatusOK) {
286 size_was_null = (query.
287 GetParameter("@size_was_null").
288 AsInt4() != 0);
289 }
290 return status;
291 } catch (const std::exception & ex) {
292 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
293 x_PostCheckConnection();
294 throw;
295 } catch (...) {
296 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
297 x_PostCheckConnection();
298 throw;
299 }
300 } catch (...) {
301 g_DoPerfLogging("MS_SQL_" + proc_name_for_perf_log,
302 CNSTPreciseTime::Current() - start,
303 CRequestStatus::e500_InternalServerError);
304 throw;
305 }
306 }
307
308
309 int
ExecSP_UpdateObjectOnWrite(const string & object_key,const string & object_loc,Int8 size,Int8 client_id,Int8 user_id,const TNSTDBValue<CTimeSpan> & ttl,const TNSTDBValue<CTimeSpan> & prolong_on_write,const TNSTDBValue<CTime> & object_expiration,bool & size_was_null)310 CNSTDatabase::ExecSP_UpdateObjectOnWrite(
311 const string & object_key,
312 const string & object_loc, Int8 size,
313 Int8 client_id, Int8 user_id,
314 const TNSTDBValue<CTimeSpan> & ttl,
315 const TNSTDBValue<CTimeSpan> & prolong_on_write,
316 const TNSTDBValue<CTime> & object_expiration,
317 bool & size_was_null)
318 {
319 // Calculate separate expirations for two cases:
320 // - record is found
321 // - record is not found
322 // It is easier to do in C++ than in MS SQL stored procedure
323 CTime current_time(CTime::eCurrent);
324 TNSTDBValue<CTime> exp_record_found;
325 TNSTDBValue<CTime> exp_record_not_found;
326 x_CalculateExpiration(current_time, ttl, prolong_on_write,
327 object_expiration,
328 exp_record_found, exp_record_not_found);
329
330 const string proc_name = "UpdateObjectOnWrite";
331 CNSTPreciseTime start = CNSTPreciseTime::Current();
332 try {
333 x_PreCheckConnection();
334
335 int status;
336 try {
337 CDatabase db = m_Db->Clone();
338 CQuery query = db.NewQuery();
339
340 query.SetParameter("@object_key", object_key);
341 query.SetParameter("@object_loc", object_loc);
342 query.SetParameter("@object_size", size);
343 query.SetParameter("@client_id", client_id);
344 query.SetParameter("@user_id", user_id);
345 query.SetParameter("@current_time", current_time);
346 query.SetOutputParameter("@size_was_null", eSDB_Int4);
347
348 if (exp_record_found.m_IsNull)
349 query.SetNullParameter("@object_exp_if_found",
350 eSDB_DateTime);
351 else
352 query.SetParameter("@object_exp_if_found",
353 exp_record_found.m_Value);
354 if (exp_record_not_found.m_IsNull)
355 query.SetNullParameter("@object_exp_if_not_found",
356 eSDB_DateTime);
357 else
358 query.SetParameter("@object_exp_if_not_found",
359 exp_record_not_found.m_Value);
360
361 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
362 query.VerifyDone();
363
364 status = x_CheckStatus(query, proc_name);
365 g_DoPerfLogging("MS_SQL_" + proc_name,
366 CNSTPreciseTime::Current() - start,
367 CRequestStatus::e200_Ok);
368
369 if (status == kSPStatusOK) {
370 size_was_null = (query.
371 GetParameter("@size_was_null").
372 AsInt4() != 0);
373 }
374 return status;
375 } catch (const std::exception & ex) {
376 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
377 x_PostCheckConnection();
378 throw;
379 } catch (...) {
380 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
381 x_PostCheckConnection();
382 throw;
383 }
384 } catch (...) {
385 g_DoPerfLogging("MS_SQL_" + proc_name,
386 CNSTPreciseTime::Current() - start,
387 CRequestStatus::e500_InternalServerError);
388 throw;
389 }
390 }
391
392
393 int
ExecSP_UpdateUserKeyObjectOnWrite(const string & object_key,const string & object_loc,Int8 size,Int8 client_id,const TNSTDBValue<CTimeSpan> & ttl,const TNSTDBValue<CTimeSpan> & prolong_on_write,const TNSTDBValue<CTime> & object_expiration)394 CNSTDatabase::ExecSP_UpdateUserKeyObjectOnWrite(
395 const string & object_key,
396 const string & object_loc, Int8 size, Int8 client_id,
397 const TNSTDBValue<CTimeSpan> & ttl,
398 const TNSTDBValue<CTimeSpan> & prolong_on_write,
399 const TNSTDBValue<CTime> & object_expiration)
400 {
401 // Calculate separate expirations for two cases:
402 // - record is found
403 // - record is not found
404 // It is easier to do in C++ than in MS SQL stored procedure
405 CTime current_time(CTime::eCurrent);
406 TNSTDBValue<CTime> exp_record_found;
407 TNSTDBValue<CTime> exp_record_not_found;
408 x_CalculateExpiration(current_time, ttl, prolong_on_write,
409 object_expiration,
410 exp_record_found, exp_record_not_found);
411
412 const string proc_name = "UpdateUserKeyObjectOnWrite";
413 CNSTPreciseTime start = CNSTPreciseTime::Current();
414 try {
415 x_PreCheckConnection();
416
417 int status;
418 try {
419 CDatabase db = m_Db->Clone();
420 CQuery query = db.NewQuery();
421
422 query.SetParameter("@object_key", object_key);
423 query.SetParameter("@object_loc", object_loc);
424 query.SetParameter("@object_size", size);
425 query.SetParameter("@client_id", client_id);
426 query.SetParameter("@current_time", current_time);
427
428 if (exp_record_found.m_IsNull)
429 query.SetNullParameter("@object_exp_if_found",
430 eSDB_DateTime);
431 else
432 query.SetParameter("@object_exp_if_found",
433 exp_record_found.m_Value);
434 if (exp_record_not_found.m_IsNull)
435 query.SetNullParameter("@object_exp_if_not_found",
436 eSDB_DateTime);
437 else
438 query.SetParameter("@object_exp_if_not_found",
439 exp_record_not_found.m_Value);
440
441 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
442 query.VerifyDone();
443
444 status = x_CheckStatus(query, proc_name);
445 g_DoPerfLogging("MS_SQL_" + proc_name,
446 CNSTPreciseTime::Current() - start,
447 CRequestStatus::e200_Ok);
448 return status;
449 } catch (const std::exception & ex) {
450 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
451 x_PostCheckConnection();
452 throw;
453 } catch (...) {
454 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
455 x_PostCheckConnection();
456 throw;
457 }
458 } catch (...) {
459 g_DoPerfLogging("MS_SQL_" + proc_name,
460 CNSTPreciseTime::Current() - start,
461 CRequestStatus::e500_InternalServerError);
462 throw;
463 }
464 }
465
466
467 int
ExecSP_UpdateObjectOnRead(const string & object_key,const string & object_loc,Int8 size,Int8 client_id,const TNSTDBValue<CTimeSpan> & ttl,const TNSTDBValue<CTimeSpan> & prolong_on_read,const TNSTDBValue<CTime> & object_expiration,bool & size_was_null)468 CNSTDatabase::ExecSP_UpdateObjectOnRead(
469 const string & object_key,
470 const string & object_loc,
471 Int8 size, Int8 client_id,
472 const TNSTDBValue<CTimeSpan> & ttl,
473 const TNSTDBValue<CTimeSpan> & prolong_on_read,
474 const TNSTDBValue<CTime> & object_expiration,
475 bool & size_was_null)
476 {
477 // Calculate separate expirations for two cases:
478 // - record is found
479 // - record is not found
480 // It is easier to do in C++ than in MS SQL stored procedure
481 CTime current_time(CTime::eCurrent);
482 TNSTDBValue<CTime> exp_record_found;
483 TNSTDBValue<CTime> exp_record_not_found;
484 x_CalculateExpiration(current_time, ttl, prolong_on_read,
485 object_expiration,
486 exp_record_found, exp_record_not_found);
487
488 const string proc_name = "UpdateObjectOnRead";
489 CNSTPreciseTime start = CNSTPreciseTime::Current();
490
491 size_was_null = true;
492 try {
493 x_PreCheckConnection();
494
495 int status;
496 try {
497 CDatabase db = m_Db->Clone();
498 CQuery query = db.NewQuery();
499
500 query.SetParameter("@object_key", object_key);
501 query.SetParameter("@object_loc", object_loc);
502 query.SetParameter("@object_size", size);
503 query.SetParameter("@client_id", client_id);
504 query.SetParameter("@current_time", current_time);
505 query.SetOutputParameter("@size_was_null", eSDB_Int4);
506
507 if (exp_record_found.m_IsNull)
508 query.SetNullParameter("@object_exp_if_found",
509 eSDB_DateTime);
510 else
511 query.SetParameter("@object_exp_if_found",
512 exp_record_found.m_Value);
513 if (exp_record_not_found.m_IsNull)
514 query.SetNullParameter("@object_exp_if_not_found",
515 eSDB_DateTime);
516 else
517 query.SetParameter("@object_exp_if_not_found",
518 exp_record_not_found.m_Value);
519
520 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
521 query.VerifyDone();
522
523 status = x_CheckStatus(query, proc_name);
524 g_DoPerfLogging("MS_SQL_" + proc_name,
525 CNSTPreciseTime::Current() - start,
526 CRequestStatus::e200_Ok);
527
528 if (status == kSPStatusOK) {
529 size_was_null = (query.
530 GetParameter("@size_was_null").
531 AsInt4() != 0);
532 }
533 return status;
534 } catch (const std::exception & ex) {
535 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
536 x_PostCheckConnection();
537 throw;
538 } catch (...) {
539 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
540 x_PostCheckConnection();
541 throw;
542 }
543 } catch (...) {
544 g_DoPerfLogging("MS_SQL_" + proc_name,
545 CNSTPreciseTime::Current() - start,
546 CRequestStatus::e500_InternalServerError);
547 throw;
548 }
549 }
550
551
552 int
ExecSP_UpdateObjectOnRelocate(const string & object_key,const string & object_loc,Int8 client_id,const TNSTDBValue<CTimeSpan> & ttl,const TNSTDBValue<CTimeSpan> & prolong_on_relocate,const TNSTDBValue<CTime> & object_expiration)553 CNSTDatabase::ExecSP_UpdateObjectOnRelocate(
554 const string & object_key,
555 const string & object_loc, Int8 client_id,
556 const TNSTDBValue<CTimeSpan> & ttl,
557 const TNSTDBValue<CTimeSpan> & prolong_on_relocate,
558 const TNSTDBValue<CTime> & object_expiration)
559 {
560 // Calculate separate expirations for two cases:
561 // - record is found
562 // - record is not found
563 // It is easier to do in C++ than in MS SQL stored procedure
564 CTime current_time(CTime::eCurrent);
565 TNSTDBValue<CTime> exp_record_found;
566 TNSTDBValue<CTime> exp_record_not_found;
567 x_CalculateExpiration(current_time, ttl, prolong_on_relocate,
568 object_expiration,
569 exp_record_found, exp_record_not_found);
570
571 const string proc_name = "UpdateObjectOnRelocate";
572 CNSTPreciseTime start = CNSTPreciseTime::Current();
573 try {
574 x_PreCheckConnection();
575
576 int status;
577 try {
578 CDatabase db = m_Db->Clone();
579 CQuery query = db.NewQuery();
580
581 query.SetParameter("@object_key", object_key);
582 query.SetParameter("@object_loc", object_loc);
583 query.SetParameter("@client_id", client_id);
584 query.SetParameter("@current_time", current_time);
585
586 if (exp_record_found.m_IsNull)
587 query.SetNullParameter("@object_exp_if_found",
588 eSDB_DateTime);
589 else
590 query.SetParameter("@object_exp_if_found",
591 exp_record_found.m_Value);
592 if (exp_record_not_found.m_IsNull)
593 query.SetNullParameter("@object_exp_if_not_found",
594 eSDB_DateTime);
595 else
596 query.SetParameter("@object_exp_if_not_found",
597 exp_record_not_found.m_Value);
598
599 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
600 query.VerifyDone();
601
602 status = x_CheckStatus(query, proc_name);
603 g_DoPerfLogging("MS_SQL_" + proc_name,
604 CNSTPreciseTime::Current() - start,
605 CRequestStatus::e200_Ok);
606 return status;
607 } catch (const std::exception & ex) {
608 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
609 x_PostCheckConnection();
610 throw;
611 } catch (...) {
612 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
613 x_PostCheckConnection();
614 throw;
615 }
616 } catch (...) {
617 g_DoPerfLogging("MS_SQL_" + proc_name,
618 CNSTPreciseTime::Current() - start,
619 CRequestStatus::e500_InternalServerError);
620 throw;
621 }
622 }
623
624
625 int
UpdateExpirationIfExists(const string & object_key,const TNSTDBValue<CTimeSpan> & ttl,const TNSTDBValue<CTimeSpan> & prolong_on_read,const TNSTDBValue<CTime> & object_expiration)626 CNSTDatabase::UpdateExpirationIfExists(
627 const string & object_key,
628 const TNSTDBValue<CTimeSpan> & ttl,
629 const TNSTDBValue<CTimeSpan> & prolong_on_read,
630 const TNSTDBValue<CTime> & object_expiration)
631 {
632 // Here the only expiration for the case a record is found needs to be
633 // calculated. The procedure however is a generic one and calculates the
634 // expiration for a not found record. Use it and ignore the second
635 // calculated value.
636 CTime current_time(CTime::eCurrent);
637 TNSTDBValue<CTime> exp_record_found;
638 TNSTDBValue<CTime> exp_record_not_found;
639 x_CalculateExpiration(current_time, ttl, prolong_on_read,
640 object_expiration,
641 exp_record_found, exp_record_not_found);
642
643 const string proc_name = "SetObjectExpiration";
644 CNSTPreciseTime start = CNSTPreciseTime::Current();
645 try {
646 x_PreCheckConnection();
647
648 int status;
649 try {
650 CDatabase db = m_Db->Clone();
651 CQuery query = db.NewQuery();
652
653 query.SetParameter("@object_key", object_key);
654
655 if (exp_record_found.m_IsNull)
656 query.SetNullParameter("@expiration", eSDB_DateTime);
657 else
658 query.SetParameter("@expiration", exp_record_found.m_Value);
659 query.SetParameter("@create_if_not_found", 0, eSDB_Int4);
660
661 query.SetNullParameter("@object_loc", eSDB_String);
662 query.SetNullParameter("@client_id", eSDB_Int8);
663 query.SetOutputParameter("@object_size", eSDB_Int8);
664 query.SetNullParameter("@ttl", eSDB_Int8);
665
666 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
667 query.VerifyDone();
668
669 status = x_CheckStatus(query, proc_name);
670
671 g_DoPerfLogging("MS_SQL_" + proc_name,
672 CNSTPreciseTime::Current() - start,
673 CRequestStatus::e200_Ok);
674 return status;
675 } catch (const std::exception & ex) {
676 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
677 x_PostCheckConnection();
678 throw;
679 } catch (...) {
680 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
681 x_PostCheckConnection();
682 throw;
683 }
684 } catch (...) {
685 g_DoPerfLogging("MS_SQL_" + proc_name,
686 CNSTPreciseTime::Current() - start,
687 CRequestStatus::e500_InternalServerError);
688 throw;
689 }
690 }
691
692
693 int
ExecSP_UpdateUserIDForObject(const string & object_key,Int8 user_id)694 CNSTDatabase::ExecSP_UpdateUserIDForObject(const string & object_key,
695 Int8 user_id)
696 {
697 const string proc_name = "UpdateUserIDForObject";
698 CNSTPreciseTime start = CNSTPreciseTime::Current();
699 try {
700 x_PreCheckConnection();
701
702 try {
703 CDatabase db = m_Db->Clone();
704 CQuery query = db.NewQuery();
705
706 query.SetParameter("@object_key", object_key);
707 query.SetParameter("@u_id", user_id);
708
709 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
710 query.VerifyDone();
711
712 int status = x_CheckStatus(query, proc_name);
713 g_DoPerfLogging("MS_SQL_" + proc_name,
714 CNSTPreciseTime::Current() - start,
715 CRequestStatus::e200_Ok);
716 return status;
717 } catch (const std::exception & ex) {
718 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
719 x_PostCheckConnection();
720 throw;
721 } catch (...) {
722 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
723 x_PostCheckConnection();
724 throw;
725 }
726 } catch (...) {
727 g_DoPerfLogging("MS_SQL_" + proc_name,
728 CNSTPreciseTime::Current() - start,
729 CRequestStatus::e500_InternalServerError);
730 throw;
731 }
732 }
733
734
735 int
ExecSP_RemoveObject(const string & object_key)736 CNSTDatabase::ExecSP_RemoveObject(const string & object_key)
737 {
738 const string proc_name = "RemoveObject";
739 CNSTPreciseTime start = CNSTPreciseTime::Current();
740 try {
741 x_PreCheckConnection();
742
743 int status;
744 try {
745 CDatabase db = m_Db->Clone();
746 CQuery query = db.NewQuery();
747
748 query.SetParameter("@object_key", object_key);
749
750 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
751 query.VerifyDone();
752
753 status = x_CheckStatus(query, proc_name);
754 g_DoPerfLogging("MS_SQL_" + proc_name,
755 CNSTPreciseTime::Current() - start,
756 CRequestStatus::e200_Ok);
757 return status;
758 } catch (const std::exception & ex) {
759 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
760 x_PostCheckConnection();
761 throw;
762 } catch (...) {
763 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
764 x_PostCheckConnection();
765 throw;
766 }
767 } catch (...) {
768 g_DoPerfLogging("MS_SQL_" + proc_name,
769 CNSTPreciseTime::Current() - start,
770 CRequestStatus::e500_InternalServerError);
771 throw;
772 }
773 }
774
775
776 int
ExecSP_SetExpiration(const string & object_key,const TNSTDBValue<CTimeSpan> & ttl,bool create_if_not_found,const string & object_loc,Int8 client_id,TNSTDBValue<Int8> & object_size)777 CNSTDatabase::ExecSP_SetExpiration(const string & object_key,
778 const TNSTDBValue<CTimeSpan> & ttl,
779 bool create_if_not_found,
780 const string & object_loc,
781 Int8 client_id,
782 TNSTDBValue<Int8> & object_size)
783 {
784 const string proc_name = "SetObjectExpiration";
785 CNSTPreciseTime start = CNSTPreciseTime::Current();
786 try {
787 x_PreCheckConnection();
788
789 int status;
790 try {
791 CDatabase db = m_Db->Clone();
792 CQuery query = db.NewQuery();
793
794 query.SetParameter("@object_key", object_key);
795
796 if (ttl.m_IsNull) {
797 query.SetNullParameter("@expiration", eSDB_DateTime);
798 query.SetNullParameter("@ttl", eSDB_Int8);
799 } else {
800 query.SetParameter("@expiration", CTime(CTime::eCurrent) +
801 ttl.m_Value);
802 query.SetParameter("@ttl",
803 static_cast<Int8>(ttl.m_Value.GetAsDouble()));
804 }
805 query.SetParameter("@create_if_not_found", create_if_not_found,
806 eSDB_Int4);
807 query.SetParameter("@object_loc", object_loc);
808 query.SetParameter("@client_id", client_id);
809 query.SetOutputParameter("@object_size", eSDB_Int8);
810
811 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
812 query.VerifyDone();
813
814 status = x_CheckStatus(query, proc_name);
815
816 if (status == kSPStatusOK) {
817 object_size.m_IsNull = query.GetParameter("@object_size").
818 IsNull();
819 if (!object_size.m_IsNull)
820 object_size.m_Value = query.GetParameter("@object_size").
821 AsInt8();
822 }
823
824 g_DoPerfLogging("MS_SQL_" + proc_name,
825 CNSTPreciseTime::Current() - start,
826 CRequestStatus::e200_Ok);
827 return status;
828 } catch (const std::exception & ex) {
829 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
830 x_PostCheckConnection();
831 throw;
832 } catch (...) {
833 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
834 x_PostCheckConnection();
835 throw;
836 }
837 } catch (...) {
838 g_DoPerfLogging("MS_SQL_" + proc_name,
839 CNSTPreciseTime::Current() - start,
840 CRequestStatus::e500_InternalServerError);
841 throw;
842 }
843 }
844
845
846 int
ExecSP_AddAttribute(const string & object_key,const string & object_loc,const string & attr_name,const string & attr_value,Int8 client_id,bool create_if_not_found,const TNSTDBValue<CTimeSpan> & ttl)847 CNSTDatabase::ExecSP_AddAttribute(const string & object_key,
848 const string & object_loc,
849 const string & attr_name,
850 const string & attr_value,
851 Int8 client_id,
852 bool create_if_not_found,
853 const TNSTDBValue<CTimeSpan> & ttl)
854 {
855 const string proc_name = "AddAttribute";
856 CNSTPreciseTime start = CNSTPreciseTime::Current();
857 try {
858 x_PreCheckConnection();
859
860 int status;
861 try {
862 CDatabase db = m_Db->Clone();
863 CQuery query = db.NewQuery();
864
865 query.SetParameter("@object_key", object_key);
866 query.SetParameter("@attr_name", attr_name);
867 query.SetParameter("@attr_value", attr_value, eSDB_Binary);
868 query.SetParameter("@client_id", client_id);
869 query.SetParameter("@create_if_not_found", create_if_not_found,
870 eSDB_Int4);
871 query.SetParameter("@object_loc", object_loc);
872
873 if (ttl.m_IsNull)
874 query.SetNullParameter("@object_expiration", eSDB_DateTime);
875 else
876 query.SetParameter("@object_expiration",
877 CTime(CTime::eCurrent) + ttl.m_Value);
878
879 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
880 query.VerifyDone();
881
882 status = x_CheckStatus(query, proc_name);
883 g_DoPerfLogging("MS_SQL_" + proc_name,
884 CNSTPreciseTime::Current() - start,
885 CRequestStatus::e200_Ok);
886 return status;
887 } catch (const std::exception & ex) {
888 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
889 x_PostCheckConnection();
890 throw;
891 } catch (...) {
892 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
893 x_PostCheckConnection();
894 throw;
895 }
896 } catch (...) {
897 g_DoPerfLogging("MS_SQL_" + proc_name,
898 CNSTPreciseTime::Current() - start,
899 CRequestStatus::e500_InternalServerError);
900 throw;
901 }
902 }
903
904
905 int
ExecSP_GetAttributeNames(const string & object_key,vector<string> & attr_names)906 CNSTDatabase::ExecSP_GetAttributeNames(const string & object_key,
907 vector<string> & attr_names)
908 {
909 const string proc_name = "GetAttributeNames";
910 CNSTPreciseTime start = CNSTPreciseTime::Current();
911 try {
912 x_PreCheckConnection();
913
914 int status;
915 try {
916 CDatabase db = m_Db->Clone();
917 CQuery query = db.NewQuery();
918
919 query.SetParameter("@object_key", object_key);
920 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
921
922 // NOTE: reading result recordset must be done before getting the
923 // status code. And it is safe to iterate even if a recordset
924 // is not there
925 ITERATE(CQuery, qit, query.SingleSet()) {
926 attr_names.push_back(qit["name"].AsString());
927 }
928 query.VerifyDone();
929
930 status = x_CheckStatus(query, proc_name);
931 g_DoPerfLogging("MS_SQL_" + proc_name,
932 CNSTPreciseTime::Current() - start,
933 CRequestStatus::e200_Ok);
934 return status;
935 } catch (const std::exception & ex) {
936 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
937 x_PostCheckConnection();
938 throw;
939 } catch (...) {
940 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
941 x_PostCheckConnection();
942 throw;
943 }
944 } catch (...) {
945 g_DoPerfLogging("MS_SQL_" + proc_name,
946 CNSTPreciseTime::Current() - start,
947 CRequestStatus::e500_InternalServerError);
948 throw;
949 }
950 }
951
952
953 int
ExecSP_GetAttribute(const string & object_key,const string & attr_name,bool need_update,string & value)954 CNSTDatabase::ExecSP_GetAttribute(const string & object_key,
955 const string & attr_name,
956 bool need_update,
957 string & value)
958 {
959 const string proc_name = "GetAttribute";
960 CNSTPreciseTime start = CNSTPreciseTime::Current();
961 try {
962 x_PreCheckConnection();
963
964 int status;
965 try {
966 CDatabase db = m_Db->Clone();
967 CQuery query = db.NewQuery();
968
969 query.SetParameter("@object_key", object_key);
970 query.SetParameter("@attr_name", attr_name);
971 query.SetParameter("@need_update", need_update,
972 eSDB_Int4);
973 query.SetOutputParameter("@attr_value", eSDB_Binary);
974
975 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
976 query.VerifyDone();
977 status = x_CheckStatus(query, proc_name);
978
979 if (status == kSPStatusOK)
980 value = query.GetParameter("@attr_value").AsString();
981 else
982 value = "";
983 g_DoPerfLogging("MS_SQL_" + proc_name,
984 CNSTPreciseTime::Current() - start,
985 CRequestStatus::e200_Ok);
986 return status;
987 } catch (const std::exception & ex) {
988 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
989 x_PostCheckConnection();
990 throw;
991 } catch (...) {
992 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
993 x_PostCheckConnection();
994 throw;
995 }
996 } catch (...) {
997 g_DoPerfLogging("MS_SQL_" + proc_name,
998 CNSTPreciseTime::Current() - start,
999 CRequestStatus::e500_InternalServerError);
1000 throw;
1001 }
1002 }
1003
1004
1005 int
ExecSP_DelAttribute(const string & object_key,const string & attr_name)1006 CNSTDatabase::ExecSP_DelAttribute(const string & object_key,
1007 const string & attr_name)
1008 {
1009 const string proc_name = "DelAttribute";
1010 CNSTPreciseTime start = CNSTPreciseTime::Current();
1011 try {
1012 x_PreCheckConnection();
1013
1014 int status;
1015 try {
1016 CDatabase db = m_Db->Clone();
1017 CQuery query = db.NewQuery();
1018
1019 query.SetParameter("@object_key", object_key);
1020 query.SetParameter("@attr_name", attr_name);
1021
1022 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1023 query.VerifyDone();
1024
1025 status = x_CheckStatus(query, proc_name);
1026 g_DoPerfLogging("MS_SQL_" + proc_name,
1027 CNSTPreciseTime::Current() - start,
1028 CRequestStatus::e200_Ok);
1029 return status;
1030 } catch (const std::exception & ex) {
1031 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1032 x_PostCheckConnection();
1033 throw;
1034 } catch (...) {
1035 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1036 x_PostCheckConnection();
1037 throw;
1038 }
1039 } catch (...) {
1040 g_DoPerfLogging("MS_SQL_" + proc_name,
1041 CNSTPreciseTime::Current() - start,
1042 CRequestStatus::e500_InternalServerError);
1043 throw;
1044 }
1045 }
1046
1047
1048 int
ExecSP_GetObjectFixedAttributes(const string & object_key,TNSTDBValue<CTime> & expiration,TNSTDBValue<CTime> & creation,TNSTDBValue<CTime> & obj_read,TNSTDBValue<CTime> & obj_write,TNSTDBValue<CTime> & attr_read,TNSTDBValue<CTime> & attr_write,TNSTDBValue<Int8> & read_count,TNSTDBValue<Int8> & write_count,TNSTDBValue<string> & client_name,TNSTDBValue<string> & user_namespace,TNSTDBValue<string> & user_name,TNSTDBValue<Int8> & obj_ttl)1049 CNSTDatabase::ExecSP_GetObjectFixedAttributes(
1050 const string & object_key,
1051 TNSTDBValue<CTime> & expiration,
1052 TNSTDBValue<CTime> & creation,
1053 TNSTDBValue<CTime> & obj_read,
1054 TNSTDBValue<CTime> & obj_write,
1055 TNSTDBValue<CTime> & attr_read,
1056 TNSTDBValue<CTime> & attr_write,
1057 TNSTDBValue<Int8> & read_count,
1058 TNSTDBValue<Int8> & write_count,
1059 TNSTDBValue<string> & client_name,
1060 TNSTDBValue<string> & user_namespace,
1061 TNSTDBValue<string> & user_name,
1062 TNSTDBValue<Int8> & obj_ttl
1063 )
1064 {
1065 const string proc_name = "GetObjectFixedAttributes";
1066 CNSTPreciseTime start = CNSTPreciseTime::Current();
1067 try {
1068 x_PreCheckConnection();
1069
1070 int status;
1071 try {
1072 CDatabase db = m_Db->Clone();
1073 CQuery query = db.NewQuery();
1074
1075 query.SetParameter("@object_key", object_key);
1076 query.SetOutputParameter("@expiration", eSDB_DateTime);
1077 query.SetOutputParameter("@creation", eSDB_DateTime);
1078 query.SetOutputParameter("@obj_read", eSDB_DateTime);
1079 query.SetOutputParameter("@obj_write", eSDB_DateTime);
1080 query.SetOutputParameter("@attr_read", eSDB_DateTime);
1081 query.SetOutputParameter("@attr_write", eSDB_DateTime);
1082 query.SetOutputParameter("@read_cnt", eSDB_Int8);
1083 query.SetOutputParameter("@write_cnt", eSDB_Int8);
1084 query.SetOutputParameter("@client_name", eSDB_String);
1085 query.SetOutputParameter("@user_namespace", eSDB_String);
1086 query.SetOutputParameter("@user_name", eSDB_String);
1087 query.SetOutputParameter("@obj_ttl", eSDB_Int8);
1088
1089 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1090 query.VerifyDone();
1091 status = x_CheckStatus(query, proc_name);
1092
1093 if (status == kSPStatusOK) {
1094 expiration.m_IsNull = query.GetParameter("@expiration").
1095 IsNull();
1096 if (!expiration.m_IsNull)
1097 expiration.m_Value = query.GetParameter("@expiration").
1098 AsDateTime();
1099 creation.m_IsNull = query.GetParameter("@creation").IsNull();
1100 if (!creation.m_IsNull)
1101 creation.m_Value = query.GetParameter("@creation").
1102 AsDateTime();
1103 obj_read.m_IsNull = query.GetParameter("@obj_read").IsNull();
1104 if (!obj_read.m_IsNull)
1105 obj_read.m_Value = query.GetParameter("@obj_read").
1106 AsDateTime();
1107 obj_write.m_IsNull = query.GetParameter("@obj_write").IsNull();
1108 if (!obj_write.m_IsNull)
1109 obj_write.m_Value = query.GetParameter("@obj_write").
1110 AsDateTime();
1111 attr_read.m_IsNull = query.GetParameter("@attr_read").IsNull();
1112 if (!attr_read.m_IsNull)
1113 attr_read.m_Value = query.GetParameter("@attr_read").
1114 AsDateTime();
1115 attr_write.m_IsNull = query.GetParameter("@attr_write").
1116 IsNull();
1117 if (!attr_write.m_IsNull)
1118 attr_write.m_Value = query.GetParameter("@attr_write").
1119 AsDateTime();
1120 read_count.m_IsNull = query.GetParameter("@read_cnt").IsNull();
1121 if (!read_count.m_IsNull)
1122 read_count.m_Value = query.GetParameter("@read_cnt").
1123 AsInt8();
1124 write_count.m_IsNull = query.GetParameter("@write_cnt").
1125 IsNull();
1126 if (!write_count.m_IsNull)
1127 write_count.m_Value = query.GetParameter("@write_cnt").
1128 AsInt8();
1129 client_name.m_IsNull = query.GetParameter("@client_name").
1130 IsNull();
1131 if (!client_name.m_IsNull)
1132 client_name.m_Value = query.GetParameter("@client_name").
1133 AsString();
1134 user_namespace.m_IsNull = query.GetParameter("@user_namespace").
1135 IsNull();
1136 if (!user_namespace.m_IsNull)
1137 user_namespace.m_Value = query.
1138 GetParameter("@user_namespace").
1139 AsString();
1140 user_name.m_IsNull = query.GetParameter("@user_name").
1141 IsNull();
1142 if (!user_name.m_IsNull)
1143 user_name.m_Value = query.GetParameter("@user_name").
1144 AsString();
1145
1146 obj_ttl.m_IsNull = query.GetParameter("@obj_ttl").
1147 IsNull();
1148 if (!obj_ttl.m_IsNull)
1149 obj_ttl.m_Value = query.GetParameter("@obj_ttl").
1150 AsInt8();
1151 }
1152 g_DoPerfLogging("MS_SQL_" + proc_name,
1153 CNSTPreciseTime::Current() - start,
1154 CRequestStatus::e200_Ok);
1155 return status;
1156 } catch (const std::exception & ex) {
1157 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1158 x_PostCheckConnection();
1159 throw;
1160 } catch (...) {
1161 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1162 x_PostCheckConnection();
1163 throw;
1164 }
1165 } catch (...) {
1166 g_DoPerfLogging("MS_SQL_" + proc_name,
1167 CNSTPreciseTime::Current() - start,
1168 CRequestStatus::e500_InternalServerError);
1169 throw;
1170 }
1171 }
1172
1173
1174 int
ExecSP_GetObjectExpiration(const string & object_key,TNSTDBValue<CTime> & expiration,TNSTDBValue<Int8> & individual_object_ttl)1175 CNSTDatabase::ExecSP_GetObjectExpiration(
1176 const string & object_key,
1177 TNSTDBValue<CTime> & expiration,
1178 TNSTDBValue<Int8> & individual_object_ttl)
1179 {
1180 const string proc_name = "GetObjectExpiration";
1181 CNSTPreciseTime start = CNSTPreciseTime::Current();
1182 try {
1183 x_PreCheckConnection();
1184
1185 int status;
1186 try {
1187 CDatabase db = m_Db->Clone();
1188 CQuery query = db.NewQuery();
1189
1190 query.SetParameter("@object_key", object_key);
1191 query.SetOutputParameter("@expiration", eSDB_DateTime);
1192 query.SetOutputParameter("@ttl", eSDB_Int8);
1193
1194 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1195 query.VerifyDone();
1196 status = x_CheckStatus(query, proc_name);
1197
1198 if (status == kSPStatusOK) {
1199 expiration.m_IsNull = query.GetParameter("@expiration").
1200 IsNull();
1201 if (!expiration.m_IsNull)
1202 expiration.m_Value = query.GetParameter("@expiration").
1203 AsDateTime();
1204 individual_object_ttl.m_IsNull = query.GetParameter("@ttl").
1205 IsNull();
1206 if (!individual_object_ttl.m_IsNull)
1207 individual_object_ttl.m_Value = query.GetParameter("@ttl").
1208 AsInt8();
1209 }
1210 g_DoPerfLogging("MS_SQL_" + proc_name,
1211 CNSTPreciseTime::Current() - start,
1212 CRequestStatus::e200_Ok);
1213 return status;
1214 } catch (const std::exception & ex) {
1215 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1216 x_PostCheckConnection();
1217 throw;
1218 } catch (...) {
1219 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1220 x_PostCheckConnection();
1221 throw;
1222 }
1223 } catch (...) {
1224 g_DoPerfLogging("MS_SQL_" + proc_name,
1225 CNSTPreciseTime::Current() - start,
1226 CRequestStatus::e500_InternalServerError);
1227 throw;
1228 }
1229 }
1230
1231
1232 map<string, string>
ExecSP_GetGeneralDBInfo(void)1233 CNSTDatabase::ExecSP_GetGeneralDBInfo(void)
1234 {
1235 map<string, string> result;
1236 const string proc_name = "sp_spaceused";
1237 CNSTPreciseTime start = CNSTPreciseTime::Current();
1238 try {
1239 x_PreCheckConnection();
1240
1241 try {
1242 CDatabase db = m_Db->Clone();
1243 CQuery query = db.NewQuery();
1244
1245 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1246
1247 // sp_spaceused provides two recordsets 1 record each, e.g.
1248 // NETSTORAGE 224.88 MB 98.34 MB
1249 // 1696 KB 752 KB 736 KB 208 KB
1250 ITERATE(CQuery, qit, query.SingleSet()) {
1251 for (size_t k = 1; k <= qit.GetTotalColumns(); ++k) {
1252 string columnName = qit.GetColumnName(k);
1253 result[columnName] = qit[k].AsString();
1254 }
1255 }
1256 query.VerifyDone();
1257
1258 g_DoPerfLogging("MS_SQL_" + proc_name,
1259 CNSTPreciseTime::Current() - start,
1260 CRequestStatus::e200_Ok);
1261 return result;
1262 } catch (const std::exception & ex) {
1263 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1264 x_PostCheckConnection();
1265 throw;
1266 } catch (...) {
1267 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1268 x_PostCheckConnection();
1269 throw;
1270 }
1271 } catch (...) {
1272 g_DoPerfLogging("MS_SQL_" + proc_name,
1273 CNSTPreciseTime::Current() - start,
1274 CRequestStatus::e500_InternalServerError);
1275 throw;
1276 }
1277 }
1278
1279
1280 map<string, string>
ExecSP_GetStatDBInfo(void)1281 CNSTDatabase::ExecSP_GetStatDBInfo(void)
1282 {
1283 map<string, string> result;
1284 const string proc_name = "GetStatInfo";
1285 CNSTPreciseTime start = CNSTPreciseTime::Current();
1286 try {
1287 x_PreCheckConnection();
1288
1289 try {
1290 CDatabase db = m_Db->Clone();
1291 CQuery query = db.NewQuery();
1292
1293 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1294
1295 ITERATE(CQuery, qit, query.SingleSet()) {
1296 for (size_t k = 1; k <= qit.GetTotalColumns(); ++k) {
1297 string columnName = qit.GetColumnName(k);
1298 result[columnName] = qit[k].AsString();
1299 }
1300 }
1301 query.VerifyDone();
1302
1303 g_DoPerfLogging("MS_SQL_" + proc_name,
1304 CNSTPreciseTime::Current() - start,
1305 CRequestStatus::e200_Ok);
1306 return result;
1307 } catch (const std::exception & ex) {
1308 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1309 x_PostCheckConnection();
1310 throw;
1311 } catch (...) {
1312 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1313 x_PostCheckConnection();
1314 throw;
1315 }
1316 } catch (...) {
1317 g_DoPerfLogging("MS_SQL_" + proc_name,
1318 CNSTPreciseTime::Current() - start,
1319 CRequestStatus::e500_InternalServerError);
1320 throw;
1321 }
1322 }
1323
1324
1325 int
ExecSP_GetClientObjects(const string & client_name,TNSTDBValue<Int8> limit,Int8 & total,vector<string> & locators)1326 CNSTDatabase::ExecSP_GetClientObjects(const string & client_name,
1327 TNSTDBValue<Int8> limit,
1328 Int8 & total,
1329 vector<string> & locators)
1330 {
1331 const string proc_name = "GetClientObjects";
1332 CNSTPreciseTime start = CNSTPreciseTime::Current();
1333 try {
1334 x_PreCheckConnection();
1335
1336 int status;
1337 try {
1338 CDatabase db = m_Db->Clone();
1339 CQuery query = db.NewQuery();
1340
1341 query.SetParameter("@client_name", client_name);
1342 if (limit.m_IsNull)
1343 query.SetNullParameter("@limit", eSDB_Int8);
1344 else
1345 query.SetParameter("@limit", limit.m_Value);
1346 query.SetOutputParameter("@total_object_cnt", eSDB_Int8);
1347
1348 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1349
1350 // NOTE: reading result recordset must be done before getting the
1351 // status code
1352 ITERATE(CQuery, qit, query.SingleSet()) {
1353 locators.push_back(qit["object_loc"].AsString());
1354 }
1355
1356 if (!query.GetParameter("@total_object_cnt").IsNull())
1357 total = query.GetParameter("@total_object_cnt").AsInt8();
1358 query.VerifyDone();
1359
1360 status = x_CheckStatus(query, proc_name);
1361 g_DoPerfLogging("MS_SQL_" + proc_name,
1362 CNSTPreciseTime::Current() - start,
1363 CRequestStatus::e200_Ok);
1364 return status;
1365 } catch (const std::exception & ex) {
1366 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1367 x_PostCheckConnection();
1368 throw;
1369 } catch (...) {
1370 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1371 x_PostCheckConnection();
1372 throw;
1373 }
1374 } catch (...) {
1375 g_DoPerfLogging("MS_SQL_" + proc_name,
1376 CNSTPreciseTime::Current() - start,
1377 CRequestStatus::e500_InternalServerError);
1378 throw;
1379 }
1380 }
1381
1382
1383 int
ExecSP_GetUserObjects(const string & user_name,const string & user_name_space,TNSTDBValue<Int8> limit,Int8 & total,vector<string> & locators)1384 CNSTDatabase::ExecSP_GetUserObjects(const string & user_name,
1385 const string & user_name_space,
1386 TNSTDBValue<Int8> limit,
1387 Int8 & total,
1388 vector<string> & locators)
1389 {
1390 const string proc_name = "GetUserObjects";
1391 CNSTPreciseTime start = CNSTPreciseTime::Current();
1392 try {
1393 x_PreCheckConnection();
1394
1395 int status;
1396 try {
1397 CDatabase db = m_Db->Clone();
1398 CQuery query = db.NewQuery();
1399
1400 query.SetParameter("@user_name", user_name);
1401 query.SetParameter("@user_name_space", user_name_space);
1402 if (limit.m_IsNull)
1403 query.SetNullParameter("@limit", eSDB_Int8);
1404 else
1405 query.SetParameter("@limit", limit.m_Value);
1406 query.SetOutputParameter("@total_object_cnt", eSDB_Int8);
1407
1408 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1409
1410 // NOTE: reading result recordset must be done before getting the
1411 // status code
1412 ITERATE(CQuery, qit, query.SingleSet()) {
1413 locators.push_back(qit["object_loc"].AsString());
1414 }
1415
1416 if (!query.GetParameter("@total_object_cnt").IsNull())
1417 total = query.GetParameter("@total_object_cnt").AsInt8();
1418 query.VerifyDone();
1419
1420 status = x_CheckStatus(query, proc_name);
1421 g_DoPerfLogging("MS_SQL_" + proc_name,
1422 CNSTPreciseTime::Current() - start,
1423 CRequestStatus::e200_Ok);
1424 return status;
1425 } catch (const std::exception & ex) {
1426 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1427 x_PostCheckConnection();
1428 throw;
1429 } catch (...) {
1430 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1431 x_PostCheckConnection();
1432 throw;
1433 }
1434 } catch (...) {
1435 g_DoPerfLogging("MS_SQL_" + proc_name,
1436 CNSTPreciseTime::Current() - start,
1437 CRequestStatus::e500_InternalServerError);
1438 throw;
1439 }
1440 }
1441
1442
1443 int
ExecSP_GetClients(vector<string> & names)1444 CNSTDatabase::ExecSP_GetClients(vector<string> & names)
1445 {
1446 const string proc_name = "GetClients";
1447 CNSTPreciseTime start = CNSTPreciseTime::Current();
1448 try {
1449 x_PreCheckConnection();
1450
1451 int status;
1452 try {
1453 CDatabase db = m_Db->Clone();
1454 CQuery query = db.NewQuery();
1455
1456 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1457
1458 // NOTE: reading result recordset must be done before getting the
1459 // status code. And it is safe to iterate over a recordset
1460 // even if there is no one.
1461 ITERATE(CQuery, qit, query.SingleSet()) {
1462 names.push_back(qit["name"].AsString());
1463 }
1464 query.VerifyDone();
1465
1466 status = x_CheckStatus(query, proc_name);
1467 g_DoPerfLogging("MS_SQL_" + proc_name,
1468 CNSTPreciseTime::Current() - start,
1469 CRequestStatus::e200_Ok);
1470 return status;
1471 } catch (const std::exception & ex) {
1472 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1473 x_PostCheckConnection();
1474 throw;
1475 } catch (...) {
1476 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1477 x_PostCheckConnection();
1478 throw;
1479 }
1480 } catch (...) {
1481 g_DoPerfLogging("MS_SQL_" + proc_name,
1482 CNSTPreciseTime::Current() - start,
1483 CRequestStatus::e500_InternalServerError);
1484 throw;
1485 }
1486 }
1487
1488
1489 int
ExecSP_GetUsers(vector<pair<string,string>> & users)1490 CNSTDatabase::ExecSP_GetUsers(vector< pair<string, string> > & users)
1491 {
1492 const string proc_name = "GetUsers";
1493 CNSTPreciseTime start = CNSTPreciseTime::Current();
1494 try {
1495 x_PreCheckConnection();
1496
1497 int status;
1498 try {
1499 CDatabase db = m_Db->Clone();
1500 CQuery query = db.NewQuery();
1501
1502 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1503
1504 // NOTE: reading result recordset must be done before getting the
1505 // status code. And it is safe to iterate over a recordset
1506 // even if there is no one.
1507 ITERATE(CQuery, qit, query.SingleSet()) {
1508 users.push_back(make_pair(qit["name"].AsString(),
1509 qit["name_space"].AsString()));
1510 }
1511 query.VerifyDone();
1512
1513 status = x_CheckStatus(query, proc_name);
1514 g_DoPerfLogging("MS_SQL_" + proc_name,
1515 CNSTPreciseTime::Current() - start,
1516 CRequestStatus::e200_Ok);
1517 return status;
1518 } catch (const std::exception & ex) {
1519 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1520 x_PostCheckConnection();
1521 throw;
1522 } catch (...) {
1523 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1524 x_PostCheckConnection();
1525 throw;
1526 }
1527 } catch (...) {
1528 g_DoPerfLogging("MS_SQL_" + proc_name,
1529 CNSTPreciseTime::Current() - start,
1530 CRequestStatus::e500_InternalServerError);
1531 throw;
1532 }
1533 }
1534
1535
1536 int
ExecSP_DoesObjectExist(const string & object_key)1537 CNSTDatabase::ExecSP_DoesObjectExist(const string & object_key)
1538 {
1539 const string proc_name = "DoesObjectExist";
1540 CNSTPreciseTime start = CNSTPreciseTime::Current();
1541 try {
1542 x_PreCheckConnection();
1543
1544 int status;
1545 try {
1546 CDatabase db = m_Db->Clone();
1547 CQuery query = db.NewQuery();
1548
1549 query.SetParameter("@object_key", object_key);
1550
1551 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1552 query.VerifyDone();
1553
1554 status = x_CheckStatus(query, proc_name);
1555 g_DoPerfLogging("MS_SQL_" + proc_name,
1556 CNSTPreciseTime::Current() - start,
1557 CRequestStatus::e200_Ok);
1558 return status;
1559 } catch (const std::exception & ex) {
1560 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1561 x_PostCheckConnection();
1562 throw;
1563 } catch (...) {
1564 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1565 x_PostCheckConnection();
1566 throw;
1567 }
1568 } catch (...) {
1569 g_DoPerfLogging("MS_SQL_" + proc_name,
1570 CNSTPreciseTime::Current() - start,
1571 CRequestStatus::e500_InternalServerError);
1572 throw;
1573 }
1574 }
1575
1576
1577 int
ExecSP_GetObjectSizeAndLocator(const string & object_key,TNSTDBValue<Int8> & object_size,TNSTDBValue<string> & object_locator)1578 CNSTDatabase::ExecSP_GetObjectSizeAndLocator(
1579 const string & object_key,
1580 TNSTDBValue<Int8> & object_size,
1581 TNSTDBValue<string> & object_locator)
1582 {
1583 const string proc_name = "GetObjectSizeAndLocator";
1584 CNSTPreciseTime start = CNSTPreciseTime::Current();
1585 try {
1586 x_PreCheckConnection();
1587
1588 int status;
1589 try {
1590 CDatabase db = m_Db->Clone();
1591 CQuery query = db.NewQuery();
1592 query.SetParameter("@object_key", object_key);
1593 query.SetOutputParameter("@object_size", eSDB_Int8);
1594 query.SetOutputParameter("@object_locator", eSDB_String);
1595
1596 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1597 query.VerifyDone();
1598 status = x_CheckStatus(query, proc_name);
1599
1600 if (status == kSPStatusOK) {
1601 object_size.m_IsNull = query.
1602 GetParameter("@object_size").IsNull();
1603 if (!object_size.m_IsNull)
1604 object_size.m_Value = query.
1605 GetParameter("@object_size").AsInt8();
1606 object_locator.m_IsNull = query.
1607 GetParameter("@object_locator").IsNull();
1608 if (!object_locator.m_IsNull)
1609 object_locator.m_Value = query.
1610 GetParameter("@object_locator").AsString();
1611 }
1612
1613 g_DoPerfLogging("MS_SQL_" + proc_name,
1614 CNSTPreciseTime::Current() - start,
1615 CRequestStatus::e200_Ok);
1616 return status;
1617 } catch (const std::exception & ex) {
1618 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1619 x_PostCheckConnection();
1620 throw;
1621 } catch (...) {
1622 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1623 x_PostCheckConnection();
1624 throw;
1625 }
1626 } catch (...) {
1627 g_DoPerfLogging("MS_SQL_" + proc_name,
1628 CNSTPreciseTime::Current() - start,
1629 CRequestStatus::e500_InternalServerError);
1630 throw;
1631 }
1632 }
1633
1634
1635 int
ExecSP_GetObjectSize(const string & object_key,TNSTDBValue<Int8> & object_size)1636 CNSTDatabase::ExecSP_GetObjectSize(const string & object_key,
1637 TNSTDBValue<Int8> & object_size)
1638 {
1639 const string proc_name = "GetObjectSize";
1640 CNSTPreciseTime start = CNSTPreciseTime::Current();
1641 try {
1642 x_PreCheckConnection();
1643
1644 int status;
1645 try {
1646 CDatabase db = m_Db->Clone();
1647 CQuery query = db.NewQuery();
1648
1649 query.SetParameter("@object_key", object_key);
1650 query.SetOutputParameter("@object_size", eSDB_Int8);
1651
1652 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1653 query.VerifyDone();
1654 status = x_CheckStatus(query, proc_name);
1655
1656 if (status == kSPStatusOK) {
1657 object_size.m_IsNull = query.GetParameter("@object_size").
1658 IsNull();
1659 if (!object_size.m_IsNull)
1660 object_size.m_Value = query.GetParameter("@object_size").
1661 AsInt8();
1662 }
1663
1664 g_DoPerfLogging("MS_SQL_" + proc_name,
1665 CNSTPreciseTime::Current() - start,
1666 CRequestStatus::e200_Ok);
1667 return status;
1668 } catch (const std::exception & ex) {
1669 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1670 x_PostCheckConnection();
1671 throw;
1672 } catch (...) {
1673 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1674 x_PostCheckConnection();
1675 throw;
1676 }
1677 } catch (...) {
1678 g_DoPerfLogging("MS_SQL_" + proc_name,
1679 CNSTPreciseTime::Current() - start,
1680 CRequestStatus::e500_InternalServerError);
1681 throw;
1682 }
1683 }
1684
1685
1686 int
ExecSP_UpdateObjectSizeIfNULL(const string & object_key,TNSTDBValue<Int8> & object_size)1687 CNSTDatabase::ExecSP_UpdateObjectSizeIfNULL(const string & object_key,
1688 TNSTDBValue<Int8> & object_size)
1689 {
1690 const string proc_name = "UpdateObjectSizeIfNULL";
1691 CNSTPreciseTime start = CNSTPreciseTime::Current();
1692 try {
1693 x_PreCheckConnection();
1694
1695 int status;
1696 try {
1697 CDatabase db = m_Db->Clone();
1698 CQuery query = db.NewQuery();
1699
1700 query.SetParameter("@object_key", object_key);
1701 query.SetOutputParameter("@object_size", eSDB_Int8);
1702
1703 query.ExecuteSP(proc_name, GetExecuteSPTimeout());
1704 query.VerifyDone();
1705 status = x_CheckStatus(query, proc_name);
1706
1707 if (status == kSPStatusOK) {
1708 object_size.m_IsNull = query.GetParameter("@object_size").
1709 IsNull();
1710 if (!object_size.m_IsNull)
1711 object_size.m_Value = query.GetParameter("@object_size").
1712 AsInt8();
1713 }
1714
1715 g_DoPerfLogging("MS_SQL_" + proc_name,
1716 CNSTPreciseTime::Current() - start,
1717 CRequestStatus::e200_Ok);
1718 return status;
1719 } catch (const std::exception & ex) {
1720 m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1721 x_PostCheckConnection();
1722 throw;
1723 } catch (...) {
1724 m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1725 x_PostCheckConnection();
1726 throw;
1727 }
1728 } catch (...) {
1729 g_DoPerfLogging("MS_SQL_" + proc_name,
1730 CNSTPreciseTime::Current() - start,
1731 CRequestStatus::e500_InternalServerError);
1732 throw;
1733 }
1734 }
1735
1736
x_PreCheckConnection(void)1737 void CNSTDatabase::x_PreCheckConnection(void)
1738 {
1739 CFastMutexGuard guard(m_DbLock);
1740
1741 if (m_Db == NULL || !m_Connected)
1742 NCBI_THROW(CNetStorageServerException, eDatabaseError,
1743 "There is no connection to metadata information database");
1744
1745 // It is possible that a connection has been lost and restored while there
1746 // were no activities
1747 if (!m_Db->IsConnected(CDatabase::eFastCheck)) {
1748 try {
1749 m_Db->Close();
1750 m_Db->Connect();
1751 } catch (...) {
1752 // To avoid interfering the connection restoring thread nothing is
1753 // done here. Basically the fact that we are here means there is no
1754 // connection anymore. The exception is suppressed however a stored
1755 // procedure execution exception will be generated a few moments
1756 // later and a normal procedure of the connection restoration will
1757 // be activated.
1758 }
1759 }
1760 }
1761
1762
x_PostCheckConnection(void)1763 void CNSTDatabase::x_PostCheckConnection(void)
1764 {
1765 CFastMutexGuard guard(m_DbLock);
1766
1767 if (m_Db == NULL)
1768 return; // It must never happened - the existance of the m_Db is
1769 // checked in the pre condition
1770
1771 if (!m_Db->IsConnected(CDatabase::eFastCheck)) {
1772 m_Connected = false;
1773 m_Server->RegisterAlert(eDBConnect, "Database connection lost");
1774 ERR_POST(Critical << "Database connection has been lost");
1775 m_RestoreConnectionThread->Wakeup();
1776 }
1777 }
1778
1779
x_CheckStatus(CQuery & query,const string & procedure)1780 int CNSTDatabase::x_CheckStatus(CQuery & query,
1781 const string & procedure)
1782 {
1783 int status = query.GetStatus();
1784 if (status > 0)
1785 NCBI_THROW(CNetStorageServerException, eDatabaseError,
1786 "Error executing " + procedure + " stored "
1787 "procedure (return code " + NStr::NumericToString(status) +
1788 "). See MS SQL log for details.");
1789 return status;
1790 }
1791
1792
x_ReadDbAccessInfo(bool is_initialization)1793 bool CNSTDatabase::x_ReadDbAccessInfo(bool is_initialization)
1794 {
1795 CNetStorageDApp * app = dynamic_cast<CNetStorageDApp*>
1796 (CNcbiApplication::Instance());
1797 const CNcbiRegistry & reg = app->GetConfig();
1798
1799 m_DbAccessInfo.m_Service = reg.GetString("database", "service", "");
1800 m_DbAccessInfo.m_Database = reg.GetString("database", "database", "");
1801 m_DbAccessInfo.m_UserName = reg.GetString("database", "user_name", "");
1802 m_SPTimeout = CTimeout(reg.GetDouble("database",
1803 "execute_sp_timeout",
1804 default_execute_sp_timeout,
1805 0, IRegistry::eReturn));
1806
1807 // Try to decrypt
1808 try {
1809 m_DbAccessInfo.m_Password = reg.GetEncryptedString("database",
1810 "password",
1811 IRegistry::fPlaintextAllowed);
1812 } catch (const CRegistryException & ex) {
1813 if (is_initialization) {
1814 if (ex.GetErrCode() == CRegistryException::eDecryptionFailed) {
1815 m_Server->RegisterAlert(eDecryptDBPass, string(ex.what()));
1816 ERR_POST(Critical << "Decrypting [database]/password "
1817 "error: " << ex);
1818 }
1819 }
1820 return false;
1821 }
1822 return true;
1823 }
1824
1825
x_CreateDatabase(bool is_initialization)1826 void CNSTDatabase::x_CreateDatabase(bool is_initialization)
1827 {
1828 if (x_ReadDbAccessInfo(is_initialization)) {
1829 string uri = "dbapi://" + m_DbAccessInfo.m_UserName +
1830 ":" + m_DbAccessInfo.m_Password +
1831 "@" + m_DbAccessInfo.m_Service +
1832 "/" + m_DbAccessInfo.m_Database;
1833
1834 CSDB_ConnectionParam db_params(uri);
1835 m_Db = new CDatabase(db_params);
1836 }
1837 }
1838
1839
1840 // Calculates the new object expiration for two cases:
1841 // - object is found in the DB
1842 // - object is not found in the DB (and thus should be created)
1843 void
x_CalculateExpiration(const CTime & current_time,const TNSTDBValue<CTimeSpan> & ttl,const TNSTDBValue<CTimeSpan> & prolong,const TNSTDBValue<CTime> & object_expiration,TNSTDBValue<CTime> & exp_record_found,TNSTDBValue<CTime> & exp_record_not_found)1844 CNSTDatabase::x_CalculateExpiration(
1845 const CTime & current_time,
1846 const TNSTDBValue<CTimeSpan> & ttl,
1847 const TNSTDBValue<CTimeSpan> & prolong,
1848 const TNSTDBValue<CTime> & object_expiration,
1849 TNSTDBValue<CTime> & exp_record_found,
1850 TNSTDBValue<CTime> & exp_record_not_found)
1851 {
1852 if (prolong.m_IsNull) {
1853 // This could happen only if:
1854 // - a prolong is configured as a <multiplier> ttl
1855 // - service TTL is configured as infinity
1856 // - the object individual TTL is not set
1857 exp_record_found.m_IsNull = true;
1858 exp_record_not_found.m_IsNull = true;
1859 return;
1860 }
1861
1862 // Here: prolong value is finite
1863 CTimeSpan prolong_val = prolong.m_Value;
1864
1865 if (prolong_val.IsEmpty()) {
1866 // Prolong time has NOT been configured
1867 if (object_expiration.m_IsNull) {
1868 exp_record_found.m_IsNull = true;
1869 if (ttl.m_IsNull) {
1870 exp_record_not_found.m_IsNull = true;
1871 } else {
1872 exp_record_not_found.m_IsNull = false;
1873 exp_record_not_found.m_Value = current_time + ttl.m_Value;
1874 }
1875 } else {
1876 exp_record_found.m_IsNull = false;
1877 exp_record_found.m_Value = object_expiration.m_Value;
1878
1879 // Record exists (otherwise the object_expiration is NULL).
1880 // So the expiration for the case the record is not found is
1881 // not strictly required. However, to be on the safe side set it
1882 // too.
1883 if (ttl.m_IsNull) {
1884 exp_record_not_found.m_IsNull = true;
1885 } else {
1886 exp_record_not_found.m_IsNull = false;
1887 exp_record_not_found.m_Value = current_time + ttl.m_Value;
1888 }
1889 }
1890 } else {
1891 // Prolong time has been configured
1892 if (object_expiration.m_IsNull) {
1893 exp_record_found.m_IsNull = true;
1894 if (ttl.m_IsNull) {
1895 exp_record_not_found.m_IsNull = true;
1896 } else {
1897 exp_record_not_found.m_IsNull = false;
1898 if (ttl.m_Value > prolong_val)
1899 exp_record_not_found.m_Value = current_time + ttl.m_Value;
1900 else
1901 exp_record_not_found.m_Value = current_time + prolong_val;
1902 }
1903 } else {
1904 exp_record_found.m_IsNull = false;
1905 if (object_expiration.m_Value > current_time + prolong_val)
1906 exp_record_found.m_Value = object_expiration.m_Value;
1907 else
1908 exp_record_found.m_Value = current_time + prolong_val;
1909
1910 // Record exists (otherwise the object_expiration is NULL).
1911 // So the expiration for the case the record is not found is
1912 // not strictly required. However, to be on the safe side set it
1913 // too.
1914 if (ttl.m_IsNull) {
1915 exp_record_not_found.m_IsNull = true;
1916 } else {
1917 exp_record_not_found.m_IsNull = false;
1918 if (ttl.m_Value > prolong_val)
1919 exp_record_not_found.m_Value = current_time + ttl.m_Value;
1920 else
1921 exp_record_not_found.m_Value = current_time + prolong_val;
1922 }
1923 }
1924 }
1925 }
1926
1927
1928 CTimeout
GetExecuteSPTimeout(void)1929 CNSTDatabase::GetExecuteSPTimeout(void)
1930 {
1931 CFastMutexGuard lock(m_SPTimeoutMutex);
1932 return m_SPTimeout;
1933 }
1934
1935
1936 END_NCBI_SCOPE
1937
1938