Gaudi Framework, version v23r5

Home   Generated: Wed Nov 28 2012
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
IODataManager.cpp
Go to the documentation of this file.
1 // Framework include files
2 #include "GaudiKernel/Debugger.h"
7 #include "IODataManager.h"
8 #include "GaudiKernel/SmartIF.h"
9 #include "GaudiKernel/Incident.h"
11 
12 #include <set>
13 
15 
16 using namespace Gaudi;
17 
19 
21 
22 IODataManager::IODataManager(CSTR nam, ISvcLocator* svcloc)
23  : base_class(nam, svcloc), m_ageLimit(2)
24 {
25  declareProperty("CatalogType", m_catalogSvcName="Gaudi::MultiFileCatalog/FileCatalog");
26  declareProperty("UseGFAL", m_useGFAL = true);
27  declareProperty("QuarantineFiles", m_quarantine = true);
28  declareProperty("AgeLimit", m_ageLimit = 2);
29 }
30 
33  // Initialize base class
35  MsgStream log(msgSvc(), name());
36  if ( !status.isSuccess() ) {
37  log << MSG::ERROR << "Error initializing base class Service!" << endmsg;
38  return status;
39  }
40  // Retrieve conversion service handling event iteration
41  m_catalog = serviceLocator()->service(m_catalogSvcName);
42  if( !m_catalog.isValid() ) {
43  log << MSG::ERROR
44  << "Unable to localize interface IFileCatalog from service:"
45  << m_catalogSvcName << endmsg;
46  return StatusCode::FAILURE;
47  }
48  m_incSvc = serviceLocator()->service("IncidentSvc");
49  if( !m_incSvc.isValid() ) {
50  log << MSG::ERROR << "Error initializing IncidentSvc Service!" << endmsg;
51  return status;
52  }
53 
54  return status;
55 }
56 
58 StatusCode IODataManager::finalize() {
59  m_catalog = 0; // release
60  return Service::finalize();
61 }
62 
63 // Small routine to issue exceptions
64 StatusCode IODataManager::error(CSTR msg, bool rethrow) {
65  MsgStream log(msgSvc(),name());
66  log << MSG::ERROR << "Error: " << msg << endmsg;
67  if ( rethrow ) {
69  }
70  return S_ERROR;
71 }
73 IODataManager::Connections IODataManager::connections(const IInterface* owner) const {
74  Connections conns;
75  for(ConnectionMap::const_iterator i=m_connectionMap.begin(); i!=m_connectionMap.end();++i) {
76  IDataConnection* c = (*i).second->connection;
77  if ( 0 == owner || c->owner() == owner )
78  conns.push_back(c);
79  }
80  return conns;
81 }
82 
84 StatusCode IODataManager::connectRead(bool keep_open, Connection* con) {
85  if ( !establishConnection(con) ) {
86  return connectDataIO(UNKNOWN,Connection::READ,con->name(),"UNKNOWN",keep_open,con);
87  }
88  std::string dsn = con ? con->name() : std::string("Unknown");
89  return error("Failed to connect to data:"+dsn,false);
90 }
91 
93 StatusCode IODataManager::connectWrite(Connection* con,IoType mode,CSTR doctype) {
94  if ( !establishConnection(con) ) {
95  return connectDataIO(UNKNOWN,mode,con->name(),doctype,true,con);
96  }
97  std::string dsn = con ? con->name() : std::string("Unknown");
98  return error("Failed to connect to data:"+dsn,false);
99 }
100 
102 StatusCode IODataManager::read(Connection* con, void* const data, size_t len) {
103  return establishConnection(con).isSuccess() ? con->read(data,len) : S_ERROR;
104 }
105 
107 StatusCode IODataManager::write(Connection* con, const void* data, int len) {
108  return establishConnection(con).isSuccess() ? con->write(data,len) : S_ERROR;
109 }
110 
112 long long int IODataManager::seek(Connection* con, long long int where, int origin) {
113  return establishConnection(con).isSuccess() ? con->seek(where,origin) : -1;
114 }
115 
116 StatusCode IODataManager::disconnect(Connection* con) {
117  if ( con ) {
118  std::string dataset = con->name();
119  std::string dsn = dataset;
120  StatusCode sc = con->disconnect();
121  if ( ::strncasecmp(dsn.c_str(),"FID:",4)==0 )
122  dsn = dataset.substr(4);
123  else if ( ::strncasecmp(dsn.c_str(),"LFN:",4)==0 )
124  dsn = dataset.substr(4);
125  else if ( ::strncasecmp(dsn.c_str(),"PFN:",4)==0 )
126  dsn = dataset.substr(4);
127 
128  FidMap::iterator j = m_fidMap.find(dataset);
129  if ( j != m_fidMap.end() ) {
130  std::string fid = (*j).second;
131  std::string gfal_name = "gfal:guid:" + fid;
132  ConnectionMap::iterator i=m_connectionMap.find(fid);
133  m_fidMap.erase(j);
134  if ( (j=m_fidMap.find(fid)) != m_fidMap.end() )
135  m_fidMap.erase(j);
136  if ( (j=m_fidMap.find(gfal_name)) != m_fidMap.end() )
137  m_fidMap.erase(j);
138  if ( i != m_connectionMap.end() ) {
139  if ( (*i).second ) {
140  IDataConnection* c = (*i).second->connection;
141  std::string pfn = c->pfn();
142  if ( (j=m_fidMap.find(pfn)) != m_fidMap.end() )
143  m_fidMap.erase(j);
144  if ( c->isConnected() ) {
145  MsgStream log(msgSvc(),name());
146  c->disconnect();
147  log << MSG::INFO << "Disconnect from dataset " << dsn
148  << " [" << fid << "]" << endmsg;
149  }
150  delete (*i).second;
151  m_connectionMap.erase(i);
152  }
153  }
154  }
155  return sc;
156  }
157  return S_ERROR;
158 }
159 
160 StatusCode IODataManager::reconnect(Entry* e) {
162  if ( e && e->connection ) {
163  switch(e->ioType) {
164  case Connection::READ:
165  sc = e->connection->connectRead();
166  break;
167  case Connection::UPDATE:
168  case Connection::CREATE:
169  case Connection::RECREATE:
170  sc = e->connection->connectWrite(e->ioType);
171  break;
172  default:
173  return S_ERROR;
174  }
175  if ( sc.isSuccess() && e->ioType == Connection::READ ) {
176  std::vector<Entry*> to_retire;
177  e->connection->resetAge();
178  for(ConnectionMap::iterator i=m_connectionMap.begin(); i!=m_connectionMap.end();++i) {
179  IDataConnection* c = (*i).second->connection;
180  if ( e->connection != c && c->isConnected() && !(*i).second->keepOpen ) {
181  c->ageFile();
182  if ( c->age() > m_ageLimit ) {
183  to_retire.push_back((*i).second);
184  }
185  }
186  }
187  if ( !to_retire.empty() ) {
188  MsgStream log(msgSvc(),name());
189  for(std::vector<Entry*>::iterator j=to_retire.begin(); j!=to_retire.end();++j) {
190  IDataConnection* c = (*j)->connection;
191  c->disconnect();
192  log << MSG::INFO << "Disconnect from dataset " << c->pfn()
193  << " [" << c->fid() << "]" << endmsg;
194  }
195  }
196  }
197  }
198  return sc;
199 }
200 
202 IIODataManager::Connection* IODataManager::connection(CSTR dataset) const {
203  FidMap::const_iterator j = m_fidMap.find(dataset);
204  if ( j != m_fidMap.end() ) {
205  ConnectionMap::const_iterator i=m_connectionMap.find((*j).second);
206  return (i != m_connectionMap.end()) ? (*i).second->connection : 0;
207  }
208  return 0;
209 }
210 
211 StatusCode IODataManager::establishConnection(Connection* con) {
212  if ( con ) {
213  if ( !con->isConnected() ) {
214  ConnectionMap::const_iterator i=m_connectionMap.find(con->name());
215  if ( i != m_connectionMap.end() ) {
216  Connection* c = (*i).second->connection;
217  if ( c != con ) {
218  m_incSvc->fireIncident(Incident(con->name(),IncidentType::FailInputFile));
219  return error("Severe logic bug: Twice identical connection object for DSN:"+con->name(),true);
220  }
221  if ( reconnect((*i).second).isSuccess() ) {
222  return S_OK;
223  }
224  }
225  return S_ERROR;
226  }
227  con->resetAge();
228  return S_OK;
229  }
230  return error("Severe logic bug: No connection object avalible.",true);
231 }
232 
234 IODataManager::connectDataIO(int typ, IoType rw, CSTR dataset, CSTR technology,bool keep_open,Connection* connection) {
235  MsgStream log(msgSvc(),name());
236  std::string dsn = dataset;
237  try {
239  if ( ::strncasecmp(dsn.c_str(),"FID:",4)==0 )
240  dsn = dataset.substr(4), typ = FID;
241  else if ( ::strncasecmp(dsn.c_str(),"LFN:",4)==0 )
242  dsn = dataset.substr(4), typ = LFN;
243  else if ( ::strncasecmp(dsn.c_str(),"PFN:",4)==0 )
244  dsn = dataset.substr(4), typ = PFN;
245  else if ( typ == UNKNOWN )
246  return connectDataIO(PFN, rw, dsn, technology, keep_open, connection);
247 
248  if(std::find(s_badFiles.begin(),s_badFiles.end(),dsn) != s_badFiles.end()) {
249  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
250  return IDataConnection::BAD_DATA_CONNECTION;
251  }
252  if ( typ == FID ) {
253  ConnectionMap::iterator fi = m_connectionMap.find(dsn);
254  if ( fi == m_connectionMap.end() ) {
255  IFileCatalog::Files files;
256  m_catalog->getPFN(dsn,files);
257  if ( files.size() == 0 ) {
258  if ( !m_useGFAL ) {
259  if ( m_quarantine ) s_badFiles.insert(dsn);
260  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
261  error("connectDataIO> failed to resolve FID:"+dsn,false).ignore();
262  return IDataConnection::BAD_DATA_CONNECTION;
263  }
264  else if ( dsn.length() == 36 && dsn[8]=='-' && dsn[13]=='-' ) {
265  std::string gfal_name = "gfal:guid:" + dsn;
266  m_fidMap[dsn] = m_fidMap[dataset] = m_fidMap[gfal_name] = dsn;
267  sc = connectDataIO(PFN, rw, gfal_name, technology, keep_open, connection);
268  if ( sc.isSuccess() ) return sc;
269  if ( m_quarantine ) s_badFiles.insert(dsn);
270  }
271  if ( m_quarantine ) s_badFiles.insert(dsn);
272  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
273  error("connectDataIO> Failed to resolve FID:"+dsn,false).ignore();
274  return IDataConnection::BAD_DATA_CONNECTION;
275  }
276  std::string pfn = files[0].first;
277  m_fidMap[dsn] = m_fidMap[dataset] = m_fidMap[pfn] = dsn;
278  sc = connectDataIO(PFN, rw, pfn, technology, keep_open, connection);
279  if ( !sc.isSuccess() ) {
280  if ( m_quarantine ) s_badFiles.insert(pfn);
281  m_incSvc->fireIncident(Incident(pfn,IncidentType::FailInputFile));
282  return IDataConnection::BAD_DATA_CONNECTION;
283  }
284 
285  return sc;
286  }
287  return S_ERROR;
288  //Connection* c = (*fi).second->connection;
289  //sc = connectDataIO(PFN, rw, c->pfn(), technology, keep_open, connection);
290  //if ( !sc.isSuccess() && m_quarantine ) s_badFiles.insert(c->pfn());
291  //return sc;
292  }
293  std::string fid;
294  FidMap::iterator j = m_fidMap.find(dsn);
295  if ( j == m_fidMap.end() ) {
296  IFileCatalog::Files files;
297  switch(typ) {
298  case LFN:
299  fid = m_catalog->lookupLFN(dsn);
300  if ( fid.empty() ) {
301  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
302  log << MSG::ERROR << "Failed to resolve LFN:" << dsn
303  << " Cannot access this dataset." << endmsg;
304  return IDataConnection::BAD_DATA_CONNECTION;
305  }
306  break;
307  case PFN:
308  fid = m_catalog->lookupPFN(dsn);
309  if ( !fid.empty() ) m_catalog->getPFN(fid, files);
310  if ( files.empty() ) {
311  if ( rw == Connection::CREATE || rw == Connection::RECREATE ) {
312  if ( fid.empty() ) fid = m_catalog->createFID();
313  m_catalog->registerPFN(fid,dsn,technology);
314  log << MSG::INFO << "Referring to dataset " << dsn
315  << " by its file ID:" << fid << endmsg;
316  }
317  else {
318  fid = dsn;
319  }
320  }
321  break;
322  }
323  }
324  else {
325  fid = (*j).second;
326  }
327  if ( typ == PFN ) {
328  // Open PFN
329  ConnectionMap::iterator fi = m_connectionMap.find(fid);
330  if ( fi == m_connectionMap.end() ) {
331  connection->setFID(fid);
332  connection->setPFN(dsn);
333  Entry* e = new Entry(technology, keep_open, rw, connection);
334  // Here we open the file!
335  if ( !reconnect(e).isSuccess() ) {
336  delete e;
337  if ( m_quarantine ) s_badFiles.insert(dsn);
338  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
339  error("connectDataIO> Cannot connect to database: PFN="+dsn+" FID="+fid,false).ignore();
340  return IDataConnection::BAD_DATA_CONNECTION;
341  }
342  fid = connection->fid();
343  m_fidMap[dataset] = m_fidMap[dsn] = m_fidMap[fid] = fid;
344  if ( !(rw==Connection::CREATE || rw==Connection::RECREATE) ) {
345  if ( strcasecmp(dsn.c_str(),fid.c_str()) == 0 ) {
346  log << MSG::ERROR << "Referring to existing dataset " << dsn
347  << " by its physical name." << endmsg;
348  log << "You may not be able to navigate back to the input file"
349  << " -- processing continues" << endmsg;
350  }
351  }
352  m_connectionMap.insert(std::make_pair(fid,e));
353  return S_OK;
354  }
355  // Here we open the file!
356  if ( !reconnect((*fi).second).isSuccess() ) {
357  if ( m_quarantine ) s_badFiles.insert(dsn);
358  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
359  error("connectDataIO> Cannot connect to database: PFN="+dsn+" FID="+fid,false).ignore();
360  return IDataConnection::BAD_DATA_CONNECTION;
361  }
362  return S_OK;
363  }
364  sc = connectDataIO(FID, rw, fid, technology, keep_open, connection);
365  if ( !sc.isSuccess() && m_quarantine ) {
366  s_badFiles.insert(fid);
367  }
368  else if ( typ == LFN ) {
369  m_fidMap[dataset] = fid;
370  }
371  return sc;
372  }
373  catch (std::exception& e) {
374  error(std::string("connectDataIO> Caught exception:")+e.what(), false).ignore();
375  }
376  catch(...) {
377  error(std::string("connectDataIO> Caught unknown exception"), false).ignore();
378  }
379  m_incSvc->fireIncident(Incident(dsn,IncidentType::FailInputFile));
380  error("connectDataIO> The dataset "+dsn+" cannot be opened.",false).ignore();
381  s_badFiles.insert(dsn);
382  return IDataConnection::BAD_DATA_CONNECTION;
383 }

Generated at Wed Nov 28 2012 12:17:18 for Gaudi Framework, version v23r5 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004