]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTreeManager.cxx
Memory leak corrected (Andreas)
[u/mrichter/AliRoot.git] / MUON / AliMUONTreeManager.cxx
CommitLineData
de6dbd08 1/**************************************************************************
2* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3* *
4* Author: The ALICE Off-line Project. *
5* Contributors are mentioned in the code where appropriate. *
6* *
7* Permission to use, copy, modify and distribute this software and its *
8* documentation strictly for non-commercial purposes is hereby granted *
9* without fee, provided that the above copyright notice appears in all *
10* copies and that both the copyright notice and this permission notice *
11* appear in the supporting documentation. The authors make no claims *
12* about the suitability of this software for any purpose. It is *
13* provided "as is" without express or implied warranty. *
14**************************************************************************/
15
16// $Id$
17
3d1463c8 18//-----------------------------------------------------------------------------
de6dbd08 19/// \class AliMUONTreeManager
20///
21/// Helper class to handle the relationships TTree<->MUON data containers
22///
23/// The general way of dealing with I/O for MUON is a two stage process :
24///
25/// 1) first get a TTree pointer using the AliLoader mechanism (this is AliRoot
26/// general)
27///
28/// 2) connect that TTree to a MUON (virtual) data container using
29/// the container's Connect(TTree&) method (this is MUON specific)
30///
31/// This class helps implementing stage 2 in the relevant store implementations
32///
33/// \see AliMUONVStore
34///
35/// Basically, the relationship Tree<->Store is possible because
36/// the TreeManager, when creating branches, uses the UserInfo part of the
37/// TTree to store the relationship branch -> MUON store classname.
38///
39/// \author Laurent Aphecetche, Subatech
3d1463c8 40//-----------------------------------------------------------------------------
de6dbd08 41
42#include "AliMUONTreeManager.h"
43
44#include "AliLog.h"
45#include "AliMUONObjectPair.h"
46#include <TList.h>
47#include <TObjString.h>
48#include <TTree.h>
49#include <TBranch.h>
50#include <Riostream.h>
51
52/// \cond CLASSIMP
53ClassImp(AliMUONTreeManager)
54/// \endcond
55
56//_____________________________________________________________________________
57AliMUONTreeManager::AliMUONTreeManager() : TObject()
58{
59 /// Default ctor
60}
61
62//_____________________________________________________________________________
63AliMUONTreeManager::~AliMUONTreeManager()
64{
65 /// Dtor
66}
67
68//_____________________________________________________________________________
69void
70AliMUONTreeManager::GetEvent(TTree& tree, Int_t event) const
71{
72 /// Equivalent to tree.GetEvent(event) is NDEBUG is not defined,
73 /// otherwise insure that selected branches have a non-zero address
74 /// (the contrary indicating we'll get a memory leak when reading the
75 /// tree).
76
77#ifndef NDEBUG
78 TObjArray* branches = tree.GetListOfBranches();
79 TIter next(branches);
80 TBranch* branch;
81 Bool_t error(kFALSE);
82
83 while ( ( branch = static_cast<TBranch*>(next()) ) )
84 {
85 TString bname(branch->GetName());
86 if ( branch->GetAddress() == 0 &&
87 tree.GetBranchStatus(bname.Data()) == 1 )
88 {
89 AliError(Form("Branch %s has status 1 and no address",bname.Data()));
90 error = kTRUE;
91 }
92 }
93
94 if ( error )
95 {
96 ShowStatus(tree);
97 }
98#endif
99
100 tree.GetEvent(event);
101}
102
103//_____________________________________________________________________________
104void
105AliMUONTreeManager::ShowStatus(TTree& tree) const
106{
107 /// Show main branches status and address
108 TObjArray* branches = tree.GetListOfBranches();
109 TIter next(branches);
110 TBranch* branch;
111
112 while ( ( branch = static_cast<TBranch*>(next()) ) )
113 {
114 TString bname(branch->GetName());
115 Int_t status = tree.GetBranchStatus(bname.Data());
116 cout << Form("%50s Status %d Address %p",bname.Data(),status,branch->GetAddress()) << endl;
117 }
118}
119
120//_____________________________________________________________________________
121void
122AliMUONTreeManager::AddClassName(TTree& tree, const char* pattern,
123 const char* className) const
124{
125 /// Adds a association (pattern,className) to the UserInfo() of tree
126 /// It is mandatory to use this method in MakeBranches(), as this is the key
127 /// to get an automatic container creation from a tree.
128
129 TString test(GetClassName(tree,pattern,kFALSE));
130 if ( test.Length() == 0 )
131 {
132 // not already there
133 TList* userInfo = tree.GetUserInfo();
134 userInfo->Add(new AliMUONObjectPair(new TObjString(pattern),
135 new TObjString(className),
136 kTRUE,kTRUE));
137 }
138}
139
140//_____________________________________________________________________________
141Bool_t
142AliMUONTreeManager::MakeBranch(TTree& tree, const char* storeClassName,
143 const char* branchClassName,
144 const char* branchName,
145 void* address,
146 Int_t bufferSize, Int_t splitLevel) const
147{
148 /// Create a branch in the tree
149 AddClassName(tree,branchName,storeClassName);
150 TBranch* branch = tree.Branch(branchName,branchClassName,address,bufferSize,splitLevel);
151 return ( branch != 0x0 );
152}
153
154//_____________________________________________________________________________
155Bool_t
156AliMUONTreeManager::SetAddress(TTree& tree, const char* branchName,
157 void* address) const
158{
159 /// Set the address for one branch
160 TBranch* branch = tree.GetBranch(branchName);
161 if (branch)
162 {
163 branch->SetAddress(address);
164 return kTRUE;
165 }
166 AliError(Form("Did not find branch %s in tree %s",branchName,tree.GetName()));
167 return kFALSE;
168}
169
170//_____________________________________________________________________________
171TObject*
172AliMUONTreeManager::CreateObject(const TTree& tree, const char* detail) const
173{
174 /// Object creation from tree, using
175 /// the (pattern,className) pairs stored in the UserInfo() of TTree.
176 TString className(GetClassName(tree,detail,kTRUE));
177 TClass* classPtr = TClass::GetClass(className.Data());
178 if (!classPtr)
179 {
180 AliError(Form("Could not get class %s",className.Data()));
181 return 0x0;
182 }
183 return reinterpret_cast<TObject*>(classPtr->New());
184}
185
186//_____________________________________________________________________________
187void
188AliMUONTreeManager::UpdateBranchStatuses(TTree& tree, const char* pattern) const
189{
190 /// Loop over tree branches and set their status if their name matches
191 /// the pattern :
192 /// - zero if branch address is null and
193 /// - one otherwise
194 /// This will avoid memory leak, if we set the address to only part
195 /// of the branches before doing a tree.GetEvent(i)
196 ///
197 /// WARNING : this is a time consuming operation, as we loop over branches
198 /// at least twice (one here, and the TTree::SetBranchStatus is itself
199 /// a loop). So use only when necessary.
200 ///
201
202 TIter next(tree.GetListOfBranches());
203 TBranch* branch;
204
205 while ( ( branch = static_cast<TBranch*>(next()) ) )
206 {
207 TString bname(branch->GetName());
208 if ( bname.Contains(pattern) )
209 {
210 tree.SetBranchStatus(Form("%s*",branch->GetName()),1);
211 }
212 else
213 {
214 if ( !branch->GetAddress() )
215 {
216 tree.SetBranchStatus(Form("%s*",branch->GetName()),0);
217 }
218 }
219 }
220
221}
222
223//_____________________________________________________________________________
224const char*
225AliMUONTreeManager::GetClassName(const TTree& tree, const char* pattern,
226 Bool_t makeDefault) const
227{
228 /// Find out, using the TTree::UserInfo, the classname corresponding to
229 /// pattern.
230 /// If makeDefault=true and we cannot find the pattern in the UserInfo,
231 /// we return DefaultClassName(pattern)
232 ///
233
234 TTree& vtree = const_cast<TTree&>(tree); // not pretty, but the GetUserInfo is not const...
235
236 TIter next(vtree.GetUserInfo());
237
238 TObject* object;
239
240 while ( ( object = next() ) )
241 {
242 AliMUONObjectPair* pair = static_cast<AliMUONObjectPair*>(object);
243 TString key = (static_cast<TObjString*>(pair->First()))->String();
244 TString value = (static_cast<TObjString*>(pair->Second()))->String();
245 if ( key.Contains(pattern,TString::kIgnoreCase) )
246 {
247 return value.Data();
248 }
249 }
250
251 if ( makeDefault ) return DefaultClassName(tree.GetName(),pattern);
252
253 return 0x0;
254}
255
256//_____________________________________________________________________________
257const char*
258AliMUONTreeManager::DefaultClassName(const char* treeName, const char* pattern) const
259{
260 /// For backward compatibility only. Decides, based on the tree name and a
261 /// pattern, which store class should be used.
262
263 TString name(treeName);
264 TString spattern(pattern);
265 spattern.ToUpper();
266
267 if ( name == "TreeH" )
268 {
269 return "AliMUONHitStoreV1";
270 }
271
272 if ( name == "TreeD" || name == "TreeS" )
273 {
274 if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
275 if ( spattern.Contains("DIGIT") ) return "AliMUONDigitStoreV1";
276 }
277
278 if ( name == "TreeR" )
279 {
280 if ( spattern.Contains("CLUSTER") ) return "AliMUONClusterStoreV1";
281 if ( spattern.Contains("TRIGGER") ) return "AliMUONTriggerStoreV1";
282 }
283
284 if ( name == "TreeT" )
285 {
286 if ( spattern.Contains("TRIGGER" ) ) return "AliMUONTriggerTrackStoreV1";
287 if ( spattern.Contains("TRACK") ) return "AliMUONTrackStoreV1";
288 }
289
290 AliError(Form("Do not know how to create default class for tree %s pattern %s",
291 treeName,pattern));
292 return "";
293}
294
295
296
297
298
299
300