Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 74
Текст из файла (страница 74)
Each sub-session class isderived from CFsDispatchObject, which deals with the closing ofthese objects.The CFileCB class represents an open file – the server has to createan instance of this class before access to a particular file is possible.CFileCB contains the full file name (including drive and extensions),the file size, the file attributes and the last time the file was modified.If you look at the previous table, you can see that an RFile objectis actually a handle on a CFileShare rather than a CFileCB. This isbecause many clients may have the same file open, and CFileSharecorresponds to one client’s particular view of the open file.
CFileSharestores the current file position for its client, together with the mode inwhich the file was opened. A CFileCB object remains instantiated bythe server as long as there are one or more CFileShare objects open onit. Once the last share is closed, then the file server closes the CFileCBobject too.To further illustrate the relationship between the CFileCB andCFileShare classes, Figure 9.4 shows two clients, each with files open.Client 1 has a single file open. Client 2 has two files open, but one ofthem is the same as the one opened by Client 1.350THE FILE SERVERclient 2client 1RFileRFsRFileRFsRFilefile serverCSessionFsCSessionFsiHandlesiHandlesCFileShareCFileShareCObjectIxCObjectIxCFileShareCFileCBCFileCBFigure 9.4 The relationship between CFileShare and CFileCB9.3.2Processing requestsThe EKA1 version of the file server is single-threaded.
This single threadprocesses all requests, for all drives. When the thread blocks, waiting onan I/O operation on a particular drive, it is unable to process requests forany other drive.We took the opportunity to improve the file server design in EKA2. Itis multi-threaded and allows concurrent access to each drive.
As well asthe main file server thread, there is normally a thread for each logicaldrive, and a thread for handling session disconnection. So, for example,while the server is processing a request to write a large block of data toa multimedia file on a removable media drive, it is still able to acceptand process a read request to an INI file on the main internal user datadrive. This design also enables the file server to support file systems forremote drives. These are drives that are connected to the mobile phonevia a network connection. Requests to a remote drive could take a verylong time to complete.
Such requests block the thread associated withthe remote drive, but, because it is multi-threaded, the file server can stillaccess the other drives in the system.A client using asynchronous requests can have requests outstandingconcurrently on more than one drive from a single session. With theTHE FILE SERVER351multi-threaded scheme, these can truly be handled concurrently. OnEKA1, although the client may be given the impression that they arehandled concurrently, in fact they are processed sequentially.Figure 9.5 illustrates the running F32 threads in a Symbian OS phonethat has a single drive. The main file server thread initially handles allclient requests.
It goes on to service those requests that don’t require anyaccess to the media device itself and those that won’t block a thread,before completing them and returning the result to the client. Theserequests must not block since this will delay the entire file server fromprocessing new requests.SessiondisconnectthreadCSessionFs::ServiceL()Mainfile serverthreadCSessionFs::Disconnect()DrivethreadFSYFigure 9.5 The F32 threadsThe main thread passes any requests that involve a call down to the filesystem or that may block to a separate drive thread.
We allow requests ondrive threads to be ‘‘long-running’’ operations. While these drive threadsare busy or blocked handling a request, new requests for the drive areadded to a drive-thread queue. In most circumstances, it queues requestsin a FIFO order. (There is only one exception to this, which I will talkabout later.) All drive threads have the same priority, which is slightly lessthan that of the main file server thread.There is a certain overhead in transferring requests to a separate drivethread, and so we avoid this where possible. Some types of drive, suchas the ROM drive and the internal RAM drive, never perform ‘‘longrunning’’ operations and never block the thread.
We designate suchdrives ‘‘synchronous drives’’, and process all requests for them in themain file server thread – synchronous drives do not have a separate drivethread. However, even with asynchronous drives, we can handle certainrequests without access to the media device itself – for example, requests352THE FILE SERVERto set or retrieve information held by the file server. We classify thesetypes of operation as ‘‘synchronous operations’’ and the main file serverthread always processes these too. (The Boolean member of the TOperation class – iIsSync indicates which operations are synchronous;see Figure 9.3.) I will now list some examples of synchronous operations:• RFs::NotifyChange()• RFs::Drive()• RFs::SetSessionPath().As we have seen, when a client closes a session, this can result in the fileserver having to close down sub-sessions – and this may mean that it hasto write to disk. For example, if closing a CFileShare object results inthe server closing a CFileCB object too, the server may need to flushthe current size of the file to the disk.
If the file is on an asynchronousdrive, then this will have to be handled by the drive thread. Also, beforethe file server destroys a session, it needs to clean up any outstandingrequests for that session – and these may be queued or in progress on oneor more drive threads. In this case, we may need to wait for a drive threadto unblock before the requests can be unqueued. Again, we can’t tieup the main file server thread while these session termination operationstake place, and this is why we use a separate thread to manage sessiondisconnection.Figure 9.6 shows a diagram of the server-side classes that deal withthe processing of a request.CFsRequestCRequestThreadiDriveNumber : TIntiScratchValue : TInt64Dispatch()Process()iSessioniListniWaitingLock : RSemaphore1 iListLock : RFastLockReceive()DeliverFront()DeliverBack()iOperationCSessionFsTOperationCFsInternalRequestCDriveThreadiDriveNumber : TIntCFsMessageRequestiMessage : RMessage2CDisconnectThreadiRequest : CFsInternalRequestCFsClientMessageRequestiSrc : TParseiDest : TParseFigure 9.6 The F32 server-side classes which perform request processingTHE FILE SERVER3539.3.2.1 Request objectsThe abstract class, CFsRequest, encapsulates a request within the fileserver, and we use it to pass these requests from one server thread toanother.
The initiating thread, which will either be the main file serverthread or the session disconnect thread, generates a request object. Ifthe initiating thread cannot handle the request, then this delivers it tothe target thread, which will be either a drive thread or the sessiondisconnect thread. The initiating thread may need to store the request inthe target thread’s request queue until it can be processed. CFsRequesthas a reference to the corresponding TOperation object for the request,iOperation. It also has a pointer to the session that originated therequest, iSession, and a member holding the number of the drive onwhich the request is to be performed, iDriveNumber.Most requests come from file server clients. However, the server cangenerate internal requests too:• CancelSessionOp. The session disconnect thread generates thisrequest, and it is delivered to all drive threads, requesting them tocancel any requests they hold for the session being closed• DispatchObjectCloseOp.
This is generated when a sub-sessionobject is closed. As I have already mentioned, sub-session closure canresult in a write to disk. Because of this, sub-session closure has tobe carried out on the correct drive thread for the object. This meansthat the initiating thread must issue a DispatchObjectCloseOprequest to the appropriate drive thread.A separate class derived from CFsRequest represents each different typeof request. CFsMessageRequest encapsulates requests originating froma client, and CFsInternalRequest represents an internal file serverrequest.
Each of these classes has different Complete() methods. Completion of a CFsMessageRequest results in the request-handling threadsignaling back to the client, by calling RMessagePtr2::Complete().Completion of an internal request means that the handling thread willsignal the file server thread that initiated the request.Some client requests involve one or even two file names as arguments, and so CFsClientMessageRequest, derived from CFsMessageRequest is provided. This contains two TParse members to holdthis information. The first such member is iSrc, which is used byrequests which involve a source path name such as RFile::Create()and RFile::Read().