adaptively adjust LB period time
[charm.git] / src / ck-ldb / LBDBManager.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**
9  * \addtogroup CkLdb
10 */
11 /*@{*/
12
13 #ifndef LBDB_H
14 #define LBDB_H
15
16 #include "converse.h"
17 #include "lbdb.h"
18 #include "cklists.h"
19
20 #include "LBObj.h"
21 #include "LBOM.h"
22 #include "LBComm.h"
23 #include "LBMachineUtil.h"
24
25 class LocalBarrier {
26 friend class LBDB;
27 public:
28   LocalBarrier() { cur_refcount = 1; client_count = 0; max_client = 0;
29                    max_receiver= 0; at_count = 0; on = CmiFalse; 
30         #if CMK_BLUEGENE_CHARM
31         first_free_client_slot = 0;
32         #endif
33     };
34   ~LocalBarrier() { };
35
36   LDBarrierClient AddClient(LDResumeFn fn, void* data);
37   void RemoveClient(LDBarrierClient h);
38   LDBarrierReceiver AddReceiver(LDBarrierFn fn, void* data);
39   void RemoveReceiver(LDBarrierReceiver h);
40   void TurnOnReceiver(LDBarrierReceiver h);
41   void TurnOffReceiver(LDBarrierReceiver h);
42   void AtBarrier(LDBarrierClient h);
43   void TurnOn() { on = CmiTrue; CheckBarrier(); };
44   void TurnOff() { on = CmiFalse; };
45
46 private:
47   void CallReceivers(void);
48   void CheckBarrier();
49   void ResumeClients(void);
50
51   struct client {
52     void* data;
53     LDResumeFn fn;
54     int refcount;
55   };
56   struct receiver {
57     void* data;
58     LDBarrierFn fn;
59     int on;
60   };
61
62   CkVec<client*> clients;
63   CkVec<receiver*> receivers;
64
65   int cur_refcount;
66   int max_client;
67   int client_count;
68   int max_receiver;
69   int at_count;
70   CmiBool on;
71
72   #if CMK_BLUEGENE_CHARM
73   int first_free_client_slot;
74   #endif
75 };
76
77 class LBDB {
78 public:
79   LBDB();
80   ~LBDB() { }
81
82   void SetPeriod(double secs) {batsync.setPeriod(secs);}
83   double GetPeriod() {return batsync.getPeriod();}
84
85   void insert(LBOM *om);
86
87   LDOMHandle AddOM(LDOMid _userID, void* _userData, LDCallbacks _callbacks);
88   LDObjHandle AddObj(LDOMHandle _h, LDObjid _id, void *_userData,
89                      CmiBool _migratable);
90   void UnregisterObj(LDObjHandle _h);
91
92   void RegisteringObjects(LDOMHandle _h);
93   void DoneRegisteringObjects(LDOMHandle _h);
94
95   inline void LocalBarrierOn() 
96        { localBarrier.TurnOn();}
97   inline void LocalBarrierOff() 
98        { localBarrier.TurnOff();}
99
100   inline LBOM *LbOM(LDOMHandle h) 
101        { return oms[h.handle]; };
102   inline LBObj *LbObj(const LDObjHandle &h) const 
103        { return objs[h.handle]; };
104   inline LBObj *LbObjIdx(int h) const 
105        { return objs[h]; };
106   void DumpDatabase(void);
107
108   inline void TurnStatsOn(void) 
109        {statsAreOn = CmiTrue; machineUtil.StatsOn();}
110   inline void TurnStatsOff(void) 
111        {statsAreOn = CmiFalse;machineUtil.StatsOff();}
112   inline CmiBool StatsOn(void) const 
113        { return statsAreOn; };
114
115   void SetupPredictor(LDPredictModelFn on, LDPredictWindowFn onWin, LDPredictFn off, LDPredictModelFn change, void* data);
116   inline void TurnPredictorOn(void *model) {
117     if (predictCBFn!=NULL) predictCBFn->on(predictCBFn->data, model);
118     else CmiPrintf("Predictor not supported in this load balancer\n");
119   }
120   inline void TurnPredictorOn(void *model, int wind) {
121     if (predictCBFn!=NULL) predictCBFn->onWin(predictCBFn->data, model, wind);
122     else CmiPrintf("Predictor not supported in this load balancer\n");
123   }
124   inline void TurnPredictorOff(void) {
125     if (predictCBFn!=NULL) predictCBFn->off(predictCBFn->data);
126     else CmiPrintf("Predictor not supported in this load balancer\n");
127   }
128   /* the parameter model is really of class LBPredictorFunction in file LBDatabase.h */
129   inline void ChangePredictor(void *model) {
130     if (predictCBFn!=NULL) predictCBFn->change(predictCBFn->data, model);
131     else CmiPrintf("Predictor not supported in this load balancer");
132   }
133
134   void Send(const LDOMHandle &destOM, const LDObjid &destid, unsigned int bytes, int destObjProc);
135   void MulticastSend(const LDOMHandle &destOM, LDObjid *destids, int ndests, unsigned int bytes, int nMsgs);
136   int ObjDataCount();
137   void GetObjData(LDObjData *data);
138   inline int CommDataCount() { 
139     if (commTable)
140       return commTable->CommCount();
141     else return 0;
142   }
143   inline void GetCommData(LDCommData *data) 
144        { if (commTable) commTable->GetCommData(data); };
145
146   int  Migrate(LDObjHandle h, int dest);
147   void Migrated(LDObjHandle h, int waitBarrier=1);
148   int  NotifyMigrated(LDMigratedFn fn, void* data);
149   void TurnOnNotifyMigrated(int handle)
150        { migrateCBList[handle]->on = 1; }
151   void TurnOffNotifyMigrated(int handle)
152        { migrateCBList[handle]->on = 0; }
153   void RemoveNotifyMigrated(int handle);
154
155   inline void TurnManualLBOn() 
156        { useBarrier = CmiFalse; }
157   inline void TurnManualLBOff() 
158        { useBarrier = CmiTrue; }
159
160   int AddStartLBFn(LDStartLBFn fn, void* data);
161   void TurnOnStartLBFn(int handle)
162        { startLBFnList[handle]->on = 1; }
163   void TurnOffStartLBFn(int handle)
164        { startLBFnList[handle]->on = 0; }
165   void RemoveStartLBFn(LDStartLBFn fn);
166   void StartLB();
167
168   inline void IdleTime(LBRealType* walltime) 
169        { machineUtil.IdleTime(walltime); };
170   inline void TotalTime(LBRealType* walltime, LBRealType* cputime) 
171        { machineUtil.TotalTime(walltime,cputime); };
172   void BackgroundLoad(LBRealType* walltime, LBRealType* cputime);
173   void GetTime(LBRealType *total_walltime,LBRealType *total_cputime,
174                    LBRealType *idletime, LBRealType *bg_walltime, LBRealType *bg_cputime);
175   void ClearLoads(void);
176
177   /**
178     runningObj records the obj handler index so that load balancer
179     knows if an event(e.g. Send) is in an entry function or not.
180     An index is enough here because LDObjHandle can be retrieved from 
181     objs array. Copying LDObjHandle is expensive.
182   */
183   inline void SetRunningObj(const LDObjHandle &_h) 
184        { runningObj = _h.handle; obj_running = CmiTrue; };
185   inline const LDObjHandle &RunningObj() const 
186        { return objs[runningObj]->GetLDObjHandle(); };
187   inline void NoRunningObj() 
188        { obj_running = CmiFalse; };
189   inline CmiBool ObjIsRunning() const 
190        { return obj_running; };
191   
192   inline LDBarrierClient AddLocalBarrierClient(LDResumeFn fn, void* data) 
193        { return localBarrier.AddClient(fn,data); };
194   inline void RemoveLocalBarrierClient(LDBarrierClient h) 
195        { localBarrier.RemoveClient(h); };
196   inline LDBarrierReceiver AddLocalBarrierReceiver(LDBarrierFn fn, void* data) 
197        { return localBarrier.AddReceiver(fn,data); };
198   inline void RemoveLocalBarrierReceiver(LDBarrierReceiver h) 
199        { localBarrier.RemoveReceiver(h); };
200   inline void TurnOnBarrierReceiver(LDBarrierReceiver h) 
201        { localBarrier.TurnOnReceiver(h); };
202   inline void TurnOffBarrierReceiver(LDBarrierReceiver h) 
203        { localBarrier.TurnOffReceiver(h); };
204   inline void AtLocalBarrier(LDBarrierClient h) 
205        { if (useBarrier) localBarrier.AtBarrier(h); };
206   inline void ResumeClients() 
207        { localBarrier.ResumeClients(); };
208   inline void MeasuredObjTime(double wtime, double ctime) {
209     if (statsAreOn) {
210       obj_walltime += wtime;
211 #if CMK_LB_CPUTIMER
212       obj_cputime += ctime;
213 #endif
214     }
215   };
216
217   //This class controls the builtin-atsync frequency
218   class batsyncer {
219   private:
220     LBDB *db; //Enclosing LBDB object
221     double period;//Time (seconds) between builtin-atsyncs  
222     double nextT;
223     LDBarrierClient BH;//Handle for the builtin-atsync barrier 
224     static void gotoSync(void *bs);
225     static void resumeFromSync(void *bs);
226   public:
227     void init(LBDB *_db,double initPeriod);
228     void setPeriod(double p) {period=p;}
229     double getPeriod() {return period;}
230   };
231
232 private:
233   struct MigrateCB {
234     LDMigratedFn fn;
235     void* data;
236     int on;
237   };
238
239   struct StartLBCB {
240     LDStartLBFn fn;
241     void* data;
242     int on;
243   };
244
245   struct PredictCB {
246     LDPredictModelFn on;
247     LDPredictWindowFn onWin;
248     LDPredictFn off;
249     LDPredictModelFn change;
250     void* data;
251   };
252
253   typedef CkVec<LBOM*> OMList;
254   typedef CkVec<LBObj*> ObjList;
255   typedef CkVec<MigrateCB*> MigrateCBList;
256   typedef CkVec<StartLBCB*> StartLBCBList;
257
258   LBCommTable* commTable;
259   OMList oms;
260   int omCount;
261   int oms_registering;
262
263   ObjList objs;
264   int objCount;
265
266   CmiBool statsAreOn;
267   MigrateCBList migrateCBList;
268
269   PredictCB* predictCBFn;
270
271   CmiBool obj_running;
272   int runningObj;               // index of the runningObj in ObjList
273
274   batsyncer batsync;
275
276   LocalBarrier localBarrier;    // local barrier to trigger LB automatically
277   CmiBool useBarrier;           // use barrier or not
278
279   LBMachineUtil machineUtil;
280   double obj_walltime;
281 #if CMK_LB_CPUTIMER
282   double obj_cputime;
283 #endif
284
285   StartLBCBList  startLBFnList;
286   int            startLBFn_count;
287 public:
288   int useMem();
289 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
290     int validObjHandle(LDObjHandle h ){
291             if(objCount == 0)
292                 return 0;
293             if(h.handle > objCount)
294                 return 0;
295             if(objs[h.handle] == NULL)
296                 return 0;
297
298             return 1;
299     }
300 #endif
301
302
303   int getObjCount() {return objCount;}
304   const ObjList& getObjs() {return objs;}
305
306
307
308 };
309
310 #endif
311
312 /*@}*/