mmappcomponents/harvester/filehandler/src/mpxfolderscanner.cpp
changeset 61 3b098142db83
parent 27 cbb1bfb7ebfb
--- a/mmappcomponents/harvester/filehandler/src/mpxfolderscanner.cpp	Thu Sep 02 20:56:29 2010 +0300
+++ b/mmappcomponents/harvester/filehandler/src/mpxfolderscanner.cpp	Fri Sep 17 08:33:08 2010 +0300
@@ -24,6 +24,7 @@
 
 // CONSTANTS
 const TInt KFileNumBreakCount = 5;
+_LIT( KTxtBackSlash, "\\" );
 
 // ======== LOCAL FUNCTIONS ========
 
@@ -60,7 +61,7 @@
 //
 void CMPXFolderScanner::ConstructL()
     {
-    iDirScan = CDirScan::NewL(iFs);
+
     }
 
 // ---------------------------------------------------------------------------
@@ -88,10 +89,7 @@
 CMPXFolderScanner::~CMPXFolderScanner()
     {
     Cancel();
-    
-    delete iDirScan;
-    delete iDir;
-    
+    iDirQueue.ResetAndDestroy();
     iDrivesToScan.Close();
     }
     
@@ -106,6 +104,7 @@
     // Copy all the other drives we want to scan
     //
     TInt count( aDrives.Count() );
+    MPX_DEBUG2("CMPXFolderScanner::ScanL aDrives %d",count);
     for( TInt i=0; i<count; ++i )
         {
         // Check if we are already scanning this drive
@@ -125,11 +124,10 @@
         if( !SetupNextDriveToScanL() )
             {
             // Kick off the scanning
-            iStatus = KRequestPending;
-            SetActive();
-            TRequestStatus* status = &iStatus;
-            User::RequestComplete( status, KErrNone );
-            
+            iCurDirQueueEntry = iDirQueue[ 0 ];
+            iCurFullPath = iCurDirQueueEntry->iFullPath;
+            ReadDirEntry();
+
             // We've started scanning
             iScanning = ETrue;
             }
@@ -143,6 +141,17 @@
     }
 
 // ---------------------------------------------------------------------------
+// Reads dir entries asynchronously
+// ---------------------------------------------------------------------------
+//
+void CMPXFolderScanner::ReadDirEntry()
+    {
+    ASSERT( !IsActive() );
+    iCurDirQueueEntry->iDir.Read( iCurDirQueueEntry->iEntryArray, iStatus );
+    SetActive();
+    }
+
+// ---------------------------------------------------------------------------
 // Continue Scanning for more files
 // ---------------------------------------------------------------------------
 //
@@ -150,68 +159,83 @@
     {
     MPX_DEBUG1("CMPXFolderScanner::DoScanL <---");
     TBool done (EFalse);
-    
-    // Check each file in each directory
-    TInt numFiles( iDir->Count() );
-    while( iCount < numFiles )
+    TBool blocked ( EFalse );
+
+    // read successfully
+    if ( iStatus == KErrNone || iStatus == KErrEof )
         {
-        TEntry entry = (*iDir)[iCount];
+        TBuf<KMaxFileName> buffer;
+        const TEntry* entry = NULL;
+        TInt numEntries( iCurDirQueueEntry->iEntryArray.Count() );
+
+        // process the entry one by one
+        while ( iCurDirQueueEntry->iPos < numEntries )
+            {
+            entry = iCurDirQueueEntry->NextEntry();
+            buffer.Zero();
+
+            // Generates the full name of the entry
+            buffer.Append( *iCurFullPath );
+            buffer.Append( entry->iName );
+
+            if ( entry->IsDir() ) // entry is a directory
+                {
+                buffer.Append( KTxtBackSlash );
+
+                blocked = iObserver.IsPathBlockedL( buffer );
 
-        // Construct the full path and file name
-        TParse fullEntry;
-        TPtrC dirPath(iDirScan->FullPath());
-        fullEntry.Set(entry.iName, &dirPath, NULL);
-        
-        TPtrC fullname = fullEntry.FullName();
-        TInt index = iObserver.IsMediaFileL( fullname );
-        if( KErrNotFound != index )
-            {
-            iObserver.HandleFileAdditionL( fullname, index );
-            }
-        
-        // Break if we have scanned enough files
-        //
-        ++iCount;
-        if( iCount%KFileNumBreakCount == 0 )
-            {
-            return EFalse;
+                if ( !blocked )
+                    {
+                    CDirQueueEntry* newEntry = CDirQueueEntry::NewL( buffer );
+                    TInt err = newEntry->iDir.Open( iFs,
+                                                    buffer,
+                                             KEntryAttNormal | KEntryAttDir );
+                    if ( err == KErrNone )
+                        {
+                        CDirQueueEntry::PushL( iDirQueue, newEntry );
+                        }
+                    else
+                        {
+                        delete newEntry;
+                        }
+                    }
+                }
+            else // entry is a file
+                {
+                TInt index = iObserver.IsMediaFileL( buffer );
+                if( KErrNotFound != index )
+                    {
+                    iObserver.HandleFileAdditionL( buffer, index );
+                    }
+                }
+            if ( iCurDirQueueEntry->iPos % KFileNumBreakCount == 0 )
+                {
+                return done;
+                }
             }
         }
-    
-    // All files from this directory scanned, so move onto next
-    //
-    TInt err( KErrNone );
-    TBool blocked (EFalse);
-    if( iCount == numFiles )
+
+    // this dir has other entries to read
+    if ( iStatus == KErrNone )
         {
-        // Get next Folder
-        //
-        iCount = 0;          
-        delete iDir;
-        iDir = NULL;
-        do
+        iCurDirQueueEntry->ResetPosition();
+        ReadDirEntry();
+        }
+
+    // there is nothing to read or some error has occured during reading,
+    // try to move to next dir
+    else
+        {
+        CDirQueueEntry::PopAndDestroy( iDirQueue );
+        if ( iDirQueue.Count() || !SetupNextDriveToScanL() )
             {
-            TRAP(err, iDirScan->NextL(iDir));
-            blocked = iObserver.IsPathBlockedL( iDirScan->FullPath() );
-            if( blocked )
-                {
-                delete iDir;
-                iDir = NULL;
-                }
-            if( err == KErrNotReady )
-                {
-                delete iDir;
-                iDir = NULL;
-                break;
-                }
+            iCurDirQueueEntry = iDirQueue[ 0 ];
+            iCurFullPath = iCurDirQueueEntry->iFullPath;
+            ReadDirEntry();
             }
-        while ( err == KErrPathNotFound || blocked );  
-        
-        // No more directories to scan on this drive
-        //
-        if( !iDir )
+        else // there is nothing to scan
             {
-            done = SetupNextDriveToScanL();  
+            done = ETrue;
             }
         }
         
@@ -230,46 +254,44 @@
     TBool done(EFalse);
     TBool blocked(EFalse);
     // Scan next drive
-    while( iDir == NULL && !done )
+    while( iDrivesToScan.Count() && !iDirQueue.Count() )
         {
-        if( !iDrivesToScan.Count() )
+        TPath path = iDrivesToScan[0];
+
+        MPX_DEBUG1( "CMPXFolderScanner::SetupNextDriveToScanL path blocked?" );
+        blocked = iObserver.IsPathBlockedL( path );
+        MPX_DEBUG2( "CMPXFolderScanner::SetupNextDriveToScanL path blocked %i",
+                    blocked );
+
+        // If there was something to scan
+        if( !blocked )
             {
-            // No more drives or folders that we are interested in
-            done = ETrue;
-            }
-        else
-            {
-            iDirScan->SetScanDataL(iDrivesToScan[0], KEntryAttNormal, ESortNone);
-            iCount = 0;
-            TInt err(KErrNone);
-            do
+            CDirQueueEntry* newEntry = CDirQueueEntry::NewL( path );
+            TInt err = newEntry->iDir.Open( iFs,
+                                            path,
+                                            KEntryAttNormal | KEntryAttDir );
+            if ( err == KErrNone )
                 {
-                MPX_DEBUG1("CMPXFolderScanner::SetupNextDriveToScanL iDirScan->NextL()");
-                TRAP(err, iDirScan->NextL(iDir));
-                MPX_DEBUG2("CMPXFolderScanner::SetupNextDriveToScanL path %S", &iDirScan->FullPath());
-                blocked = iObserver.IsPathBlockedL( iDirScan->FullPath() );
-                MPX_DEBUG2("CMPXFolderScanner::SetupNextDriveToScanL path blocked %i", blocked);
-                if( blocked )
-                    {
-                    delete iDir;
-                    iDir = NULL;
-                    }
-                }
-            while (err == KErrPathNotFound || blocked );  
-            
-            // If there was something to scan
-            //
-            if( iDir != NULL )
-                {
+                CDirQueueEntry::PushL( iDirQueue, newEntry );
                 // Inform Observer of the new drive that we are scanning
-                iObserver.HandleOpenDriveL( ::ExtractDrive(iDrivesToScan[0]), 
+                iObserver.HandleOpenDriveL( ::ExtractDrive(iDrivesToScan[0]),
                                             iDrivesToScan[0] );
                 }
-                
-            // Remove the 0th element
-            iDrivesToScan.Remove(0); 
-            iDrivesToScan.Compress();
+            else
+                {
+                delete newEntry;
+                }
             }
+
+        // Remove the 0th element
+        iDrivesToScan.Remove(0);
+        iDrivesToScan.Compress();
+
+        }
+
+    if ( !iDirQueue.Count() )
+        {
+        done = ETrue;
         }
     
     
@@ -287,13 +309,11 @@
     
     // Reset all arrays and data
     iDrivesToScan.Reset();
-    
+    iDirQueue.ResetAndDestroy();
+
     // All done!
     iScanning = EFalse;
-    
-    delete iDir;
-    iDir = NULL;
-    
+
     // Callback to observer
     iStateObserver.HandleScanStateCompleteL( MMPXFileScanStateObserver::EScanFiles, 
                                               aErr );
@@ -319,7 +339,7 @@
         {
         DoScanCompleteL( err );
         }
-    else // if( !done )
+    else if ( iCurDirQueueEntry->iPos ) // if( !done )
         {
         MPX_DEBUG1("CMPXFolderScanner::RunL -- Run again");
         iStatus = KRequestPending;
@@ -353,4 +373,92 @@
     TRAP_IGNORE( DoScanCompleteL( aError ) );
     
     return KErrNone;
-    }        
+    }
+
+// ---------------------------------------------------------------------------
+// Two Phased Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXFolderScanner::CDirQueueEntry* CMPXFolderScanner::CDirQueueEntry::NewL(
+                                                    const TDesC& aFullPath )
+    {
+    CDirQueueEntry* self = new ( ELeave ) CDirQueueEntry;
+    CleanupStack::PushL( self );
+    self->ConstructL( aFullPath );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMPXFolderScanner::CDirQueueEntry::~CDirQueueEntry()
+    {
+    iDir.Close();
+    delete iFullPath;
+    }
+
+// ---------------------------------------------------------------------------
+// Push a dir entry into a dir entry queue
+// ---------------------------------------------------------------------------
+//
+void CMPXFolderScanner::CDirQueueEntry::PushL(
+                                     RPointerArray<CDirQueueEntry>& aDirQueue,
+                                     CDirQueueEntry* aDirEntry )
+    {
+    aDirQueue.AppendL( aDirEntry );
+    }
+
+// ---------------------------------------------------------------------------
+// Pop and destroy a dir entry from a dir entry queue
+// ---------------------------------------------------------------------------
+//
+void CMPXFolderScanner::CDirQueueEntry::PopAndDestroy(
+                                  RPointerArray< CDirQueueEntry >& aDirQueue )
+    {
+    CDirQueueEntry* entry = aDirQueue[ 0 ];
+    delete entry;
+    aDirQueue.Remove( 0 );
+    }
+
+// ---------------------------------------------------------------------------
+// CMPXFolderScanner::CDirQueueEntry::NextEntry
+// ---------------------------------------------------------------------------
+//
+const TEntry* CMPXFolderScanner::CDirQueueEntry::NextEntry()
+    {
+    const TEntry* entry = NULL;
+    if ( iPos >= 0 && iPos < iEntryArray.Count() )
+        {
+        entry = &iEntryArray[ iPos++ ];
+        }
+    return entry;
+    }
+
+// ---------------------------------------------------------------------------
+// Reset the current position of entry array
+// ---------------------------------------------------------------------------
+//
+void CMPXFolderScanner::CDirQueueEntry::ResetPosition()
+    {
+    iPos = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CMPXFolderScanner::CDirQueueEntry::CDirQueueEntry()
+    {
+    // Do nothing
+    }
+
+// ---------------------------------------------------------------------------
+// 2nd Phase Contructor
+// ---------------------------------------------------------------------------
+//
+void CMPXFolderScanner::CDirQueueEntry::ConstructL( const TDesC& aFullPath )
+    {
+    iFullPath = aFullPath.AllocL();
+    }