Logo ROOT   6.08/07
Reference Guide
TSQLMonitoring.cxx
Go to the documentation of this file.
1 // @(#)root/proofplayer:$Id$
2 // Author: J.F. Grosse-Oetringhaus, G.Ganis
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TSQLMonitoringWriter //
15 // //
16 // SQL implementation of TVirtualMonitoringWriter. //
17 // //
18 //////////////////////////////////////////////////////////////////////////
19 
20 #include "TList.h"
21 #include "TParameter.h"
22 #include "TEnv.h"
23 #include "TObjString.h"
24 #include "TSQLMonitoring.h"
25 #include "TSQLServer.h"
26 #include "TSQLResult.h"
27 
28 ////////////////////////////////////////////////////////////////////////////////
29 /// Constructor.
30 
31 TSQLMonitoringWriter::TSQLMonitoringWriter(const char *serv, const char *user,
32  const char *pass, const char *table)
33  : TVirtualMonitoringWriter("SQL", 0.0), fTable(table), fVerbose(kFALSE)
34 {
35  // Open connection to SQL server
36  fDB = TSQLServer::Connect(serv, user, pass);
37  if (!fDB || fDB->IsZombie()) {
38  SafeDelete(fDB);
39  // Invalid object
40  MakeZombie();
41  }
42  // Set the max bulk insertion size
43  fMaxBulkSize = 16 * 1024 * 1024;
44  TString smx = gEnv->GetValue("SQLMonitoringWriter.MaxBulkSize", "16M");
45  if (!smx.IsDigit()) {
46  if (smx.EndsWith("K", TString::kIgnoreCase)) {
47  smx.Remove(smx.Length()-1);
48  if (smx.IsDigit()) fMaxBulkSize = smx.Atoi() * 1024;
49  } else if (smx.EndsWith("M", TString::kIgnoreCase)) {
50  smx.Remove(smx.Length()-1);
51  if (smx.IsDigit()) fMaxBulkSize = smx.Atoi() * 1024 * 1024;
52  } else if (smx.EndsWith("G", TString::kIgnoreCase)) {
53  smx.Remove(smx.Length()-1);
54  if (smx.IsDigit()) fMaxBulkSize = smx.Atoi() * 1024 * 1024 * 1024;
55  }
56  } else {
57  fMaxBulkSize = smx.Atoi();
58  }
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Destructor
63 
65 {
66  SafeDelete(fDB);
67 }
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 /// Register query log using the information in the list which is in the form
71 /// TParameter(<par>,<value>) or TNamed(<name>,<string>). For bulk sending,
72 /// the first entry in the list is an TObjString defining the variable names
73 /// in the format
74 /// VARname1,VARname2,...
75 /// while the other entries are TObjStrings with the multiplets to be sent
76 /// VARvalue1,VARvalue2,...
77 ///
78 /// The string 'opt' allows the following additional control:
79 /// table=[<db>.]<table> allows to insert to a different table from the
80 /// one defined at construction (change is not
81 /// persistent); if <db> is not specified, the same
82 /// db defined at cinstruction is used.
83 /// bulk Do a bulk insert
84 /// More options can be given concurrently, comma-separated .
85 /// The specified table must already have been created in the DB.
86 
88 {
89  if (!fDB) {
90  // Invalid instance
91  return kFALSE;
92  }
93 
94  // The list must contain something
95  if (!values || (values && values->GetSize() < 1))
96  return kFALSE;
97 
98  // Parse options
99  TString table(fTable), op, ops(opt);
100  Ssiz_t from = 0;
101  Bool_t bulk = kFALSE;
102  while (ops.Tokenize(op, from, ",")) {
103  if (op == "bulk") {
104  bulk = kTRUE;
105  } else if (op.BeginsWith("table=")) {
106  op.ReplaceAll("table=", "");
107  if (!op.IsNull()) {
108  Ssiz_t idot = table.Index('.');
109  if (idot != kNPOS && op.Index('.') == kNPOS) {
110  table.Remove(idot+1);
111  table += op;
112  } else {
113  table = op;
114  }
115  }
116  }
117  }
118 
119  TIter nxi(values);
120  TObject *o = 0;
121 
122  // now prepare the strings
123  TString sql = TString::Format("INSERT INTO %s", table.Data());
124 
125  TSQLResult *res = 0;
126  if (!bulk) {
127 
128  // the column and values strings
129  char c = '(';
130  TString cols, vals;
131  while ((o = nxi())) {
132  if (!strncmp(o->ClassName(), "TNamed", 6)) {
133  cols += TString::Format("%c%s", c, ((TNamed *)o)->GetName());
134  vals += TString::Format("%c'%s'", c, ((TNamed *)o)->GetTitle());
135  } else if (!strcmp(o->ClassName(), "TParameter<Long64_t>")) {
136  cols += TString::Format("%c%s", c, ((TParameter<Long64_t> *)o)->GetName());
137  vals += TString::Format("%c%lld", c, ((TParameter<Long64_t> *)o)->GetVal());
138  } else if (!strcmp(o->ClassName(), "TParameter<double>")) {
139  cols += TString::Format("%c%s", c, ((TParameter<double> *)o)->GetName());
140  vals += TString::Format("%c%f", c, ((TParameter<double> *)o)->GetVal());
141  } else if (!strcmp(o->ClassName(), "TParameter<float>")) {
142  cols += TString::Format("%c%s", c, ((TParameter<float> *)o)->GetName());
143  vals += TString::Format("%c%f", c, ((TParameter<float> *)o)->GetVal());
144  } else if (!strcmp(o->ClassName(), "TParameter<int>")) {
145  cols += TString::Format("%c%s", c, ((TParameter<int> *)o)->GetName());
146  vals += TString::Format("%c%d", c, ((TParameter<int> *)o)->GetVal());
147  } else if (!strcmp(o->ClassName(), "TParameter<long>")) {
148  cols += TString::Format("%c%s", c, ((TParameter<long> *)o)->GetName());
149  vals += TString::Format("%c%ld", c, ((TParameter<long> *)o)->GetVal());
150  }
151  c = ',';
152  }
153  cols += ")";
154  vals += ")";
155 
156  // Put everything together
157  sql += TString::Format(" %s VALUES %s", cols.Data(), vals.Data());
158 
159  // Post query
160  if (fVerbose) Info("SendParameters", "sending: '%s'", sql.Data());
161  if (!(res = fDB->Query(sql))) {
162  Error("SendParameters", "insert into %s failed", table.Data());
163  if (sql.Length() > 1024) {
164  TString head(sql(0,508)), tail(sql(sql.Length()-512,512));
165  Printf("%s...%s", head.Data(), tail.Data());
166  } else {
167  Printf("%s", sql.Data());
168  }
169  return kFALSE;
170  }
171  delete res;
172 
173  } else {
174  // Prepare for bulk submission
175  o = nxi();
176  TObjString *os = dynamic_cast<TObjString *>(o);
177  if (!os) {
178  Error("SendParameters", "bulk insert: first entry in list is not 'TObjString' but '%s'", o->ClassName() );
179  return kFALSE;
180  }
181  // Continue preparing the string
182  sql += TString::Format(" (%s) VALUES ", os->GetName());
183  TString head = sql;
184  if (fVerbose) Info("SendParameters", "sending: '%s' (bulk of %d nplets)", head.Data(), values->GetSize() - 1);
185  char c = ' ';
186  while ((o = nxi())) {
187  if ((os = dynamic_cast<TObjString *>(o))) {
188  sql += TString::Format("%c(%s)", c, os->GetName());
189  c = ',';
190  } else {
191  Warning("SendParameters", "bulk insert: ignoring not 'TObjString' entry ('%s')", o->ClassName() );
192  }
193  // Check size (we cannot exceed fMaxBulkSize ('max_allowed_packet' in [mysqld] conf section)
194  if (sql.Length() > 0.9 * fMaxBulkSize) {
195  if (!(res = fDB->Query(sql))) {
196  Error("SendParameters", "bulk insert into %s failed", table.Data());
197  if (sql.Length() > 1024) {
198  TString hd(sql(0,508)), tl(sql(sql.Length()-512,512));
199  Printf("%s...%s", hd.Data(), tl.Data());
200  } else {
201  Printf("%s", sql.Data());
202  }
203  return kFALSE;
204  }
205  delete res;
206  sql = head;
207  c = ' ';
208  }
209  }
210  // Check if there is still something to send
211  if (sql.Length() > head.Length()) {
212  if (!(res = fDB->Query(sql))) {
213  Error("SendParameters", "bulk insert into %s failed", table.Data());
214  if (sql.Length() > 1024) {
215  TString hd(sql(0,508)), tl(sql(sql.Length()-512,512));
216  Printf("%s...%s", hd.Data(), tl.Data());
217  } else {
218  Printf("%s", sql.Data());
219  }
220  return kFALSE;
221  }
222  delete res;
223  }
224  }
225 
226  // Done successfully
227  return kTRUE;
228 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
static TSQLServer * Connect(const char *db, const char *uid, const char *pw)
The db should be of the form: <dbms>://<host>[:<port>][/<database>], e.g.
Definition: TSQLServer.cxx:61
Collectable string class.
Definition: TObjString.h:32
return c
virtual TSQLResult * Query(const char *sql)=0
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
Bool_t SendParameters(TList *values, const char *)
Register query log using the information in the list which is in the form TParameter(<par>,<value>) or TNamed(<name>,<string>).
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
Basic string class.
Definition: TString.h:137
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
#define SafeDelete(p)
Definition: RConfig.h:507
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:188
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2335
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
TSQLMonitoringWriter(const TSQLMonitoringWriter &)
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2221
A doubly linked list.
Definition: TList.h:47
const char * GetName() const
Returns name of object.
Definition: TObjString.h:42
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:496
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
Ssiz_t Length() const
Definition: TString.h:390
virtual ~TSQLMonitoringWriter()
Destructor.
#define Printf
Definition: TGeoToOCC.h:18
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
int Ssiz_t
Definition: RtypesCore.h:63
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2241
Bool_t IsZombie() const
Definition: TObject.h:120
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
Bool_t IsNull() const
Definition: TString.h:387
Mother of all ROOT objects.
Definition: TObject.h:37
const Ssiz_t kNPOS
Definition: Rtypes.h:115
void MakeZombie()
Definition: TObject.h:47
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1965
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1807
virtual Int_t GetSize() const
Definition: TCollection.h:95
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
const char * Data() const
Definition: TString.h:349