~ubuntu-branches/ubuntu/utopic/adios/utopic

« back to all changes in this revision

Viewing changes to src/aggregation.cpp

  • Committer: Package Import Robot
  • Author(s): Alastair McKinstry
  • Date: 2013-12-09 15:21:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20131209152131-jtd4fpmdv3xnunnm
Tags: 1.5.0-1
* New upstream.
* Standards-Version: 3.9.5
* Include latest config.{sub,guess} 
* New watch file.
* Create libadios-bin for binaries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * aggregation.cpp
3
 
 *
4
 
 *  Created on: Mar 9, 2009
5
 
 *      Author: thkorde
6
 
 */
7
 
 
8
 
#ifdef HAVE_CONFIG_H
9
 
#include "config.h"
10
 
#endif
11
 
 
12
 
#include <assert.h>
13
 
 
14
 
#include <nssi_server.h>
15
 
 
16
 
#include <algorithm>
17
 
#include <map>
18
 
#include <list>
19
 
 
20
 
using namespace std;
21
 
 
22
 
#include "aggregation.h"
23
 
 
24
 
 
25
 
struct ltstr
26
 
{
27
 
  bool operator()(const char* s1, const char* s2) const
28
 
  {
29
 
    return strcmp(s1, s2) < 0;
30
 
  }
31
 
};
32
 
 
33
 
 
34
 
 
35
 
typedef struct {
36
 
    int ahead_count;
37
 
    int behind_count;
38
 
    int same_count;
39
 
    int no_match_count;
40
 
} chunk_location_count_t;
41
 
 
42
 
typedef list<aggregation_chunk_details_t *> chunk_details_t;
43
 
typedef list<aggregation_chunk_details_t *>::iterator chunk_details_iterator_t;
44
 
 
45
 
typedef struct {
46
 
    aggregation_chunk_details_t *details;
47
 
    chunk_details_t              component_chunks;
48
 
} aggregation_chunk_t;
49
 
 
50
 
typedef list<aggregation_chunk_t *> chunks_t;
51
 
typedef list<aggregation_chunk_t *>::iterator chunks_iterator_t;
52
 
 
53
 
 
54
 
typedef struct {
55
 
    char      var_path[ADIOS_PATH_MAX];
56
 
    char      var_name[ADIOS_PATH_MAX];
57
 
    chunks_t *chunks;
58
 
    int       chunks_received;
59
 
} per_var_details_t;
60
 
 
61
 
typedef map<const char *, per_var_details_t *, ltstr> var_map_t;
62
 
typedef map<const char *, per_var_details_t *, ltstr>::iterator var_map_iterator_t;
63
 
typedef pair<const char *, per_var_details_t *> var_map_pair_t;
64
 
 
65
 
typedef struct {
66
 
    int        fd;
67
 
    var_map_t  vars;
68
 
    write_type type; /* direct, aggregate independent, aggregate collective */
69
 
} file_details_t;
70
 
 
71
 
static map<int, file_details_t *> open_file_map;
72
 
typedef map<int, file_details_t *>::iterator open_file_map_iterator_t;
73
 
typedef pair<int, file_details_t *> open_file_map_pair_t;
74
 
 
75
 
 
76
 
 
77
 
static int DEBUG=0;
78
 
 
79
 
 
80
 
 
81
 
 
82
 
bool compare_chunks_for_aggregation(const aggregation_chunk_t* c1, const aggregation_chunk_t* c2)
83
 
{
84
 
    aggregation_chunk_details_t *details1=c1->details;
85
 
    aggregation_chunk_details_t *details2=c2->details;
86
 
 
87
 
    for (int i=0;i<details1->ndims;i++) {
88
 
        if (details1->count[i] < details2->count[i]) {
89
 
            return true;
90
 
        } else if (details1->count[i] > details2->count[i]) {
91
 
            return false;
92
 
        }
93
 
    }
94
 
    for (int i=0;i<details1->ndims;i++) {
95
 
        if (details1->offset[i] < details2->offset[i]) {
96
 
            return true;
97
 
        } else if (details1->offset[i] > details2->offset[i]) {
98
 
            return false;
99
 
        }
100
 
    }
101
 
    return false;
102
 
}
103
 
 
104
 
bool compare_chunks_for_caching(const aggregation_chunk_t* c1, const aggregation_chunk_t* c2)
105
 
{
106
 
    aggregation_chunk_details_t *details1=c1->details;
107
 
    aggregation_chunk_details_t *details2=c2->details;
108
 
 
109
 
    for (int i=0;i<details1->ndims;i++) {
110
 
        if (details1->offset[i] < details2->offset[i]) {
111
 
            return true;
112
 
        } else if (details1->offset[i] > details2->offset[i]) {
113
 
            return false;
114
 
        }
115
 
    }
116
 
    return false;
117
 
}
118
 
 
119
 
file_details_t *new_open_file(const int fd)
120
 
{
121
 
    file_details_t *details=NULL;
122
 
 
123
 
    details = new file_details_t;
124
 
    details->fd = fd;
125
 
 
126
 
    return details;
127
 
}
128
 
 
129
 
int use_aggregation(const int fd)
130
 
{
131
 
    file_details_t *details=NULL;
132
 
 
133
 
    details = open_file_map[fd];
134
 
    if ((details->type == WRITE_AGGREGATE_INDEPENDENT) ||
135
 
        (details->type == WRITE_AGGREGATE_COLLECTIVE)) {
136
 
        return TRUE;
137
 
    }
138
 
 
139
 
    return FALSE;
140
 
}
141
 
 
142
 
int use_caching(const int fd)
143
 
{
144
 
    file_details_t *details=NULL;
145
 
 
146
 
    details = open_file_map[fd];
147
 
    if ((details->type == WRITE_CACHING_INDEPENDENT) ||
148
 
        (details->type == WRITE_CACHING_COLLECTIVE)) {
149
 
        return TRUE;
150
 
    }
151
 
 
152
 
    return FALSE;
153
 
}
154
 
 
155
 
int use_collective(const int fd)
156
 
{
157
 
    file_details_t *details=NULL;
158
 
 
159
 
    details = open_file_map[fd];
160
 
    if ((details->type == WRITE_AGGREGATE_COLLECTIVE) ||
161
 
        (details->type == WRITE_CACHING_COLLECTIVE)) {
162
 
        return TRUE;
163
 
    }
164
 
 
165
 
    return FALSE;
166
 
}
167
 
 
168
 
int use_independent(const int fd)
169
 
{
170
 
    file_details_t *details=NULL;
171
 
 
172
 
    details = open_file_map[fd];
173
 
    if ((details->type == WRITE_AGGREGATE_INDEPENDENT) ||
174
 
        (details->type == WRITE_CACHING_INDEPENDENT)) {
175
 
        return TRUE;
176
 
    }
177
 
 
178
 
    return FALSE;
179
 
}
180
 
 
181
 
int use_direct(const int fd)
182
 
{
183
 
    file_details_t *details=NULL;
184
 
 
185
 
    details = open_file_map[fd];
186
 
    if (details->type == WRITE_DIRECT) {
187
 
        return TRUE;
188
 
    }
189
 
 
190
 
    return FALSE;
191
 
}
192
 
 
193
 
int getTypeSize(
194
 
        enum ADIOS_DATATYPES type,
195
 
        void *val)
196
 
{
197
 
    switch (type)
198
 
    {
199
 
    case adios_byte:
200
 
    case adios_unsigned_byte:
201
 
        return 1;
202
 
 
203
 
    case adios_string:
204
 
        return strlen ((char *) val);
205
 
 
206
 
    case adios_short:
207
 
    case adios_unsigned_short:
208
 
        return 2;
209
 
 
210
 
    case adios_integer:
211
 
    case adios_unsigned_integer:
212
 
        return 4;
213
 
 
214
 
    case adios_real:
215
 
        return 4;
216
 
 
217
 
    case adios_long:
218
 
    case adios_unsigned_long:
219
 
        return 8;
220
 
 
221
 
    case adios_double:
222
 
        return 8;
223
 
 
224
 
    case adios_long_double:
225
 
        return 16;
226
 
 
227
 
    case adios_complex:
228
 
        return 2 * 4;
229
 
 
230
 
    case adios_double_complex:
231
 
        return 2 * 8;
232
 
 
233
 
    default:
234
 
        return -1;
235
 
    }
236
 
}
237
 
 
238
 
void add_file(const int fd,
239
 
            const write_type write_type)
240
 
{
241
 
    file_details_t *details=NULL;
242
 
 
243
 
    details = open_file_map[fd];
244
 
    if (details == NULL) {
245
 
        details=new_open_file(fd);
246
 
        open_file_map[fd]=details;
247
 
    }
248
 
 
249
 
    details->type = write_type;
250
 
}
251
 
 
252
 
void add_chunk(aggregation_chunk_details_t *chunk_details)
253
 
{
254
 
    file_details_t  *file_details=NULL;
255
 
 
256
 
    if (DEBUG > 3) printf("adding chunk: fd(%d) var_name(%s)\n", chunk_details->fd, chunk_details->var_name);
257
 
 
258
 
    chunk_details->atype_size = getTypeSize(chunk_details->atype, chunk_details->buf);
259
 
    if ((chunk_details->len > 0) && (chunk_details->num_elements > 0)) {
260
 
        if ((chunk_details->len/chunk_details->num_elements) != chunk_details->atype_size) {
261
 
            printf("datatype size conflict: (%lu/%d)==%lu is not equal to %d\n",
262
 
                    chunk_details->len, chunk_details->num_elements, chunk_details->len/chunk_details->num_elements, chunk_details->atype_size);
263
 
            print_chunk(chunk_details);
264
 
        }
265
 
    }
266
 
 
267
 
    file_details = open_file_map[chunk_details->fd];
268
 
    if (file_details == NULL) {
269
 
        printf("failed to add chunk.  cannot aggregate.\n");
270
 
        return;
271
 
    }
272
 
    per_var_details_t *var_details = file_details->vars[chunk_details->var_name];
273
 
    if (var_details == NULL) {
274
 
//        if (DEBUG > 3) printf("var_details don't exist for %s\n", chunk_details->var_name);
275
 
        var_details=new per_var_details_t;
276
 
        strcpy(var_details->var_path, chunk_details->var_path);
277
 
        strcpy(var_details->var_name, chunk_details->var_name);
278
 
        var_details->chunks = new chunks_t;
279
 
        var_details->chunks_received=0;
280
 
        file_details->vars[chunk_details->var_name]=var_details;
281
 
    } else {
282
 
//        if (DEBUG > 3) printf("var_details already exist for %s\n", chunk_details->var_name);
283
 
    }
284
 
    aggregation_chunk_t *chunk=new aggregation_chunk_t;
285
 
    chunk->details = chunk_details;
286
 
    var_details->chunks->push_back(chunk);
287
 
    var_details->chunks_received++;
288
 
 
289
 
    return;
290
 
}
291
 
 
292
 
void destroy_chunk(aggregation_chunk_details_t *details)
293
 
{
294
 
    free(details->offset);
295
 
    free(details->count);
296
 
    for (int i=0;i<details->ndims;i++) {
297
 
        free(details->offset_path[i]);
298
 
        free(details->offset_name[i]);
299
 
        free(details->count_path[i]);
300
 
        free(details->count_name[i]);
301
 
    }
302
 
    free(details->offset_path);
303
 
    free(details->offset_name);
304
 
    free(details->count_path);
305
 
    free(details->count_name);
306
 
//    if (DEBUG > 3) printf("freeing details->buf(%p)\n", details->buf);
307
 
    free(details->buf);
308
 
    delete details;
309
 
}
310
 
 
311
 
void cleanup_aggregation_chunks(const int fd)
312
 
{
313
 
    file_details_t  *details=NULL;
314
 
    var_map_iterator_t var_iter;
315
 
    per_var_details_t *var_details=NULL;
316
 
    aggregation_chunk_t *chunk=NULL;
317
 
    chunks_iterator_t chunks_iter;
318
 
    chunk_details_iterator_t component_iter;
319
 
 
320
 
//    if (DEBUG > 3) printf("entered cleanup_aggregation_chunks\n");
321
 
//    if (DEBUG > 3) printf("cleaning up - fd(%d)\n", fd);
322
 
 
323
 
    details = open_file_map[fd];
324
 
    if (details == NULL) {
325
 
        return;
326
 
    }
327
 
//    var_iter = details->vars.begin();
328
 
//    for (; var_iter != details->vars.end(); ++var_iter) {
329
 
//        var_details = var_iter->second;
330
 
//        if (var_details != NULL) {
331
 
//            if (DEBUG > 3) printf("var_details first(%p) second(%s)\n", var_iter->first, var_details->var_name);
332
 
//        } else {
333
 
//            if (DEBUG > 3) printf("var_details is NULL\n");
334
 
//        }
335
 
//    }
336
 
    var_iter = details->vars.begin();
337
 
    for (; var_iter != details->vars.end();) {
338
 
        var_details = var_iter->second;
339
 
        if (var_details != NULL) {
340
 
//            cleanup_aggregation_chunks(fd, var_details->var_name);
341
 
            chunks_iter = var_details->chunks->begin();
342
 
            for (;chunks_iter != var_details->chunks->end(); ++chunks_iter) {
343
 
                chunk = *chunks_iter;
344
 
                component_iter = chunk->component_chunks.begin();
345
 
                for (;component_iter != chunk->component_chunks.end(); ++component_iter) {
346
 
//                    if (DEBUG > 3) printf("cleanup - destroying component\n");
347
 
                    destroy_chunk(*component_iter);
348
 
                }
349
 
                chunk->component_chunks.clear();
350
 
//                if (DEBUG > 3) printf("cleanup - destroying details\n");
351
 
                destroy_chunk(chunk->details);
352
 
                delete chunk;
353
 
            }
354
 
            var_details->chunks->clear();
355
 
            var_details->chunks_received=0;
356
 
            delete var_details;
357
 
        } else {
358
 
//            if (DEBUG > 3) printf("cannot cleanup - var_details is NULL\n");
359
 
        }
360
 
        details->vars.erase(var_iter++);
361
 
    }
362
 
//    details->vars.clear();
363
 
 
364
 
    for(var_map_iterator_t vars_iter=details->vars.begin(); vars_iter!=details->vars.end(); ++vars_iter) {
365
 
        per_var_details_t *pvd=vars_iter->second;
366
 
        if (pvd != NULL) {
367
 
            if (DEBUG > 3) printf("var_details first(%p) second(%s)\n", vars_iter->first, vars_iter->second->var_name);
368
 
        } else {
369
 
            if (DEBUG > 3) printf("var_details is NULL\n");
370
 
        }
371
 
    }
372
 
}
373
 
 
374
 
void cleanup_aggregation_chunks(const int fd, const char *var_name)
375
 
{
376
 
    file_details_t  *details=NULL;
377
 
    aggregation_chunk_t *chunk=NULL;
378
 
    chunks_iterator_t chunks_iter;
379
 
    chunk_details_iterator_t component_iter;
380
 
    var_map_iterator_t vars_iter;
381
 
 
382
 
//    if (DEBUG > 3) printf("cleaning up - fd(%d) var_name(%s)\n", fd, var_name);
383
 
 
384
 
    // for each variable, iterate over the chunks and destroy them
385
 
 
386
 
    details = open_file_map[fd];
387
 
 
388
 
    per_var_details_t *var_details = details->vars[var_name];
389
 
    if (var_details != NULL) {
390
 
        chunks_iter = var_details->chunks->begin();
391
 
        for (;chunks_iter != var_details->chunks->end(); ++chunks_iter) {
392
 
            chunk = *chunks_iter;
393
 
            component_iter = chunk->component_chunks.begin();
394
 
            for (;component_iter != chunk->component_chunks.end(); ++component_iter) {
395
 
//                if (DEBUG > 3) printf("cleanup - destroying component\n");
396
 
                destroy_chunk(*component_iter);
397
 
            }
398
 
            chunk->component_chunks.clear();
399
 
//            if (DEBUG > 3) printf("cleanup - destroying details\n");
400
 
            destroy_chunk(chunk->details);
401
 
            delete chunk;
402
 
        }
403
 
        var_details->chunks->clear();
404
 
        var_details->chunks_received=0;
405
 
        delete var_details;
406
 
    } else {
407
 
//        if (DEBUG > 3) printf("cleanup failed - var_details is NULL (%s)\n", var_name);
408
 
    }
409
 
 
410
 
    var_map_iterator_t iter=details->vars.find(var_name);
411
 
    if (iter != details->vars.end()) {
412
 
//        if (DEBUG > 3) printf("erasing var_details with iter\n");
413
 
        details->vars.erase(iter);
414
 
    } else {
415
 
//        if (DEBUG > 3) printf("cannot erase var_details with iter.  var_details not found.\n");
416
 
    }
417
 
 
418
 
}
419
 
 
420
 
static void recursive_print_chunk(aggregation_chunk_details_t *details, int offset, int *index, int current_dim)
421
 
{
422
 
    int my_offset=0;
423
 
    char tmp_str[20];
424
 
    char out_str[1024];
425
 
    int remaining=1023;
426
 
 
427
 
    if (current_dim < details->ndims-1) {
428
 
        for (int i=0;i<details->count[current_dim];i++) {
429
 
            my_offset = index[current_dim];
430
 
            for (int i=current_dim+1;i<details->ndims;i++) {
431
 
                my_offset *= details->count[i];
432
 
            }
433
 
 
434
 
            index[current_dim+1]=0;
435
 
            recursive_print_chunk(details, offset+my_offset, index, current_dim+1);
436
 
            index[current_dim] += details->atype_size;
437
 
        }
438
 
        //if (DEBUG > 3) printf("-----------------------------\n");
439
 
    } else {
440
 
        if (details->buf == NULL) {
441
 
            if (DEBUG > 3) printf("details->buf == NULL\n");
442
 
        } else {
443
 
            out_str[0]='\0';
444
 
            for (int i=0;i<details->count[current_dim];i++) {
445
 
                my_offset = offset+index[current_dim];
446
 
 
447
 
//                if (i==0) if (DEBUG > 3) printf("[%d][%d][%d] (my_offset==%d)\n", index[0], index[1], index[2], my_offset);
448
 
                if ((details->atype == adios_byte) || (details->atype == adios_unsigned_byte)) {
449
 
                    sprintf(tmp_str, "%c, ", *(char *)(((char *)details->buf) + my_offset));
450
 
                }
451
 
                else if (details->atype == adios_short || details->atype == adios_unsigned_short) {
452
 
                    sprintf(tmp_str, "%hx, ", *(short *)(((char *)details->buf) + my_offset));
453
 
                }
454
 
                else if (details->atype == adios_integer || details->atype == adios_unsigned_integer) {
455
 
                    sprintf(tmp_str, "%x, ", *(int *)(((char *)details->buf) + my_offset));
456
 
                }
457
 
                else if (details->atype == adios_long || details->atype == adios_unsigned_long) {
458
 
                    sprintf(tmp_str, "%lx, ", *(int *)(((char *)details->buf) + my_offset));
459
 
                }
460
 
                else if (details->atype == adios_real) {
461
 
                    sprintf(tmp_str, "%f, ", *(float *)(((char *)details->buf) + my_offset));
462
 
                }
463
 
                else if (details->atype == adios_double) {
464
 
                    sprintf(tmp_str, "%f, ", *(double *)(((char *)details->buf) + my_offset));
465
 
                }
466
 
                strncat(out_str, tmp_str, remaining);
467
 
                remaining -= strlen(out_str);
468
 
 
469
 
                index[current_dim] += details->atype_size;
470
 
            }
471
 
//            if (DEBUG > 3) printf("[%d][%d][%d] (my_offset==%d)\n", index[0], index[1], index[2], my_offset);
472
 
            if (DEBUG > 3) printf("%s\n", out_str);
473
 
        }
474
 
    }
475
 
}
476
 
 
477
 
void print_chunk(aggregation_chunk_details_t *details)
478
 
{
479
 
    int *index=(int *)calloc(details->ndims, sizeof(int));
480
 
    char tmp_str[20];
481
 
    char out_str[1024];
482
 
    int remaining=1023;
483
 
 
484
 
    if (DEBUG > 3) printf("+++++++++++++++++++++++++++++\n");
485
 
 
486
 
    if (DEBUG > 3) printf("fd==%d\n", details->fd);
487
 
    if (DEBUG > 3) printf("var_path==%s\n", details->var_path);
488
 
    if (DEBUG > 3) printf("var_name==%s\n", details->var_name);
489
 
    if (DEBUG > 3) printf("ndims==%d\n", details->ndims);
490
 
    if (DEBUG > 3) printf("len==%ld\n", details->len);
491
 
    if (DEBUG > 3) printf("num_elements==%d\n", details->num_elements);
492
 
    out_str[0]='\0';
493
 
    remaining=1023;
494
 
    for (int i=0;(i<details->ndims) && (remaining>0);i++) {
495
 
        sprintf(tmp_str, "%ld,", details->offset[i]);
496
 
        strncat(out_str, tmp_str, remaining);
497
 
        remaining -= strlen(tmp_str);
498
 
    }
499
 
    if (DEBUG > 3) printf("offset[]==%s\n", out_str);
500
 
    out_str[0]='\0';
501
 
    remaining=1023;
502
 
    for (int i=0;(i<details->ndims) && (remaining>0);i++) {
503
 
        sprintf(tmp_str, "%ld,", details->count[i]);
504
 
        strncat(out_str, tmp_str, remaining);
505
 
        remaining -= strlen(tmp_str);
506
 
    }
507
 
    if (DEBUG > 3) printf("count[]==%s\n", out_str);
508
 
    if (DEBUG > 3) printf("buf==%p\n", details->buf);
509
 
 
510
 
//    int offset=0;
511
 
//    int current_dim=0;
512
 
//    recursive_print_chunk(details, offset, index, current_dim);
513
 
    if (DEBUG > 3) printf("+++++++++++++++++++++++++++++\n");
514
 
 
515
 
    free(index);
516
 
}
517
 
 
518
 
void print_chunk(aggregation_chunk_t *c)
519
 
{
520
 
    if (c->details == NULL) {
521
 
        if (DEBUG > 3) printf("chunk has no details.  perhaps it was aggregated into another chunk.\n");
522
 
        return;
523
 
    }
524
 
    print_chunk(c->details);
525
 
}
526
 
 
527
 
static void recursive_copy_chunk(aggregation_chunk_details_t *src,
528
 
                                 aggregation_chunk_details_t *dst,
529
 
                                 int src_offset,
530
 
                                 int dst_offset,
531
 
                                 int *src_index,
532
 
                                 int *dst_index,
533
 
                                 int current_dim)
534
 
{
535
 
    int my_src_offset=0;
536
 
    int my_dst_offset=0;
537
 
 
538
 
    if (current_dim < src->ndims-1) {
539
 
        for (int i=0;i<src->count[current_dim];i++) {
540
 
            my_src_offset = src_index[current_dim];
541
 
            my_dst_offset = dst_index[current_dim];
542
 
//            if (DEBUG > 3) printf("join_offset(%d) offset_diff[%d](%d)\n",
543
 
//                    join_offset, current_dim, src->offset[current_dim] - dst->offset[current_dim]);
544
 
            my_dst_offset += ((src->offset[current_dim] - dst->offset[current_dim]) * src->atype_size);
545
 
            for (int j=current_dim+1;j<src->ndims;j++) {
546
 
                my_src_offset *= src->count[j];
547
 
                my_dst_offset *= dst->count[j];
548
 
            }
549
 
 
550
 
            src_index[current_dim+1]=0;
551
 
            dst_index[current_dim+1]=0;
552
 
            recursive_copy_chunk(src, dst, src_offset+my_src_offset, dst_offset+my_dst_offset,
553
 
                                 src_index, dst_index, current_dim+1);
554
 
            src_index[current_dim] += src->atype_size;
555
 
            dst_index[current_dim] += dst->atype_size;
556
 
        }
557
 
    } else {
558
 
        dst_offset += ((src->offset[current_dim] - dst->offset[current_dim]) * src->atype_size);
559
 
        memcpy(((char *)dst->buf) + dst_offset,
560
 
               ((char *)src->buf) + src_offset,
561
 
               src->count[current_dim]*src->atype_size);
562
 
    }
563
 
}
564
 
 
565
 
static void recursive_aggregate_chunks(aggregation_chunk_t *src1,
566
 
                                       aggregation_chunk_t *src2,
567
 
                                       aggregation_chunk_t *dst)
568
 
{
569
 
    int *src_index=(int *)calloc(src1->details->ndims, sizeof(int));
570
 
    int *dst_index=(int *)calloc(dst->details->ndims, sizeof(int));
571
 
    int src_offset=0;
572
 
    int dst_offset=0;
573
 
    int current_dim=0;
574
 
 
575
 
    memset(src_index, 0, src1->details->ndims*sizeof(int));
576
 
    memset(dst_index, 0, dst->details->ndims*sizeof(int));
577
 
    recursive_copy_chunk(src1->details, dst->details, src_offset, dst_offset, src_index, dst_index, current_dim);
578
 
    memset(src_index, 0, src2->details->ndims*sizeof(int));
579
 
    memset(dst_index, 0, dst->details->ndims*sizeof(int));
580
 
    recursive_copy_chunk(src2->details, dst->details, src_offset, dst_offset, src_index, dst_index, current_dim);
581
 
 
582
 
    free(src_index);
583
 
    free(dst_index);
584
 
}
585
 
 
586
 
static void copy_chunk(aggregation_chunk_details_t *src,
587
 
                       aggregation_chunk_details_t *dst)
588
 
{
589
 
    int *src_index=(int *)calloc(src->ndims, sizeof(int));
590
 
    int *dst_index=(int *)calloc(dst->ndims, sizeof(int));
591
 
    int src_offset=0;
592
 
    int dst_offset=0;
593
 
    int current_dim=0;
594
 
 
595
 
    memset(src_index, 0, src->ndims*sizeof(int));
596
 
    memset(dst_index, 0, dst->ndims*sizeof(int));
597
 
    recursive_copy_chunk(src, dst, src_offset, dst_offset, src_index, dst_index, current_dim);
598
 
 
599
 
    free(src_index);
600
 
    free(dst_index);
601
 
}
602
 
 
603
 
aggregation_chunk_t *aggregate_chunks(aggregation_chunk_t *c1,
604
 
                                      aggregation_chunk_t *c2,
605
 
                                      int join_dim)
606
 
{
607
 
    aggregation_chunk_t *out=new aggregation_chunk_t;
608
 
 
609
 
    //if (DEBUG > 3) printf("entered aggregate_chunks\n");
610
 
 
611
 
    assert(c1->details->ndims == c2->details->ndims);
612
 
    assert(out != NULL);
613
 
 
614
 
    out->details = new aggregation_chunk_details_t;
615
 
 
616
 
    out->details->fd           = c1->details->fd;
617
 
    strcpy(out->details->var_path, c1->details->var_path);
618
 
    strcpy(out->details->var_name, c1->details->var_name);
619
 
    out->details->ndims        = c1->details->ndims;
620
 
//    out->details->buf          = calloc(c1->details->len+c2->details->len, c1->details->atype_size);
621
 
    out->details->buf          = NULL;
622
 
    out->details->atype        = c1->details->atype;
623
 
    out->details->len          = c1->details->len+c2->details->len;
624
 
    out->details->atype     = c1->details->atype;
625
 
    out->details->num_elements = c1->details->num_elements+c2->details->num_elements;
626
 
    out->details->atype_size   = c1->details->atype_size;
627
 
    out->details->offset_path  = (char **)calloc(c1->details->ndims, sizeof(char *));
628
 
    out->details->offset_name  = (char **)calloc(c1->details->ndims, sizeof(char *));
629
 
    out->details->offset       = (uint64_t *)calloc(c1->details->ndims, sizeof(uint64_t));
630
 
    out->details->count_path   = (char **)calloc(c1->details->ndims, sizeof(char *));
631
 
    out->details->count_name   = (char **)calloc(c1->details->ndims, sizeof(char *));
632
 
    out->details->count        = (uint64_t *)calloc(c1->details->ndims, sizeof(uint64_t));
633
 
 
634
 
    for (int i=0;i<c1->details->ndims;i++) {
635
 
        out->details->offset_path[i]  = strdup(c1->details->offset_path[i]);
636
 
        out->details->offset_name[i]  = strdup(c1->details->offset_name[i]);
637
 
        out->details->count_path[i]   = strdup(c1->details->count_path[i]);
638
 
        out->details->count_name[i]   = strdup(c1->details->count_name[i]);
639
 
    }
640
 
    memcpy(out->details->offset, c1->details->offset, c1->details->ndims*sizeof(uint64_t));
641
 
    memcpy(out->details->count, c1->details->count, c1->details->ndims*sizeof(uint64_t));
642
 
    out->details->count[join_dim] += c2->details->count[join_dim];
643
 
 
644
 
//    recursive_aggregate_chunks(c1, c2, out);
645
 
 
646
 
    if (c1->component_chunks.size() > 0) {
647
 
        out->component_chunks.merge(c1->component_chunks);
648
 
        c1->component_chunks.clear();
649
 
        destroy_chunk(c1->details);
650
 
    } else {
651
 
        out->component_chunks.push_back(c1->details);
652
 
    }
653
 
    c1->details = NULL;
654
 
    if (c2->component_chunks.size() > 0) {
655
 
        out->component_chunks.merge(c2->component_chunks);
656
 
        c2->component_chunks.clear();
657
 
        destroy_chunk(c2->details);
658
 
    } else {
659
 
        out->component_chunks.push_back(c2->details);
660
 
    }
661
 
    c2->details = NULL;
662
 
 
663
 
    assert(out != NULL);
664
 
 
665
 
    //if (DEBUG > 3) printf("finished\n");
666
 
 
667
 
    return(out);
668
 
}
669
 
 
670
 
/*
671
 
 * Aggregate a particular variable in the file.
672
 
 *
673
 
 * Aggregation rules:
674
 
 *  - dimension count must be equal
675
 
 *  - strides must be equal
676
 
 *  - counts on matching faces must be equal
677
 
 *  -
678
 
 *
679
 
 */
680
 
int try_aggregation(const int fd, const char *var_name)
681
 
{
682
 
    int aggregation_success=FALSE;
683
 
 
684
 
    file_details_t  *file_details=NULL;
685
 
    per_var_details_t *var_details=NULL;
686
 
    aggregation_chunk_t *base_chunk=NULL;
687
 
    aggregation_chunk_t *candidate_chunk=NULL;
688
 
    aggregation_chunk_t *new_chunk=NULL;
689
 
    chunks_iterator_t base_iter, candidate_iter;
690
 
    int *offset_diff;
691
 
    chunk_location_count_t chunk_location_count;
692
 
    int dim_with_movement=-1;
693
 
 
694
 
    chunks_t agg_chunks;
695
 
 
696
 
    int failed=FALSE;
697
 
 
698
 
    file_details = open_file_map[fd];
699
 
    if (file_details == NULL) {
700
 
//        if (DEBUG > 3) printf("agg failed for %s: file_details==NULL\n", var_name);
701
 
        return(aggregation_success);
702
 
    }
703
 
    var_details = file_details->vars[var_name];
704
 
    if (var_details == NULL) {
705
 
//        if (DEBUG > 3) printf("agg failed for %s: var_details==NULL\n", var_name);
706
 
        return(aggregation_success);
707
 
    }
708
 
    if (var_details->chunks->size() < 2) {
709
 
//        if (DEBUG > 3) printf("returning with chunk count(%d)\n", var_details->chunks->size());
710
 
        return(aggregation_success);
711
 
    }
712
 
    if (DEBUG > 3) printf("chunk count(%d)\n", var_details->chunks->size());
713
 
 
714
 
 
715
 
    if (DEBUG > 3) printf("trying aggregation - fd(%d) var_name(%s)\n", fd, var_name);
716
 
 
717
 
    var_details->chunks->sort(compare_chunks_for_aggregation);
718
 
 
719
 
    if (DEBUG > 4) {
720
 
        printf("*****************\n");
721
 
        printf("start aggregation (begin list)\n");
722
 
        printf("*****************\n");
723
 
        int chunk_count;
724
 
        aggregation_chunk_details_t **chunks = get_chunks(fd, var_name, &chunk_count);
725
 
        for (int i=0;i<chunk_count;i++) {
726
 
            print_chunk(chunks[i]);
727
 
        }
728
 
        free(chunks);
729
 
        printf("*****************\n");
730
 
        printf("start aggregation (end list)\n");
731
 
        printf("*****************\n");
732
 
    }
733
 
 
734
 
    int success_this_pass=TRUE;
735
 
    while (success_this_pass==TRUE) {
736
 
        success_this_pass=FALSE;
737
 
 
738
 
//        if (DEBUG > 3) printf("top: while loop\n");
739
 
 
740
 
 
741
 
        base_iter = var_details->chunks->begin();
742
 
        base_chunk = *base_iter;
743
 
        offset_diff=new int[base_chunk->details->ndims];
744
 
        for (;base_iter != var_details->chunks->end(); ++base_iter) {
745
 
//            if (DEBUG > 3) printf("top: base_iter loop\n");
746
 
 
747
 
            base_chunk = *base_iter;
748
 
 
749
 
            //if (base_chunk != NULL)      print_chunk(base_chunk);
750
 
 
751
 
            // look for a chunk that can be aggregated to the base chunk
752
 
            candidate_iter = base_iter;
753
 
            candidate_iter++;
754
 
            for (;candidate_iter != var_details->chunks->end(); ++candidate_iter) {
755
 
//                if (DEBUG > 3) printf("top: candidate_iter loop\n");
756
 
 
757
 
                candidate_chunk = *candidate_iter;
758
 
 
759
 
                //if (candidate_chunk != NULL) print_chunk(candidate_chunk);
760
 
 
761
 
                failed=FALSE;
762
 
 
763
 
                if (base_chunk->details->ndims != candidate_chunk->details->ndims) {
764
 
                    continue;
765
 
                }
766
 
//                if (candidate_chunk->details->offset[0] != base_chunk->details->offset[0]) {
767
 
//                    continue;
768
 
//                }
769
 
                for (int i=0; i<base_chunk->details->ndims; i++) {
770
 
                    offset_diff[i] = candidate_chunk->details->offset[i] - base_chunk->details->offset[i];
771
 
                }
772
 
                if (failed) continue;
773
 
 
774
 
                chunk_location_count.ahead_count=0;
775
 
                chunk_location_count.behind_count=0;
776
 
                chunk_location_count.same_count=0;
777
 
                chunk_location_count.no_match_count=0;
778
 
                int agg_dims=base_chunk->details->ndims; /* the number of dimensions to aggregate */
779
 
                for (int i=0; i<agg_dims; i++) {
780
 
                    if ((offset_diff[i] < 0) && (-offset_diff[i] == candidate_chunk->details->count[i])) {
781
 
                        // the candidate is "behind/below" and touching the base chunk in this dimension
782
 
                        chunk_location_count.behind_count++;
783
 
                        dim_with_movement=i;
784
 
                    } else if ((offset_diff[i] > 0) && (offset_diff[i] == base_chunk->details->count[i])) {
785
 
                        // the candidate is "ahead of/above" and touching the base chunk in this dimension
786
 
                        chunk_location_count.ahead_count++;
787
 
                        dim_with_movement=i;
788
 
                    } else if (offset_diff[i] == 0) {
789
 
                        // the candidate is "equal to" the base chunk in this dimension
790
 
                        chunk_location_count.same_count++;
791
 
                    } else {
792
 
                        // the candidate and the base chunk don't match in this dimension
793
 
                        chunk_location_count.no_match_count++;
794
 
                    }
795
 
                }
796
 
 
797
 
#ifdef DEBUG
798
 
                /*
799
 
                 * These tests can be interesting, but are not required to get the job done.
800
 
                 */
801
 
                if (chunk_location_count.no_match_count > 0) {
802
 
                    // no matching face found.  can't aggregate.
803
 
                    continue;
804
 
                }
805
 
 
806
 
                if (chunk_location_count.same_count == base_chunk->ndims) {
807
 
                    // base and candidate have same offset.  bad?  can't aggregate.
808
 
                    continue;
809
 
                }
810
 
 
811
 
                if (chunk_location_count.ahead_count > 1) {
812
 
                    // movement in more than one direction
813
 
                    continue;
814
 
                }
815
 
                if (chunk_location_count.behind_count > 1) {
816
 
                    // movement in more than one direction
817
 
                    continue;
818
 
                }
819
 
                if ((chunk_location_count.ahead_count > 0)  &&
820
 
                        (chunk_location_count.behind_count > 0)) {
821
 
                    // movement in more than one direction
822
 
                    continue;
823
 
                }
824
 
 
825
 
                if ((chunk_location_count.ahead_count == 0)  &&
826
 
                        (chunk_location_count.behind_count == 0)) {
827
 
                    // possible movement, but the chunks don't touch
828
 
                    continue;
829
 
                }
830
 
#endif
831
 
 
832
 
                // check that the matching faces have the same dimensions
833
 
                for (int i=0; i<base_chunk->details->ndims; i++) {
834
 
                    if ((i != dim_with_movement) &&
835
 
                        (base_chunk->details->count[i] != candidate_chunk->details->count[i])) {
836
 
                        failed=TRUE;
837
 
                        break;
838
 
                    }
839
 
                }
840
 
                if (failed) continue;
841
 
 
842
 
                /*
843
 
                 * Do NOT uncomment these print_chunk() lines in production code.
844
 
                 * They are *very* slow even if the debug level is set low and
845
 
                 * nothing is being logged.
846
 
                 */
847
 
//                netcdf_debug_level=LOG_ALL;
848
 
//                if (DEBUG > 3) printf("*****************\n");
849
 
//                if (DEBUG > 3) printf("base chunk\n");
850
 
//                if (DEBUG > 3) printf("*****************\n");
851
 
//                if (base_chunk != NULL)      print_chunk(base_chunk);
852
 
//                if (DEBUG > 3) printf("*****************\n");
853
 
//                if (DEBUG > 3) printf("candidate chunk\n");
854
 
//                if (DEBUG > 3) printf("*****************\n");
855
 
//                if (candidate_chunk != NULL) print_chunk(candidate_chunk);
856
 
//                netcdf_debug_level=old;
857
 
 
858
 
                if ((chunk_location_count.ahead_count == 1)  &&
859
 
                        (chunk_location_count.behind_count == 0) &&
860
 
                        (chunk_location_count.same_count == agg_dims-1)) {
861
 
                    // aggregation is base + candidate
862
 
                    new_chunk = aggregate_chunks(base_chunk, candidate_chunk, dim_with_movement);
863
 
                } else if ((chunk_location_count.ahead_count == 0)  &&
864
 
                        (chunk_location_count.behind_count == 1) &&
865
 
                        (chunk_location_count.same_count == agg_dims-1)) {
866
 
                    // aggregation is candidate + base
867
 
                    new_chunk = aggregate_chunks(candidate_chunk, base_chunk, dim_with_movement);
868
 
                } else {
869
 
                    // chunks aren't aligned
870
 
                    //if (DEBUG > 3) printf("**********\nchunks are not aligned\n**********\n");
871
 
                    continue;
872
 
                }
873
 
 
874
 
                assert(new_chunk != NULL);
875
 
 
876
 
                /*
877
 
                 * Do NOT uncomment these print_chunk() lines in production code.
878
 
                 * They are *very* slow even if the debug level is set low and
879
 
                 * nothing is being logged.
880
 
                 */
881
 
//                netcdf_debug_level=LOG_ALL;
882
 
//                if (DEBUG > 3) printf("*****************\n");
883
 
//                if (DEBUG > 3) printf("new chunk\n");
884
 
//                if (DEBUG > 3) printf("*****************\n");
885
 
//                if (new_chunk != NULL)       print_chunk(new_chunk);
886
 
//                netcdf_debug_level=old;
887
 
 
888
 
                var_details->chunks->remove(base_chunk);
889
 
                var_details->chunks->remove(candidate_chunk);
890
 
                delete base_chunk;
891
 
                delete candidate_chunk;
892
 
 
893
 
                agg_chunks.push_back(new_chunk);
894
 
 
895
 
                aggregation_success = TRUE;
896
 
                success_this_pass = TRUE;
897
 
 
898
 
                break;
899
 
            }
900
 
            if (success_this_pass == TRUE) break;
901
 
        }
902
 
        chunks_iterator_t agg_iter = agg_chunks.begin();
903
 
        for (;agg_iter != agg_chunks.end();agg_iter++) {
904
 
            var_details->chunks->push_back(*agg_iter);
905
 
        }
906
 
        agg_chunks.clear();
907
 
 
908
 
        delete[] offset_diff;
909
 
    }
910
 
 
911
 
    if (DEBUG > 4) {
912
 
        printf("*****************\n");
913
 
        printf("end aggregation (begin list)\n");
914
 
        printf("*****************\n");
915
 
        int chunk_count;
916
 
        aggregation_chunk_details_t **chunks = get_chunks(fd, var_name, &chunk_count);
917
 
        for (int i=0;i<chunk_count;i++) {
918
 
            print_chunk(chunks[i]);
919
 
        }
920
 
        free(chunks);
921
 
        printf("*****************\n");
922
 
        printf("end aggregation (end list)\n");
923
 
        printf("*****************\n");
924
 
    }
925
 
 
926
 
//    netcdf_debug_level=LOG_ALL;
927
 
    chunks_iterator_t dst_iter=var_details->chunks->begin();
928
 
    for(;dst_iter != var_details->chunks->end();dst_iter++) {
929
 
        chunk_details_iterator_t component_iter=(*dst_iter)->component_chunks.begin();
930
 
        if (((*dst_iter)->details->buf == NULL) && ((*dst_iter)->details->len > 0)) {
931
 
            (*dst_iter)->details->buf = (char *)malloc((*dst_iter)->details->len);
932
 
//            if (DEBUG > 3) printf("allocated dst_iter->details->buf(%p), len(%ld)\n",
933
 
//                    (*dst_iter)->details->buf,
934
 
//                    (*dst_iter)->details->len);
935
 
        } else {
936
 
//            if (DEBUG > 3) printf("did not allocate dst_iter->details->buf(%p)\n", (*dst_iter)->details->buf);
937
 
        }
938
 
        for(;component_iter != (*dst_iter)->component_chunks.end();component_iter++) {
939
 
            //if (DEBUG > 3) printf("copying component\n");
940
 
            copy_chunk(*component_iter, (*dst_iter)->details);
941
 
            //if (DEBUG > 3) printf("destroying component\n");
942
 
            destroy_chunk(*component_iter);
943
 
        }
944
 
        (*dst_iter)->component_chunks.clear();
945
 
    }
946
 
//    netcdf_debug_level=old;
947
 
 
948
 
//    netcdf_debug_level=LOG_ALL;
949
 
    //if (DEBUG > 3) printf("*****************\n");
950
 
    //if (DEBUG > 3) printf("chunks after aggregation\n");
951
 
    //if (DEBUG > 3) printf("*****************\n");
952
 
//    base_iter = var_details->chunks->begin();
953
 
//    for (;base_iter != var_details->chunks->end(); ++base_iter) {
954
 
//        base_chunk = *base_iter;
955
 
//        if (base_chunk != NULL)
956
 
//            print_chunk(base_chunk);
957
 
//    }
958
 
//    netcdf_debug_level=old;
959
 
 
960
 
    return(aggregation_success);
961
 
}
962
 
 
963
 
/*
964
 
 * Aggregate all variables in the file.
965
 
 *
966
 
 */
967
 
int try_aggregation(const int fd)
968
 
{
969
 
    int aggregation_success=FALSE;
970
 
 
971
 
    file_details_t    *file_details=NULL;
972
 
    var_map_iterator_t var_iter;
973
 
    per_var_details_t *var_details=NULL;
974
 
 
975
 
    if (DEBUG > 3) printf("entered try_aggregation - fd(%d)\n", fd);
976
 
 
977
 
    file_details = open_file_map[fd];
978
 
    if (file_details == NULL) {
979
 
        return(aggregation_success);
980
 
    }
981
 
    var_iter = file_details->vars.begin();
982
 
    for (; var_iter != file_details->vars.end(); var_iter++) {
983
 
        var_details = var_iter->second;
984
 
        if (var_details == NULL) {
985
 
//            if (DEBUG > 3) printf("var_details==NULL.  continuing\n");
986
 
            continue;
987
 
        } else {
988
 
//            if (DEBUG > 3) printf("aggregating var_name(%s)\n", var_details->var_name);
989
 
            while(try_aggregation(fd, var_details->var_name) == TRUE);
990
 
        }
991
 
    }
992
 
 
993
 
    aggregation_success = TRUE;
994
 
 
995
 
    return(aggregation_success);
996
 
}
997
 
 
998
 
int aggregate_data_ready_to_write(const int fd, const char *var_name)
999
 
{
1000
 
//    file_details_t *details = open_file_map[fd];
1001
 
//    int chunks_needed=0;
1002
 
 
1003
 
//    if (details->num_participants > 0) {
1004
 
//        chunks_needed = details->num_participants;
1005
 
//    } else {
1006
 
//        chunks_needed = details->participants->size();
1007
 
//    }
1008
 
//
1009
 
//    if (details->vars[var_name]->chunks_received == chunks_needed) {
1010
 
//        return TRUE;
1011
 
//    }
1012
 
 
1013
 
    return FALSE;
1014
 
}
1015
 
 
1016
 
int cache_data_ready_to_write(const int fd, const char *var_name)
1017
 
{
1018
 
//    file_details_t *details = open_file_map[fd];
1019
 
//    int chunks_needed=0;
1020
 
 
1021
 
//    if (details->num_participants > 0) {
1022
 
//        chunks_needed = details->num_participants;
1023
 
//    } else {
1024
 
//        chunks_needed = details->participants->size();
1025
 
//    }
1026
 
//
1027
 
//    if (details->vars[var_name]->chunks_received == chunks_needed) {
1028
 
//        return TRUE;
1029
 
//    }
1030
 
 
1031
 
    return FALSE;
1032
 
}
1033
 
 
1034
 
aggregation_chunk_details_t **get_chunks(const int fd, const char *var_name, int *chunk_count)
1035
 
{
1036
 
    file_details_t *details=NULL;
1037
 
    per_var_details_t *var_details=NULL;
1038
 
    aggregation_chunk_details_t **chunks=NULL;
1039
 
    chunks_iterator_t iter;
1040
 
 
1041
 
    if (DEBUG > 3) printf("entered get_chunks - fd(%d) var_name(%s)\n", fd, var_name);
1042
 
 
1043
 
    *chunk_count=0;
1044
 
 
1045
 
    details = open_file_map[fd];
1046
 
    if (details == NULL) {
1047
 
        return(NULL);
1048
 
    }
1049
 
    var_details = details->vars[var_name];
1050
 
    if (var_details == NULL) {
1051
 
        return(NULL);
1052
 
    }
1053
 
 
1054
 
    *chunk_count = details->vars[var_name]->chunks->size();
1055
 
 
1056
 
    if (DEBUG > 3) printf("found %d chunks to return\n", *chunk_count);
1057
 
 
1058
 
    if (*chunk_count == 0) {
1059
 
        return(NULL);
1060
 
    }
1061
 
    chunks = (aggregation_chunk_details_t **)malloc(*chunk_count*sizeof(aggregation_chunk_details_t *));
1062
 
 
1063
 
    var_details->chunks->sort(compare_chunks_for_caching);
1064
 
 
1065
 
    iter = var_details->chunks->begin();
1066
 
    for (int i=0;iter != var_details->chunks->end(); ++iter,i++) {
1067
 
        chunks[i] = (*iter)->details;
1068
 
//        print_chunk(chunks[i]);
1069
 
    }
1070
 
 
1071
 
    //if (DEBUG > 3) printf("finished\n");
1072
 
 
1073
 
    return(chunks);
1074
 
}
1075
 
 
1076
 
aggregation_chunk_details_t **get_chunks(const int fd, int *chunk_count)
1077
 
{
1078
 
    file_details_t  *details=NULL;
1079
 
    var_map_iterator_t var_iter;
1080
 
    per_var_details_t *var_details=NULL;
1081
 
    aggregation_chunk_details_t **chunks=NULL;
1082
 
    chunks_iterator_t chunks_iter;
1083
 
 
1084
 
    if (DEBUG > 3) printf("entered get_chunks - fd(%d)\n", fd);
1085
 
 
1086
 
    *chunk_count=0;
1087
 
 
1088
 
    details = open_file_map[fd];
1089
 
    if (details == NULL) {
1090
 
        return(NULL);
1091
 
    }
1092
 
    var_iter = details->vars.begin();
1093
 
    for (; var_iter != details->vars.end(); ++var_iter) {
1094
 
        var_details = var_iter->second;
1095
 
        *chunk_count += var_details->chunks->size();
1096
 
    }
1097
 
 
1098
 
    if (DEBUG > 3) printf("found %d chunks to return\n", *chunk_count);
1099
 
 
1100
 
    if (*chunk_count == 0) {
1101
 
        return(NULL);
1102
 
    }
1103
 
    chunks = (aggregation_chunk_details_t **)malloc(*chunk_count*sizeof(aggregation_chunk_details_t *));
1104
 
 
1105
 
    int i=0;
1106
 
    var_iter = details->vars.begin();
1107
 
    for (; var_iter != details->vars.end(); var_iter++) {
1108
 
        var_details = var_iter->second;
1109
 
        var_details->chunks->sort(compare_chunks_for_caching);
1110
 
        chunks_iter = var_details->chunks->begin();
1111
 
        for (;chunks_iter != var_details->chunks->end(); ++chunks_iter,i++) {
1112
 
            chunks[i] = (*chunks_iter)->details;
1113
 
//            print_chunk(chunks[i]);
1114
 
        }
1115
 
    }
1116
 
 
1117
 
    //if (DEBUG > 3) printf("finished\n");
1118
 
 
1119
 
    return(chunks);
1120
 
}