Symbian3/PDK/Source/GUID-89BCF9A5-ABBD-5523-BA76-FDB00B806A30.dita
author Graeme Price <GRAEME.PRICE@NOKIA.COM>
Fri, 15 Oct 2010 14:32:18 +0100
changeset 15 307f4279f433
parent 14 578be2adaf3e
permissions -rw-r--r--
Initial contribution of the Adaptation Documentation.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-89BCF9A5-ABBD-5523-BA76-FDB00B806A30" xml:lang="en"><title>Migration
Tutorial: Fair Scheduling and File Caching</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>Describes how to implement and configure the <xref href="GUID-5B24741C-7CE0-58E8-98C9-1D1CACCD476F.dita">fair
scheduling and file caching</xref> features for file systems implementations. </p>
<section id="GUID-450D57A3-928B-5389-B941-595DB20A7CEA"><title>Enabling fair
scheduling</title><p>The <codeph>MExtendedFileInterface</codeph> API enables
fair scheduling. The FAT, FAT32 and LFFS file systems support <codeph>MExtendedFileInterface</codeph>,
this API allows requests to be split into one or more segments with the <codeph>aOffset</codeph> parameter.
Support has been built in for large files by changing the file’s position
parameter (<codeph>aPos</codeph>) from a <xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref> to a <xref href="GUID-AAE85115-A8AA-3F6C-BA8C-69F5A23B0D90.dita"><apiname>TInt64</apiname></xref>. </p> <p>To
enable fair scheduling, the file system mounted on a particular drive must
support <xref href="GUID-63DF657C-434D-353D-A536-8AF9D97C8260.dita#GUID-63DF657C-434D-353D-A536-8AF9D97C8260/GUID-E57D0ED6-C351-37F4-8E80-5A64144B6655"><apiname>CFileCB::MExtendedFileInterface</apiname></xref>. The object returned
by <xref href="GUID-0012B043-9FC4-3953-928E-CB6107E0486A.dita#GUID-0012B043-9FC4-3953-928E-CB6107E0486A/GUID-EFDD2A6C-1319-30FC-9FC6-9653E0A2F827"><apiname>CFileSystem::NewFileL()</apiname></xref> must be derived from <codeph>CFileCB</codeph> and <codeph>CFileCB::MExtendedFileInterface</codeph>.
The file server determines whether this is the case by calling <xref href="GUID-63DF657C-434D-353D-A536-8AF9D97C8260.dita#GUID-63DF657C-434D-353D-A536-8AF9D97C8260/GUID-D3628A6F-8E6D-39CA-8D36-EB3BC4154DF2"><apiname>CFileCB::GetInterface</apiname></xref>. </p> <p>The <xref href="GUID-63DF657C-434D-353D-A536-8AF9D97C8260.dita#GUID-63DF657C-434D-353D-A536-8AF9D97C8260/GUID-E57D0ED6-C351-37F4-8E80-5A64144B6655"><apiname>CFileCB::MExtendedFileInterface</apiname></xref> interface is as follows: </p><codeblock id="GUID-27EC7D5D-7BB6-5427-9EF0-71561F7AB847" xml:space="preserve">class MExtendedFileInterface
{
public:
    virtual void ReadL(TInt64 aPos, TInt&amp; aLength, TDes8* aDes, const RMessagePtr2&amp; aMessage, TInt aOffset) = 0;
    virtual void WriteL(TInt64 aPos, TInt&amp; aLength, const TDesC8* aDes, const RMessagePtr2&amp; aMessage, TInt aOffset) = 0;
    virtual void SetSizeL(TInt64 aSize) = 0;
};</codeblock> <p>The file system indicates its support for <codeph>MExtendedFileInterface</codeph> by
intercepting the <xref href="GUID-63DF657C-434D-353D-A536-8AF9D97C8260.dita#GUID-63DF657C-434D-353D-A536-8AF9D97C8260/GUID-F13F53A3-502A-38E4-B8E3-4099DC44EEC0"><apiname>CFileCB::EExtendedFileInterface</apiname></xref> enumeration
in the <xref href="GUID-63DF657C-434D-353D-A536-8AF9D97C8260.dita#GUID-63DF657C-434D-353D-A536-8AF9D97C8260/GUID-CBCFC605-C942-3D4E-8ABA-2EF454E5A44B"><apiname>CFileCB::GetInterface()</apiname></xref> method as in the following
example: </p><codeblock id="GUID-714AB83B-0A24-5E81-92B8-CB425002B426" xml:space="preserve">TInt CFatFileCB::GetInterface(TInt aInterfaceId, TAny*&amp; aInterface, TAny* aInput)
    {
    switch(aInterfaceId)
        {
        case EExtendedFileInterface:
            ((CFileCB::MExtendedFileInterface*&amp;) aInterface) = this;
            return KErrNone;

        //etc.

        default:
            return CFileCB::GetInterface(aInterfaceId, aInterface, aInput);
        }
    }</codeblock> </section>
<section id="GUID-719C7E0C-790B-5C61-9EA8-E2687397340F"><title>Enabling read
and write caching</title><p>To enable caching, the file system must support
reads and writes to local buffers, which are buffers created and owned by
the file server itself rather by a client of the file server. </p><p>The local
media subsystem already supports local messages, but the file system and any
file system extensions need to be examined carefully to ensure that they do
not call any <xref href="GUID-78E0DEDD-C020-3174-AD0A-E4C18C4C9213.dita"><apiname>RMessagePtr2</apiname></xref> methods, otherwise a panic results. </p> <p>The
file server calls <xref href="GUID-FADDE053-CC1C-39BC-A52D-27093041BE20.dita#GUID-FADDE053-CC1C-39BC-A52D-27093041BE20/GUID-239159E5-1A98-3FE1-9A0D-803BEDB99DCE"><apiname>CMountCB::LocalBufferSupport()</apiname></xref> to find
out whether the file system and all file system extensions mounted on a particular
drive fully support local buffers before it enables caching. The file system
handles the <xref href="GUID-FADDE053-CC1C-39BC-A52D-27093041BE20.dita#GUID-FADDE053-CC1C-39BC-A52D-27093041BE20/GUID-87F36D0F-CAA5-35ED-9E99-BB8F7B9564C2"><apiname>CMountCB::ELocalBufferSupport</apiname></xref> enumeration in
its <xref href="GUID-FADDE053-CC1C-39BC-A52D-27093041BE20.dita#GUID-FADDE053-CC1C-39BC-A52D-27093041BE20/GUID-CABEF8F6-637C-3223-80C6-FBC8B7247030"><apiname>CMountCB::GetInterface()</apiname></xref> method and passes the request
on to the first proxy drive, as in the following example: </p><codeblock id="GUID-969BBBAE-5C1F-5032-831D-3C17E58285AE" xml:space="preserve">TInt CFatMountCB::GetInterface(TInt aInterfaceId, TAny*&amp; aInterface, TAny* /*aInput*/) 
    {
    TInt r= KErrNone;
    switch(aInterfaceId)
        {
        // file caching supported, so pass query on to first proxy drive
        case CMountCB::ELocalBufferSupport:
            r = LocalDrive()-&gt;LocalBufferSupport();
            break;
        default:
            r=KErrNotSupported;
        }
    return r;
    }</codeblock> <p>If no file system extensions are loaded, then the query
is eventually handled by <xref href="GUID-F47F56E4-3754-365B-B529-53C1D2A29503.dita#GUID-F47F56E4-3754-365B-B529-53C1D2A29503/GUID-7C0145B1-531A-367C-92DF-61EBB46F01CB"><apiname>CLocalProxyDrive::GetInterface()</apiname></xref>,
which returns <codeph>KErrNone</codeph> to indicate that <xref href="GUID-32659A02-6541-3D15-AB88-B70FBD7DF9B0.dita"><apiname>TBusLocalDrive</apiname></xref> and
the local media sub-system support local buffers. </p> <p>If there are any
file system extensions, they must handle the <xref href="GUID-B0BD0F3D-9081-3DBE-8375-F5000D6D39ED.dita#GUID-B0BD0F3D-9081-3DBE-8375-F5000D6D39ED/GUID-53AC960F-9EE3-3410-9DD6-1BAC08C7B8E8"><apiname>CProxyDrive::ELocalBufferSupport</apiname></xref> enumeration,
as in the following example: </p><codeblock id="GUID-67D3FAA1-9FC3-5653-B21D-73BC13AA36AE" xml:space="preserve">TInt CBitExtProxyDrive::GetInterface(TInt aInterfaceId, TAny*&amp; aInterface, TAny* aInput)
    {
    switch(aInterfaceId)
        {
        // file caching supported, so pass query on to next proxy drive
        case ELocalBufferSupport:
            return CBaseExtProxyDrive::LocalBufferSupport();

        default:
            return CBaseExtProxyDrive::GetInterface(aInterfaceId, aInterface, aInput);
        }       
    }</codeblock> </section>
<section id="GUID-020006B9-1A1E-523B-9CFA-927CDE5D5058"><title>Configuring
caching</title><p>The global and drive-specific cache property defaults are
defined in <filepath>f32\sfile\sf_file_cache_defs.h</filepath>. They may be
overridden for a particular drive by appropriate entries in the Base Starter
component's <filepath>ESTART.TXT</filepath> configuration file. The format
of this file has been enhanced to support the<codeph> .ini</codeph> file style
syntax: </p><codeblock id="GUID-E0DBF04F-8F7E-55E4-8210-D5697A5B3FDB" xml:space="preserve">C: 0  ELOCAL FAT  0       FS_FORMAT_COLD,FS_SYNC_DRIVE     # IRAM
D: 1  ELOCAL FAT  0       FS_SCANDRIVE                     # MMC (textshell)
I: 2  ELOCAL FAT  0       FS_FORMAT_CORRUPT                # NAND - USER DATA
K: 8  ELFFS  LFFS 0       FS_FORMAT_CORRUPT                # LFFS 

[DriveD]
FileCacheSize 256
FairSchedulingLen 128
FileCacheRead ON
FileCacheReadAhead ON
FileCacheWrite ON
ClosedFileKeepAliveTime 3000
DirtyDataFlushTime 3000
FileCacheReadAsync ON

[DriveI]
FileCacheWrite ENABLED

[DriveK]
FileCacheWrite ENABLED

[FileCache]
GlobalCacheEnabled ON
GlobalCacheSize 32768
GlobalCacheMaxLockedSize 1024
LowMemoryThreshold 10</codeblock> <p>In this example, write caching is enabled
on drives I and K and has been turned on by default on drive D.</p><note>Most
of the properties in the example are set to their default values: the definitions
are redundant but are shown for illustrative purposes. </note> <p>For details,
see <xref href="GUID-8BA1EEC2-78A3-54CC-95D9-81BF2659963D.dita">Base Starter Technology</xref>. </p> <p id="GUID-16751410-EFC2-55B8-8BC0-ED5F97F98EBB"><b>Global cache settings</b> </p><p>The
following table holds the global caching properties: </p><table id="GUID-4CBAD2A4-52DE-5BA1-98CC-0B1F6BFC54E1">
<tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/>
<tbody>
<row>
<entry><p> <b>Property</b>  </p> </entry>
<entry><p> <b>Type</b>  </p> </entry>
<entry><p> <b>Comments</b>  </p> </entry>
<entry><p> <b>Default value</b>  </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-91B81C0D-72F9-3226-BEEF-2E8153104102.dita"><apiname>GlobalCacheEnabled</apiname></xref>  </p></entry>
<entry><p>boolean </p></entry>
<entry><p>on or off</p></entry>
<entry><p>on</p></entry>
</row>
<row>
<entry><p> <xref href="GUID-BAC3ED91-7A3A-3255-B22E-6B6C0CB266E0.dita"><apiname>GlobalCacheSize</apiname></xref>  </p></entry>
<entry><p>integer </p> </entry>
<entry><p>Size of disconnected chunk shared by all files in kilobytes.</p></entry>
<entry><p>32768K (32MB) </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-BEE48B25-B374-3348-B97C-BA2D634E0330.dita"><apiname>GlobalCacheMaxLockedSize</apiname></xref>  </p></entry>
<entry><p>integer </p> </entry>
<entry><p>Maximum amount of locked RAM for all files in kilobytes.</p></entry>
<entry><p>1024K (1 MB) </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-36596759-4ABC-3F8E-A09E-97464094A58A.dita"><apiname>LowMemoryThreshold</apiname></xref>  </p></entry>
<entry><p>integer </p></entry>
<entry><p>Low memory threshold expressed as a percentage of total RAM. If
the amount of RAM drops below this value, attempts to allocate memory for
file caching fails.</p></entry>
<entry><p>10% </p> </entry>
</row>
</tbody>
</tgroup>
</table> <p id="GUID-E7F45784-14F2-505C-B21C-0A8010B0B232"><b>File cache settings</b> </p><p>The
properties <xref href="GUID-9278B920-FFEF-3710-8080-B33D028B7A12.dita"><apiname>FileCacheRead</apiname></xref>, <xref href="GUID-33E32FCF-9E02-3254-A9DA-3A6D0B1A52B5.dita"><apiname>FileCacheReadAhead</apiname></xref> and <xref href="GUID-C869ED9F-7F9D-33BC-A1C2-5E21B50A6BFC.dita"><apiname>FileCacheWrite</apiname></xref> may
each be in one of 3 states: </p><ul>
<li id="GUID-71396310-22E1-564A-A094-3EED4721688D"><p> <codeph>OFF</codeph> -
file caching is permanently off and cannot be turned on.</p> </li>
<li id="GUID-032E8EB7-4291-5276-852E-BD910CEC8633"><p> <codeph>ENABLED</codeph> -
file caching is off by default but may be turned on using an appropriate file
open mode, such as <xref href="GUID-4310DC20-300C-3FEB-B1A5-DBA37D5FC940.dita"><apiname>EFileReadBuffered</apiname></xref>  </p> </li>
<li id="GUID-2644023A-855F-5BDE-8A43-57A534E3367A"><p> <codeph>ON</codeph> -
file caching is on by default but may be turned off using an appropriate file
open mode, such as <xref href="GUID-449D6D3A-3F00-35F6-BDFB-DF957F98CA8B.dita"><apiname>EFileReadDirectIO</apiname></xref>. </p> </li>
</ul><p>See <xref href="GUID-3FEEFC4D-19B5-502A-8310-40646B9C34BC.dita">Run time
cache settings</xref>. </p><p>If <xref href="GUID-7F7B7C49-5F60-3B10-A241-98306795A768.dita"><apiname>FileCacheReadAsync</apiname></xref> is
set, media driver reads on this drive are asynchronous. This results in read
ahead requests being issued before completing a client read request. However,
if <codeph>FileCacheReadAsync</codeph> is OFF, then media driver reads on
this drive are synchronous. So, issuing a read ahead is likely to block any
client thread that is normally running at lower priority than the media driver's
thread. In this case read ahead requests only happen during periods of inactivity
to improve latency. </p><table id="GUID-B022918E-9335-5D44-B029-D48B36E45937">
<tgroup cols="4"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/><colspec colname="col3"/>
<tbody>
<row>
<entry><p> <b>Property</b>  </p> </entry>
<entry><p> <b>Type</b>  </p> </entry>
<entry><p> <b>Comments</b>  </p> </entry>
<entry><p> <b>Default value</b>  </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-3B777E89-8E4C-3540-958F-C621741895C8.dita"><apiname>FileCacheSize</apiname></xref>  </p> </entry>
<entry><p>integer </p> </entry>
<entry><p>Maximum amount of locked or unlocked RAM per file.</p></entry>
<entry><p>128K </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-23E2F01D-BD7B-39D3-B7B2-F23E20D273C5.dita"><apiname>FairSchedulingLen</apiname></xref>  </p> </entry>
<entry><p>integer </p> </entry>
<entry><p>Read &amp; write requests greater than this length are split up
into 2 or more requests.</p></entry>
<entry><p>128K </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-9278B920-FFEF-3710-8080-B33D028B7A12.dita"><apiname>FileCacheRead</apiname></xref>  </p></entry>
<entry><p>string </p></entry>
<entry><p>OFF, ENABLED or ON.</p></entry>
<entry><p>ENABLED </p></entry>
</row>
<row>
<entry><p> <xref href="GUID-33E32FCF-9E02-3254-A9DA-3A6D0B1A52B5.dita"><apiname>FileCacheReadAhead</apiname></xref>  </p></entry>
<entry><p>string </p></entry>
<entry><p>OFF, ENABLED or ON.</p></entry>
<entry><p>ON </p></entry>
</row>
<row>
<entry><p> <xref href="GUID-C869ED9F-7F9D-33BC-A1C2-5E21B50A6BFC.dita"><apiname>FileCacheWrite</apiname></xref>  </p></entry>
<entry><p>string </p></entry>
<entry><p>OFF, ENABLED or ON.</p></entry>
<entry><p>ENABLED </p></entry>
</row>
<row>
<entry><p> <xref href="GUID-7F7B7C49-5F60-3B10-A241-98306795A768.dita"><apiname>FileCacheReadAsync</apiname></xref>  </p> </entry>
<entry><p>boolean </p> </entry>
<entry><p>ON or OFF. If set, media driver reads on this drive are asynchronous.</p></entry>
<entry><p>OFF </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-A91BE0A1-A79D-3828-9E86-7850839BBFE9.dita"><apiname>ClosedFileKeepAliveTime</apiname></xref>  </p> </entry>
<entry><p>integer </p> </entry>
<entry><p>Time after which a file is removed from the closed file queue, in
milliseconds. </p></entry>
<entry><p>3000ms (3 secs) </p> </entry>
</row>
<row>
<entry><p> <xref href="GUID-78907F25-9D0F-3B76-BDB0-514FC22CAECA.dita"><apiname>DirtyDataFlushTime</apiname></xref>  </p> </entry>
<entry><p>integer </p> </entry>
<entry><p>Time after which a file containing dirty data is flushed, in milliseconds.</p></entry>
<entry><p>3000ms (3 secs) </p> </entry>
</row>
</tbody>
</tgroup>
</table> </section>
</conbody></concept>