Skip to content

Conversation

@vgvassilev
Copy link
Member

This patch allows TFileMerger to work with externally created TFile-s. Being
able to control the creation of the TFile objects give us a chance to use
in-memory files. This is very helpful in benchmarking when we want to simulate
fast disks or we just want to avoid disk wearout.

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

@phsft-bot
Copy link

@phsft-bot
Copy link

Build failed on ubuntu14/native.
See console output.

Failing tests:

@phsft-bot
Copy link

@phsft-bot
Copy link

Build failed on mac1012/native.
See console output.

Failing tests:

@phsft-bot
Copy link

ASSERT_TRUE(t != nullptr);

double d;
t->SetBranchAddress(name, &d);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting branch address to a stack address requires to either call t->ResetBranchAddresses(); or delete the TTree (otherwise it is technically in an invalid state).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that file.Get(name) allocates an object and it is the user's responsibility to deallocate it? If yes, I assume I can transform it into a unique_ptr and would that work well with having a t->ResetBranchAddresses();?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that file.Get(name) allocates an object and it is the user's responsibility to deallocate it?

In the case of a TTree, the point is an implicit shared pointer. You can delete it (and the TFile will be informed) and you can let the TFile delete it (but your are not directly inform when it does unless you are registered in the list of cleanups).

If yes, I assume I can transform it into a unique_ptr

Yes, you can as long as you make sure that the lifetime of the unique_ptr is less or equal to the litetime of the TFile.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be done.


static void CreateATuple(TMemFile &file, const char *name, double value)
{
auto mytree = new TTree(name, "A tree");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be (guaranteed to be) consistent, you may want to add

mytree->SetDirectory(&file);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... would that mean I will have to reset it in the end of that function?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... would that mean I will have to reset it in the end of that function?

Why? Because "file" in all your use case is already the current directory, adding SetDirectory would be a nop however if for somewhere 'file' is not the current directory at the time CreateATuple then the behavior of the function would not be what you expects. (it would attach the TTree to another file and thus the file.Write at the end would not store the TTree at alll).

And actually that reminds me we have a new constructor to use instead of (new + SetDirectory):

auto mytree = new TTree(name, "A tree", &file);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

CreateATuple(b, "b_tree", 2.);

TFileMerger merger;
auto output = new TMemFile("output.root", "CREATE");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not having output being a unique_ptr? (Maybe using std::make_unique :) )

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, the TMemFile got deleted by the merger.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but then you do:

 merger.OutputFile(std::unique_ptr<TFile>(output));

So I don't see the difference :) (and yes ownership needs to pass for this function to the TMemFile ....

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

@phsft-bot
Copy link

@phsft-bot
Copy link

@phsft-bot
Copy link

Build failed on mac1012/native.
See console output.

Failing tests:

@phsft-bot
Copy link

@phsft-bot
Copy link

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

Copy link
Member Author

@vgvassilev vgvassilev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments should be addressed.

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

@phsft-bot
Copy link

@phsft-bot
Copy link

@phsft-bot
Copy link

Build failed on mac1012/native.
See console output.

Warnings:

  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/R.h:40:10: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/R_ext/RS.h:29:10: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/Rinternals.h:60:11: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/library/Rcpp/include/Rcpp/r/headers.h:57:10: warning: non-portable path to file '<RVersion.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/R_ext/Visibility.h:29:10: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/R.h:40:10: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/R_ext/RS.h:29:10: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/Rinternals.h:60:11: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/library/Rcpp/include/Rcpp/r/headers.h:57:10: warning: non-portable path to file '<RVersion.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]
  • /cvmfs/sft.cern.ch/lcg/releases/R/3.2.5-c8cca/x86_64-mac1012-clang81-opt/lib/R/include/R_ext/Visibility.h:29:10: warning: non-portable path to file '<RConfig.h>'; specified path differs in case from file name on disk [-Wnonportable-include-path]

And 10 more

Failing tests:

@phsft-bot
Copy link

@pcanal
Copy link
Member

pcanal commented Oct 2, 2017

looks relevant to me?

Maybe, maybe not. This is the list of cleanups.

@Axel-Naumann
Copy link
Member

Well we need a stacktrace of the crash to correlate. E.g. the TMemFiles are generally subject to the list of cleanup thread issues (disclaimer: I didn't check the patch).

@eguiraud
Copy link
Contributor

eguiraud commented Oct 2, 2017

here is a stacktrace. I think an interesting piece of information would be the name of the gDirectory when ~TContext bombs and the name of the directory its destructor would like to set as gDir.

@pcanal
Copy link
Member

pcanal commented Oct 2, 2017

#8  <signal handler called>
#9  0x00007f089b3f153c in TDirectory::UnregisterContext(TDirectory::TContext*) () at ../root/core/base/src/TDirectory.cxx:1247
#10 0x00000000004ea2ee in TDirectory::TContext::~TContext() () at include/TDirectory.h:79

This usually happens when a thread has/had a gDirectory pointing to a file/directory and that this directory is deleted by another thread.

@vgvassilev
Copy link
Member Author

Is there a way to understand if those race conditions pre-existing to this patch?

@Axel-Naumann
Copy link
Member

Axel-Naumann commented Oct 2, 2017 via email

@eguiraud
Copy link
Contributor

eguiraud commented Oct 2, 2017

yeah i'm here to help. in addition to the suggestions above, since you said that the crash disappears if you run the problematic test in isolation, it might be interesting to check whether the different threads have a gDirectory in a dirty state after the execution of the previous test.
Those invalid gDirs might be picked up by the TContexts in the test that crashes.

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

This patch allows TFileMerger to work with externally created TFile-s. Being
able to control the creation of the TFile objects give us a chance to use
in-memory files. This is very helpful in benchmarking when we want to simulate
fast disks or we just want to avoid disk wearout.
@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

@phsft-bot
Copy link

Build failed on slc6/gcc62.
See console output.

Errors:

  • ERROR: Timeout after 10 minutes
  • ERROR: Error fetching remote repo 'origin'
  • stderr: error: RPC failed; result=18, HTTP code = 200
  • ERROR: Error fetching remote repo 'origin'

@vgvassilev
Copy link
Member Author

@phsft-bot build!

Seems like the failure is infrastructure but let's retrigger.

@phsft-bot
Copy link

Starting build on centos7/gcc49, mac1012/native, slc6/gcc49, slc6/gcc62, ubuntu14/native with flags -Dvc=OFF -Dimt=ON -Dccache=ON
How to customize builds

@vgvassilev
Copy link
Member Author

I found the race condition, it was in the way we created the output TFile. It had to have TContext RAII object protecting the gDirectory.

@dpiparo shall I dismiss your request for changes as they are already in?

@dpiparo
Copy link
Member

dpiparo commented Oct 5, 2017

@vgvassilev if the changes are addressed, for sure. Thanks!

@vgvassilev vgvassilev dismissed dpiparo’s stale review October 5, 2017 08:28

The requests for changes were addressed.

@vgvassilev vgvassilev merged commit c409c25 into root-project:master Oct 5, 2017
@vgvassilev vgvassilev deleted the UseMemFiles branch October 5, 2017 08:29
std::function<void(void)> fCallback; //< Callback for when data is removed from queue

ClassDef(TBufferMerger, 0);
ClassDef(TBufferMerger, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this? This only matters for classes that are streamed. This should have remained as 0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, when you have a ClassDef and you change data members you also should bump the ClassDef version.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, when you have a ClassDef and you change data members you also should bump the ClassDef version.

only when you change a persistent member :) ... and version == 0 means that all data members are implicitly marked transient.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall I revert it back to 0?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, done. I don't understand how is that a non persistent data member but you are the expert.

@pcanal
Copy link
Member

pcanal commented Oct 5, 2017

Ok, done. I don't understand how is that a non persistent data member but you are the expert.

Humm ... when the class version is set to zero then all the data member of the class are consider transient ... i.e. non-persistent .... When you increase to the version to 1, this turned implicitly all the data member to become persistent.

@eguiraud
Copy link
Contributor

eguiraud commented Oct 5, 2017 via email

@pcanal
Copy link
Member

pcanal commented Oct 5, 2017

Any class that inherits from TObject must have a ClassDef otherwise some the routines are inconsistent (like IsA() ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants