midp_file_cache.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 530 行 · 第 1/2 页
C
530 行
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <kni.h>#include "midp_file_cache.h"#include <midpMalloc.h>#include <midpStorage.h> /* IMPL_NOTE: use PCSL File API */#include <midp_logging.h>#include <midp_properties_port.h>#include <string.h>#include <stdio.h>#define CHECK_ERROR(pszError) \ if (pszError != (char*) NULL) { \ REPORT_ERROR(LC_RMS, "File cache error"); \ return; \ }#define DATA(b) (((char*)b)+sizeof(MidpFileCacheBlock))#define UNINITIALIZED_CACHED_VALUE (-1)/* Cache for a single file */static MidpFileCache *mFileCache;/* Cache limit for a single file */static unsigned int fileCacheLimit = 0;/** * Test if region 1 that starts from position x1 with size s1 * overlaps with region 2 that starts from position x2 with * size s2. */static int is_overlap(long x1, long s1, long x2, long s2) { if (x1 <= x2) { if (x2 < x1 + s1) { return 1; } else { return 0; } } else { if (x1 < x2 + s2) { return 1; } else { return 0; } }}/** * Test if region 1 that starts from position x1 with size s1 * completely includes region 2 that starts from position x2 with * size s2. */static int is_include(long x1, long s1, long x2, long s2) { return (x1 <= x2 && x1+s1 >= x2+s2);}/** * Initializes mFileCache->cachedAvailableSpace with the number * of available bytes on the storage defined by mFileCache->storageId. */static void midp_init_cached_free_space() { if (mFileCache) { mFileCache->cachedAvailableSpace = storage_get_free_space( mFileCache->storageId); }}/* Upon success write, update file position, size and available space */static void updateCachedSizes(long lengthWritten) { mFileCache->cachedPosition += lengthWritten; if (mFileCache->cachedPosition > mFileCache->cachedFileSize) { if (mFileCache->cachedAvailableSpace == UNINITIALIZED_CACHED_VALUE) { midp_init_cached_free_space(); } mFileCache->cachedAvailableSpace -= mFileCache->cachedPosition - mFileCache->cachedFileSize; mFileCache->cachedFileSize = mFileCache->cachedPosition; }}/* Directly write to storage. File position will be updated also. */staticvoid uncachedWrite(char** ppszError, int handle, char *buffer, int length) { *ppszError = NULL; storagePosition(ppszError, handle, mFileCache->cachedPosition); if (*ppszError == NULL) { storageWrite(ppszError, handle, buffer, length); if (*ppszError == NULL) { updateCachedSizes(length); } }}/* Initialize file cache limit reading RMS_CACHE_LIMIT property, * using RMS_CACHE_LIMIT constant as default value. * File cache limit is initialized only once. */static void initFileCacheLimit() { if (0 == fileCacheLimit) { int rmsCacheLimit = getInternalPropertyInt("RMS_CACHE_LIMIT"); if (0 == rmsCacheLimit) { REPORT_INFO(LC_AMS, "RMS_CACHE_LIMIT property not set"); /* set XML constant value as property value */ rmsCacheLimit = RMS_CACHE_LIMIT; } fileCacheLimit = (unsigned)rmsCacheLimit; }}/** * Flush the cache and stop current file caching. * Seek cached position for the case the file won't be closed after * flushing (it's possible if a few files are openned simultaneously). */static void midp_file_cache_finalize(char **ppszError, int stayOpen) { *ppszError = NULL; if (mFileCache != NULL) { midp_file_cache_flush(ppszError, mFileCache->handle); /* Do no seek for the file that is either damaged or to be closed */ if (*ppszError == NULL && stayOpen) { storagePosition(ppszError, mFileCache->handle, mFileCache->cachedPosition); } /* If read is cached, free all read blocks here */ midpFree(mFileCache); mFileCache = NULL; }}/** A helper function for midp_file_cache_flush(). */staticvoid midp_file_cache_flush_using_buffer(char** ppszError, int handle, char* buf, long bufsize) { MidpFileCacheBlock *b; /* current cache block */ MidpFileCacheBlock *n; /* next cache block */ MidpFileCacheBlock *q; /* first block not (yet) copied to the buffer, finally, the value to be stored in mFileCache->blocks */ char *bufPos; /* first not yet used byte in the write buffer */ long startPos, endPos; /* positions in the file cached in a series of buffers, from...upto */ long len; *ppszError = NULL; while ((b = mFileCache->blocks) != NULL) { if ( NULL != buf && NULL != (n = b->next) && n->position == b->position + b->length /* adjacent? */ && b->length + n->length < bufsize ) { /* begin merging blocks */ /* position in the buffer */ bufPos = buf; /* position in the file */ startPos = endPos = b->position; b = mFileCache->blocks; /* now copy a series of adjacent blocks to the write buffer */ do { len = b->length; memcpy(bufPos,DATA(b),len); endPos += len; bufPos += len; b = b->next; } while ( NULL != b && b->position == endPos && endPos - startPos + b->length < bufsize ); q = b; /* q is next to the last copied block */ /* the cache state has not been modified yet */ /* now write from the write buffer */ storagePosition(ppszError, handle, startPos); CHECK_ERROR(*ppszError); storageWrite(ppszError, handle, buf, endPos-startPos); CHECK_ERROR(*ppszError); /* write successful, now free the cache blocks */ while ( q != (b = mFileCache->blocks)) { mFileCache->size -= b->length + sizeof(MidpFileCacheBlock); mFileCache->blocks = b->next; midpFree(b); } } else { storagePosition(ppszError, handle, b->position); CHECK_ERROR(*ppszError); storageWrite(ppszError, handle, DATA(b), b->length); CHECK_ERROR(*ppszError); mFileCache->size -= b->length + sizeof(MidpFileCacheBlock); mFileCache->blocks = b->next; midpFree(b); } } storageCommitWrite(ppszError, handle); CHECK_ERROR(*ppszError); /* ASSERT (mFileCache->size == 0) */ if (mFileCache->size != 0) { REPORT_ERROR(LC_RMS, "File cache out of sync"); }}void midp_file_cache_flush(char** ppszError, int handle) { char *buf; /* write buffer */ long bufsize; /* its size */ *ppszError = NULL; if (mFileCache == NULL || mFileCache->handle != handle || mFileCache->blocks == NULL) { return; } /* allocate a buffer, as large as possible, but no larger than the cache */ /* the buffer will be freed before the function returns */ bufsize = mFileCache->size; do { buf = (char*)midpMalloc(bufsize); if (buf != NULL) { midp_file_cache_flush_using_buffer(ppszError, handle, buf, bufsize); midpFree(buf); break; } else if (bufsize > (signed) (4*sizeof(MidpFileCacheBlock))) { /* we prefer to have at least some buffer so that failure to allocate a big buffer does not lead to slowing down write operations by multiple times (e.g. 5x to 12x on non-cached compact flash) */ bufsize >>= 1; } else { /* failed to allocate buffer of any size */ midp_file_cache_flush_using_buffer(ppszError, handle, NULL, 0); break; } } while(1);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?