Fixed memory leak inside ComlibStrategy/OneTimeMulticastStrategy. The message would
[charm.git] / src / ck-com / RectMulticastStrategy.C
1 /**
2    @addtogroup ComlibCharmStrategy
3 */
4 /*@{*/
5
6 /** @file */
7
8
9
10 //#define COMLIB_RECT_DEBUG
11 //#define LOCAL_MULTI_OFF
12 /********************************************************
13         Section multicast strategy sgetRectGeometryuite. DirectMulticast and its
14         derivatives, multicast messages to a section of array elements
15         created on the fly. The section is invoked by calling a
16         section proxy. These strategies can also multicast to a subset
17         of processors for groups.
18
19         These strategies are non-bracketed. When the first request is
20         made a route is dynamically built on the section. The route
21         information is stored in
22
23  - Sameer Kumar
24
25 **********************************************/
26
27 /** EJB
28  *
29  * RectMulticastStrategy is designed to use the Rectangular broadcast
30  * feature of the bgml library to accelerate multicasts.
31  * 
32  * It will use the AsyncRectBcast feature which has ways to define rectangles.
33  * 
34  *
35  * The interaction with the rectangle layer works thusly:
36  *  initialize the rectangle for the section using 
37  *     bgl_machine_RectBcastinit
38  *     to create the communicator
39  *
40  *  That returns a request object which must be kept and used in each
41  *  rectangular send.
42  *
43  *  send using a single invocation of bgl_machine_RectBcast
44  *   If the root is inside the rectangle do this on the root
45  *   else forward to (preferably a corner) something in the rectangle.
46  *
47  *   This latter case is the only use of a forwarding comlib
48  *   object in this strategy.  Remote delivery is otherwise handled by
49  *   the converse machine level and BG/L.  There is no other use of
50  *   comlib forwarding schemes.
51  *
52  *   The all cases the rectangle sender will not receive a copy from the
53  *   interface so it will need to do its own local multicast.
54  * 
55  *  On receipt at the intermediate/destination (all intermediates are
56  *  destinations) processor level we deliver using local multicast if
57  *  our list of multicast subscribing chares is not null.  If null,
58  *  ignore the message (machine broadcast may be a bit overzealous).
59  *
60  *   This is a 2 pass process.
61  *
62  *    When create on src is triggered.  send geometry to entire
63  *    rectangle (including processors which have no chares in the
64  *    section list) so every element can initialize.  Use a remote
65  *    listsend on every element in the rectangle.
66  *
67  *    Create on intermediate should be the receiver of that 1st pass process.
68  *    Each intermediate should initialize the rectangle, but not send.
69  *    
70  *    Subsequent sends can then use the rectangle send.
71  *
72  *
73  */
74
75
76     // rectangle communicator (arrid| srcpe |section id)  -> request
77
78
79 #include "RectMulticastStrategy.h"
80 CkpvDeclare(comRectHashType *, com_rect_ptr); 
81 #ifdef CMK_RECT_API
82 #include "bgltorus.h"
83 #include "bgml.h"
84 extern "C" void    *   bgl_machine_RectBcastInit  (unsigned               commID, const BGTsRC_Geometry_t* geometry);
85
86 extern "C"  void bgl_machine_RectBcast (unsigned                 commid,                            const char             * sndbuf,                        unsigned                 sndlen); 
87
88
89 extern "C" void  bgl_machine_RectBcastConfigure (void *(*Fn)(int));
90
91 extern "C" void isSane( void *, unsigned);
92
93 CkpvExtern(CkGroupID, cmgrID);
94
95 void *sourceOffRectstrategyHandler(void *msg) {
96     CmiMsgHeaderBasic *conv_header = (CmiMsgHeaderBasic *) msg;
97     int instid = conv_header->stratid;
98     ComlibPrintf("sourceOff handler called on %d\n",CkMyPe(), instid);
99
100     RectMulticastStrategy *strat = (RectMulticastStrategy *)    ConvComlibGetStrategy(instid);
101     strat->handleMessageForward(msg);
102     return NULL;
103 }
104
105 void * rectRequest (int comm) {
106   //  fprintf(stderr,"[%d] rectRequest for %d gives %p\n",CkMyPe(),comm,CkpvAccess(com_rect_ptr)->get(comm));
107 #ifdef COMLIB_RECT_DEBUG
108   CkAssert(CkpvAccess(com_rect_ptr)->get(comm)!=NULL);
109   isSane(CkpvAccess(com_rect_ptr)->get(comm),comm);
110 #endif
111   return CkpvAccess(com_rect_ptr)->get(comm);
112 }
113
114 RectMulticastStrategy::RectMulticastStrategy(CkArrayID aid)
115     : Strategy(), CharmStrategy() {
116
117     ainfo.setDestinationArray(aid);
118     setType(ARRAY_STRATEGY);
119 }
120
121 //Destroy all old built routes
122 RectMulticastStrategy::~RectMulticastStrategy() {
123     
124     ComlibPrintf("Calling Destructor\n");
125
126     if(getLearner() != NULL)
127         delete getLearner();
128         
129     CkHashtableIterator *ht_iterator = sec_ht.iterator();
130     ht_iterator->seekStart();
131     while(ht_iterator->hasNext()){
132         void **data;
133         data = (void **)ht_iterator->next();        
134         ComlibRectSectionHashObject *obj = (ComlibRectSectionHashObject *) (* data);
135         if(obj != NULL)
136             delete obj;
137     }
138 }
139
140 void RectMulticastStrategy::insertMessage(CharmMessageHolder *cmsg){
141   cmsg->checkme();
142
143   
144   //    ComlibPrintf("[%d] Comlib Rect Section Multicast: insertMessage \n", 
145
146
147     if(cmsg->dest_proc == IS_SECTION_MULTICAST && cmsg->sec_id != NULL) { 
148         CkSectionID *sid = cmsg->sec_id;
149         int cur_sec_id = sid->getSectionID();
150         ComlibPrintf("[%d] Comlib Rect Section Multicast: insertMessage section id %d\n", CkMyPe(), cur_sec_id);           
151         if(cur_sec_id > 0) {        
152             sinfo.processOldSectionMessage(cmsg);            
153
154             //      ComlibPrintf("[%d] insertMessage old sectionid %d \n",CkMyPe(),cur_sec_id);
155             ComlibPrintf("[%d] insertMessage old sectionid %d \n",CkMyPe(),cur_sec_id);
156             ComlibSectionHashKey 
157                 key(CkMyPe(), sid->_cookie.sInfo.cInfo.id);        
158             ComlibRectSectionHashObject *obj = sec_ht.get(key);
159
160             if(obj == NULL)
161                 CkAbort("Cannot Find Section\n");
162
163             envelope *env = UsrToEnv(cmsg->getCharmMessage());
164 #ifndef LOCAL_MULTI_OFF
165             localMulticast(env, obj);
166 #endif
167             if(obj->sourceInRectangle) 
168               {
169                 remoteMulticast(env, obj);
170               }
171             else // forward
172               {
173                 forwardMulticast(env, obj);
174               }
175         }
176         else {
177           ComlibPrintf("[%d] insertMessage new section id %d\n", CkMyPe(), cur_sec_id);           
178           //New sec id, so send it along with the message
179           void *newmsg = sinfo.getNewMulticastMessage(cmsg, needSorting());
180           insertSectionID(sid);
181
182           ComlibSectionHashKey 
183             key(CkMyPe(), sid->_cookie.sInfo.cInfo.id);        
184           ComlibPrintf("[%d] insertMessage new sectionid %d \n",CkMyPe(),sid->_cookie.sInfo.cInfo.id);
185           ComlibRectSectionHashObject *obj = sec_ht.get(key);
186
187           if(obj == NULL)
188             CkAbort("Cannot Find Section\n");
189
190           /*
191             ComlibPrintf("%u: Src = %d dest:", key.hash(), CkMyPe());
192             for (int i=0; i<obj->npes; ++i)
193             ComlibPrintf(" %d",obj->pelist[i]);
194             ComlibPrintf(", map:");
195             ComlibMulticastMsg *lll = (ComlibMulticastMsg*)newmsg;
196             envelope *ppp = UsrToEnv(newmsg);
197             CkUnpackMessage(&ppp);
198             int ttt=0;
199             for (int i=0; i<lll->nPes; ++i) {
200             ComlibPrintf(" %d (",lll->indicesCount[i].pe);
201             for (int j=0; j<lll->indicesCount[i].count; ++j) {
202             ComlibPrintf(" %d",((int*)&(lll->indices[ttt]))[1]);
203             ttt++;
204             }
205             ComlibPrintf(" )");
206             }
207             CkPackMessage(&ppp);
208             ComlibPrintf("\n");
209           */
210           // our object needs indices, npes, pelist
211           sinfo.getRemotePelist(sid->_nElems, sid->_elems, obj->npes, obj->pelist);
212           sinfo.getLocalIndices(sid->_nElems, sid->_elems, obj->indices);
213           char *msg = cmsg->getCharmMessage();
214           /*
215             ComlibMulticastMsg *lll = (ComlibMulticastMsg*)newmsg;
216             envelope *ppp = UsrToEnv(newmsg);
217             CkUnpackMessage(&ppp);
218             int ttt=0;
219             int uuu=0;
220             for (int i=0; i<lll->nPes; ++i) {
221             //        ComlibPrintf(" %d (",lll->indicesCount[i].pe);
222             uuu++;
223             for (int j=0; j<lll->indicesCount[i].count; ++j) {
224             //          ComlibPrintf(" %d",((int*)&(lll->indices[ttt]))[1]);
225             ttt++;
226             }
227             //        ComlibPrintf(" )");
228             }
229
230
231             ComlibPrintf("[%d] newmsg for sendRectDest has %d indices %d pes\n",CkMyPe(),ttt, uuu);
232             CkAssert(uuu>0);
233             CkAssert(ttt>0);
234           */
235           envelope *ppp = UsrToEnv(newmsg);
236           CkPackMessage(&ppp);      
237 #ifndef LOCAL_MULTI_OFF
238           localMulticast(UsrToEnv(msg), obj);
239 #endif
240
241           sendRectDest(obj ,CkMyPe(), UsrToEnv(newmsg));
242           //            CkFreeMsg(msg);     // need this?
243
244         }        
245     }
246     else 
247         CkAbort("Section multicast cannot be used without a section proxy");
248
249     delete cmsg;       
250 }
251
252 void RectMulticastStrategy::insertSectionID(CkSectionID *sid) {
253
254   //    ComlibPrintf("[%d] insertSectionId \n", CkMyPe());   
255     ComlibPrintf("[%d] insertSectionId \n", CkMyPe());   
256
257     
258     ComlibSectionHashKey 
259         key(CkMyPe(), sid->_cookie.sInfo.cInfo.id);
260
261     ComlibRectSectionHashObject *obj = NULL;    
262     obj = sec_ht.get(key);
263     
264     if(obj != NULL)
265         delete obj;
266     
267     obj = createObjectOnSrcPe(sid->_nElems, sid->_elems, sid->_cookie.sInfo.cInfo.id);
268     sec_ht.put(key) = obj;
269
270 }
271
272
273 ComlibRectSectionHashObject *
274 RectMulticastStrategy::createObjectOnSrcPe(int nindices, CkArrayIndexMax *idxlist, unsigned int thisSectionID) {
275
276     ComlibPrintf("[%d] createObjectOnSrcPe \n", CkMyPe());   
277     ComlibPrintf("[%d] Rect createObjectOnSrcPe \n", CkMyPe());   
278     ComlibRectSectionHashObject *obj = new ComlibRectSectionHashObject();
279     
280     sinfo.getRemotePelist(nindices, idxlist, obj->npes, obj->pelist);
281     sinfo.getLocalIndices(nindices, idxlist, obj->indices);
282     // TODO: how do we get the root pe here?
283     // cheap hack, assume section built from root
284     int rootpe=CkMyPe();
285     BGLTorusManager *bgltm= BGLTorusManager::getObject();
286     int x,y,z;
287     bgltm->getCoordinatesByRank(rootpe,x, y, z);
288     obj->aid=sinfo.getDestArrayID();
289     unsigned int comm=computeKey( thisSectionID, rootpe, sinfo.getDestArrayID());
290     CkAssert(obj->npes>0);
291     BGTsRC_Geometry_t *geometry=getRectGeometry(obj ,rootpe);
292     // handle the root not in rectangle case
293     if( x >= geometry->x0 && x  < geometry->x0+ geometry->xs &&
294         y >= geometry->y0 && y  < geometry->y0+ geometry->ys &&
295         z >= geometry->z0 && z  < geometry->z0+ geometry->zs)
296       { // ok
297         ComlibPrintf("[%d] create root %d %d %d %d in rectangle %d %d %d, %d %d %d comm id = %d geom root %d %d %d geom t0 %d tr %d ts %d\n", CkMyPe(), rootpe, x, y, z, 
298                      geometry->x0, geometry->y0, geometry->z0,
299                      geometry->xs, geometry->ys, geometry->zs, comm,
300                      geometry->xr, geometry->yr, geometry->zr,
301                      geometry->t0, geometry->tr, geometry->ts
302                      );   
303         obj->sourceInRectangle=true;
304         obj->cornerRoot=rootpe;
305         void *request = CkpvAccess(com_rect_ptr)->get(comm);
306         if(request==NULL)
307           {
308             request=bgl_machine_RectBcastInit(comm, geometry);
309             ComlibPrintf("[%d] csrc init comm %d section %d srcpe %d request %p\n",CkMyPe(), comm, thisSectionID, rootpe, request);
310             CkpvAccess(com_rect_ptr)->put(comm)= request;
311 #ifdef COMLIB_RECT_DEBUG
312             isSane(request,comm);
313 #endif
314           }
315         else{
316           ComlibPrintf("[%d] csrc already init comm %d section %d srcpe %d\n",CkMyPe(), comm, thisSectionID, rootpe);
317         }
318 #ifdef COMLIB_RECT_DEBUG
319         void *getrequest =     CkpvAccess(com_rect_ptr)->get(comm);
320         CkAssert(*((char *) request)==*((char *)getrequest));
321         isSane(getrequest,comm);
322 #endif
323       }
324     else // sender not inside rectangle.
325       {  // we cannot initialize or use the rectangle from here
326         ComlibPrintf("[%d] root %d %d %d %d NOT in rectangle %d %d %d, %d %d %d  \n", CkMyPe(), rootpe, x, y, z, 
327                      geometry->x0, geometry->y0, geometry->z0,
328                      geometry->xs, geometry->ys, geometry->zs
329                      );   
330
331         obj->sourceInRectangle=false;
332         obj->cornerRoot=assignCornerRoot(geometry, rootpe);
333         /*  if we were to actually use the geom from here.
334           obj->sourceInRectangle=false;
335           geometry.xr=geometry.x0;
336           geometry.yr=geometry.y0;
337           geometry.zr=geometry.z0;
338         */
339
340       }
341     //    delete geometry;
342     return obj;
343 }
344
345
346 void RectMulticastStrategy::sendRectDest(ComlibRectSectionHashObject *obj, int srcpe, envelope *env) {
347   ComlibPrintf("[%d] sendRectDest \n", CkMyPe());   
348
349   BGTsRC_Geometry_t *geometry=getRectGeometry(obj,srcpe);
350   // now make a list of PEs based on the prism formed by the corners
351   BGLTorusManager *bgltm= BGLTorusManager::getObject();
352   int npes=geometry->xs* geometry->ys *geometry->zs;
353   ComlibPrintf("[%d] sendRectDest has %d * %d * %d = %d pes\n", CkMyPe(), geometry->xs, geometry->ys, geometry->zs, npes);
354   int *pelist= new int[npes];
355   int destpe=0;
356   for(int x=geometry->x0;x<geometry->xs+geometry->x0;x++)
357     for(int y=geometry->y0;y<geometry->ys+geometry->y0;y++)
358       for(int z=geometry->z0;z<geometry->zs+geometry->z0;z++)
359         {
360           int pe=bgltm->coords2rank(x,y,z);  
361           if(pe!=srcpe) //don't send this to ourselves
362             pelist[destpe++]=pe;
363         }
364   //  for(int i=0;i<destpe;i++)
365   //    ComlibPrintf("rect pe %d is %d\n",i,pelist[i]);
366   delete geometry;
367   //now we have the list, fire off the message
368   if(destpe == 0) {
369     CmiFree(env);
370     return;    
371   }
372     
373   //CmiSetHandler(env, handlerId);
374   CmiSetHandler(env, CkpvAccess(strategy_handlerid));
375
376   ((CmiMsgHeaderBasic *) env)->stratid = getInstance();
377
378   //Collect Multicast Statistics
379   RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, destpe);
380     
381   CkPackMessage(&env);
382   //Sending a remote multicast
383   CmiSyncListSendAndFree(destpe, pelist, env->getTotalsize(), (char*)env);
384   //CmiSyncBroadcastAndFree(env->getTotalsize(), (char*)env);
385
386
387
388
389 // based on the outside rectangle root coords, pick a root
390 int RectMulticastStrategy::assignCornerRoot(BGTsRC_Geometry_t *geometry, int srcpe)
391 {
392   fprintf(stderr,"[%d] in assign corner for not in rect root %d\n",CkMyPe(), srcpe);
393   ComlibPrintf("[%d] in assign corner for not in rect root %d\n",CkMyPe(), srcpe);
394   // just find the shortest hopcount
395   BGLTorusManager *bgltm= BGLTorusManager::getObject();
396
397   int pelist[8];
398   // make a list of the corners
399   int destpe=0;
400   pelist[destpe++]=bgltm->coords2rank(geometry->x0,geometry->y0,geometry->z0);
401   pelist[destpe++]=bgltm->coords2rank(geometry->x0+ geometry->xs-1, 
402                                       geometry->y0,geometry->z0);
403   pelist[destpe++]=bgltm->coords2rank(geometry->x0,geometry->y0+geometry->ys-1,
404                                       geometry->z0);
405   pelist[destpe++]=bgltm->coords2rank(geometry->x0,geometry->y0,
406                                       geometry->z0 + geometry->zs-1);
407   pelist[destpe++]=bgltm->coords2rank(geometry->x0+ geometry->xs-1, 
408                                       geometry->y0 +geometry->ys-1,
409                                       geometry->z0);
410   pelist[destpe++]=bgltm->coords2rank(geometry->x0+ geometry->xs-1, 
411                                       geometry->y0,
412                                       geometry->z0+geometry->zs-1);
413   pelist[destpe++]=bgltm->coords2rank(geometry->x0,
414                                       geometry->y0+ geometry->ys-1,
415                                       geometry->z0+ geometry->zs-1);
416   pelist[destpe++]=bgltm->coords2rank(geometry->x0+ geometry->xs-1, 
417                                       geometry->y0+ geometry->ys-1,
418                                       geometry->z0+ geometry->zs-1);
419
420   int newrootidx=bgltm->pickClosestRank(srcpe, pelist, destpe);
421   int newroot=pelist[newrootidx];
422   int x, y,z;
423   bgltm->getCoordinatesByRank(newroot, x,y ,z);
424   geometry->xr=x;
425   geometry->yr=y;
426   geometry->zr=z;
427   ComlibPrintf("[%d] choosing proc %d at %d,%d,%d as corner root\n",CkMyPe(), newroot, x,y ,z);
428   return(newroot);
429 }
430
431 BGTsRC_Geometry_t *RectMulticastStrategy::getRectGeometry(ComlibRectSectionHashObject *obj, int srcpe)
432 {
433     // define geometry/
434     ComlibPrintf("[%d] getRectGeometry \n", CkMyPe());   
435     BGTsRC_Geometry_t *geometry = new BGTsRC_Geometry_t;
436     // find the bounding box for the pelist
437     // get a torus manager pointer
438     BGLTorusManager *bgltm= BGLTorusManager::getObject();
439     // initialize to max
440     geometry->x0=bgltm->getXNodeSize()*2+1;
441     geometry->y0=bgltm->getYNodeSize()*2+1;
442     geometry->z0=bgltm->getZNodeSize()*2+1;
443     int xmax=0;
444     int ymax=0;
445     int zmax=0;
446     for(int i=0;i<obj->npes;i++)
447       { 
448         int x=0; int y=0; int z=0;
449         bgltm->getCoordinatesByRank(obj->pelist[i], x,y,z);
450         geometry->x0 = (x < geometry->x0) ? x : geometry->x0;
451         geometry->y0 = (y < geometry->y0) ? y : geometry->y0;
452         geometry->z0 = (z < geometry->z0) ? z : geometry->z0;
453         xmax = (x > xmax) ? x : xmax;
454         ymax = (y > ymax) ? y : ymax;
455         zmax = (z > zmax) ? z : zmax;
456       }
457     geometry->xs = xmax + 1 - geometry->x0;
458     geometry->ys = ymax + 1 - geometry->y0;
459     geometry->zs = zmax + 1 - geometry->z0;
460     geometry->t0=0; //non VN mode values
461     geometry->ts=1;
462     geometry->tr=0;
463
464     int x,y,z;
465     bgltm->getCoordinatesByRank(srcpe,x, y, z);
466     geometry->xr=x;
467     geometry->yr=y;
468     geometry->zr=z;
469     if(bgltm->isVnodeMode())
470       {
471         ComlibPrintf("VN mode Untested for rectbcast!\n");
472         // torus manager screws with us on this a bit
473         // if VN determine whether we are TXYZ or XYZT
474         // then use lowest/highest/root x or z and some division for t0 ts tr
475         // also need to halve the VN doubled dimension in [xyz]s [xyz]0 [xyz]r
476
477         // Assume TXYZ
478         geometry->ts=2;
479         geometry->t0 = geometry->x0 % 2;
480         geometry->ts = geometry->xs % 2;
481         geometry->tr = geometry->xr % 2;
482         geometry->x0 /= 2;
483         geometry->xs /= 2;
484         geometry->xr /= 2;
485       }
486     return geometry;
487 }
488
489 ComlibRectSectionHashObject *
490 RectMulticastStrategy::createObjectOnIntermediatePe(int nindices,
491                                                       CkArrayIndexMax *idxlist,
492                                                       int npes,
493                                                       ComlibMulticastIndexCount *counts,
494                                                       int srcpe, int thisSectionID) {
495
496     ComlibPrintf("[%d] createObjectOnIntermediatePe \n", CkMyPe());   
497     ComlibRectSectionHashObject *obj = new ComlibRectSectionHashObject();
498     CkAssert(npes>0);
499     sinfo.getRemotePelist(nindices, idxlist, obj->npes, obj->pelist);
500     sinfo.getLocalIndices(nindices, idxlist, obj->indices);
501     obj->aid=sinfo.getDestArrayID();
502     //obj->indices.resize(0);
503     //for (int i=0; i<nindices; ++i) obj->indices.insertAtEnd(idxlist[i]);
504     //sinfo.getLocalIndices(nindices, idxlist, obj->indices);
505     BGLTorusManager *bgltm= BGLTorusManager::getObject();
506     int x,y,z;
507     bgltm->getCoordinatesByRank(srcpe,x, y, z);
508
509     unsigned int comm = computeKey( thisSectionID, srcpe, sinfo.getDestArrayID());
510
511     if(obj->npes<=0)
512       {
513         ComlibPrintf("[%d] nindices %d, npes %d, obj->npes %d\n", CkMyPe(), nindices, npes, obj->npes);
514       }
515     CkAssert(obj->npes>0);
516     BGTsRC_Geometry_t *geometry=getRectGeometry(obj,srcpe);
517     // handle the root not in rectangle case
518     if( x >= geometry->x0 && x  < geometry->x0+ geometry->xs &&
519         y >= geometry->y0 && y  < geometry->y0+ geometry->ys &&
520         z >= geometry->z0 && z  < geometry->z0+ geometry->zs)
521       { // ok
522         ComlibPrintf("[%d] create intermediate %d %d %d %d in rectangle %d %d %d, %d %d %d comm = %d \n", CkMyPe(), srcpe, x, y, z, 
523                      geometry->x0, geometry->y0, geometry->z0,
524                      geometry->xs, geometry->ys, geometry->zs, comm
525                      );   
526
527         obj->sourceInRectangle=true;
528         obj->cornerRoot=srcpe;
529       }
530     else
531       {
532         ComlibPrintf("[%d] root %d %d %d %d NOT in rectangle %d %d %d, %d %d %d  \n", CkMyPe(), srcpe, x, y, z, 
533                      geometry->x0, geometry->y0, geometry->z0,
534                      geometry->xs, geometry->ys, geometry->zs
535                      );   
536
537
538         obj->sourceInRectangle=false;
539         // fix the root to a corner
540         obj->cornerRoot=assignCornerRoot(geometry,srcpe);
541       }
542
543     void *request = CkpvAccess(com_rect_ptr)->get(comm);
544     if(request==NULL)
545       {
546         request=bgl_machine_RectBcastInit(comm, geometry);
547         ComlibPrintf("[%d] cinter init comm %d section %d srcpe %d\n",CkMyPe(), comm, thisSectionID, srcpe);    
548       }
549     else{
550       ComlibPrintf("[%d] cinter already init comm %d section %d srcpe %d\n",CkMyPe(), comm, thisSectionID, srcpe);
551     }
552     // we don't actually need the request on a typical intermediate
553     // only the forwarding case cares.
554     CkpvAccess(com_rect_ptr)->put(comm)= request;
555 #ifdef COMLIB_RECT_DEBUG
556     void *getrequest =     CkpvAccess(com_rect_ptr)->get(comm);
557     CkAssert(*((char *) request)==*((char *)getrequest));
558     isSane(getrequest,comm);
559 #endif
560     //    delete geometry;
561     return obj;
562 }
563
564
565 void RectMulticastStrategy::doneInserting(){
566     //Do nothing! Its a bracketed strategy
567 }
568
569 extern void CmiReference(void *);
570
571 //Send the multicast message the local array elements. The message is 
572 //copied and sent if elements exist. 
573 void RectMulticastStrategy::localMulticast(envelope *env, 
574                                            ComlibRectSectionHashObject *obj) {
575     int nIndices = obj->indices.size();
576     
577     if(obj->msg != NULL) {
578         CmiFree(obj->msg);
579         obj->msg = NULL;
580     } 
581     
582     if(nIndices > 0) {
583         void *msg = EnvToUsr(env);
584         void *msg1 = msg;
585         
586         msg1 = CkCopyMsg(&msg);
587         
588         ComlibArrayInfo::localMulticast(&(obj->indices), UsrToEnv(msg1));
589     }    
590 }
591
592
593 //Calls default multicast scheme to send the messages. It could 
594 //also call a converse lower level strategy to do the muiticast.
595 //For example pipelined multicast
596 void RectMulticastStrategy::remoteMulticast(envelope *env, 
597                                             ComlibRectSectionHashObject *obj) {
598
599     ComlibPrintf("[%d] remoteMulticast \n", CkMyPe());       
600     int npes = obj->npes;
601     int *pelist = obj->pelist;
602     
603     //    if(npes == 0) {
604     //        CmiFree(env);
605     //        return;    
606     //    }
607     
608     //CmiSetHandler(env, handlerId);
609     CmiSetHandler(env, CkpvAccess(strategy_handlerid));
610
611     ((CmiMsgHeaderBasic *) env)->stratid = getInstance();
612
613     //Collect Multicast Statistics
614     RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, npes);
615     int srcpe=env->getSrcPe();    
616     CkPackMessage(&env);
617
618
619     //    int destid=env->getGroupNum().idx;    
620     
621     //Sending a remote multicast
622     ComlibMulticastMsg *cbmsg = (ComlibMulticastMsg *)EnvToUsr(env);
623     int sectionID=cbmsg->_cookie.sInfo.cInfo.id;
624     CkArrayID destid=obj->aid;
625     // bgl_machineRectBcast should only be called once globally
626     // per multicast
627     int comm=computeKey(sectionID, srcpe, destid);
628     ComlibPrintf("[%d] rectbcast using comm %d section %d srcpe %d request %p\n",CkMyPe(), comm, sectionID, srcpe, CkpvAccess(com_rect_ptr)->get(comm));
629 #ifdef COMLIB_RECT_DEBUG
630     isSane(CkpvAccess(com_rect_ptr)->get(comm),comm);
631 #endif
632     bgl_machine_RectBcast(comm  , (char*)env, env->getTotalsize());
633     //CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env);
634     //CmiSyncBroadcastAndFree(env->getTotalsize(), (char*)env);
635 }
636
637 // For source not in rectangle case, forward to corner of rectangle
638 //
639 void RectMulticastStrategy::forwardMulticast(envelope *env, 
640                                               ComlibRectSectionHashObject *obj) {
641
642     ComlibPrintf("[%d] forwardMulticast \n", CkMyPe());       
643     int *pelist = obj->pelist;
644     int npes    = obj->npes;
645     if(npes == 0) {
646         CmiFree(env);
647         return;    
648     }
649     // handler is changed to special root handler
650     CmiSetHandler(env, handlerId);
651
652     ((CmiMsgHeaderBasic *) env)->stratid = getInstance();
653
654     //Collect Multicast Statistics
655     RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, npes);
656     
657     CkPackMessage(&env);
658     //Sending a remote multicast
659     ComlibMulticastMsg *cbmsg = (ComlibMulticastMsg *)EnvToUsr(env);
660     int sectionID=cbmsg->_cookie.sInfo.cInfo.id;
661
662     //   CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env);
663     CmiSyncSendAndFree(obj->cornerRoot, env->getTotalsize(), (char*)env);
664     //CmiSyncBroadcastAndFree(env->getTotalsize(), (char*)env);
665 }
666
667
668 void RectMulticastStrategy::pup(PUP::er &p){
669
670     CharmStrategy::pup(p);
671 }
672
673 void RectMulticastStrategy::beginProcessing(int numElements){
674     
675     //handlerId = CkRegisterHandler((CmiHandler)DMHandler);    
676     handlerId = CkRegisterHandler((CmiHandler)sourceOffRectstrategyHandler);    
677     bgl_machine_RectBcastConfigure (rectRequest);
678     CkArrayID dest;
679     int nidx;
680     CkArrayIndexMax *idx_list;
681
682     ainfo.getDestinationArray(dest, idx_list, nidx);
683     sinfo = ComlibSectionInfo(dest, myInstanceID);
684
685     ComlibLearner *learner = new ComlibLearner();
686     //setLearner(learner);
687 }
688
689 void RectMulticastStrategy::handleMessage(void *msg){
690     envelope *env = (envelope *)msg;
691     RECORD_RECV_STATS(getInstance(), env->getTotalsize(), env->getSrcPe());
692
693     //Section multicast base message
694     CkMcastBaseMsg *cbmsg = (CkMcastBaseMsg *)EnvToUsr(env);
695     
696     int status = cbmsg->_cookie.sInfo.cInfo.status;
697     ComlibPrintf("[%d] In handleMessage %d\n", CkMyPe(), status);
698     
699     if(status == COMLIB_MULTICAST_NEW_SECTION)
700         handleNewMulticastMessage(env);
701     else {
702         //status == COMLIB_MULTICAST_OLD_SECTION, use the cached section id
703         ComlibSectionHashKey key(cbmsg->_cookie.pe, 
704                                  cbmsg->_cookie.sInfo.cInfo.id);    
705         
706         ComlibRectSectionHashObject *obj;
707         obj = sec_ht.get(key);
708         
709         if(obj == NULL)
710             CkAbort("Destination indices is NULL\n");
711 #ifndef LOCAL_MULTI_OFF        
712         localMulticast(env, obj);
713 #endif
714         // remote is handled by the rectangle
715
716     }
717 }
718
719 void RectMulticastStrategy::handleMessageForward(void *msg){
720   
721     envelope *env = (envelope *)msg;
722     RECORD_RECV_STATS(getInstance(), env->getTotalsize(), env->getSrcPe());
723
724     //Section multicast base message
725     CkMcastBaseMsg *cbmsg = (CkMcastBaseMsg *)EnvToUsr(env);
726     
727     int status = cbmsg->_cookie.sInfo.cInfo.status;
728     ComlibPrintf("[%d] In handleMessageForward %d\n", CkMyPe(), status);
729     
730     if(status == COMLIB_MULTICAST_NEW_SECTION)
731         handleNewMulticastMessage(env);
732     else {
733         //status == COMLIB_MULTICAST_OLD_SECTION, use the cached section id
734         ComlibSectionHashKey key(cbmsg->_cookie.pe, 
735                                  cbmsg->_cookie.sInfo.cInfo.id);    
736         
737         ComlibRectSectionHashObject *obj;
738         obj = sec_ht.get(key);
739         
740         if(obj == NULL)
741             CkAbort("Destination indices is NULL\n");
742 #ifndef LOCAL_MULTI_OFF                
743         localMulticast(env, obj);
744 #endif
745         remoteMulticast(env, obj);
746     }
747 }
748
749 #include <string>
750
751 void RectMulticastStrategy::handleNewMulticastMessage(envelope *env) {
752     
753     ComlibPrintf("[%d] : In handleNewMulticastMessage\n", CkMyPe());
754
755     CkUnpackMessage(&env);    
756     int sender=env->getSrcPe();
757     int localElems;
758     envelope *newenv;
759     CkArrayIndexMax *local_idx_list;    
760     
761     sinfo.unpack(env, localElems, local_idx_list, newenv);
762
763     ComlibMulticastMsg *cbmsg = (ComlibMulticastMsg *)EnvToUsr(env);
764     ComlibSectionHashKey key(cbmsg->_cookie.pe, 
765                              cbmsg->_cookie.sInfo.cInfo.id);
766     
767     ComlibRectSectionHashObject *old_obj = NULL;
768
769     old_obj = sec_ht.get(key);
770
771     if(old_obj != NULL) {
772         delete old_obj;
773     }
774
775     /*
776     CkArrayIndexMax *idx_list_array = new CkArrayIndexMax[idx_list.size()];
777     for(int count = 0; count < idx_list.size(); count++)
778         idx_list_array[count] = idx_list[count];
779     */
780
781     int cur_sec_id=cbmsg->_cookie.sInfo.cInfo.id;
782
783     // need everyPe for rectangle not just local_idx_list
784
785     ComlibMulticastMsg *lll = cbmsg;
786     envelope *ppp = UsrToEnv(cbmsg);
787     CkUnpackMessage(&ppp);
788     int ttt=0;
789     int uuu=0;
790     for (int i=0; i<lll->nPes; ++i) {
791       //              ComlibPrintf(" %d (",lll->indicesCount[i].pe);
792       uuu++;
793       for (int j=0; j<lll->indicesCount[i].count; ++j) {
794         //              ComlibPrintf(" %d",((int*)&(lll->indices[ttt]))[1]);
795         ttt++;
796       }
797       //              ComlibPrintf(" )");
798     }
799     ComlibPrintf("[%d] cbmsg for intermediate has %d indices %d pes\n",CkMyPe(),ttt, uuu);
800     CkAssert(uuu>0);
801     CkAssert(ttt>0);
802
803     ComlibRectSectionHashObject *new_obj = createObjectOnIntermediatePe(ttt, cbmsg->indices, cbmsg->nPes, cbmsg->indicesCount, sender, cur_sec_id );
804     // now revise obj for local use only
805     sinfo.getRemotePelist(localElems, local_idx_list, new_obj->npes, new_obj->pelist);
806     sinfo.getLocalIndices(localElems, local_idx_list, new_obj->indices);
807
808     sec_ht.put(key) = new_obj;
809     CkPackMessage(&newenv);   
810 #ifndef LOCAL_MULTI_OFF        
811
812     localMulticast(newenv, new_obj); //local multicast always copies
813 #endif
814     CmiFree(newenv);  //NEED this
815 }
816 #endif
817
818
819 /*@}*/