/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * SOURCE: memfs.c * * MODULE: conversion * * PURPOSE: * Memory Filing System used by some of the convertor modules * * COMMENTS * None */ #include "mymalloc/mymalloc.h" #include #include #include #include "conversion/memfs.hh" /* can't use RMDBGOUT because this is C, not C++ */ const int MEMFSDBGLEVEL = 4; extern int RManDebug; /* This function for internal use only */ int memfs_ensure(thandle_t handle, toff_t off) { memFSContext *memFS = (memFSContext *)handle; char **mam2=NULL; int mamSize2=0, i=0; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_ensure: %d\n", off); fflush(stdout); } #endif /* Do we have to allocate a bigger mam? */ mamSize2 = (off >> MEMFS_LD_BLOCKSIZE); if (mamSize2 >= memFS->mamSize) { /* Always allocate mam in powers of 2. That ensures that if we run out of space the new mam will be twice as big as the old one. */ i = 0; while (mamSize2 != 0) {mamSize2 >>= 1; i++;} mamSize2 = (1 << i); #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_ensure: growing mam from %d to %d\n", memFS->mamSize, mamSize2); fflush(stdout); } #endif if ((mam2 = (char **)mymalloc(mamSize2 * sizeof(char*))) == NULL) return -1; /* Copy existing mam entries */ memcpy ((void*)mam2, (void*) memFS->mam, memFS->mamSize * sizeof(char*)); /* Init new mam entries */ for (i=memFS->mamSize; i < mamSize2; i++) { mam2[i] = NULL; } /* free old mam */ free(memFS->mam); memFS->mam = mam2; memFS->mamSize = mamSize2; } /* Calculate again because its value might have been changed by the above block */ mamSize2 = (off >> MEMFS_LD_BLOCKSIZE); if ((memFS->mam)[mamSize2] == NULL) { /* We don't just have to allocate this one new block but all the ones with lower addresses that aren't defined yet as well */ for (i=memFS->mamHighest+1; i <= mamSize2; i++) { if (((memFS->mam)[i] = (char*)mymalloc((1 << MEMFS_LD_BLOCKSIZE) * sizeof(char))) == NULL) return -1; } memFS->mamHighest = mamSize2; } /* All done, the memFS can now hold an object of size off */ return 0; } /* Initialise the memory filing system */ int memfs_initfs(thandle_t handle) { memFSContext *memFS = (memFSContext *)handle; int i=0; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_initfs\n"); fflush(stdout); } #endif memFS->pos = 0; memFS->high = 0; memFS->mamSize = MEMFS_MAM_ENTRIES; if ((memFS->mam = (char **)mymalloc(MEMFS_MAM_ENTRIES * sizeof(char *))) == NULL) return -1; if (((memFS->mam)[0] = (char*)mymalloc((1 << MEMFS_LD_BLOCKSIZE) * sizeof(char))) == NULL) return -1; memFS->mamHighest = 0; for (i=1; imam)[i] = NULL; } return 0; } /* Kill the memory filing system, freeing all its resources */ void memfs_killfs(thandle_t handle) { memFSContext *memFS = (memFSContext *)handle; int i=0; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_killfs\n"); fflush(stdout); } #endif for (i=0; i < memFS->mamSize; i++) { if ((memFS->mam)[i] == NULL) break; free((memFS->mam)[i]); } free(memFS->mam); } /* Reset file pointers, leave memory setup */ void memfs_newfile(thandle_t handle) { memFSContext *memFS = (memFSContext *)handle; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_newfile\n"); fflush(stdout); } #endif memFS->pos = 0; memFS->high = 0; } tsize_t memfs_read(thandle_t handle, tdata_t mem, tsize_t size) { tsize_t todo=0, transfered = 0; int block=0, offset=0, x=0; memFSContext *memFS = (memFSContext *)handle; /* Don't read over the end of the "file" */ todo = memFS->high - memFS->pos; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_read: (%d, left: %d)\n", todo, memFS->high); fflush(stdout); } #endif if (todo > size) todo = size; while (todo > 0) { block = (memFS->pos >> MEMFS_LD_BLOCKSIZE); offset = memFS->pos - (block << MEMFS_LD_BLOCKSIZE); /* Space left in this buffer */ x = (1 << MEMFS_LD_BLOCKSIZE) - offset; if (x > todo) x = todo; memcpy((void*)mem, (void*)(((memFS->mam)[block]) + offset), x); /* tdata_t is some kind of void *, so we have to do this cast */ mem = (tdata_t)(((char*)mem) + x); memFS->pos += x; transfered += x; todo -= x; } return transfered; } tsize_t memfs_write(thandle_t handle, tdata_t mem, tsize_t size) { tsize_t transfered = 0; memFSContext *memFS = (memFSContext *)handle; int block=0, offset=0, x=0; /* Make sure there's enough room for this write */ if (memfs_ensure(handle, memFS->pos + size) < 0) return 0; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_write (%d)\n",size); fflush(stdout); } #endif while (size > 0) { /* See memfs_read */ block = (memFS->pos >> MEMFS_LD_BLOCKSIZE); offset = memFS->pos - (block << MEMFS_LD_BLOCKSIZE); x = (1 << MEMFS_LD_BLOCKSIZE) - offset; if (x > size) x = size; memcpy((void*)(((memFS->mam)[block]) + offset), (void*)mem, x); mem = (tdata_t)(((char *)mem) + x); memFS->pos += x; transfered += x; size -= x; } if (memFS->pos > memFS->high) {memFS->high = memFS->pos;} return transfered; } toff_t memfs_seek(thandle_t handle, toff_t offset, int mode) { memFSContext *memFS = (memFSContext *)handle; switch (mode) { case SEEK_SET: memFS->pos = offset; break; case SEEK_CUR: memFS->pos += offset; break; case SEEK_END: memFS->pos = memFS->high + offset; break; default: break; } if (memFS->pos < 0) memFS->pos = 0; /* Don't limit to end of file (this actually caused problems!) */ memfs_ensure(handle, memFS->pos); if (memFS->pos > memFS->high) memFS->high = memFS->pos; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_seek: Set pos to %d\n", memFS->pos); fflush(stdout); } #endif return memFS->pos; } int memfs_close(thandle_t handle) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_close:\n"); fflush(stdout); } #endif return 1; /* = success? */ } toff_t memfs_size(thandle_t handle) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_size:\n"); fflush(stdout); } #endif return (((memFSContext *)handle)->high); } int memfs_map(thandle_t handle, tdata_t *memp, toff_t *top) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_map: %p, %d\n", *memp, *top); fflush(stdout); } #endif return 0; } void memfs_unmap(thandle_t handle, tdata_t mem, toff_t to) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_unmap: %p, %d\n", mem, to); fflush(stdout); } #endif } /* Read-only from memory (simple chunky model, not block-oriented) */ void memfs_chunk_initfs(thandle_t handle, char *src, r_Long size) { memFSContext *memFS = (memFSContext *)handle; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_initfs: %p, %d\n", src, size); fflush(stdout); } #endif memFS->pos = 0; memFS->chunk = src; memFS->high = size; } tsize_t memfs_chunk_read(thandle_t handle, tdata_t mem, tsize_t size) { tsize_t todo=0; memFSContext *memFS = (memFSContext *)handle; todo = memFS->high - memFS->pos; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_read: %d (left %d)\n", size, todo); fflush(stdout); } #endif if (todo > size) todo = size; if (todo > 0) { memcpy((void*)mem, (void*)(memFS->chunk + memFS->pos), todo); memFS->pos += todo; } return todo; } toff_t memfs_chunk_seek(thandle_t handle, toff_t offset, int mode) { memFSContext *memFS = (memFSContext *)handle; switch (mode) { case SEEK_SET: memFS->pos = offset; break; case SEEK_CUR: memFS->pos += offset; break; case SEEK_END: memFS->pos = memFS->high + offset; break; default: break; } if (memFS->pos < 0) memFS = 0; /* Since file can't be extended this is OK here */ if (memFS->pos > memFS->high) memFS->pos = memFS->high; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_seek: Position to %d\n", memFS->pos); fflush(stdout); } #endif return memFS->pos; } int memfs_chunk_close(thandle_t handle) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_close:\n"); fflush(stdout); } #endif return 1; } toff_t memfs_chunk_size(thandle_t handle) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_size:\n"); fflush(stdout); } #endif return (((memFSContext *)handle)->high); } /* Map file to memory -- since we already have it in memory in the first place this is very simple. */ int memfs_chunk_map(thandle_t handle, tdata_t *memp, toff_t *top) { memFSContext *memFS = (memFSContext *)handle; #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_map:\n"); fflush(stdout); } #endif *memp = (tdata_t)(memFS->chunk); *top = (toff_t)(memFS->high); return 1; /* Success? */ } void memfs_chunk_unmap(thandle_t handle, tdata_t mem, toff_t to) { #ifdef RMANDEBUG if (RManDebug >= MEMFSDBGLEVEL) { printf("memfs_chunk_unmap: %p, %d\n", mem, to); fflush(stdout); } #endif }