pspfile.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 954 行 · 第 1/2 页
C
954 行
/*************************************************************************** * * * db.* * * open source database kernel * * * * Copyright (c) 2000 Centura Software Corporation. All rights reserved. * * * * Use of this software, whether in source code format, or in executable, * * binary object code form, is governed by the CENTURA OPEN SOURCE LICENSE * * which is fully described in the LICENSE.TXT file, included within this * * distribution of source code files. * * * * Except as provided herein, the contents of this file are subject to the * * Centura Open Source Public License Version 1.0 (the "License"); you may * * not use this file except in compliance with the License. A copy of the * * License will be provided to you by Club ITTIA. * * * * Software distributed under the License is distributed on an "AS IS" * * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * * License for the specific language governing rights and limitations * * under the License. * * * * The Original Code is db.linux version 1.0, released February 29, 2000. * * * * The Initial Developer of the Original Code is Centura Software * * Corporation. Portions created by Centura Software Corporation are * * Copyright (C) 1984-2000 Centura Software Corporation. All Rights * * Reserved. * * * * This file contains modifications to the Original Code made by ITTIA. * * This file may only be used in accordance with the ITTIA DB.* V.2 * * License Agreement which is available at WWW.ITTIA.COM. * * * **************************************************************************//* pspfile.c - Contains generic file functions */#include "psp.h"#include "pspint.h"#define PSP_STATE_EMPTY 0#define PSP_STATE_CLOSED 1#define PSP_STATE_OPEN 2#define PSP_BLKSIZE 4096typedef struct { size_t offset; char block[PSP_BLKSIZE];} PSPSTREAM;typedef struct { DB_TCHAR *f_name; PSP_FDESC f_desc; FILE *f_fhandle; PSP_SEM f_sem; PSPSTREAM *f_stream; psp_thread_t f_tid; unsigned int f_flags; unsigned short f_xflags; short f_count; char f_state; char f_active; char f_ru;} PSPFTAB;#define FTABINCR 32static PSPFTAB **ftab = NULL;static PSP_MEMTAG fileTag = 0;static long handleLimit = 0;static long filesOpen = 0;static size_t handles = 0;static size_t ftabSize = 0;static size_t lruNext = 0;static PSP_SEM fileSem = NO_PSP_SEM;/* ========================================================================== Cleanup a file table entry*/static void cleanupFile( register PSPFTAB *p){ if (p->f_xflags & PSP_FLAG_SYNC) psp_syncDelete(p->f_sem); p->f_state = PSP_STATE_EMPTY; if (p->f_stream) psp_zFreeMemory(&p->f_stream, fileTag); if (p->f_name) psp_zFreeMemory(&p->f_name, fileTag);}/* ========================================================================== Open a file that is currently closed.*/static short reopenFile( register PSPFTAB *p){ short rv;#ifdef PSP_STDIO_SUPPORT if (p->f_xflags & PSP_FLAG_FPRINTF) { if (p->f_flags & O_TRUNC) psp_fileRemove(p->f_name); if ((p->f_fhandle = vtfopen(p->f_name, DB_TEXT("a+t"))) == NULL) { cleanupFile(p); return PSP_FAILED; } } else#endif /* PSP_STDIO_SUPPORT */ { rv = psp_flOpen(p->f_name, p->f_flags, p->f_xflags, &p->f_desc); if (!p->f_desc) { cleanupFile(p); return PSP_FAILED; } } filesOpen++; p->f_state = PSP_STATE_OPEN; return PSP_OKAY;}/* ========================================================================== Select the least recently used file and close it to reuse the file handle*/static void closeOneOpenFile( void){ register PSPFTAB *p = ftab[lruNext]; /* the lruNext index will cycle around the length of the file table in search of a handle which has not been "recently used". This is the only place where the f_ru flag will be cleared. It is set when the file is opened or accessed. Thus, a file will be selected for closing by this algorithm only when this algorithm has cleared the flag and then found it cleared a second time around. */ for ( ; ; ) { if (p) { if (p->f_state == PSP_STATE_OPEN && !p->f_active && !(p->f_xflags & PSP_FLAG_STICKY)) { if (!p->f_ru) break; else p->f_ru = 0; } } if (++lruNext >= ftabSize) lruNext = 0; p = ftab[lruNext]; } /* this file may now be closed */#ifdef PSP_STDIO_SUPPORT if (p->f_xflags & PSP_FLAG_FPRINTF) fclose(p->f_fhandle); else#endif /* PSP_STDIO_SUPPORT */ psp_flClose(p->f_desc); filesOpen--; p->f_state = PSP_STATE_CLOSED; if (++lruNext >= ftabSize) lruNext = 0;}/* ========================================================================== Begin access to a file*/static void BeginFileAccess( register PSPFTAB *p){ if (p->f_xflags & PSP_FLAG_SYNC) psp_syncEnterExcl(p->f_sem); if (!handleLimit) return; p->f_active++; p->f_ru = 1; if (p->f_state != PSP_STATE_OPEN) { psp_syncEnterExcl(fileSem); if (filesOpen >= handleLimit) closeOneOpenFile(); psp_syncExitExcl(fileSem); reopenFile(p); }}/* ========================================================================== End access to a file*/static void EndFileAccess( register PSPFTAB *p){ if (handleLimit) p->f_active--; if (p->f_xflags & PSP_FLAG_SYNC) psp_syncExitExcl(p->f_sem);}/* ========================================================================== Initialize the PSP file handling subsytem*/int psp_fileInit( void){ filesOpen = 0; handles = 0; lruNext = 0; if ((fileSem = psp_syncCreate(PSP_MUTEX_SEM)) == NO_PSP_SEM) return PSP_FAILED; if ((fileTag = psp_createTag(NULL, PSP_TAG_NOSEM)) == NULL_MEMTAG) { psp_syncDelete(fileSem); return PSP_FAILED; } ftabSize = FTABINCR; ftab = psp_cGetMemory(FTABINCR * sizeof(PSPFTAB *), fileTag); if (ftab == NULL) { psp_freeTagMemory(fileTag, 1); psp_syncDelete(fileSem); return PSP_FAILED; } return PSP_OKAY;}/* ========================================================================== Terminate the PSP file handling subsytem*/void psp_fileTerm( void){ size_t ii; register PSPFTAB *p; for (ii = 0; ii < handles; ii++) { p = ftab[ii]; if (!p || p->f_state == PSP_STATE_EMPTY) break; if (p->f_state == PSP_STATE_OPEN) {#ifdef PSP_STDIO_SUPPORT if (p->f_xflags & PSP_FLAG_FPRINTF) fclose(p->f_fhandle); else#endif psp_flClose(p->f_desc); } if (p->f_xflags & PSP_FLAG_SYNC) psp_syncDelete(p->f_sem); } psp_freeTagMemory(fileTag, 1); psp_syncDelete(fileSem);}/* ========================================================================== Open a file*/PSP_FH psp_fileOpen( const DB_TCHAR *name, unsigned int flags, unsigned short xflags){ register size_t ii; register PSPFTAB *p = NULL; if (!psp_inited) return NULL; if (flags & O_TRUNC) flags |= O_CREAT; /* O_TRUNC requires O_CREAT */ psp_syncEnterExcl(fileSem); for (ii = 0; ii < handles; ii++) { p = ftab[ii]; if (!p || p->f_state == PSP_STATE_EMPTY) continue; if (vtstrcmp(p->f_name, name) == 0) { if (p->f_xflags != xflags || p->f_flags != flags) { vtprintf(DB_TEXT("Already open file (%s) opened with different flags\n"), name); psp_syncExitExcl(fileSem); return NULL; } p->f_count++; return p; } } do { if (handles < ftabSize) p = ftab[handles++] = psp_cGetMemory(sizeof(PSPFTAB), fileTag); else { for (ii = 0; ii < ftabSize; ii++) { p = ftab[ii]; if (!p || p->f_state == PSP_STATE_EMPTY) break; } if (ii == ftabSize) { ftab = psp_cExtendMemory(ftab, (ftabSize + FTABINCR) * sizeof(PSPFTAB *), FTABINCR * sizeof(PSPFTAB *), fileTag); ftabSize += FTABINCR; p = ftab[ii]; } } } while (!p); p->f_flags = flags; p->f_xflags = xflags; p->f_state = PSP_STATE_CLOSED; p->f_count = 1; p->f_ru = 1; p->f_name = psp_strdup(name, fileTag); p->f_sem = (xflags & PSP_FLAG_SYNC) ? psp_syncCreate(PSP_MUTEX_SEM) : NO_PSP_SEM; p->f_tid = psp_threadId(); if (xflags & PSP_FLAG_STREAM) p->f_stream = psp_getMemory(sizeof(PSPSTREAM), fileTag); else p->f_stream = NULL; if (reopenFile(p) != PSP_OKAY) p = NULL; else p->f_flags &= O_TRUNC; /* must turn of O_TRUNC after initial open */ psp_syncExitExcl(fileSem); return p;}/* ========================================================================== Close a file*/void psp_fileClose( PSP_FH handle){ register PSPFTAB *p = (PSPFTAB *) handle; psp_syncEnterExcl(fileSem); if (--p->f_count == 0) { if (p->f_state == PSP_STATE_OPEN) {#ifdef PSP_STDIO_SUPPORT if (p->f_xflags & PSP_FLAG_FPRINTF) fclose(p->f_fhandle); else#endif psp_flClose(p->f_desc); filesOpen--; p->f_state = PSP_STATE_CLOSED; } cleanupFile(p); } psp_syncExitExcl(fileSem);}/* ========================================================================== Write formatted output to a file*/int psp_filePrintf( PSP_FH handle, const DB_TCHAR *format, ...){ register PSPFTAB *p = (PSPFTAB *) handle; int bytes; va_list mark;#ifdef PSP_STDIO_SUPPORT if (!(p->f_xflags & PSP_FLAG_FPRINTF)) { /* TBD: Log out warning about accessing binary file */ vtprintf(DB_TEXT("File not opened with printf capability\n")); }#endif if (p->f_stream) { /* TBD: Log out warning about accessing stream file */ vtprintf(DB_TEXT("Invalid file mode, file is a stream\n")); } BeginFileAccess(p); va_start(mark, format); bytes = vvftprintf(p->f_fhandle, format, mark); va_end(mark); EndFileAccess(p); return bytes;}/* ========================================================================== Seek to a specified location in a file*/void psp_fileSeek( PSP_FH handle, size_t addr){ register PSPFTAB *p = (PSPFTAB *) handle; int bytes; if (p->f_xflags & PSP_FLAG_SYNC) { /* TBD: Log out warning about accessing file needing synchronization */ vtprintf(DB_TEXT("Invalid file mode, file was opened with PSP_FLAG_SYNC\n")); } BeginFileAccess(p); if (p->f_stream) { psp_flSeek(p->f_desc, (addr / PSP_BLKSIZE) * PSP_BLKSIZE, SEEK_SET); bytes = psp_flRead(p->f_desc, p->f_stream->block, PSP_BLKSIZE); if (bytes < 0) bytes = 0; if (bytes < PSP_BLKSIZE) p->f_stream->block[bytes] = DB_TEXT('\0'); addr %= PSP_BLKSIZE; p->f_stream->offset = (size_t) bytes < addr ? (size_t) bytes : addr; } else psp_flSeek(p->f_desc, addr, SEEK_SET); EndFileAccess(p);}/* ========================================================================== Write to a file*/int psp_fileWrite( PSP_FH handle, const void *buf, size_t size){ register PSPFTAB *p = (PSPFTAB *) handle; int bytes; if (p->f_xflags & PSP_FLAG_SYNC) { /* TBD: Log out warning about accessing file needing synchronization */ vtprintf(DB_TEXT("Invalid file mode, file was opened with PSP_FLAG_SYNC\n")); } if (p->f_stream) { /* TBD: Log out warning about accessing stream file */ vtprintf(DB_TEXT("Invalid file mode, file is a stream\n")); } if (size == 0) return 0; BeginFileAccess(p); if ((bytes = psp_flWrite(p->f_desc, buf, size)) == -1) { /* TBD: Log out error about write failure */ vtprintf(DB_TEXT("Write failed, errno = %d\n"), errno); } EndFileAccess(p);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?