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
|
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "segment.h"
static int _segment_format (int,int,int,int,int,int,int);
static int write_int(int,int);
static int zero_fill(int, long);
/* fd must be open for write */
/*!
* \brief format a segment file
*
* The segmentation routines require a disk file
* to be used for paging segments in and out of memory. This routine formats the
* file open for write on file descriptor <b>fd</b> for use as a segment file.
* A segment file must be formatted before it can be processed by other segment
* routines. The configuration parameters <b>nrows, ncols, srows, scols</b>,
* and <b>len</b> are written to the beginning of the segment file which is
* then filled with zeros.
* The corresponding nonsegmented data matrix, which is to be transferred to the
* segment file, is <b>nrows</b> by <b>ncols.</b> The segment file is to be
* formed of segments which are <b>srows</b> by <b>scols.</b> The data items
* have length <b>len</b> bytes. For example, if the <i>data type is int</i>,
* \textbf{<i>len</i> }<i>is sizeof(int).</i>
* Return codes are: 1 ok; else -1 could not seek or write <i>fd</i>, or -3
* illegal configuration parameter(s).
*
* \param fd
* \param nrows
* \param ncols
* \param srows
* \param scols
* \param len
* \return int
*/
int segment_format (int fd,int nrows,int ncols,int srows,int scols,int len)
{
return _segment_format (fd, nrows, ncols, srows, scols, len, 1);
}
int segment_format_nofill (
int fd,int nrows,int ncols,int srows,int scols,int len)
{
return _segment_format (fd, nrows, ncols, srows, scols, len, 0);
}
static int _segment_format(
int fd,
int nrows,int ncols,
int srows,int scols,
int len,int fill)
{
long nbytes ;
int spr, size;
if (nrows <= 0 || ncols <= 0 || len <= 0 || srows <= 0 || scols <= 0)
{
G_warning (
"segement_format(fd,%d,%d,%d,%d,%d): illegal value(s)\n",
nrows, ncols, srows, scols, len);
return -3;
}
if (lseek (fd, 0L, 0) == (off_t)-1)
{
G_warning ("Segment_format: %s\n",strerror(errno));
return -1;
}
if (!write_int (fd, nrows) || !write_int (fd, ncols)
|| !write_int (fd, srows) || !write_int (fd, scols)
|| !write_int (fd, len)) return -1;
if (!fill) return 1;
spr = ncols / scols ;
if(ncols % scols)
spr++ ;
size = srows * scols * len;
/* calculate total number of segments */
nbytes = spr * ((nrows + srows - 1)/ srows);
nbytes *= size ;
/* fill segment file with zeros */
/* NOTE: this could be done faster using lseek() by seeking
* ahead nbytes and then writing a single byte of 0,
* provided lseek() on all version of UNIX will create a file
* with holes that read as zeros.
*/
if(zero_fill (fd, nbytes) < 0)
return -1;
return 1;
}
static int write_int (int fd,int n)
{
int x;
int bytes_wrote;
x = n;
if((bytes_wrote = write (fd, &x, sizeof(int)) == sizeof(int) ) < 0)
G_warning("%s\n",strerror(errno));
return bytes_wrote;
}
static int zero_fill(int fd, long nbytes)
{
char buf[10240];
register char *b;
register int n;
/* zero buf */
n = nbytes > sizeof(buf) ? sizeof(buf) : nbytes ;
b = buf;
while (n-- > 0)
*b++ = 0;
while (nbytes > 0)
{
n = nbytes > sizeof(buf) ? sizeof(buf) : nbytes ;
if(write (fd, buf, n) != n) {
G_warning("%s\n",strerror(errno));
return -1;
}
nbytes -= n;
}
return 1;
}
|