Пример #1
0
/* Create a file, and the ncio struct to go with it.

   path - path of file to create.
   ioflags - flags from nc_create
   initialsz - From the netcdf man page: "The argument
               initialsize sets the initial size of the file at creation time."
   igeto -
   igetsz -
   sizehintp - the size of a page of data for buffered reads and writes.
   parameters - arbitrary data
   nciopp - pointer to a pointer that will get location of newly
   created and inited ncio struct.
   mempp - pointer to pointer to the initial memory read.
*/
int
memio_create(const char* path, int ioflags,
    size_t initialsz,
    off_t igeto, size_t igetsz, size_t* sizehintp,
    void* parameters /*ignored*/,
    ncio* *nciopp, void** const mempp)
{
    ncio* nciop;
    int fd;
    int status;
    NCMEMIO* memio = NULL;

    if(path == NULL ||* path == 0)
        return NC_EINVAL;
    
    status = memio_new(path, ioflags, initialsz, &nciop, &memio);
    if(status != NC_NOERR)
        return status;

    if(memio->persist) {
	/* Verify the file is writeable or does not exist*/
	if(fileexists(path) && !fileiswriteable(path))
	    {status = EPERM; goto unwind_open;}	
    }

    /* Allocate the memory for this file */
    memio->memory = (char*)malloc((size_t)memio->alloc);
    if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}
    memio->locked = 0;

#ifdef DEBUG
fprintf(stderr,"memio_create: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc);
#endif

    fd = nc__pseudofd();
    *((int* )&nciop->fd) = fd;

    fSet(nciop->ioflags, NC_WRITE); /* Always writeable */

    if(igetsz != 0)
    {
        status = nciop->get(nciop,
                igeto, igetsz,
                RGN_WRITE,
                mempp);
        if(status != NC_NOERR)
            goto unwind_open;
    }

    /* Pick a default sizehint */
    if(sizehintp) *sizehintp = (size_t)pagesize;

    *nciopp = nciop;
    return NC_NOERR;

unwind_open:
    memio_close(nciop,1);
    return status;
}
Пример #2
0
/* This function opens the data file. It is only called from nc.c,
   from nc__open_mp and nc_delete_mp.

   path - path of data file.
   ioflags - flags passed into nc_open.
   igeto - looks like this function can do an initial page get, and
   igeto is going to be the offset for that. But it appears to be
   unused 
   igetsz - the size in bytes of initial page get (a.k.a. extent). Not
   ever used in the library.
   sizehintp - the size of a page of data for buffered reads and writes.
   nciopp - pointer to pointer that will get address of newly created
   and inited ncio struct.
   mempp - pointer to pointer to the initial memory read.
*/
int
memio_open(const char* path,
    int ioflags,
    off_t igeto, size_t igetsz, size_t* sizehintp,
    ncio* *nciopp, void** const mempp)
{
    ncio* nciop;
    int fd;
    int status;
    int persist = (fIsSet(ioflags,NC_WRITE)?1:0);
    int oflags;
    NCMEMIO* memio = NULL;
    size_t sizehint;
    off_t filesize;

    if(path == NULL ||* path == 0)
        return EINVAL;

    assert(sizehintp != NULL);
    sizehint = *sizehintp;

    /* Open the file, but make sure we can write it if needed */
    oflags = (persist ? O_RDWR : O_RDONLY);    
#ifdef O_BINARY
    fSet(oflags, O_BINARY);
#endif
    oflags |= O_EXCL;
#ifdef vms
    fd = open(path, oflags, 0, "ctx=stm");
#else
    fd  = open(path, oflags, OPENMODE);
#endif
#ifdef DEBUG
    if(fd < 0) {
	fprintf(stderr,"open failed: file=%s err=",path);
	perror("");
    }
#endif
    if(fd < 0) {status = errno; goto unwind_open;}

    /* get current filesize  = max(|file|,initialize)*/
    filesize = lseek(fd,0,SEEK_END);
    if(filesize < 0) {status = errno; goto unwind_open;}
    /* move pointer back to beginning of file */
    (void)lseek(fd,0,SEEK_SET);
    if(filesize < (off_t)sizehint)
        filesize = (off_t)sizehint;

    status = memio_new(path, ioflags, filesize, &nciop, &memio);
    if(status != NC_NOERR)
	return status;
    memio->size = filesize;

    memio->memory = (char*)malloc(memio->alloc);
    if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}

#ifdef DEBUG
fprintf(stderr,"memio_open: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc);
#endif

    /* Read the file into the memio memory */
    /* We need to do multiple reads because there is no
       guarantee that the amount read will be the full amount */
    {
	off_t red = memio->size;
	char* pos = memio->memory;
	while(red > 0) {
	    ssize_t count = read(fd, pos, red);
	    if(count < 0)
	        {close(fd); status = errno; goto unwind_open;}
	    if(count == 0)
	        {close(fd); status = NC_ENOTNC; goto unwind_open;}
	    red -= count;
	    pos += count;
	}
    }
    (void)close(fd); /* until memio_close() */

    /* Use half the filesize as the blocksize */
    sizehint = filesize/2;

    fd = nc__pseudofd();
    *((int* )&nciop->fd) = fd; 

    if(igetsz != 0)
    {
        status = nciop->get(nciop,
                igeto, igetsz,
                0,
                mempp);
        if(status != NC_NOERR)
            goto unwind_open;
    }

    *sizehintp = sizehint;
    *nciopp = nciop;
    return NC_NOERR;

unwind_open:
    memio_close(nciop,0);
    return status;
}
Пример #3
0
/* Create a file, and the ncio struct to go with it. This function is
   only called from nc__create_mp.

   path - path of file to create.
   ioflags - flags from nc_create
   initialsz - From the netcdf man page: "The argument
   Iinitialsize sets the initial size of the file at creation time."
   igeto - 
   igetsz - 
   sizehintp - the size of a page of data for buffered reads and writes.
   nciopp - pointer to a pointer that will get location of newly
   created and inited ncio struct.
   mempp - pointer to pointer to the initial memory read.
*/
int
memio_create(const char* path, int ioflags,
    size_t initialsz,
    off_t igeto, size_t igetsz, size_t* sizehintp,
    ncio* *nciopp, void** const mempp)
{
    ncio* nciop;
    int fd;
    int status;
    NCMEMIO* memio = NULL;
    int persist = (ioflags & NC_WRITE?1:0);
    int oflags;

    if(path == NULL ||* path == 0)
        return NC_EINVAL;

    /* For diskless open has, the file must be classic version 1 or 2.*/
    if(fIsSet(ioflags,NC_NETCDF4))
        return NC_EDISKLESS; /* violates constraints */

    status = memio_new(path, ioflags, initialsz, &nciop, &memio);
    if(status != NC_NOERR)
        return status;
    memio->size = 0;

    if(!persist) {
	memio->memory = (char*)malloc(memio->alloc);
	if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}
    } else { /*persist */
        /* Open the file, but make sure we can write it if needed */
        oflags = (persist ? O_RDWR : O_RDONLY);    
#ifdef O_BINARY
        fSet(oflags, O_BINARY);
#endif
    	oflags |= (O_CREAT|O_TRUNC);
        if(fIsSet(ioflags,NC_NOCLOBBER))
	    oflags |= O_EXCL;
#ifdef vms
        fd = open(path, oflags, 0, "ctx=stm");
#else
        fd  = open(path, oflags, OPENMODE);
#endif
        if(fd < 0) {status = errno; goto unwind_open;}

        (void)close(fd); /* will reopen at nc_close */
	/* malloc memory */
	memio->memory = (char*)malloc(memio->alloc);
	if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;}
    } /*!persist*/

#ifdef DEBUG
fprintf(stderr,"memio_create: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc);
#endif

    fd = nc__pseudofd();
    *((int* )&nciop->fd) = fd; 

    fSet(nciop->ioflags, NC_WRITE);

    if(igetsz != 0)
    {
        status = nciop->get(nciop,
                igeto, igetsz,
                RGN_WRITE,
                mempp);
        if(status != NC_NOERR)
            goto unwind_open;
    }

    /* Pick a default sizehint */
    if(sizehintp) *sizehintp = pagesize;

    *nciopp = nciop;
    return NC_NOERR;

unwind_open:
    memio_close(nciop,1);
    return status;
}
Пример #4
0
/* This function opens the data file. It is only called from nc.c,
   from nc__open_mp and nc_delete_mp.

   path - path of data file.
   ioflags - flags passed into nc_open.
   igeto - looks like this function can do an initial page get, and
   igeto is going to be the offset for that. But it appears to be
   unused 
   igetsz - the size in bytes of initial page get (a.k.a. extent). Not
   ever used in the library.
   sizehintp - the size of a page of data for buffered reads and writes.
   nciopp - pointer to pointer that will get address of newly created
   and inited ncio struct.
   mempp - pointer to pointer to the initial memory read.
*/
int
mmapio_open(const char* path,
    int ioflags,
    off_t igeto, size_t igetsz, size_t* sizehintp,
    void* parameters,
    ncio* *nciopp, void** const mempp)
{
    ncio* nciop;
    int fd;
    int status;
    int persist = (fIsSet(ioflags,NC_WRITE)?1:0);
    int oflags;
    NCMMAPIO* mmapio = NULL;
    size_t sizehint;
    off_t filesize;

    if(path == NULL ||* path == 0)
        return EINVAL;

    assert(sizehintp != NULL);
    sizehint = *sizehintp;

    /* Open the file, but make sure we can write it if needed */
    oflags = (persist ? O_RDWR : O_RDONLY);    
#ifdef O_BINARY
    fSet(oflags, O_BINARY);
#endif
    oflags |= O_EXCL;
#ifdef vms
    fd = open(path, oflags, 0, "ctx=stm");
#else
    fd  = open(path, oflags, OPENMODE);
#endif
    if(fd < 0) {status = errno; goto unwind_open;}

    /* get current filesize  = max(|file|,initialize)*/
    filesize = lseek(fd,0,SEEK_END);
    if(filesize < 0) {status = errno; goto unwind_open;}
    /* move pointer back to beginning of file */
    (void)lseek(fd,0,SEEK_SET);
    if(filesize < (off_t)sizehint)
        filesize = (off_t)sizehint;

    status = mmapio_new(path, ioflags, filesize, &nciop, &mmapio);
    if(status != NC_NOERR)
	return status;
    mmapio->size = filesize;

    mmapio->mapfd = fd;
    mmapio->memory = (char*)mmap(NULL,mmapio->alloc,
                                    persist?(PROT_READ|PROT_WRITE):(PROT_READ),
				    MAP_SHARED,
                                    mmapio->mapfd,0);
#ifdef DEBUG
fprintf(stderr,"mmapio_open: initial memory: %lu/%lu\n",(unsigned long)mmapio->memory,(unsigned long)mmapio->alloc);
#endif

    /* Use half the filesize as the blocksize */
    sizehint = filesize/2;

    /* sizehint must be multiple of 8 */
    sizehint = (sizehint / 8) * 8;
    if(sizehint < 8) sizehint = 8;

    fd = nc__pseudofd();
    *((int* )&nciop->fd) = fd; 

    if(igetsz != 0)
    {
        status = nciop->get(nciop,
                igeto, igetsz,
                0,
                mempp);
        if(status != NC_NOERR)
            goto unwind_open;
    }

    *sizehintp = sizehint;
    *nciopp = nciop;
    return NC_NOERR;

unwind_open:
    mmapio_close(nciop,0);
    return status;
}
Пример #5
0
/* Create a file, and the ncio struct to go with it. This function is
   only called from nc__create_mp.

   path - path of file to create.
   ioflags - flags from nc_create
   initialsz - From the netcdf man page: "The argument
   Iinitialsize sets the initial size of the file at creation time."
   igeto - 
   igetsz - 
   sizehintp - the size of a page of data for buffered reads and writes.
   nciopp - pointer to a pointer that will get location of newly
   created and inited ncio struct.
   mempp - pointer to pointer to the initial memory read.
*/
int
mmapio_create(const char* path, int ioflags,
    size_t initialsz,
    off_t igeto, size_t igetsz, size_t* sizehintp,
    void* parameters,
    ncio* *nciopp, void** const mempp)
{
    ncio* nciop;
    int fd;
    int status;
    NCMMAPIO* mmapio = NULL;
    int persist = (ioflags & NC_WRITE?1:0);
    int oflags;

    if(path == NULL ||* path == 0)
        return NC_EINVAL;

    /* For diskless open has, the file must be classic version 1 or 2.*/
    if(fIsSet(ioflags,NC_NETCDF4))
        return NC_EDISKLESS; /* violates constraints */

    status = mmapio_new(path, ioflags, initialsz, &nciop, &mmapio);
    if(status != NC_NOERR)
        return status;
    mmapio->size = 0;

    if(!persist) {
        mmapio->mapfd = -1;
	mmapio->memory = (char*)mmap(NULL,mmapio->alloc,
                                    PROT_READ|PROT_WRITE,
				    MAP_PRIVATE|MAP_ANONYMOUS,
                                    mmapio->mapfd,0);
	{mmapio->memory[0] = 0;} /* test writing of the mmap'd memory */
    } else { /*persist */
        /* Open the file, but make sure we can write it if needed */
        oflags = (persist ? O_RDWR : O_RDONLY);    
#ifdef O_BINARY
        fSet(oflags, O_BINARY);
#endif
    	oflags |= (O_CREAT|O_TRUNC);
        if(fIsSet(ioflags,NC_NOCLOBBER))
	    oflags |= O_EXCL;
#ifdef vms
        fd = open(path, oflags, 0, "ctx=stm");
#else
        fd  = open(path, oflags, OPENMODE);
#endif
        if(fd < 0) {status = errno; goto unwind_open;}
	mmapio->mapfd = fd;

	{ /* Cause the output file to have enough allocated space */
	lseek(fd,mmapio->alloc-1,SEEK_SET); /* cause file to appear */
        write(fd,"",mmapio->alloc);
	lseek(fd,0,SEEK_SET); /* rewind */
	}
        mmapio->memory = (char*)mmap(NULL,mmapio->alloc,
                                    PROT_READ|PROT_WRITE,
				    MAP_SHARED,
                                    mmapio->mapfd,0);
	if(mmapio->memory == NULL) {
	    return NC_EDISKLESS;
	}
    } /*!persist*/

#ifdef DEBUG
fprintf(stderr,"mmap_create: initial memory: %lu/%lu\n",(unsigned long)mmapio->memory,(unsigned long)mmapio->alloc);
#endif

    fd = nc__pseudofd();
    *((int* )&nciop->fd) = fd; 

    fSet(nciop->ioflags, NC_WRITE);

    if(igetsz != 0)
    {
        status = nciop->get(nciop,
                igeto, igetsz,
                RGN_WRITE,
                mempp);
        if(status != NC_NOERR)
            goto unwind_open;
    }

    /* Pick a default sizehint */
    if(sizehintp) *sizehintp = pagesize;

    *nciopp = nciop;
    return NC_NOERR;

unwind_open:
    mmapio_close(nciop,1);
    return status;
}
Пример #6
0
/* This function opens the data file or inmemory data
   path - path of data file.
   ioflags - flags passed into nc_open.
   igeto - looks like this function can do an initial page get, and
   igeto is going to be the offset for that. But it appears to be
   unused
   igetsz - the size in bytes of initial page get (a.k.a. extent). Not
   ever used in the library.
   sizehintp - the size of a page of data for buffered reads and writes.
   parameters - arbitrary data
   nciopp - pointer to pointer that will get address of newly created
   and inited ncio struct.
   mempp - pointer to pointer to the initial memory read.
*/
int
memio_open(const char* path,
    int ioflags,
    off_t igeto, size_t igetsz, size_t* sizehintp,
    void* parameters,
    ncio* *nciopp, void** const mempp)
{
    ncio* nciop = NULL;
    int fd = -1;
    int status = NC_NOERR;
    size_t sizehint = 0;
    NC_memio meminfo; /* use struct to avoid worrying about free'ing it */
    NCMEMIO* memio = NULL;
    size_t initialsize;
    /* Should be the case that diskless => inmemory but not converse */
    int diskless = (fIsSet(ioflags,NC_DISKLESS));
    int inmemory = fIsSet(ioflags,NC_INMEMORY);
    int locked = 0;

    assert(inmemory ? !diskless : 1);

    if(path == NULL || strlen(path) == 0)
        return NC_EINVAL;

    assert(sizehintp != NULL);

    sizehint = *sizehintp;

    memset(&meminfo,0,sizeof(meminfo));

    if(inmemory) { /* parameters provide the memory chunk */
	NC_memio* memparams = (NC_memio*)parameters;
        meminfo = *memparams;
        locked = fIsSet(meminfo.flags,NC_MEMIO_LOCKED);
	/* As a safeguard, if !locked and NC_WRITE is set,
           then we must take control of the incoming memory */
        if(!locked && fIsSet(ioflags,NC_WRITE)) {
	    memparams->memory = NULL;	    
	}	
    } else { /* read the file into a chunk of memory*/
	assert(diskless);
	status = readfile(path,&meminfo);
	if(status != NC_NOERR)
	    {goto unwind_open;}
    }

    /* Fix up initial size */
    initialsize = meminfo.size;

    /* create the NCMEMIO structure */
    status = memio_new(path, ioflags, initialsize, &nciop, &memio);
    if(status != NC_NOERR)
	{goto unwind_open;}
    memio->locked = locked;

    /* Initialize the memio memory */
    memio->memory = meminfo.memory;

    /* memio_new may have modified the allocated size, in which case,
       reallocate the memory unless the memory is locked. */    
    if(memio->alloc > meminfo.size) {
	if(memio->locked)
	    memio->alloc = meminfo.size; /* force it back to what it was */
	else {
	   void* oldmem = memio->memory;
	   memio->memory = reallocx(oldmem,memio->alloc,meminfo.size);
	   if(memio->memory == NULL)
	       {status = NC_ENOMEM; goto unwind_open;}
	}
    }

#ifdef DEBUG
fprintf(stderr,"memio_open: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc);
#endif

    if(memio->persist) {
	/* Verify the file is writeable and exists */
	if(!fileexists(path))
	    {status = ENOENT; goto unwind_open;}	
	if(!fileiswriteable(path))
	    {status = EACCES; goto unwind_open;}	
    }

    /* Use half the filesize as the blocksize ; why? */
    sizehint = (size_t)(memio->alloc/2);

    /* sizehint must be multiple of 8 */
    sizehint = (sizehint / 8) * 8;
    if(sizehint < 8) sizehint = 8;

    fd = nc__pseudofd();
    *((int* )&nciop->fd) = fd;

    if(igetsz != 0)
    {
        status = nciop->get(nciop,
                igeto, igetsz,
                0,
                mempp);
        if(status != NC_NOERR)
            goto unwind_open;
    }

    if(sizehintp) *sizehintp = sizehint;
    if(nciopp) *nciopp = nciop; else {ncio_close(nciop,0);}
    return NC_NOERR;

unwind_open:
    if(fd >= 0)
      close(fd);
    memio_close(nciop,0);
    return status;
}