Adding some user events to trace the multicasts.
[charm.git] / src / ck-com / ComlibSectionInfo.h
1 /**
2    @addtogroup CharmComlib
3    @{
4    @file
5    
6    @brief Utility classes to handle sections in comlib where they are needed
7    (basically multicast strategies).
8 */
9
10 #ifndef COMLIB_SECTION_INFO
11 #define COMLIB_SECTION_INFO
12
13 /***********
14   Helper classes that help strategies manage array sections 
15 ***********/
16
17 /** Hash key that lets a strategy access a section id data structure
18     given the source processor and the MaxSectionId on that processor
19 */
20 class ComlibSectionHashKey{
21  public:
22     int srcPe;
23     int id;
24     ComlibSectionHashKey(int _pe, int _id):srcPe(_pe), id(_id){};
25
26     //These routines allow ComlibSectionHashKey to be used in
27     //  a CkHashtableT
28     CkHashCode hash(void) const;
29     static CkHashCode staticHash(const void *a,size_t);
30     int compare(const ComlibSectionHashKey &ind) const;
31     static int staticCompare(const void *a,const void *b,size_t);
32 };
33
34 /*********** CkHashTable functions ******************/
35 inline CkHashCode ComlibSectionHashKey::hash(void) const
36 {
37     register int _id = id;
38     register int _pe = srcPe;
39     
40     register CkHashCode ret = (_id << 16) + _pe;
41     return ret;
42 }
43
44 inline int ComlibSectionHashKey::compare(const ComlibSectionHashKey &k2) const
45 {
46     if(id == k2.id && srcPe == k2.srcPe)
47         return 1;
48     
49     return 0;
50 }
51
52 /**For calls to qsort*/
53 inline int intCompare(const void *a, const void *b){
54     int a1 = *(int *) a;
55     int b1 = *(int *) b;
56
57     if(a1 < b1)
58         return -1;
59     
60     if(a1 == b1)
61         return 0;
62
63     if(a1 > b1)
64         return 1;
65
66     return 0;
67 }    
68
69 //ComlibSectionHashKey CODE
70 inline int ComlibSectionHashKey::staticCompare(const void *k1, const void *k2, 
71                                                 size_t ){
72     return ((const ComlibSectionHashKey *)k1)->
73                 compare(*(const ComlibSectionHashKey *)k2);
74 }
75
76 inline CkHashCode ComlibSectionHashKey::staticHash(const void *v,size_t){
77     return ((const ComlibSectionHashKey *)v)->hash();
78 }
79
80 /*************** End CkHashtable Functions *****************/
81
82
83 /// Holds information about a strategy, in case it is used multiple times
84 /// All this information is derived from the incoming messages
85 class ComlibSectionHashObject {
86  public:
87     //My local indices
88     CkVec<CkArrayIndexMax> indices;
89     
90     //Other processors to send this message to
91     int npes;
92     int *pelist;
93
94     void *msg;
95
96     //Flags associated with the section
97     int isOld; // 1 if the section is indeed old
98     
99     ComlibSectionHashObject(): indices(0), isOld(0) {
100         npes = 0;
101         pelist = NULL;
102         msg = NULL;
103     }
104
105     ~ComlibSectionHashObject() {
106         delete [] pelist;
107         //delete msg;
108     }
109 };
110
111
112 /** 
113     Helps a communication library strategy manage array sections, creating unique
114     identifiers for sections, and parsing messages.
115
116     The class maintains a counter for generating unique ids for each section.
117     It also provides utility functions that can extract information such as PE 
118     lists from messages.
119  */
120 class ComlibSectionInfo {
121  
122   /// Maximum section id used so far. Incremented for each new CkSectionID that gets created.
123   /// Will be used (along with the source PE) to access a hashtable on remote processors, when
124   /// looking up persistent data for the section.
125   int MaxSectionID;
126
127  public:
128
129     ComlibSectionInfo() { 
130       MaxSectionID = 1;
131     }
132    
133     /// Create a unique identifier for the supplied CkSectionID
134     inline void initSectionID(CkSectionID *sid) {
135       if (MaxSectionID > 65000) {
136         CkAbort("Too many sections allocated, wrapping of ints should be done!\n");
137       }
138       ComlibPrintf("[%d] ComlibSectionInfo::initSectionID: creating section number %d for proc %d\n",
139           CkMyPe(), MaxSectionID, sid->_cookie.pe);
140       sid->_cookie.sInfo.cInfo.id = MaxSectionID ++;
141       sid->_cookie.pe = CkMyPe();
142     }
143     
144     void processOldSectionMessage(CharmMessageHolder *cmsg);
145
146     /**
147      * Create a new message to be sent to the root processor of this broadcast
148      * to tell it that we missed some objects during delivery. This new message
149      * is returned, and it contains the same section id contained in the
150      * CkMcastBaseMsg passed as parameter.
151      */
152     CkMcastBaseMsg *getNewDeliveryErrorMsg(CkMcastBaseMsg *base);
153
154     /**
155      * Starting from a message to be sent, it generates a new message containing
156      * the information about the multicast, together with the message itself.
157      * The info about the multicast is contained in the field sec_id of cmsg.
158      * The processors will be order by MyPe() if requested.
159      * The destination array to lookup is in the envelope of the message.
160      */
161     ComlibMulticastMsg *getNewMulticastMessage(CharmMessageHolder *cmsg, int needSort, int instanceID);
162
163     /**
164      * Given a ComlibMulticastMsg arrived through the network as input (cb_env),
165      * separate it into its basic components.
166
167      * destIndeces is the pointer to the first element in this processor (as by
168      * the knowledge of the sender); nLocalElems is the count of how many
169      * elements are local. env is a new allocated memory containing the user
170      * message.
171      */
172     void unpack(envelope *cb_env, int &nLocalElems, CkArrayIndexMax *&destIndices, 
173                 envelope *&env);
174
175     void localMulticast(envelope *env);
176
177     /**
178      * Returns the number of remote procs involved in the array index list, the
179      * number of elements each proc has, and the mapping between indices and
180      * procs.
181      
182      * @param nindices size of the array idxlist (input)
183      * @param idxlist array of indices of the section (input)
184      * @param destArrayID array ID to which the indeces refer (input)
185      * @param npes number of remote processors involved (output)
186      * @param nidx number of indices that are remote (output)
187      * @param counts array of associations pe-count: number of elements in proc pe (output, new'ed(CkNumPes()))
188      * @param belongs array of integers expressing association of elements with pes: belongs[i] = index in counts of the processor having index i (output, new'ed(nindices))
189     */
190     void getPeCount(int nindices, CkArrayIndexMax *idxlist, const CkArrayID &destArrayID,
191                     int &npes, int &nidx,
192                     ComlibMulticastIndexCount *&counts, int *&belongs);
193
194     void getPeList(envelope *cb_env, int npes, int *&pelist);
195
196     /**
197      * Returns the list of remote procs (therefore not including our processor)
198      * involved in the array index list.
199
200      * @param nindices size of the array idxlist (input
201      * @param idxlist array of indices of the section (input)
202      * @param destArrayID array ID to which the indeces refer (input)
203      * @param npes number of processors involved (output)
204      * @param pelist list of the processors involved (output, new'ed)
205      */
206     void getRemotePelist(int nindices, CkArrayIndexMax *idxlist, CkArrayID &destArrayID,
207                          int &npes, int *&pelist);
208
209     /** Returns the same list as getRemotePeList, only that it does not exclude
210         the local processor from the list if it is involved. */
211     void getPeList(int nindices, CkArrayIndexMax *idxlist, CkArrayID &destArrayID,
212                    int &npes, int *&pelist);
213
214     void getLocalIndices(int nindices, CkArrayIndexMax *idxlist, CkArrayID &destArrayID,
215                          CkVec<CkArrayIndexMax> &idx_vec);   
216         
217     void getNodeLocalIndices(int nindices, CkArrayIndexMax *idxlist, CkArrayID &destArrayID,
218                          CkVec<CkArrayIndexMax> &idx_vec);   
219         
220     void pup(PUP::er &p) {
221         p | MaxSectionID;
222     }
223 };
224
225 #endif