Logo ROOT  
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
31TSQLMonitoringWriter::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()) {
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{
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 ? o->ClassName() : "noclass" );
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}
#define SafeDelete(p)
Definition: RConfig.hxx:534
#define c(i)
Definition: RSha256.hxx:101
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
const Bool_t kFALSE
Definition: RtypesCore.h:101
const Bool_t kTRUE
Definition: RtypesCore.h:100
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition: TString.cxx:2461
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:184
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A doubly linked list.
Definition: TList.h:38
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition: TNamed.h:48
Collectable string class.
Definition: TObjString.h:28
const char * GetName() const override
Returns name of object.
Definition: TObjString.h:38
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:130
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:879
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:149
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
void MakeZombie()
Definition: TObject.h:49
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:867
virtual ~TSQLMonitoringWriter()
Destructor.
Bool_t SendParameters(TList *values, const char *) override
Register query log using the information in the list which is in the form TParameter(<par>,...
TSQLMonitoringWriter(const TSQLMonitoringWriter &)=delete
virtual TSQLResult * Query(const char *sql)=0
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.: mysql://pcroot....
Definition: TSQLServer.cxx:61
Basic string class.
Definition: TString.h:136
Ssiz_t Length() const
Definition: TString.h:410
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1946
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2202
const char * Data() const
Definition: TString.h:369
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1788
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
@ kIgnoreCase
Definition: TString.h:268
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2222
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
Bool_t IsNull() const
Definition: TString.h:407
TString & Remove(Ssiz_t pos)
Definition: TString.h:673
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:2336
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639