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