Adaptation/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
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>Fair Scheduling and File Caching</title><shortdesc>Describes how to implement and configure the fair scheduling
and file caching features for file systems implementations.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<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><related-links>
<link href="GUID-5B24741C-7CE0-58E8-98C9-1D1CACCD476F.dita"><linktext>Fair
Scheduling and File Caching Background</linktext></link>
</related-links></concept>