On Wed, 26 Aug 2009, Mindaugas Kavaliauskas wrote:

Hi,

> after a month break I'm back from N42.2217 E78.4485 and back on the list. 

Wow, Issyk-kul?

> I'll try to read mail and answer some questions.
>> 2009-08-26 02:34 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
>>   * harbour/include/hbapifs.h
>>   * harbour/source/rtl/filebuf.c
>>     + added hb_fileExists() and hb_fileDelete() functions
>>     + added support for alternative file IO API used in RDD code which
>>       can be implemented by 3-rd party developers and registered using
>>       hb_fileRegister() function.
> Nice, simple and beautiful. Thank You. I guess the next step is move 

thanks,

> Harbour level file functions from hb_fs*() to hb_file*().

yes, but 1-st I plan to make some tests with it and implement some
simple demonstration servers. It's also possible that I'll move this
whole logic into hb_fs*() API. I haven't decided yet. Real life tests
should give some answers. It will be also necessary to extend method
list. Now only few ones are supported.

> BTW, I guess some 
> MT lock should be moved from s_file*() to hb_file*(). s_fileMtx and 
> s_openFiles are static variable, and it is not possible to implement for 
> example MT safe file close function for additional file protocols. Perhaps 
> additional functions to insert/delete items into/from s_openFiles list is 
> the best solution.

It's not necessary. Look at the code.
Now s_fileMtx is used for two different things.
1. to protect standard HB_FILE handlers in s_openFiles list so they are
   MT safe.
2. to protect s_pFileTypes/s_iFileTypes in hb_fileRegister() function
   to make runtime file type registration MT safe though I do not know
   if it's really necessary because in most of cases new file IO API
   will be registered by startup code. Though maybe it will be usable
   if we add unregister function.
Any other alternative IO API may use or not internal mutexes. It depends
on their internal implementation, i.e. you can very easy implement pure
redirector to hb_fs*() functions without any additional functionality with
very simple HB_FILE structure which is not stored in any list, i.e.
look at code below. I've just written it as example without any tests
so it's possible it has some typos but it should show the main idea.
It does not use any mutexes but it's fully MT safe though on POSIX
systems it restores known problem with synchronization of aliased areas.

best regards,
Przemek




/* demonstration code for alternative RDD IO API */

/* I haven't tested it but it should be fully functional and MT safe
 * alternative IO API for RDD system [druzus]
 */

/* this has to be declared before hbapifs.h is included */
#define _HB_FILE_IMPLEMENTATION_

#include "hbapi.h"
#include "hbapifs.h"
#include "hbinit.h"

/* file name prefix used by this file IO implementation */
#define FILE_PREXIF     "net:"
#define FILE_PREXIF_LEN strlen( FILE_PREXIF )


typedef struct _HB_FILE
{
   const HB_FILE_FUNCS * pFuncs;
   HB_FHANDLE hFile;
}
HB_FILE;

static PHB_FILE hb_fileNew( HB_FHANDLE hFile );

static BOOL s_fileAccept( const char * pFilename )
{
   return hb_strnicmp( pFilename, FILE_PREXIF, FILE_PREXIF_LEN ) == 0;
}

static BOOL s_fileExists( const char * pFilename, char * pRetPath )
{
   return hb_spFileExists( pFilename + FILE_PREXIF_LEN, pRetPath );
}

static BOOL s_fileDelete( const char * pFilename )
{
   return hb_fsDelete( pFilename + FILE_PREXIF_LEN );
}

static PHB_FILE s_fileOpen( const char * pFilename, const char * pDefExt,
                            USHORT uiExFlags, const char * pPaths,
                            PHB_ITEM pError )
{
   HB_FHANDLE hFile;

   hFile = hb_fsExtOpen( pFilename + FILE_PREXIF_LEN, pDefExt, uiExFlags,
                         pPaths, pError );
   if( hFile != FS_ERROR )
      return hb_fileNew( hFile );
   else
      return NULL;
}

static void s_fileClose( PHB_FILE pFile )
{
   hb_fsClose( pFile->hFile );
   hb_xfree( pFile );
}

static BOOL s_fileLock( PHB_FILE pFile, HB_FOFFSET ulStart,
                        HB_FOFFSET ulLen, int iType )
{
   return hb_fsLockLarge( pFile->hFile, ulStart, ulLen, ( USHORT ) iType );
}

static ULONG s_fileReadAt( PHB_FILE pFile, void * buffer,
                           ULONG ulSize, HB_FOFFSET llOffset )
{
   return hb_fsReadAt( pFile->hFile, buffer, ulSize, llOffset );
}

static ULONG s_fileWriteAt( PHB_FILE pFile, const void * buffer,
                            ULONG ulSize, HB_FOFFSET llOffset )
{
   return hb_fsWriteAt( pFile->hFile, buffer, ulSize, llOffset );
}

static BOOL s_fileTruncAt( PHB_FILE pFile, HB_FOFFSET llOffset )
{
   return hb_fsTruncAt( pFile->hFile, llOffset );
}

static HB_FOFFSET s_fileSize( PHB_FILE pFile )
{
   return hb_fsSeekLarge( pFile->hFile, 0, FS_END );
}

static void s_fileCommit( PHB_FILE pFile )
{
   hb_fsCommit( pFile->hFile );
}

static HB_FHANDLE s_fileHandle( PHB_FILE pFile )
{
   return pFile ? pFile->hFile : FS_ERROR;
}

const HB_FILE_FUNCS s_fileFuncs =
{
   s_fileAccept,
   s_fileExists,
   s_fileDelete,
   s_fileOpen,
   s_fileClose,
   s_fileLock,
   s_fileReadAt,
   s_fileWriteAt,
   s_fileTruncAt,
   s_fileSize,
   s_fileCommit,
   s_fileHandle
};

static PHB_FILE hb_fileNew( HB_FHANDLE hFile )
{
   PHB_FILE pFile = ( PHB_FILE ) hb_xgrab( sizeof( HB_FILE ) );

   pFile->pFuncs = &s_fileFuncs;
   pFile->hFile = hFile;

   return pFile;
}

HB_CALL_ON_STARTUP_BEGIN( _hb_file_io_init_ )
   hb_fileRegister( &s_fileFuncs );
HB_CALL_ON_STARTUP_END( _hb_file_io_init_ )

#if defined( HB_PRAGMA_STARTUP )
   #pragma startup _hb_file_io_init_
#elif defined( HB_MSC_STARTUP )
   #if defined( HB_OS_WIN_64 )
      #pragma section( HB_MSC_START_SEGMENT, long, read )
   #endif
   #pragma data_seg( HB_MSC_START_SEGMENT )
   static HB_$INITSYM hb_vm_auto_hb_file_io_init_ = _hb_file_io_init_;
   #pragma data_seg()
#endif
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to