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