1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 /****************************************************************************/
4 /*                                                                          */
5 /* File:      supp.c                                                        */
6 /*                                                                          */
7 /* Purpose:   support routines for Transfer Module                          */
8 /*                                                                          */
9 /* Author:    Klaus Birken                                                  */
10 /*            Rechenzentrum Uni Stuttgart                                   */
11 /*            Universitaet Stuttgart                                        */
12 /*            Allmandring 30                                                */
13 /*            70550 Stuttgart                                               */
14 /*            internet: birken@rus.uni-stuttgart.de                         */
15 /*                                                                          */
16 /* History:   93/11/30 kb  begin (xfer.c)                                   */
17 /*            95/03/21 kb  added variable sized objects (XferCopyObjX)      */
18 /*            95/04/05 kb  V1.3: extracted from xfer.c                      */
19 /*                                                                          */
20 /* Remarks:                                                                 */
21 /*                                                                          */
22 /****************************************************************************/
23 
24 /****************************************************************************/
25 /*                                                                          */
26 /* include files                                                            */
27 /*            system include files                                          */
28 /*            application include files                                     */
29 /*                                                                          */
30 /****************************************************************************/
31 
32 /* standard C library */
33 #include <config.h>
34 #include <cstdlib>
35 #include <cstdio>
36 #include <cassert>
37 
38 #include <new>
39 
40 #include <dune/uggrid/parallel/ddd/dddi.h>
41 
42 USING_UG_NAMESPACE
43 
44 /*
45         NOTE: all container-classes from ooppcc.h are implemented in this
46               source file by setting the following define.
47  */
48 #define ContainerImplementation
49 /* this is the hardliner version, for debugging only
50    #define _CHECKALLOC(ptr)   assert(ptr!=NULL)
51  */
52 #define _CHECKALLOC(ptr)   if (ptr==NULL) return (NULL)
53 
54 #include "xfer.h"
55 
56 /****************************************************************************/
57 /*                                                                          */
58 /* definition of constants, macros                                          */
59 /*                                                                          */
60 /****************************************************************************/
61 
62 #define ADDDATASEGM_SIZE 256
63 #define SIZESSEGM_SIZE 2048
64 
65 
66 
67 
68 /****************************************************************************/
69 /*                                                                          */
70 /* data types                                                               */
71 /*                                                                          */
72 /****************************************************************************/
73 
74 namespace DDD {
75 namespace Xfer {
76 
77 /* segment of AddDatas */
78 struct AddDataSegm
79 {
80   AddDataSegm *next;
81   int nItems;
82 
83   XFERADDDATA item[ADDDATASEGM_SIZE];
84 };
85 
86 
87 /* segment of AddData-Sizes */
88 struct SizesSegm
89 {
90   SizesSegm   *next;
91   int current;
92 
93   int data[SIZESSEGM_SIZE];
94 };
95 
96 } /* namespace Xfer */
97 } /* namespace DDD */
98 START_UGDIM_NAMESPACE
99 
100 using namespace DDD::Xfer;
101 
102 /****************************************************************************/
103 /*                                                                          */
104 /* class member function implementations                                    */
105 /*                                                                          */
106 /****************************************************************************/
107 
108 #define ClassName XICopyObj
109 
110 /*
111         compare-method in order to eliminate double XICopyObj-items.
112         merge priorities from similar XICopyObj-items.
113 
114         the items are sorted according to key (dest,gid),
115         all in ascending order. if dest and gid are equal,
116         we merge priorities and get a new priority together with
117         the information whether first item wins over second.
118         in both cases, we use the new priority for next comparison.
119 
120         this implements rule XFER-C1.
121  */
Method(Compare)122 int Method(Compare) (ClassPtr item1, ClassPtr item2, const DDD::DDDContext* context)
123 {
124   DDD_PRIO newprio;
125   int ret;
126 
127   if (item1->dest < item2->dest) return(-1);
128   if (item1->dest > item2->dest) return(1);
129 
130   if (item1->gid < item2->gid) return(-1);
131   if (item1->gid > item2->gid) return(1);
132 
133 
134   /* items have equal gid and dest, so they are considered as equal. */
135   /* however, we must check priority, and patch both items with
136      the new priority after merge. */
137   ret = PriorityMerge(&context->typeDefs()[OBJ_TYPE(item1->hdr)],
138                       item1->prio, item2->prio, &newprio);
139 
140   item1->prio = newprio;
141 
142   if (ret==PRIO_FIRST || ret==PRIO_UNKNOWN)
143   {
144     /* tell XferInitCopyInfo() that item is rejected */
145     item2->prio = PRIO_INVALID;
146   }
147   else
148   {
149     /* communicate new priority to XferInitCopyInfo() */
150     item2->prio = newprio;
151   }
152 
153   return(0);
154 }
155 
156 
Method(Print)157 void Method(Print) (ParamThis _PRINTPARAMS)
158 {
159   fprintf(fp, "XICopyObj dest=%d gid=" DDD_GID_FMT " prio=%d\n",
160           This->dest, This->gid, This->prio);
161 }
162 
163 #undef ClassName
164 
165 
166 
167 /****************************************************************************/
168 
169 #define ClassName XISetPrio
170 
171 /*
172         compare-method in order to eliminate double XISetPrio-items.
173         merge priorities from similar XISetPrio-items.
174 
175         the items are sorted according to key (gid),
176         all in ascending order. if both gids are equal,
177         we merge priorities and get a new priority together with
178         the information whether first item wins over second.
179         in both cases, we use the new priority for next comparison.
180 
181         this implements rule XFER-P1.
182  */
Method(Compare)183 int Method(Compare) (ClassPtr item1, ClassPtr item2, const DDD::DDDContext* context)
184 {
185   DDD_PRIO newprio;
186   int ret;
187 
188   /* ascending GID is needed for ExecLocalXI___ */
189   if (item1->gid < item2->gid) return(-1);
190   if (item1->gid > item2->gid) return(1);
191 
192 
193   /* items have equal gid and dest, so they are considered as equal. */
194   /* however, we must check priority, and patch both items with
195      the new priority after merge. */
196   ret = PriorityMerge(&context->typeDefs()[OBJ_TYPE(item1->hdr)],
197                       item1->prio, item2->prio, &newprio);
198 
199   item1->prio = item2->prio = newprio;
200 
201 
202   if (ret==PRIO_FIRST || ret==PRIO_UNKNOWN)
203   {
204     /* tell XferInitCopyInfo() that item is rejected */
205     item2->prio = PRIO_INVALID;
206   }
207   else
208   {
209     /* communicate new priority to XferInitCopyInfo() */
210     item2->prio = newprio;
211   }
212 
213   return(0);
214 }
215 
216 
Method(Print)217 void Method(Print) (ParamThis _PRINTPARAMS)
218 {
219   fprintf(fp, "XISetPrio gid=" DDD_GID_FMT " prio=%d\n", This->gid, This->prio);
220 }
221 
222 #undef ClassName
223 
224 
225 /****************************************************************************/
226 
227 
228 /*
229     include templates
230  */
231 #define T XIDelCmd
232 #define SLL_WithOrigOrder
233 #include "sll.ct"
234 #undef T
235 
236 #define T XIDelObj
237 #include "sll.ct"
238 #undef T
239 
240 #define T XINewCpl
241 #include "sll.ct"
242 #undef T
243 
244 #define T XIOldCpl
245 #include "sll.ct"
246 #undef T
247 
248 
249 
250 #define T XIAddCpl
251 #include "sll.ct"
252 #undef T
253 
254 #define T XIDelCpl
255 #include "sll.ct"
256 #undef T
257 
258 #define T XIModCpl
259 #include "sll.ct"
260 #undef T
261 
262 
263 
264 /****************************************************************************/
265 
266 
NewAddDataSegm(DDD::DDDContext & context)267 static AddDataSegm *NewAddDataSegm(DDD::DDDContext& context)
268 {
269   auto& ctx = context.xferContext();
270   AddDataSegm *segm;
271 
272   segm = (AddDataSegm *) OO_Allocate(sizeof(AddDataSegm));
273   if (segm==NULL)
274     throw std::bad_alloc();
275 
276   segm->next      = ctx.segmAddData;
277   ctx.segmAddData = segm;
278   segm->nItems    = 0;
279 
280   return(segm);
281 }
282 
283 
FreeAddDataSegms(DDD::DDDContext & context)284 static void FreeAddDataSegms(DDD::DDDContext& context)
285 {
286   auto& ctx = context.xferContext();
287   AddDataSegm *segm = ctx.segmAddData;
288   AddDataSegm *next = NULL;
289 
290   while (segm!=NULL)
291   {
292     next = segm->next;
293     OO_Free (segm /*,sizeof(AddDataSegm)*/);
294 
295     segm = next;
296   }
297 
298   ctx.segmAddData = nullptr;
299 }
300 
301 
302 /****************************************************************************/
303 
304 
NewSizesSegm(DDD::DDDContext & context)305 static SizesSegm *NewSizesSegm(DDD::DDDContext& context)
306 {
307   auto& ctx = context.xferContext();
308   SizesSegm *segm;
309 
310   segm = (SizesSegm *) OO_Allocate (sizeof(SizesSegm));
311   if (segm==NULL)
312     throw std::bad_alloc();
313 
314   segm->next    = ctx.segmSizes;
315   ctx.segmSizes = segm;
316   segm->current = 0;
317 
318   return(segm);
319 }
320 
321 
FreeSizesSegms(DDD::DDDContext & context)322 static void FreeSizesSegms(DDD::DDDContext& context)
323 {
324   auto& ctx = context.xferContext();
325   SizesSegm *segm = ctx.segmSizes;
326   SizesSegm *next = NULL;
327 
328   while (segm!=NULL)
329   {
330     next = segm->next;
331     OO_Free (segm /*,sizeof(SizesSegm)*/);
332 
333     segm = next;
334   }
335 
336   ctx.segmSizes = nullptr;
337 }
338 
339 
340 /****************************************************************************/
341 
342 
NewXIAddData(DDD::DDDContext & context)343 XFERADDDATA *NewXIAddData(DDD::DDDContext& context)
344 {
345   auto& ctx = context.xferContext();
346   AddDataSegm *segm = ctx.segmAddData;
347   XFERADDDATA *xa;
348 
349   if (segm==NULL || segm->nItems==ADDDATASEGM_SIZE)
350   {
351     segm = NewAddDataSegm(context);
352   }
353 
354   xa = &(segm->item[segm->nItems++]);
355   xa->next = ctx.theXIAddData->add;
356   ctx.theXIAddData->add = xa;
357 
358   return(xa);
359 }
360 
361 
362 
FreeAllXIAddData(DDD::DDDContext & context)363 void FreeAllXIAddData(DDD::DDDContext& context)
364 {
365   FreeAddDataSegms(context);
366   FreeSizesSegms(context);
367 }
368 
369 
370 /****************************************************************************/
371 
AddDataAllocSizes(DDD::DDDContext & context,int cnt)372 int *AddDataAllocSizes (DDD::DDDContext& context, int cnt)
373 {
374   auto& ctx = context.xferContext();
375   SizesSegm *segm = ctx.segmSizes;
376   int *pos;
377 
378   if (segm==NULL || segm->current+cnt>=SIZESSEGM_SIZE)
379   {
380     segm = NewSizesSegm(context);
381   }
382 
383   pos = segm->data + segm->current;
384   segm->current += cnt;
385 
386   return(pos);
387 }
388 
389 
390 /****************************************************************************/
391 
392 
393 /*
394         get quantitative resource usage
395  */
GetSizesXIAddData(const DDD::DDDContext & context,int * nSegms,int * nItems,size_t * alloc_mem,size_t * used_mem)396 void GetSizesXIAddData(const DDD::DDDContext& context, int *nSegms, int *nItems, size_t *alloc_mem, size_t *used_mem)
397 {
398   const auto& ctx = context.xferContext();
399   size_t allocated=0, used=0;
400   int ns=0, ni=0;
401 
402   {
403     for (const AddDataSegm* segm=ctx.segmAddData; segm!=NULL; segm=segm->next)
404     {
405       /* count number of segments and number of items */
406       ns++;
407       ni+=segm->nItems;
408 
409       /* compute memory usage */
410       allocated += sizeof(AddDataSegm);
411       used += (sizeof(AddDataSegm) -
412                (sizeof(XFERADDDATA)*(ADDDATASEGM_SIZE-segm->nItems)));
413     }
414   }
415 
416   /* TODO: add resources for SizesSegm */
417 
418 
419   *nSegms    = ns;
420   *nItems    = ni;
421   *alloc_mem = allocated;
422   *used_mem  = used;
423 }
424 
425 
426 /****************************************************************************/
427 
428 END_UGDIM_NAMESPACE
429