锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / Darwin服务器 / 使用文件
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

使用文件


QTSS支持文件系统模块,因此可以透明而又简单地和定制的文件系统协同工作。举例来说,一个QTSS文件系统模块可以允许QTSS模块读取一个定制的网络文件系统,或者一个定制的数据库。对读取文件的支持包含如下组件:

  • QTSS文件系统回调函数,任何模块都可以使用这些函数来打开,读取,和关闭文件。如何调用文件系统的回调函数在“通过回调函数读取文件”部分中进行描述。QTSS文件系统回调函数使QTSS很容易就可以和很多不同的文件系统类型协同工作。使用文件系统回调函数读取所有文件的QTSS模块可以透明地使用部署在服务器上的任何文件系统。
  • 在进行文件系统注册的模块中实现文件系统角色。这些角色在QTSS和特定的文件系统之间起到桥梁的作用。在“实现QTSS文件系统模块”部分对这些角色进行描述。举例来说,您可以写一个文件系统模块,来实现QTSS和定制的数据库,或者定制的网络文件系统的接口。

通过回调函数读取文件

在QTSS中,文件由一个QTSS流来表示,因此您可以通过现有的QTSS流回调函数来读取文件。可用于操作文件的回调函数如下:

  • QTSS_OpenFileObject,用于打开本地操作系统中的一个文件。这是仅用于操作文件的两个回调函数之一。
  • QTSS_CloseFileObject,用于关闭先前通过QTSS_OpenFileObject函数打开的文件。 这是仅用于操作文件的两个回调函数之一。
  • QTSS_Read,用于从文件对象的流中读取数据,该文件对象是之前通过QTSS_OpenFileObject对象创建而成的。
  • QTSS_Seek,用于设置文件对象的流的当前位置。
  • QTSS_Advise,用于告诉文件系统模块流中的指定部分很快就会被读取。
  • QTSS_RequestEvent,用于告诉文件系统模块本函数的调用模块希望在事件掩码指定的事件发生的时候得到通知。这里所说的事件是指某个流变为可读或者变为可写的时机。

在QTSS中,一个文件就是一个QTSS_Object对象,该对象有其自己的对象类型,即QTSS_FileObject,这使您可以通过标准的QTSS回调函数(QTSS_GetValue,QTSS_GetValueAsString,和QTSS_GetValuePtr)来获取文件的元信息,比如文件的长度和修改日期。您可以通过标准的QTSS回调函数来将任意数量的文件系统元信息和文件对象存储在一起。举例来说,一个和POSIX文件系统协同工作的模块希望为存储POSIX文件系统描述符的文件对象添加一个属性。文件对象中还有一个QTSS流引用,在调用对文件进行操作的QTSS流例程,比如QTSS_Read时,可以使用该引用。

The sample code in 列表 3-7 中的实例代码显示了如何打开一个文件,确定文件的长度,读取整个文件,关闭文件,以及返回文件中含有的数据。

Listing 2-7 Reading a file

QTSS_Error ReadEntireFile(char* inPath, void** outData, UInt32* outDataLen)

{

    QTSS_Object theFileObject = NULL;

    QTSS_Error theErr = QTSS_OpenFileObject(inPath, qtssOpenFileNoFlags, &theFileObject);

    if (theErr != QTSS_NoErr)

        return theErr; // The file wasn't found or it couldn't be opened.

    // The file is open. Find out how long it is.

    UInt64* theLength = NULL;

    UInt32 theParamLen = 0;

    theErr = QTSS_GetValuePtr(theFileObject, qtssFlObjLength, 0, (void**)&theLength, &theParamLen);

    if (theErr != QTSS_NoErr)

        return theErr;

    if (theParamLen != sizeof(UInt64))

        return QTSS_RequestFailed;;

    // Allocate memory for the file data.

    *outData = new char[*theLength + 1];

    *outDataLen = *theLength;

    // Read the data

    UInt32 recvLen = 0;

    theErr = QTSS_Read(theFileObject, *outData, *outDataLen, &recvLen);

    if ((theErr != QTSS_NoErr) || (recvLen != *outDataLen))

    {

        delete *outData;

        return theErr;

    }

    // Close the file.

    (void)QTSS_CloseFileObject(theFileObject);

}

 

实现QTSS文件系统模块

文件系统模块为QTSS模块提供了一种途径,来读取特定文件系统的文件,无论该文件系统的类型是什么。典型情况下,文件系统模块处理的是文件系统中所有路径的一个子集合,但是也可能处理系统中的所有路径。如果文件系统模块只处理特定的路径子集,则通常会处理某个根路径下的所有路径。举例来说,处理存储在某个特定数据库中的文件可能只负责从/Local/database_root/目录下的所有路径。

实现一个QTSS文件系统模块首先要从注册为下面的某个角色开始:

  • Open File Preprocess(打开文件预处理)角色,服务器在响应通过QTSS_OpenFileObject回调函数打开文件的模块(或者服务器)进行响应时,会调用这个角色。如果模块并不处理某个特定类型的文件,则立即返回QTSS_FileNotFound。如果模块能够处理指定类型的文件,则会将文件打开,更新由服务器提供的文件对象,并返回QTSS_NoErr。如果在这个期间发生错误,则模块会返回QTSS_RequestFailed。一旦模块返回QTSS_NoErr,就应该准备处理与被打开文件相关的Advise File(建议文件),Read File(读取文件),Request Event File(请求事件文件)和Close File(关闭文件)角色。服务器会调用注册了Open File Preprocess 角色的所有模块,直到某个被调用的模块返回QTSS_NoErr或者QTSS_RequestFailed。
  • Open File角色,当所有处理Open File Preprocess角色的模块都返回QTSS_FileNotFound时,模块(或者服务器)会调用QTSS_OpenFileObject回调函数,服务器在响应这些模块(或者服务器)的时候调用这个角色。只有一个模块可以注册为Open File角色。和因为Open File Preprocess角色被调用的模块一样,被以Open File角色调用的模块必须确定自己是否可以处理指定的文件。如果可以处理,则打开该文件,更新由服务器提供的文件对象,并返回QTSS_NoErr。如果在这个过程中出现错误,或者模块不能处理指定的文件,则分别返回QTSS_RequestFailed或QTSS_FileNotFound。

如果文件系统模块处理的是系统中存在的文件的一个子集,则应该注册Open File Preprocess角色。举例来说,为数据库之外的文件提供服务的文件系统模块可能只处理某个根目录下面的文件。所有其它路径应该由其它可以处理这些路径的模块来负责。

如果文件系统模块实现了系统中缺省的文件系统,则应该注册Open File角色。举例来说,在一个UNIX系统上,处理Open File角色的模块可能会在服务器和标准的POSIX文件系统之间提讴歌内一个接口。

一旦模块从Open File角色或者Open File Preprocess角色返回QTSS_NoErr,就要为这个新打开的文件负责,就应该准备好处理下面这些代表该文件的角色:

  • Advise File角色,这个角色在响应通过QTSS_Advise回调函数获得文件对象的模块(或者服务器)时被调用。QTSS_Advise回调函数用来通知文件系统模块很快需要操作文件的指定区域。
  • Read File角色,这个角色在响应通过QTSS_Read回调函数获得文件对象的模块(或者服务器)时被调用。文件系统模块有义务对这个角色进行处理,以尽可能地在由调用者提供的缓冲区中填充正确的文件数据。
  • Request Event File角色,这个角色在响应通过QTSS_RequestEvent回调函数获得文件对象的模块(或者服务器)时被调用。
  • Close File角色,这个角色在响应通过QTSS_Close回调函数获得文件对象的模块(或者服务器)时被调用。模块应该为这个角色对应的文件清除所有文件系统和仅用于模块的数据结构。对于给定的文件对象来说,这个角色总是文件系统模块中最后一个被调用的角色。

请注意:模块不需要显式注册Advise File,Read File,Request Event File或者Close File 角色,也可以处理这些角色。相反,从某个打开文件的角色中返回QTSS_NoErr或者QTSS_RequestFailed的本身就说明了对特定文件对象的所有权,因此也就意味着模块已经注册了这些角色。

文件系统模块角色

这个部分描述如下文件系统模块角色:

Open File Preprocess角色

服务器会调用Open File Preprocess角色,来响应通过QTSS_OpenFileObject 回调函数打开文件的模块。模块有义务对这个角色进行处理,以确定是否处理指定需要打开的文件类型。如果要对该文件类型进行处理,而且该文件存在,则模块就打开该文件,更新由服务器提供的文件对象,然后返回QTSS_NoErr。

Open File Preprocess角色在被调用的时候会收到一个QTSS_OpenFile_Params结构,该结构定义如下:

typedef struct
    {
    char*               inPath;
    QTSS_OpenFileFlags  inFlags;
    QTSS_Object         inFileObject;
     } QTSS_OpenFile_Params;s
 

 

inPath

这是一个以null结尾的C字符串,包含将要被打开的文件的全路径。

inFlags

这是一个文件打开的标志参数,指定调用QTSS_OpenFileObject 的模块是否可以处理异步的度操作(qtssOpenFileAsync),或者是否希望以从头到尾的顺序读取文件(qtssOpenFileReadAhead)。

inFileObject

这是一个QTSS对象,模块如果可以打开由inPath参数指定的文件,则会更新这个对象。

如果指定的文件是模块要处理的文件,则模块应该做好打开和配置文件所需要的一切必工作。它可以使用inFileObject对象来为该文件存储任何专门用于模块的信息。此外,模块还应该设定文件对象中qtssFlObjLenth和qtssFlObjModDate属性的值。

如果指定的文件是模块要处理的,但是在准备配置文件的过程中发生错误,则模块应该返回QTSS_RequestFailed。

如果注册了Open File Preprocess角色的所有模块都返回QTSS_FileNotFound,则服务器会调用一个注册了Open File角色的模块。

希望被以Open File Preprocess角色调用的模块必须在其Register角色中调用QTSS_AddRole函数,并指定QTSS_OpenFilePreprocess_Role作为角色参数。注册为这个角色的模块也必须处理下面这些角色,但是不必显式地加以注册: Advise File,Read File,Request Event File,和Close File。

Open File 角色

在所有注册了Open File Preprocess角色的所有模块都被调用,并且都返回QTSS_FileNotFound的时候,服务器会调用注册了Open File角色的模块。只有一个模块可以注册Open File角色,该模块就是在QTSS启动的时候第一个注册该角色的模块。

和以Open File Preprocess角色被调用的模块一样,模块有义务对Open File角色进行处理,以确定是否可以处理即将被打开的文件的类型。如果要处理该类型的文件,而且文件存在,则模块就打开该文件,更新由服务器提供的文件对象,并返回QTSS_NoErr。

模块在被调用的时候会收到一个QTSS_OpenFile_Params结构,该结构定义如下:

typedef struct
     {
    char*               inPath;
    QTSS_OpenFileFlags  inFlags;
    QTSS_Object         inFileObject;
     } QTSS_OpenFile_Params;

 

inPath

这是一个以null结尾的C字符串,包含将要被打开的文件的全路径。

inFlags

这是一个文件打开的标志参数,指定调用QTSS_OpenFileObject 的模块是否可以处理异步的度操作(qtssOpenFileAsync),或者是否希望以从头到尾的顺序读取文件(qtssOpenFileReadAhead)。

inFileObject

这是一个QTSS对象,模块如果可以打开由inPath参数指定的文件,则会更新这个对象。

如果指定的文件是模块要处理的文件,则模块应该做好打开和配置文件所需要的一切必工作。它可以使用inFileObject对象来为该文件存储任何专门用于模块的信息。此外,模块还应该设定文件对象中qtssFlObjLength和qtssFlObjModDate属性的值。

如果指定的文件是模块要处理的,但是在准备配置文件的过程中发生错误,则模块应该返回QTSS_RequestFailed。

希望被以Open File Preprocess角色调用的模块必须在其Register角色中调用QTSS_AddRole函数,并指定QTSS_OpenFile_Role作为角色参数。注册为这个角色的模块也必须处理下面这些角色,但是不必显式地加以注册:Advise File,Read File,Request Event File,和Close File。

Advise File 角色

当模块(或者服务器)为某个文件对象调用QTSS_Advise回调函数,以通知文件系统模块文件的指定部分很快就会被读取的时候,服务器就会以Advise File角色调用各个模块。

Advise File角色在被调用的时候会接收到一个QTSS_AdviseFile_Params结构,该结构定义如下:

typedef struct
     {
    QTSS_Object         inFileObject;
    UInt64              inPosition;
    UInt32              inSize;
     } QTSS_AdviseFile_Params;

 

inFileObject

这是个文件对象,代表已经打开的文件。文件系统模块使用文件对象来确定与调用QTSS_Advise回调函数相关联的文件。

inPosition

相对于文件开头的偏移量,以字节数记,表示即将被读取部分的开头。

inSize

将被读取的部分的字节数。

服务器并不要求文件系统模块在处理这个角色的时候做任何事情,但是这个角色可以使模块有机会读取文件的指定部分。

文件系统模块并不需要显式注册这个角色。

模块在完成这个角色的处理之后,应该总是返回QTSS_NoErr。

Read File 角色

当模块(或者服务器)为某个文件对象调用QTSS_Read回调函数,以读取相应的文件时,服务器会以Read File角色调用各个模块来进行响应。

Read File角色在被调用的时候会接收到一个QTSS_ReadFile_Params 结构,该结构定义如下:

typedef struct
     {   QTSS_Object inFileObject;
    UInt64      inFilePosition;
    void*       ioBuffer;
    UInt32      inBufLen;
    UInt32*     outLenRead;
     } QTSS_ReadFile_Params;

 

inFileObject

这是一个文件对象,表示即将被读取的文件。文件系统模块通过这个文件对象来确定与之前调用的QTSS_Read函数相关联的文件。

inFilePosition

相对于文件开头的偏移量,以字节数记,表示即将被读取部分的开头。服务器对文件的位置进行维护,将它作为文件对象的属性进行存储,因此文件系统模块并不一定要在内部对文件的位置进行缓存,而是在任何时候都可以得到这个位置信息。

ioBuffer

这是一个缓冲区的指针,文件系统模块将读到的数据放置到这个缓冲区上。

ioBufLen

ioBuffer指向的缓冲区的长度。

outLenRead

实际读取到的字节数。

文件系统模块应该尽可能将文件数据填充到由ioBuffer参数指向的缓冲区,这些数据是从文件中读出来的,其在文件中的起始位置由inFilePosition参数来指定。

如果文件是以qtssOpenFileAsync标识打开的,则在读取数据可能导致线程阻塞的时候,模块应该返回QTSS_WouldBlock。否则,模块将会阻塞线程,直到得到所有的数据。当ioBuffer指向的缓冲区满,或者到达文件的尾部,文件系统模块应该将outLenRead参数设置为已经读取到的字节数,并返回QTSS_NoErr。

如果因为某种原因导致读操作失败,则处理这个角色的文件系统模块应该返回QTSS_RequestFailed。

文件系统模块不需要显式注册这个角色。

Close File 角色

当模块(或者服务器)为某个文件对象调用QTSS_CloseFile回调函数,来关闭某个已经打开的文件时,服务器会调用各个模块的Close File角色进行相应。

Close File 角色在被调用的时候会接收到一个QTSS_CloseFile_Params 结构,该结构定义如下:

typedef struct
     {
    QTSS_Object         inFileObject;
     } QTSS_CloseFile_Params;

 

inFileObject

这是一个文件对象,表示即将被关闭的文件。文件系统模块使用这个文件对象来确定与之前调用的QTSS_Close函数相关联的文件。

处理这个角色的模块应该释放之前为这个即将被关闭的文件创建的任何数据结构。

对于任何给定的文件对象,这个角色是文件系统模块中最后一个被调用的角色。

文件系统模块不需要显式注册这个角色。

模块在处理完成这个角色之后,应该总是返回QTSS_NoErr。

Request Event File角色

当模块(或者服务器)调用QTSS_RequestEvent回调函数时,服务器会调用各个模块的Request Event File角色来进行响应。如果模块或者服务器调用QTSS_OpenFileObject函数,并指定qtssOpenFileAsync标识,则处理该文件对象的文件系统模块可能会从其Read File角色返回QTSS_WouldBlock。出现这种情况时,QTSS_Read函数的调用者可能会调用QTSS_RequestEvent回调函数,来告诉服务器QTSS_Read的调用者希望在数据可以读取的时候得到通知。

Request Event File角色在被调用的时候会接收带一个QTSS_RequestEventFile_Params结构,该结构定义如下:

typedef struct
     {
    QTSS_Object     inFileObject;
    QTSS_EventType  inEventMask;
     } QTSS_RequestEventFile_Params;

 

inFileObject

这是一个文件对象,表示被请求通知的文件。文件系统模块使用这个文件对象来确定与之前调用的QTSS_RequestEvent 函数相关联的文件。

inEventMask

事件掩码,指定请求通知的事件类型。可能的值为QTSS_ReadableEvent和QTSS_WriteableEvent。

如果文件系统模块正在实现的文件系统支持通知,则文件系统模块应该进行一切必要的准备,以接收与之前调用过的QTSS_RequestEvent回调函数相关联的文件的事件。当文件变为可读的时候,文件系统模块应该调用QTSS_SignalStream回调函数,并传入该文件对象的流引用(这个流引用可以通过访问对象的qtssFlObjStream属性得到)。调用QTSS_SignalStream函数可以告诉服务器应该将“文件现在已经可读”的消息通知QTSS_RequestEvent函数的调用者。

文件系统模块不需要显式注册这个角色。

模块在处理完成这个角色之后,应该总是返回QTSS_NoErr。

Open File角色的实例代码

列表 3-8中的实例代码处理的是Open File角色,但是也可以用于处理Open File Preprocess角色。这段代码将POSIX文件系统层用作文件系统,而且不支持异步I/O。

Listing 2-8 Handling the Open File Role

QTSS_Error OpenFile(QTSS_OpenFile_Params* inParams)
     {
    // Use the POSIX open call to attempt to open the specified file.
    // If it doesn't exist, return QTSS_FileNotFound
    int theFile = open(inParams->inPath, O_RDONLY);
    if (theFile == -1)
        return QTSS_FileNotFound;
    // Use the POSIX stat call to get the length and the modification date
    // of the file. This information must be set in the QTSS_FileObject
    // by every file system module.
    UInt64 theLength = 0;
    time_t theModDate = 0;
    struct stat theStatStruct;
    if (::fstat(fFile, &theStatStruct) >= 0)
    {
        theLength = buf.st_size;
        theModDate = buf.st_mtime;
    }
    else
    {
        ::close(theFile);
        return QTSS_RequestFailed; // Stat failed
    }
   // Set the file length and the modification date attributes of this file
    // object before returning
   (void)QTSS_SetValue(inParams->inFileObject, qtssFlObjLength, 0, &theLength, sizeof(theLength));
   (void)QTSS_SetValue(inParams->inFileObject, qtssFlObjModDate, 0, &theModDate, sizeof(theModDate));
    // Place the file reference in a custom attribute in the QTSS_FileObject.
   // This way, we can easily get the file reference in other role handlers,
   // such as the QTSS_ReadFile_Role and the QTSS_CloseFile_Role.
   QTSS_Error theErr = QTSS_SetValue(inParams->inFileObject, sFileRefAttr, 0,
                    &theFile, sizeof(theFileSource));
  if (theErr != QTSS_NoErr)
  {
      ::close(theFile);
      return QTSS_RequestFailed;
     }
  return QTSS_NoErr;
}

 

实现异步通知

如果模块或者服务器调用QTSS_OpenFileObject 函数,并在调用时指定qtssOpenFileAsync标志,则处理该文件对象的文件系统模块可能在其QTSS_ReadFile_Role角色函数中返回QTSS_WouldBlock。一旦这种情况出现,QTSS_Read函数的调用者可能希望在被请求的数据变为可读的时候得到通知。通过调用QTSS_RequestEvent回调函数可以做到这点,该函数告诉服务器调用者希望在可以从文件读取数据的时候得到通知。

并不是所有文件系统都支持通知机制,而且如果支持的话,每个文件系统架构的通知机制也有各自的特殊之处。因此,一个文件系统模块是否支持通知机制,取决于文件系统模块开发者的考虑。一般地说,文件系统模块支持异步通知且不会在QTSS_ReadFile_Role角色中阻塞会更好一些,因为阻塞在一个文件操作中,可能会导致很多服务器向客户提供的服务中断。

有两个工具可以帮助文件系统模块实现通知机制:

  • QTSS_RequestEventFile_Role,当模块(或者服务器)为某个文件对象调用QTSS_RequestEvent回调函数的时候,服务器会调用这个角色进行响应。模块不需要显式注册这个角色。如果模块没有实现异步通知机制,应该在这个角色返回QTSS_RequestFailed。如果模块实现异步通知机制,则应该在这里进行一切必要的准备工作,以便在文件变成可读的时候接收事件。
  • QTSS_SendEventToStream回调函数,在文件变为可读的时候由文件系统模块进行调用。QTSS_SendEventToStream函数告诉服务器应该将文件现在已经可读的消息通知QTSS_RequestEvent函数的调用者。
友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内