File: readcell.c

package info (click to toggle)
grass 8.4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 277,040 kB
  • sloc: ansic: 460,798; python: 227,732; cpp: 42,026; sh: 11,262; makefile: 7,007; xml: 3,637; sql: 968; lex: 520; javascript: 484; yacc: 450; asm: 387; perl: 157; sed: 25; objc: 6; ruby: 4
file content (139 lines) | stat: -rw-r--r-- 3,385 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * readcell.c - reads an entire cell layer into a buffer
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "global.h"

struct cache *readcell(int fdi, int size)
{
    DCELL *tmpbuf;
    struct cache *c;
    int nrows;
    int ncols;
    int row;
    char *filename;
    int nx, ny;
    int nblocks;
    int i;

    G_srand48(0);

    nrows = Rast_input_window_rows();
    ncols = Rast_input_window_cols();

    ny = (nrows + BDIM - 1) / BDIM;
    nx = (ncols + BDIM - 1) / BDIM;

    if (size > 0)
        nblocks = size * ((1 << 20) / sizeof(block));
    else
        nblocks = (nx + ny) * 2; /* guess */

    if (nblocks > nx * ny)
        nblocks = nx * ny;

    c = G_malloc(sizeof(struct cache));
    c->stride = nx;
    c->nblocks = nblocks;
    c->grid = (block **)G_calloc(nx * ny, sizeof(block *));
    c->blocks = (block *)G_malloc(nblocks * sizeof(block));
    c->refs = (int *)G_malloc(nblocks * sizeof(int));

    if (nblocks < nx * ny) {
        /* Temporary file must be created in input location */
        filename = G_tempfile();
        c->fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
        if (c->fd < 0)
            G_fatal_error(_("Unable to open temporary file"));
        remove(filename);
    }
    else
        c->fd = -1;

    G_debug(1, "%d of %d blocks in memory", nblocks, nx * ny);

    G_important_message(_("Allocating memory and reading input map..."));
    G_percent(0, nrows, 5);

    for (i = 0; i < c->nblocks; i++)
        c->refs[i] = -1;

    tmpbuf = (DCELL *)G_malloc(nx * sizeof(block));

    for (row = 0; row < nrows; row += BDIM) {
        int x, y;

        for (y = 0; y < BDIM; y++) {
            G_percent(row + y, nrows, 5);

            if (row + y >= nrows)
                break;

            Rast_get_d_row(fdi, &tmpbuf[y * nx * BDIM], row + y);
        }

        for (x = 0; x < nx; x++)
            for (y = 0; y < BDIM; y++)
                if (c->fd >= 0) {
                    if (write(c->fd, &tmpbuf[(y * nx + x) * BDIM],
                              BDIM * sizeof(DCELL)) < 0)
                        G_fatal_error(_("Error writing segment file"));
                }
                else
                    memcpy(&c->blocks[BKIDX(c, HI(row), x)][LO(y)][0],
                           &tmpbuf[(y * nx + x) * BDIM], BDIM * sizeof(DCELL));
    }

    G_free(tmpbuf);

    if (c->fd < 0)
        for (i = 0; i < c->nblocks; i++) {
            c->grid[i] = &c->blocks[i];
            c->refs[i] = i;
        }

    return c;
}

block *get_block(struct cache *c, int idx)
{
    int replace = G_lrand48() % c->nblocks;
    block *p = &c->blocks[replace];
    int cref = c->refs[replace];
    off_t offset = (off_t)idx * sizeof(DCELL) << L2BSIZE;

    if (c->fd < 0)
        G_fatal_error(_("Internal error: cache miss on fully-cached map"));

    if (cref >= 0)
        c->grid[cref] = NULL;

    c->grid[idx] = p;
    c->refs[replace] = idx;

    if (lseek(c->fd, offset, SEEK_SET) < 0)
        G_fatal_error(_("Error seeking on segment file"));

    if (read(c->fd, p, sizeof(block)) < 0)
        G_fatal_error(_("Error reading segment file"));

    return p;
}

void release_cache(struct cache *c)
{
    G_free(c->refs);
    G_free(c->blocks);
    G_free(c->grid);

    G_free(c);
    c = NULL;
}