Processing requests
The EKA1 version of the file server is single-threaded. This single thread processes all requests, for all drives. When the thread blocks, waiting on an I/O operation on a particular drive, it is unable to process requests for any other drive.
We took the opportunity to improve the file server design in EKA2. It is multi-threaded and allows concurrent access to each drive. As well as the main file server thread, there is normally a thread for each logical drive, and a thread for handling session disconnection. So, for example, while the server is processing a request to write a large block of data to a multimedia file on a removable media drive, it is still able to accept and process a read request to an INI file on the main internal user data drive. This design also enables the file server to support file systems for remote drives. These are drives that are connected to the mobile phone via a network connection. Requests to a remote drive could take a very long time to complete. Such requests block the thread associated with the remote drive, but, because it is multi-threaded, the file server can still access the other drives in the system.
A client using asynchronous requests can have requests outstanding concurrently on more than one drive from a single session. With the multi-threaded scheme, these can truly be handled concurrently. On EKA1, although the client may be given the impression that they are handled concurrently, in fact they are processed sequentially.
Figure 9.5 illustrates the running F32 threads in a Symbian OS phone that has a single drive. The main file server thread initially handles all client requests. It goes on to service those requests that don't require any access to the media device itself and those that won't block a thread, before completing them and returning the result to the client. These requests must not block since this will delay the entire file server from processing new requests.
CSessionFs::ServiceL()
- CSessionFs::Disconnect()
Figure 9.5 The F32 threads
Figure 9.5 The F32 threads
The main thread passes any requests that involve a call down to the file system or that may block to a separate drive thread. We allow requests on drive threads to be "long-running" operations. While these drive threads are busy or blocked handling a request, new requests for the drive are added to a drive-thread queue. In most circumstances, it queues requests in a FIFO order. (There is only one exception to this, which I will talk about later.) All drive threads have the same priority, which is slightly less than that of the main file server thread.
There is a certain overhead in transferring requests to a separate drive thread, and so we avoid this where possible. Some types of drive, such as the ROM drive and the internal RAM drive, never perform "long-running" operations and never block the thread. We designate such drives "synchronous drives'', and process all requests for them in the main file server thread - synchronous drives do not have a separate drive thread. However, even with asynchronous drives, we can handle certain requests without access to the media device itself - for example, requests to set or retrieve information held by the file server. We classify these types of operation as ''synchronous operations'' and the main file server thread always processes these too. (The Boolean member of the TOp-eration class - iIsSync indicates which operations are synchronous; see Figure 9.3.) I will now list some examples of synchronous operations:
As we have seen, when a client closes a session, this can result in the file server having to close down sub-sessions - and this may mean that it has to write to disk. For example, if closing a CFileShare object results in the server closing a CFileCB object too, the server may need to flush the current size of the file to the disk. If the file is on an asynchronous drive, then this will have to be handled by the drive thread. Also, before the file server destroys a session, it needs to clean up any outstanding requests for that session - and these may be queued or in progress on one or more drive threads. In this case, we may need to wait for a drive thread to unblock before the requests can be unqueued. Again, we can't tie up the main file server thread while these session termination operations take place, and this is why we use a separate thread to manage session disconnection.
Figure 9.6 shows a diagram of the server-side classes that deal with the processing of a request.
- Figure 9.6 The F32 server-side classes which perform request processing
Post a comment