// @(#)root/tree:$Id$
// Author: Rene Brun   04/06/2006

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TTreeCacheUnzip
#define ROOT_TTreeCacheUnzip


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TTreeCacheUnzip                                                      //
//                                                                      //
// Specialization of TTreeCache for parallel Unzipping                  //
//                                                                      //
// Fabrizio Furano (CERN) Aug 2009                                      //
// Core TTree-related code borrowed from the previous version           //
//  by Leandro Franco and Rene Brun                                     //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifndef ROOT_TTreeCache
#include "TTreeCache.h"
#endif

#include <queue>

class TTree;
class TBranch;
class TThread;
class TCondition;
class TBasket;
class TMutex;

class TTreeCacheUnzip : public TTreeCache {
public:
   // We have three possibilities for the unzipping mode:
   // enable, disable and force
   enum EParUnzipMode { kEnable, kDisable, kForce };

protected:

   // Members for paral. managing
   TThread    *fUnzipThread[10];
   Bool_t      fActiveThread;          // Used to terminate gracefully the unzippers
   TCondition *fUnzipStartCondition;   // Used to signal the threads to start.
   TCondition *fUnzipDoneCondition;    // Used to wait for an unzip tour to finish. Gives the Async feel.
   Bool_t      fParallel;              // Indicate if we want to activate the parallelism (for this instance)
   Bool_t      fAsyncReading;
   TMutex     *fMutexList;             // Mutex to protect the various lists. Used by the condvars.
   TMutex     *fIOMutex;

   Int_t       fCycle;
   static TTreeCacheUnzip::EParUnzipMode fgParallel;  // Indicate if we want to activate the parallelism

   Int_t       fLastReadPos;
   Int_t       fBlocksToGo;

   // Unzipping related members
   Int_t      *fUnzipLen;         //! [fNseek] Length of the unzipped buffers
   char      **fUnzipChunks;      //! [fNseek] Individual unzipped chunks. Their summed size is kept under control.
   Byte_t     *fUnzipStatus;      //! [fNSeek] For each blk, tells us if it's unzipped or pending
   Long64_t    fTotalUnzipBytes;  //! The total sum of the currently unzipped blks

   Int_t       fNseekMax;         //!  fNseek can change so we need to know its max size
   Long64_t    fUnzipBufferSize;  //!  Max Size for the ready unzipped blocks (default is 2*fBufferSize)

   static Double_t fgRelBuffSize; // This is the percentage of the TTreeCacheUnzip that will be used

   // Members use to keep statistics
   Int_t       fNUnzip;           //! number of blocks that were unzipped
   Int_t       fNFound;           //! number of blocks that were found in the cache
   Int_t       fNStalls;          //! number of hits which caused a stall
   Int_t       fNMissed;          //! number of blocks that were not found in the cache and were unzipped

   std::queue<Int_t>       fActiveBlks; // The blocks which are active now

private:
   TTreeCacheUnzip(const TTreeCacheUnzip &);            //this class cannot be copied
   TTreeCacheUnzip& operator=(const TTreeCacheUnzip &);

   char *fCompBuffer;
   Int_t fCompBufferSize;

   // Private methods
   void  Init();
   Int_t StartThreadUnzip(Int_t nthreads);
   Int_t StopThreadUnzip();

public:
   TTreeCacheUnzip();
   TTreeCacheUnzip(TTree *tree, Int_t buffersize=0);
   virtual ~TTreeCacheUnzip();
   virtual Int_t       AddBranch(TBranch *b, Bool_t subbranches = kFALSE);
   virtual Int_t       AddBranch(const char *branch, Bool_t subbranches = kFALSE);
   Bool_t              FillBuffer();
   virtual Int_t       ReadBufferExt(char *buf, Long64_t pos, Int_t len, Int_t &loc);
   void                SetEntryRange(Long64_t emin,   Long64_t emax);
   virtual void        StopLearningPhase();
   void                UpdateBranches(TTree *tree);

   // Methods related to the thread
   static EParUnzipMode GetParallelUnzip();
   static Bool_t        IsParallelUnzip();
   static Int_t         SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option = TTreeCacheUnzip::kEnable);

   Bool_t               IsActiveThread();
   Bool_t               IsQueueEmpty();

   void                 WaitUnzipStartSignal();
   void                 SendUnzipStartSignal(Bool_t broadcast);

   // Unzipping related methods
   Int_t          GetRecordHeader(char *buf, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen);
   virtual void   ResetCache();
   virtual Int_t  GetUnzipBuffer(char **buf, Long64_t pos, Int_t len, Bool_t *free);
   virtual Int_t  SetBufferSize(Int_t buffersize);
   void           SetUnzipBufferSize(Long64_t bufferSize);
   static void    SetUnzipRelBufferSize(Float_t relbufferSize);
   Int_t          UnzipBuffer(char **dest, char *src);
   Int_t          UnzipCache(Int_t &startindex, Int_t &locbuffsz, char *&locbuff);

   // Methods to get stats
   Int_t  GetNUnzip() { return fNUnzip; }
   Int_t  GetNFound() { return fNFound; }
   Int_t  GetNMissed(){ return fNMissed; }

   void Print(Option_t* option = "") const;

   // static members
   static void* UnzipLoop(void *arg);
   ClassDef(TTreeCacheUnzip,0)  //Specialization of TTreeCache for parallel unzipping
};

#endif
 TTreeCacheUnzip.h:1
 TTreeCacheUnzip.h:2
 TTreeCacheUnzip.h:3
 TTreeCacheUnzip.h:4
 TTreeCacheUnzip.h:5
 TTreeCacheUnzip.h:6
 TTreeCacheUnzip.h:7
 TTreeCacheUnzip.h:8
 TTreeCacheUnzip.h:9
 TTreeCacheUnzip.h:10
 TTreeCacheUnzip.h:11
 TTreeCacheUnzip.h:12
 TTreeCacheUnzip.h:13
 TTreeCacheUnzip.h:14
 TTreeCacheUnzip.h:15
 TTreeCacheUnzip.h:16
 TTreeCacheUnzip.h:17
 TTreeCacheUnzip.h:18
 TTreeCacheUnzip.h:19
 TTreeCacheUnzip.h:20
 TTreeCacheUnzip.h:21
 TTreeCacheUnzip.h:22
 TTreeCacheUnzip.h:23
 TTreeCacheUnzip.h:24
 TTreeCacheUnzip.h:25
 TTreeCacheUnzip.h:26
 TTreeCacheUnzip.h:27
 TTreeCacheUnzip.h:28
 TTreeCacheUnzip.h:29
 TTreeCacheUnzip.h:30
 TTreeCacheUnzip.h:31
 TTreeCacheUnzip.h:32
 TTreeCacheUnzip.h:33
 TTreeCacheUnzip.h:34
 TTreeCacheUnzip.h:35
 TTreeCacheUnzip.h:36
 TTreeCacheUnzip.h:37
 TTreeCacheUnzip.h:38
 TTreeCacheUnzip.h:39
 TTreeCacheUnzip.h:40
 TTreeCacheUnzip.h:41
 TTreeCacheUnzip.h:42
 TTreeCacheUnzip.h:43
 TTreeCacheUnzip.h:44
 TTreeCacheUnzip.h:45
 TTreeCacheUnzip.h:46
 TTreeCacheUnzip.h:47
 TTreeCacheUnzip.h:48
 TTreeCacheUnzip.h:49
 TTreeCacheUnzip.h:50
 TTreeCacheUnzip.h:51
 TTreeCacheUnzip.h:52
 TTreeCacheUnzip.h:53
 TTreeCacheUnzip.h:54
 TTreeCacheUnzip.h:55
 TTreeCacheUnzip.h:56
 TTreeCacheUnzip.h:57
 TTreeCacheUnzip.h:58
 TTreeCacheUnzip.h:59
 TTreeCacheUnzip.h:60
 TTreeCacheUnzip.h:61
 TTreeCacheUnzip.h:62
 TTreeCacheUnzip.h:63
 TTreeCacheUnzip.h:64
 TTreeCacheUnzip.h:65
 TTreeCacheUnzip.h:66
 TTreeCacheUnzip.h:67
 TTreeCacheUnzip.h:68
 TTreeCacheUnzip.h:69
 TTreeCacheUnzip.h:70
 TTreeCacheUnzip.h:71
 TTreeCacheUnzip.h:72
 TTreeCacheUnzip.h:73
 TTreeCacheUnzip.h:74
 TTreeCacheUnzip.h:75
 TTreeCacheUnzip.h:76
 TTreeCacheUnzip.h:77
 TTreeCacheUnzip.h:78
 TTreeCacheUnzip.h:79
 TTreeCacheUnzip.h:80
 TTreeCacheUnzip.h:81
 TTreeCacheUnzip.h:82
 TTreeCacheUnzip.h:83
 TTreeCacheUnzip.h:84
 TTreeCacheUnzip.h:85
 TTreeCacheUnzip.h:86
 TTreeCacheUnzip.h:87
 TTreeCacheUnzip.h:88
 TTreeCacheUnzip.h:89
 TTreeCacheUnzip.h:90
 TTreeCacheUnzip.h:91
 TTreeCacheUnzip.h:92
 TTreeCacheUnzip.h:93
 TTreeCacheUnzip.h:94
 TTreeCacheUnzip.h:95
 TTreeCacheUnzip.h:96
 TTreeCacheUnzip.h:97
 TTreeCacheUnzip.h:98
 TTreeCacheUnzip.h:99
 TTreeCacheUnzip.h:100
 TTreeCacheUnzip.h:101
 TTreeCacheUnzip.h:102
 TTreeCacheUnzip.h:103
 TTreeCacheUnzip.h:104
 TTreeCacheUnzip.h:105
 TTreeCacheUnzip.h:106
 TTreeCacheUnzip.h:107
 TTreeCacheUnzip.h:108
 TTreeCacheUnzip.h:109
 TTreeCacheUnzip.h:110
 TTreeCacheUnzip.h:111
 TTreeCacheUnzip.h:112
 TTreeCacheUnzip.h:113
 TTreeCacheUnzip.h:114
 TTreeCacheUnzip.h:115
 TTreeCacheUnzip.h:116
 TTreeCacheUnzip.h:117
 TTreeCacheUnzip.h:118
 TTreeCacheUnzip.h:119
 TTreeCacheUnzip.h:120
 TTreeCacheUnzip.h:121
 TTreeCacheUnzip.h:122
 TTreeCacheUnzip.h:123
 TTreeCacheUnzip.h:124
 TTreeCacheUnzip.h:125
 TTreeCacheUnzip.h:126
 TTreeCacheUnzip.h:127
 TTreeCacheUnzip.h:128
 TTreeCacheUnzip.h:129
 TTreeCacheUnzip.h:130
 TTreeCacheUnzip.h:131
 TTreeCacheUnzip.h:132
 TTreeCacheUnzip.h:133
 TTreeCacheUnzip.h:134
 TTreeCacheUnzip.h:135
 TTreeCacheUnzip.h:136
 TTreeCacheUnzip.h:137
 TTreeCacheUnzip.h:138
 TTreeCacheUnzip.h:139
 TTreeCacheUnzip.h:140
 TTreeCacheUnzip.h:141