NCBI C++ ToolKit
nst_database.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: nst_database.cpp 99965 2023-05-25 14:06:44Z 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>
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 
47 
48 
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 {
59  this, m_DbLock));
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)
73 }
74 
75 
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);
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());
93  } catch (...) {
94  m_Server->RegisterAlert(eDBConnect, "Unknown DB connection error");
95  ERR_POST("Unknown exception while connecting to the database");
97  }
98  }
99 }
100 
101 
103 {
107 
108  if (m_Db != NULL) {
109  if (m_Connected)
110  m_Db->Close();
111  delete m_Db;
112  }
113 }
114 
115 
116 CJsonNode
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",
124  0, IRegistry::eReturn);
125  if (current_timeout == new_timeout)
126  return CJsonNode::NewNullNode();
127 
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 
136  m_SPTimeout.Set(new_timeout);
137  return diff;
138 }
139 
140 
141 int
142 CNSTDatabase::ExecSP_CreateClient(const string & client, Int8 & client_id)
143 {
144  const string proc_name = "CreateClient";
146  try {
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,
170  return status;
171  } catch (const std::exception & ex) {
172  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
174  throw;
175  } catch (...) {
176  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
178  throw;
179  }
180  } catch (...) {
181  g_DoPerfLogging("MS_SQL_" + proc_name,
182  CNSTPreciseTime::Current() - start,
184  throw;
185  }
186 }
187 
188 
189 int
191 {
192  const string proc_name = "CreateUser";
194  try {
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,
219  return status;
220  } catch (const std::exception & ex) {
221  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
223  throw;
224  } catch (...) {
225  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
227  throw;
228  }
229  } catch (...) {
230  g_DoPerfLogging("MS_SQL_" + proc_name,
231  CNSTPreciseTime::Current() - start,
233  throw;
234  }
235 }
236 
237 
238 int
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";
251  try {
253 
254  int status;
255  try {
256  CNetStorageObjectLoc object_loc_struct(
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,
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());
294  throw;
295  } catch (...) {
296  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
298  throw;
299  }
300  } catch (...) {
301  g_DoPerfLogging("MS_SQL_" + proc_name_for_perf_log,
302  CNSTPreciseTime::Current() - start,
304  throw;
305  }
306 }
307 
308 
309 int
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";
332  try {
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,
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());
378  throw;
379  } catch (...) {
380  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
382  throw;
383  }
384  } catch (...) {
385  g_DoPerfLogging("MS_SQL_" + proc_name,
386  CNSTPreciseTime::Current() - start,
388  throw;
389  }
390 }
391 
392 
393 int
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";
414  try {
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,
448  return status;
449  } catch (const std::exception & ex) {
450  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
452  throw;
453  } catch (...) {
454  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
456  throw;
457  }
458  } catch (...) {
459  g_DoPerfLogging("MS_SQL_" + proc_name,
460  CNSTPreciseTime::Current() - start,
462  throw;
463  }
464 }
465 
466 
467 int
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";
490 
491  size_was_null = true;
492  try {
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,
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());
537  throw;
538  } catch (...) {
539  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
541  throw;
542  }
543  } catch (...) {
544  g_DoPerfLogging("MS_SQL_" + proc_name,
545  CNSTPreciseTime::Current() - start,
547  throw;
548  }
549 }
550 
551 
552 int
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";
573  try {
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,
606  return status;
607  } catch (const std::exception & ex) {
608  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
610  throw;
611  } catch (...) {
612  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
614  throw;
615  }
616  } catch (...) {
617  g_DoPerfLogging("MS_SQL_" + proc_name,
618  CNSTPreciseTime::Current() - start,
620  throw;
621  }
622 }
623 
624 
625 int
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";
645  try {
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,
674  return status;
675  } catch (const std::exception & ex) {
676  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
678  throw;
679  } catch (...) {
680  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
682  throw;
683  }
684  } catch (...) {
685  g_DoPerfLogging("MS_SQL_" + proc_name,
686  CNSTPreciseTime::Current() - start,
688  throw;
689  }
690 }
691 
692 
693 int
695  Int8 user_id)
696 {
697  const string proc_name = "UpdateUserIDForObject";
699  try {
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,
716  return status;
717  } catch (const std::exception & ex) {
718  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
720  throw;
721  } catch (...) {
722  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
724  throw;
725  }
726  } catch (...) {
727  g_DoPerfLogging("MS_SQL_" + proc_name,
728  CNSTPreciseTime::Current() - start,
730  throw;
731  }
732 }
733 
734 
735 int
736 CNSTDatabase::ExecSP_RemoveObject(const string & object_key)
737 {
738  const string proc_name = "RemoveObject";
740  try {
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,
757  return status;
758  } catch (const std::exception & ex) {
759  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
761  throw;
762  } catch (...) {
763  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
765  throw;
766  }
767  } catch (...) {
768  g_DoPerfLogging("MS_SQL_" + proc_name,
769  CNSTPreciseTime::Current() - start,
771  throw;
772  }
773 }
774 
775 
776 int
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";
786  try {
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,
827  return status;
828  } catch (const std::exception & ex) {
829  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
831  throw;
832  } catch (...) {
833  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
835  throw;
836  }
837  } catch (...) {
838  g_DoPerfLogging("MS_SQL_" + proc_name,
839  CNSTPreciseTime::Current() - start,
841  throw;
842  }
843 }
844 
845 
846 int
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";
857  try {
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,
886  return status;
887  } catch (const std::exception & ex) {
888  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
890  throw;
891  } catch (...) {
892  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
894  throw;
895  }
896  } catch (...) {
897  g_DoPerfLogging("MS_SQL_" + proc_name,
898  CNSTPreciseTime::Current() - start,
900  throw;
901  }
902 }
903 
904 
905 int
906 CNSTDatabase::ExecSP_GetAttributeNames(const string & object_key,
907  vector<string> & attr_names)
908 {
909  const string proc_name = "GetAttributeNames";
911  try {
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,
934  return status;
935  } catch (const std::exception & ex) {
936  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
938  throw;
939  } catch (...) {
940  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
942  throw;
943  }
944  } catch (...) {
945  g_DoPerfLogging("MS_SQL_" + proc_name,
946  CNSTPreciseTime::Current() - start,
948  throw;
949  }
950 }
951 
952 
953 int
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";
961  try {
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,
986  return status;
987  } catch (const std::exception & ex) {
988  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
990  throw;
991  } catch (...) {
992  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
994  throw;
995  }
996  } catch (...) {
997  g_DoPerfLogging("MS_SQL_" + proc_name,
998  CNSTPreciseTime::Current() - start,
1000  throw;
1001  }
1002 }
1003 
1004 
1005 int
1006 CNSTDatabase::ExecSP_DelAttribute(const string & object_key,
1007  const string & attr_name)
1008 {
1009  const string proc_name = "DelAttribute";
1011  try {
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,
1029  return status;
1030  } catch (const std::exception & ex) {
1031  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1033  throw;
1034  } catch (...) {
1035  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1037  throw;
1038  }
1039  } catch (...) {
1040  g_DoPerfLogging("MS_SQL_" + proc_name,
1041  CNSTPreciseTime::Current() - start,
1043  throw;
1044  }
1045 }
1046 
1047 
1048 int
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";
1067  try {
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,
1155  return status;
1156  } catch (const std::exception & ex) {
1157  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1159  throw;
1160  } catch (...) {
1161  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1163  throw;
1164  }
1165  } catch (...) {
1166  g_DoPerfLogging("MS_SQL_" + proc_name,
1167  CNSTPreciseTime::Current() - start,
1169  throw;
1170  }
1171 }
1172 
1173 
1174 int
1176  const string & object_key,
1177  TNSTDBValue<CTime> & expiration,
1178  TNSTDBValue<Int8> & individual_object_ttl)
1179 {
1180  const string proc_name = "GetObjectExpiration";
1182  try {
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,
1213  return status;
1214  } catch (const std::exception & ex) {
1215  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1217  throw;
1218  } catch (...) {
1219  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1221  throw;
1222  }
1223  } catch (...) {
1224  g_DoPerfLogging("MS_SQL_" + proc_name,
1225  CNSTPreciseTime::Current() - start,
1227  throw;
1228  }
1229 }
1230 
1231 
1234 {
1236  const string proc_name = "sp_spaceused";
1238  try {
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,
1261  return result;
1262  } catch (const std::exception & ex) {
1263  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1265  throw;
1266  } catch (...) {
1267  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1269  throw;
1270  }
1271  } catch (...) {
1272  g_DoPerfLogging("MS_SQL_" + proc_name,
1273  CNSTPreciseTime::Current() - start,
1275  throw;
1276  }
1277 }
1278 
1279 
1282 {
1284  const string proc_name = "GetStatInfo";
1286  try {
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,
1306  return result;
1307  } catch (const std::exception & ex) {
1308  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1310  throw;
1311  } catch (...) {
1312  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1314  throw;
1315  }
1316  } catch (...) {
1317  g_DoPerfLogging("MS_SQL_" + proc_name,
1318  CNSTPreciseTime::Current() - start,
1320  throw;
1321  }
1322 }
1323 
1324 
1325 int
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";
1333  try {
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,
1364  return status;
1365  } catch (const std::exception & ex) {
1366  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1368  throw;
1369  } catch (...) {
1370  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1372  throw;
1373  }
1374  } catch (...) {
1375  g_DoPerfLogging("MS_SQL_" + proc_name,
1376  CNSTPreciseTime::Current() - start,
1378  throw;
1379  }
1380 }
1381 
1382 
1383 int
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";
1392  try {
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,
1424  return status;
1425  } catch (const std::exception & ex) {
1426  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1428  throw;
1429  } catch (...) {
1430  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1432  throw;
1433  }
1434  } catch (...) {
1435  g_DoPerfLogging("MS_SQL_" + proc_name,
1436  CNSTPreciseTime::Current() - start,
1438  throw;
1439  }
1440 }
1441 
1442 
1443 int
1445 {
1446  const string proc_name = "GetClients";
1448  try {
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,
1470  return status;
1471  } catch (const std::exception & ex) {
1472  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1474  throw;
1475  } catch (...) {
1476  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1478  throw;
1479  }
1480  } catch (...) {
1481  g_DoPerfLogging("MS_SQL_" + proc_name,
1482  CNSTPreciseTime::Current() - start,
1484  throw;
1485  }
1486 }
1487 
1488 
1489 int
1490 CNSTDatabase::ExecSP_GetUsers(vector< pair<string, string> > & users)
1491 {
1492  const string proc_name = "GetUsers";
1494  try {
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,
1517  return status;
1518  } catch (const std::exception & ex) {
1519  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1521  throw;
1522  } catch (...) {
1523  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1525  throw;
1526  }
1527  } catch (...) {
1528  g_DoPerfLogging("MS_SQL_" + proc_name,
1529  CNSTPreciseTime::Current() - start,
1531  throw;
1532  }
1533 }
1534 
1535 
1536 int
1537 CNSTDatabase::ExecSP_DoesObjectExist(const string & object_key)
1538 {
1539  const string proc_name = "DoesObjectExist";
1541  try {
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,
1558  return status;
1559  } catch (const std::exception & ex) {
1560  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1562  throw;
1563  } catch (...) {
1564  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1566  throw;
1567  }
1568  } catch (...) {
1569  g_DoPerfLogging("MS_SQL_" + proc_name,
1570  CNSTPreciseTime::Current() - start,
1572  throw;
1573  }
1574 }
1575 
1576 
1577 int
1579  const string & object_key,
1580  TNSTDBValue<Int8> & object_size,
1581  TNSTDBValue<string> & object_locator)
1582 {
1583  const string proc_name = "GetObjectSizeAndLocator";
1585  try {
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,
1616  return status;
1617  } catch (const std::exception & ex) {
1618  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1620  throw;
1621  } catch (...) {
1622  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1624  throw;
1625  }
1626  } catch (...) {
1627  g_DoPerfLogging("MS_SQL_" + proc_name,
1628  CNSTPreciseTime::Current() - start,
1630  throw;
1631  }
1632 }
1633 
1634 
1635 int
1636 CNSTDatabase::ExecSP_GetObjectSize(const string & object_key,
1637  TNSTDBValue<Int8> & object_size)
1638 {
1639  const string proc_name = "GetObjectSize";
1641  try {
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,
1667  return status;
1668  } catch (const std::exception & ex) {
1669  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1671  throw;
1672  } catch (...) {
1673  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1675  throw;
1676  }
1677  } catch (...) {
1678  g_DoPerfLogging("MS_SQL_" + proc_name,
1679  CNSTPreciseTime::Current() - start,
1681  throw;
1682  }
1683 }
1684 
1685 
1686 int
1688  TNSTDBValue<Int8> & object_size)
1689 {
1690  const string proc_name = "UpdateObjectSizeIfNULL";
1692  try {
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,
1718  return status;
1719  } catch (const std::exception & ex) {
1720  m_Server->RegisterAlert(eDB, proc_name + " DB error: " + ex.what());
1722  throw;
1723  } catch (...) {
1724  m_Server->RegisterAlert(eDB, proc_name + " unknown DB error");
1726  throw;
1727  }
1728  } catch (...) {
1729  g_DoPerfLogging("MS_SQL_" + proc_name,
1730  CNSTPreciseTime::Current() - start,
1732  throw;
1733  }
1734 }
1735 
1736 
1738 {
1739  CFastMutexGuard guard(m_DbLock);
1740 
1741  if (m_Db == NULL || !m_Connected) {
1742  // To be on the safe side trigger the restore connection thread
1743  // after a short delay
1744  SleepMilliSec(100);
1746 
1747  NCBI_THROW(CNetStorageServerException, eDatabaseError,
1748  "There is no connection to metadata information database");
1749  }
1750 
1751  // It is possible that a connection has been lost and restored while there
1752  // were no activities
1754  try {
1755  m_Db->Close();
1756  m_Db->Connect();
1757  } catch (...) {
1758  // To avoid interfering the connection restoring thread nothing is
1759  // done here. Basically the fact that we are here means there is no
1760  // connection anymore. The exception is suppressed however a stored
1761  // procedure execution exception will be generated a few moments
1762  // later and a normal procedure of the connection restoration will
1763  // be activated.
1764  }
1765  }
1766 }
1767 
1768 
1770 {
1771  CFastMutexGuard guard(m_DbLock);
1772 
1773  if (m_Db == NULL)
1774  return; // It must never happened - the existance of the m_Db is
1775  // checked in the pre condition
1776 
1778  m_Connected = false;
1779  m_Server->RegisterAlert(eDBConnect, "Database connection lost");
1780  ERR_POST(Critical << "Database connection has been lost");
1782  }
1783 }
1784 
1785 
1787  const string & procedure)
1788 {
1789  int status = query.GetStatus();
1790  if (status > 0)
1791  NCBI_THROW(CNetStorageServerException, eDatabaseError,
1792  "Error executing " + procedure + " stored "
1793  "procedure (return code " + NStr::NumericToString(status) +
1794  "). See MS SQL log for details.");
1795  return status;
1796 }
1797 
1798 
1799 bool CNSTDatabase::x_ReadDbAccessInfo(bool is_initialization)
1800 {
1801  CNetStorageDApp * app = dynamic_cast<CNetStorageDApp*>
1803  const CNcbiRegistry & reg = app->GetConfig();
1804 
1805  m_DbAccessInfo.m_Service = reg.GetString("database", "service", "");
1806  m_DbAccessInfo.m_Database = reg.GetString("database", "database", "");
1807  m_DbAccessInfo.m_UserName = reg.GetString("database", "user_name", "");
1808  m_SPTimeout = CTimeout(reg.GetDouble("database",
1809  "execute_sp_timeout",
1811  0, IRegistry::eReturn));
1812 
1813  // Try to decrypt
1814  try {
1815  m_DbAccessInfo.m_Password = reg.GetEncryptedString("database",
1816  "password",
1818  } catch (const CRegistryException & ex) {
1819  if (is_initialization) {
1821  m_Server->RegisterAlert(eDecryptDBPass, string(ex.what()));
1822  ERR_POST(Critical << "Decrypting [database]/password "
1823  "error: " << ex);
1824  }
1825  }
1826  return false;
1827  }
1828  return true;
1829 }
1830 
1831 
1832 void CNSTDatabase::x_CreateDatabase(bool is_initialization)
1833 {
1834  if (x_ReadDbAccessInfo(is_initialization)) {
1835  string uri = "dbapi://" + m_DbAccessInfo.m_UserName +
1836  ":" + m_DbAccessInfo.m_Password +
1837  "@" + m_DbAccessInfo.m_Service +
1838  "/" + m_DbAccessInfo.m_Database;
1839 
1840  CSDB_ConnectionParam db_params(uri);
1841  m_Db = new CDatabase(db_params);
1842  }
1843 }
1844 
1845 
1846 // Calculates the new object expiration for two cases:
1847 // - object is found in the DB
1848 // - object is not found in the DB (and thus should be created)
1849 void
1851  const CTime & current_time,
1852  const TNSTDBValue<CTimeSpan> & ttl,
1853  const TNSTDBValue<CTimeSpan> & prolong,
1854  const TNSTDBValue<CTime> & object_expiration,
1855  TNSTDBValue<CTime> & exp_record_found,
1856  TNSTDBValue<CTime> & exp_record_not_found)
1857 {
1858  if (prolong.m_IsNull) {
1859  // This could happen only if:
1860  // - a prolong is configured as a <multiplier> ttl
1861  // - service TTL is configured as infinity
1862  // - the object individual TTL is not set
1863  exp_record_found.m_IsNull = true;
1864  exp_record_not_found.m_IsNull = true;
1865  return;
1866  }
1867 
1868  // Here: prolong value is finite
1869  CTimeSpan prolong_val = prolong.m_Value;
1870 
1871  if (prolong_val.IsEmpty()) {
1872  // Prolong time has NOT been configured
1873  if (object_expiration.m_IsNull) {
1874  exp_record_found.m_IsNull = true;
1875  if (ttl.m_IsNull) {
1876  exp_record_not_found.m_IsNull = true;
1877  } else {
1878  exp_record_not_found.m_IsNull = false;
1879  exp_record_not_found.m_Value = current_time + ttl.m_Value;
1880  }
1881  } else {
1882  exp_record_found.m_IsNull = false;
1883  exp_record_found.m_Value = object_expiration.m_Value;
1884 
1885  // Record exists (otherwise the object_expiration is NULL).
1886  // So the expiration for the case the record is not found is
1887  // not strictly required. However, to be on the safe side set it
1888  // too.
1889  if (ttl.m_IsNull) {
1890  exp_record_not_found.m_IsNull = true;
1891  } else {
1892  exp_record_not_found.m_IsNull = false;
1893  exp_record_not_found.m_Value = current_time + ttl.m_Value;
1894  }
1895  }
1896  } else {
1897  // Prolong time has been configured
1898  if (object_expiration.m_IsNull) {
1899  exp_record_found.m_IsNull = true;
1900  if (ttl.m_IsNull) {
1901  exp_record_not_found.m_IsNull = true;
1902  } else {
1903  exp_record_not_found.m_IsNull = false;
1904  if (ttl.m_Value > prolong_val)
1905  exp_record_not_found.m_Value = current_time + ttl.m_Value;
1906  else
1907  exp_record_not_found.m_Value = current_time + prolong_val;
1908  }
1909  } else {
1910  exp_record_found.m_IsNull = false;
1911  if (object_expiration.m_Value > current_time + prolong_val)
1912  exp_record_found.m_Value = object_expiration.m_Value;
1913  else
1914  exp_record_found.m_Value = current_time + prolong_val;
1915 
1916  // Record exists (otherwise the object_expiration is NULL).
1917  // So the expiration for the case the record is not found is
1918  // not strictly required. However, to be on the safe side set it
1919  // too.
1920  if (ttl.m_IsNull) {
1921  exp_record_not_found.m_IsNull = true;
1922  } else {
1923  exp_record_not_found.m_IsNull = false;
1924  if (ttl.m_Value > prolong_val)
1925  exp_record_not_found.m_Value = current_time + ttl.m_Value;
1926  else
1927  exp_record_not_found.m_Value = current_time + prolong_val;
1928  }
1929  }
1930  }
1931 }
1932 
1933 
1934 CTimeout
1936 {
1938  return m_SPTimeout;
1939 }
1940 
1941 
1943 
Database connection object.
Definition: sdbapi.hpp:1137
void Close(void)
Close database object.
Definition: sdbapi.cpp:2028
void Connect(void)
Explicitly (re)connect to the database server.
Definition: sdbapi.cpp:2016
CQuery NewQuery(void)
Get new CQuery object for this database.
Definition: sdbapi.cpp:2085
CDatabase Clone(void)
Clone database object.
Definition: sdbapi.cpp:2073
@ eFastCheck
Definition: sdbapi.hpp:1142
bool IsConnected(EConnectionCheckMethod check_method=eNoCheck)
Check if database object was already connected to database server.
Definition: sdbapi.cpp:2039
JSON node abstraction.
static CJsonNode NewDoubleNode(double value)
Create a new JSON double node.
void SetByKey(const string &key, CJsonNode::TInstance value)
For a JSON object node, insert a new element or update an existing element.
static CJsonNode NewObjectNode()
Create a new JSON object node.
static CJsonNode NewNullNode()
Create a new JSON null node.
map< string, string > ExecSP_GetGeneralDBInfo(void)
int ExecSP_GetAttribute(const string &object_key, const string &attr_name, bool need_update, string &value)
int ExecSP_GetObjectExpiration(const string &object_key, TNSTDBValue< CTime > &expiration, TNSTDBValue< Int8 > &individual_object_ttl)
friend class CNSTDBConnectionThread
bool x_ReadDbAccessInfo(bool is_initialization)
int x_CheckStatus(CQuery &query, const string &procedure)
int ExecSP_GetClientObjects(const string &client_name, TNSTDBValue< Int8 > limit, Int8 &total, vector< string > &locators)
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)
CTimeout m_SPTimeout
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)
CRef< CNSTDBConnectionThread > m_RestoreConnectionThread
int ExecSP_GetUsers(vector< pair< string, string > > &users)
int ExecSP_UpdateUserIDForObject(const string &object_key, Int8 user_id)
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)
int ExecSP_GetClients(vector< string > &names)
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)
int ExecSP_CreateClient(const string &client, Int8 &client_id)
map< string, string > ExecSP_GetStatDBInfo(void)
int ExecSP_GetUserObjects(const string &user_name, const string &user_name_space, TNSTDBValue< Int8 > limit, Int8 &total, vector< string > &locators)
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)
CFastMutex m_DbLock
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)
void x_CreateDatabase(bool is_initialization)
int UpdateExpirationIfExists(const string &object_key, const TNSTDBValue< CTimeSpan > &ttl, const TNSTDBValue< CTimeSpan > &prolong_on_read, const TNSTDBValue< CTime > &object_expiration)
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)
void InitialConnect(void)
CDatabase * m_Db
CNetStorageServer * m_Server
int ExecSP_DoesObjectExist(const string &object_key)
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)
SDbAccessInfo m_DbAccessInfo
int ExecSP_GetObjectSize(const string &object_key, TNSTDBValue< Int8 > &object_size)
CNSTDatabase(CNetStorageServer *server)
CFastMutex m_SPTimeoutMutex
CTimeout GetExecuteSPTimeout(void)
int ExecSP_GetObjectSizeAndLocator(const string &object_key, TNSTDBValue< Int8 > &object_size, TNSTDBValue< string > &object_locator)
int ExecSP_RemoveObject(const string &object_key)
int ExecSP_GetAttributeNames(const string &object_key, vector< string > &attr_names)
int ExecSP_DelAttribute(const string &object_key, const string &attr_name)
void x_PreCheckConnection(void)
CJsonNode SetParameters(const IRegistry &reg)
void x_PostCheckConnection(void)
int ExecSP_UpdateObjectSizeIfNULL(const string &object_key, TNSTDBValue< Int8 > &object_size)
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)
int ExecSP_CreateUser(const CNSTUserID &user, Int8 &user_id)
static CNSTPreciseTime Current(void)
string GetName(void) const
Definition: nst_users.hpp:67
string GetNamespace(void) const
Definition: nst_users.hpp:65
static CNcbiApplication * Instance(void)
Singleton method.
Definition: ncbiapp.cpp:264
CNcbiRegistry –.
Definition: ncbireg.hpp:913
CTime GetCreationTime() const
void RegisterAlert(EAlertType alert_type, const string &messge)
Definition: nst_server.cpp:388
CCompoundIDPool GetCompoundIDPool(void) const
Definition: nst_server.hpp:89
Object used to execute queries and stored procedures on the database server and retrieve result sets.
Definition: sdbapi.hpp:232
CRegistryException –.
Definition: ncbireg.hpp:1005
Convenience class to initialize database connection parameters from URL-like strings and/or applicati...
Definition: sdbapi.hpp:933
CTimeSpan.
Definition: ncbitime.hpp:1313
CTime –.
Definition: ncbitime.hpp:296
CTimeout – Timeout interval.
Definition: ncbitime.hpp:1693
IRegistry –.
Definition: ncbireg.hpp:73
Include a standard set of the NCBI C++ Toolkit most basic headers.
static const struct name_t names[]
#define false
Definition: bool.h:36
const CNcbiRegistry & GetConfig(void) const
Get the application's cached configuration parameters (read-only).
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
void Critical(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1203
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:342
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
virtual double GetDouble(const string &section, const string &name, double default_value, TFlags flags=0, EErrAction err_action=eThrow) const
Get double value of specified parameter name.
Definition: ncbireg.cpp:420
string GetEncryptedString(const string &section, const string &name, TFlags flags=0, const string &password=kEmptyStr) const
Get a value that was (potentially) stored encrypted.
Definition: ncbireg.cpp:329
virtual string GetString(const string &section, const string &name, const string &default_value, TFlags flags=0) const
Get the parameter string value.
Definition: ncbireg.cpp:321
@ fPlaintextAllowed
Definition: ncbireg.hpp:99
@ eReturn
Return default value.
Definition: ncbireg.hpp:203
@ eDecryptionFailed
Value looked encrypted, but decryption failed.
Definition: ncbireg.hpp:1013
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
TErrCode GetErrCode(void) const
Get error code.
Definition: ncbistr.hpp:4455
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
bool Run(TRunMode flags=fRunDefault)
Run the thread.
Definition: ncbithr.cpp:724
void Join(void **exit_data=0)
Wait for the thread termination.
Definition: ncbithr.cpp:863
bool IsEmpty(void) const
Return TRUE is an object keep zero time span.
Definition: ncbitime.hpp:2579
double GetAsDouble(void) const
Return time span as number of seconds.
Definition: ncbitime.hpp:2565
double GetAsDouble(void) const
Get as number of seconds (fractional value).
Definition: ncbitime.cpp:3512
void Set(EType type)
Set special value.
Definition: ncbitime.cpp:3577
@ eCurrent
Use current time. See also CCurrentTime.
Definition: ncbitime.hpp:300
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal=eRestartOnSignal)
void g_DoPerfLogging(const CQueue &queue, const CJob &job, int status)
@ eDecryptDBPass
Definition: nst_alert.hpp:55
@ eDBConnect
Definition: nst_alert.hpp:57
@ eDB
Definition: nst_alert.hpp:52
const Int8 k_UndefinedClientID
Definition: nst_clients.hpp:49
const double default_execute_sp_timeout
const int kSPStatusOK
const Int8 k_UndefinedUserID
Definition: nst_users.hpp:42
Defines NCBI C++ secure resources API.
@ eSDB_String
Like Transact-SQL VARCHAR(N)
Definition: sdbapi.hpp:179
@ eSDB_DateTime
Like Transact-SQL DATETIME.
Definition: sdbapi.hpp:182
@ eSDB_Int4
Like Transact-SQL INT (signed 32-bit integer)
Definition: sdbapi.hpp:175
@ eSDB_Binary
Like Transact-SQL VARBINARY(N)
Definition: sdbapi.hpp:181
@ eSDB_Int8
Like Transact-SQL BIGINT (signed 64-bit integer)
Definition: sdbapi.hpp:176
static CNamedPipeClient * client
ValueType m_Value
static string query
else result
Definition: token2.c:20
Modified on Sat May 25 14:19:59 2024 by modify_doxy.py rev. 669887