Ejemplo n.º 1
0
        internal override void ImportThreadMain(string sourceDbPath,
                                                VolumeDatabase targetDb,
                                                string dbDataPath,
                                                BufferedVolumeItemWriter writer)
        {
            this.counters = new long[3];
            //idCounter = 2; // id 1 is the root item
            //totalMedia = 0;
            this.path           = new Stack <string>();
            this.mimePathPrefix = GetNonExistingPath() + "/";
            this.targetDb       = targetDb;
            this.writer         = writer;

            using (GZipStream s = new GZipStream(File.OpenRead(sourceDbPath), CompressionMode.Decompress)) {
                XmlReaderSettings settings = new XmlReaderSettings()
                {
                    DtdProcessing   = DtdProcessing.Ignore,
                    ValidationType  = ValidationType.None,
                    CheckCharacters = false
                };

                XmlReader reader = XmlTextReader.Create(s, settings);

                XmlDocument xml = new XmlDocument();
                xml.Load(reader);

                string        dummy1 = null;
                MetadataStore dummy2 = MetadataStore.Empty;

                RecursiveDump(xml.DocumentElement, 0L, 0L, ref dummy1, ref dummy1, ref dummy2);
            }
        }
Ejemplo n.º 2
0
        private static void ImportFile(IDataReader reader,
                                       long volumeID,
                                       long minFileID,
                                       string rootPath,
                                       MetadataStore metaData,
                                       VolumeDatabase db,
                                       BufferedVolumeItemWriter writer,
                                       long[] counters)
        {
            FileSystemVolumeItem item;

            if ((string)reader["type"] == "directory")
            {
                item = new DirectoryVolumeItem(db);
                counters[TOTAL_DIRS]++;
            }
            else
            {
                item = new FileVolumeItem(db);
                long size = (long)reader["size"];

                ((FileVolumeItem)item).SetFileVolumeItemFields(size, null);
                counters[TOTAL_FILES]++;
                counters[TOTAL_SIZE] += size;
            }

            string path = (string)reader["path"];

            Debug.Assert(path.StartsWith("file://"), "path starts with 'file://'");

            string name = (string)reader["name"];

            string location = DecoderUtility.UrlDecode(path);

            location = location.Substring(rootPath.Length);
            location = location.Substring(0, location.Length - name.Length - 1);

            if (location.Length == 0)
            {
                location = "/";
            }

            long itemID   = 2 + (long)reader["id"] - minFileID;           // id 1 is the root item
            long parentID = Math.Max(1, 2 + (long)reader["idparent"] - minFileID);

            item.SetFileSystemVolumeItemFields(location,
                                               DateTime.MinValue,
                                               VolumeDatabase.ID_NONE);
            item.SetVolumeItemFields(volumeID,
                                     itemID,
                                     parentID,
                                     name,
                                     Util.ReplaceDBNull <string>(reader["mime"], null),
                                     metaData,
                                     Util.ReplaceDBNull <string>(reader["comment"], null),
                                     null);

            writer.Write(item);
        }
Ejemplo n.º 3
0
        private long InsertFile(string rootPath,
                                FileInfo file,
                                BufferedVolumeItemWriter writer,
                                long parentID,
                                string mimeType,
                                MetadataStore metaData,
                                string hash)
        {
            /* if scanner has no db associated, just update the counters
             * and return
             */
            if (!this.HasDB)
            {
                Interlocked.Increment(ref VolumeInfo.files);
                Interlocked.Add(ref VolumeInfo.size, file.Length);
                return(VolumeDatabase.ID_NONE);
            }

            DateTime lastWriteTime = GetLastWriteTime(file);

            FileVolumeItem item = GetNewVolumeItem <FileVolumeItem>(parentID,
                                                                    file.Name,
                                                                    mimeType,
                                                                    metaData,
                                                                    VolumeItemType.FileVolumeItem);

            item.SetFileSystemVolumeItemFields(GetLocation(file.FullName, rootPath),
                                               lastWriteTime,
                                               VolumeDatabase.ID_NONE);

            item.SetFileVolumeItemFields(file.Length, hash);
            //item.Name = file.Name; // set the items name (defined on VolumeItem baseclass)

            writer.Write(item);

            Interlocked.Increment(ref VolumeInfo.files);
            Interlocked.Add(ref VolumeInfo.size, file.Length);

            if (!Options.DiscardSymLinks)
            {
                symLinkHelper.AddFile(file.FullName, item.ItemID);
            }

            return(item.ItemID);
        }
Ejemplo n.º 4
0
        public WaitHandle RunAsync()
        {
            if (isRunning)
            {
                throw new InvalidOperationException("Scanner is already running");
            }

            if (scanSucceeded)
            {
                throw new InvalidOperationException("Scanning has been completed successfully. Create a new scanner to scan another volume");
            }

            try {
                /* must be set (as soon as possible) in a function that is _not_ called asynchronously
                 * (i.e. dont call it in ScanningThread()) */
                isRunning             = true;
                cancellationRequested = false;
                asyncOperation        = AsyncOperationManager.CreateOperation(null);

                Reset();

                BufferedVolumeItemWriter writer = null;
                if (this.HasDB)
                {
                    writer = new BufferedVolumeItemWriter(database, true, Options.BufferSize);
                }

                /* invoke the scanning function on a new thread and return a waithandle */
                Action <PlatformIO.DriveInfo, TVolume, BufferedVolumeItemWriter> st = ScanningThread;
                IAsyncResult ar = st.BeginInvoke(drive, volume, writer, null, null);
                return(ar.AsyncWaitHandle);
            } catch (Exception) {
                isRunning = false;

                if (asyncOperation != null)
                {
                    asyncOperation.OperationCompleted();
                }

                throw;
            }
        }
Ejemplo n.º 5
0
        internal override void ScanningThreadMain(Platform.Common.IO.DriveInfo drive,
                                                  FileSystemVolume volume,
                                                  BufferedVolumeItemWriter writer)
        {
            try {
                if (Options.GenerateThumbnails)
                {
                    paths.volumeDataPath = DbData.CreateVolumeDataPath(paths.dbDataPath, volume.VolumeID);
                    paths.thumbnailPath  = DbData.CreateVolumeDataThumbsPath(paths.volumeDataPath);
                }

                string rootPath = drive.RootPath;
                // remove possible ending path seperator except for _system_ root paths
                rootPath = RemoveEndingSlash(rootPath);
                //			  if ((rootPath.Length > 1) && (rootPath[rootPath.Length - 1] == Path.DirectorySeparatorChar))
                //				  rootPath = rootPath.Substring(0, rootPath.Length - 1);

                // make sure the root path exists
                // (media may have been removed after scanner construction)
                if (!Directory.Exists(rootPath))
                {
                    throw new DirectoryNotFoundException("Root path does not exist");
                }

                DirectoryInfo dir = new DirectoryInfo(rootPath);
                RecursiveDump(rootPath, dir, writer, VolumeDatabase.ID_NONE);
                symLinkHelper.InsertSymLinkItems(writer, volume.VolumeID);

                volume.SetFileSystemVolumeFields(VolumeInfo.Files, VolumeInfo.Directories, VolumeInfo.Size);
            } catch (Exception) {
                // try to cleanup
                try {
                    if ((paths.volumeDataPath != null) && Directory.Exists(paths.volumeDataPath))
                    {
                        Directory.Delete(paths.volumeDataPath, true);
                    }
                } catch (Exception) { /* just shut up */ }

                // rethrow initial exception
                throw;
            }
        }
Ejemplo n.º 6
0
        internal override void ScanningThreadMain(PlatformIO.DriveInfo drive,
                                                  AudioCdVolume volume,
                                                  BufferedVolumeItemWriter writer)
        {
            if (Options.ComputeHashs)
            {
                SendScannerWarning(S._("Hashcode generation not implemented for audio cds yet."));

                volume.IsHashed = false;
            }

            AudioCdRootVolumeItem root = GetNewVolumeItem <AudioCdRootVolumeItem>(VolumeDatabase.ID_NONE,
                                                                                  "/",
                                                                                  null,
                                                                                  MetadataStore.Empty,
                                                                                  VolumeItemType.AudioCdRootVolumeItem);

            LocalDisc localdisc = LocalDisc.GetFromDevice(drive.Device);

            if (localdisc == null)
            {
                throw new ApplicationException("Could not read contents of the audio cd");
            }

            TimeSpan[] durations = localdisc.GetTrackDurations();
            List <AudioTrackVolumeItem> items = new List <AudioTrackVolumeItem>();

            for (int i = 0; i < durations.Length; i++)
            {
                AudioTrackVolumeItem item = GetNewVolumeItem <AudioTrackVolumeItem>(root.ItemID,
                                                                                    "Track " + (i + 1),
                                                                                    MIME_TYPE_AUDIO_TRACK,
                                                                                    MetadataStore.Empty,
                                                                                    VolumeItemType.AudioTrackVolumeItem);
                item.SetAudioTrackVolumeItemFields(durations[i]);

                items.Add(item);

                VolumeInfo.Tracks++;
                VolumeInfo.Duration = VolumeInfo.Duration.Add(durations[i]);
            }

            // retrieve musicbrainz metadata
            // (the metadata field of AudioTrackVolumeItems is set
            // depending on the EnableMusicBrainz flag)
            if (Options.EnableMusicBrainz)
            {
                try {
                    // may throw MusicBrainzNotFoundException
                    Release release = Release.Query(localdisc).PerfectMatch();

                    CheckForCancellationRequest();

                    if (release == null)
                    {
                        SendScannerWarning(S._("No MusicBrainz metadata available for this disc."));
                    }
                    else
                    {
                        var tracks = release.GetTracks();

                        if (tracks.Count != items.Count)
                        {
                            SendScannerWarning(S._("The trackcount retrieved from MusicBrainz does not match the trackcount of the local disc. Skipped."));
                        }
                        else
                        {
                            string albumTitle  = release.GetTitle();
                            int    releaseYear = GetReleaseYear(release);

                            for (int i = 0; i < tracks.Count; i++)
                            {
                                items[i].Name     = tracks[i].GetTitle();
                                items[i].MetaData = GetMetadata(tracks[i], albumTitle, releaseYear);
                            }

                            volume.Title = albumTitle;

                            // preset category
                            ReleaseType rtype = release.GetReleaseType();
                            if (rtype == ReleaseType.Album ||
                                rtype == ReleaseType.EP ||
                                rtype == ReleaseType.Compilation ||
                                rtype == ReleaseType.Remix)
                            {
                                volume.Category = PRESELECTED_CATEGORY;
                            }
                        }
                    }
                } catch (MusicBrainzNotFoundException) {
                    SendScannerWarning(S._("Error connecting to MusicBrainz server."));
                }
            }

            volume.SetAudioCdVolumeFields(VolumeInfo.Tracks, VolumeInfo.Duration);

            // write items
            if (this.HasDB)
            {
                writer.Write(root);

                foreach (AudioTrackVolumeItem item in items)
                {
                    writer.Write(item);
                }
            }
        }
Ejemplo n.º 7
0
        private void ImportThread(string sourceDbPath,
                                  VolumeDatabase targetDb,
                                  string dbDataPath,
                                  int buferSize)
        {
            Exception fatalError = null;
            bool      cancelled  = false;

            try {
                // must be the first call within the try block
                targetDb.TransactionBegin();                 // locks VolumeDatabase

                if (!File.Exists(sourceDbPath))
                {
                    throw new FileNotFoundException("Source database not found");
                }

                // note:
                // don't use the writer in a using() block here as dispose() would write
                // buffered items after an exception has been thrown.
                BufferedVolumeItemWriter writer = new BufferedVolumeItemWriter(targetDb, true, bufferSize);

                ImportThreadMain(sourceDbPath,
                                 targetDb,
                                 dbDataPath,
                                 writer);

                writer.Close();

                targetDb.TransactionCommit();                 // unlocks VolumeDatabase
                importSucceeded = true;
            } catch (Exception ex) {
                Exception cleanupException = null;
                try {
                    targetDb.TransactionRollback();                      // unlocks VolumeDatabase

                    foreach (string path in volumeDataPaths)
                    {
                        Directory.Delete(path, true);
                    }
                } catch (Exception e) {
                    cleanupException = e;
                }

                if (ex is ImportCancelledException)
                {
                    cancelled = true;
                }
                else
                {
                    /* save the error that caused the import to stop (import failure) */
                    fatalError = ex;
                    PostError(ex);

                    Debug.WriteLine("Details for exception in ImportThread():\n" + ex.ToString());
                }

                // in case an error occured while cleaning up,
                // post the error here, _after_ the initial error that made the import fail.
                if (cleanupException != null)
                {
                    PostError(cleanupException);
                }

//#if THROW_EXCEPTIONS_ON_ALL_THREADS
//				  if (!(ex is ScanCancelledException))
//					  throw;
//#endif
            } finally {
                isRunning = false;
                PostCompleted(fatalError, cancelled);
            }
        }
Ejemplo n.º 8
0
 abstract void ImportThreadMain(string sourceDbPath,
                                VolumeDatabase targetDb,
                                string dbDataPath,
                                BufferedVolumeItemWriter writer);
Ejemplo n.º 9
0
        internal override void ImportThreadMain(string sourceDbPath,
                                                VolumeDatabase targetDb,
                                                string dbDataPath,
                                                BufferedVolumeItemWriter writer)
        {
            string thumbsPath = sourceDbPath + "_thumbs";

            string sqlDisks = "SELECT * FROM disks ORDER BY id";
            string sqlFiles = "SELECT * FROM files WHERE iddisk = {0} ORDER BY iddisk, id";

            using (IDbConnection conn = SqliteDB.Open(sourceDbPath, false)) {
                long totalFiles  = CountFiles(conn);
                long fileCounter = 0;

                using (IDbCommand cmdDisks = conn.CreateCommand()) {
                    using (IDbCommand cmdFiles = conn.CreateCommand()) {
                        cmdDisks.CommandText = sqlDisks;

                        using (IDataReader readerDisks = cmdDisks.ExecuteReader()) {
                            while (readerDisks.Read())
                            {
                                long   diskID    = (long)readerDisks["id"];
                                long   minFileID = GetMinFileID(conn, diskID);
                                string rootPath  = "file://" + (string)readerDisks["root"];
                                long   volumeID  = targetDb.GetNextVolumeID();
                                long[] counters  = { 0L, 0L, 0L };

                                string volDBThumbsPath = CreateThumbsDir(dbDataPath, volumeID);

                                cmdFiles.CommandText = string.Format(sqlFiles, diskID);

                                using (IDataReader readerFiles = cmdFiles.ExecuteReader()) {
                                    while (readerFiles.Read())
                                    {
                                        long fileID = (long)readerFiles["id"];

                                        ImportFile(readerFiles,
                                                   volumeID,
                                                   minFileID,
                                                   rootPath,
                                                   ConvertMetaData(conn, fileID),
                                                   targetDb,
                                                   writer,
                                                   counters);

                                        ImportThumb(fileID,
                                                    (2 + fileID - minFileID),
                                                    thumbsPath,
                                                    volDBThumbsPath);

                                        PostProgressUpdate((++fileCounter * 100.0) / totalFiles);
                                        CheckForCancellationRequest();
                                    }
                                }

                                ImportDisk(readerDisks,
                                           volumeID,
                                           targetDb,
                                           counters);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 10
0
        private long InsertDir(string rootPath,
                               DirectoryInfo dir,
                               BufferedVolumeItemWriter writer,
                               long parentID)
        {
            /* if scanner has no db associated, just update the counters
             * and return */
            if (!this.HasDB)
            {
                // TODO :
                // increase dircounter for symlink to dirs as well?
                // nautilus refers to selected symlinks to dirs as dirs too.
                Interlocked.Increment(ref VolumeInfo.directories);
                return(VolumeDatabase.ID_NONE);
            }

            string location;
            string name;

            /* if parentID is ID_NONE, the directory is the volumes root dir
             * -> location = null, name = "/" (analog System.IO.DirectoryInfo)
             */
            if (parentID == VolumeDatabase.ID_NONE)
            {
                location = null;
                name     = PATH_SEPARATOR.ToString();
            }
            else
            {
                location = GetLocation(dir.FullName, rootPath);
                name     = dir.Name;
            }

            DateTime lastWriteTime = GetLastWriteTime(dir);

            DirectoryVolumeItem item = GetNewVolumeItem <DirectoryVolumeItem>(parentID,
                                                                              name,
                                                                              MIME_TYPE_DIRECTORY,
                                                                              MetadataStore.Empty,
                                                                              VolumeItemType.DirectoryVolumeItem);

            item.SetFileSystemVolumeItemFields(location, lastWriteTime, VolumeDatabase.ID_NONE);
            //item.Name = name; // set the items name (defined on VolumeItem baseclass)

//			  if (isSymlink) {
//				  /* don't dump symlink dirs directly into the database,
//				   * they're required to have a target item assigned.
//				   * target items are resolved in an additional step.
//				   */
//				   symLinkItems.add(symLinkTarget, item);
//			  } else {
            writer.Write(item);
//			  }

            // TODO :
            // increase dircounter for symlink to dirs as well?
            // nautilus refers to selected symlinks to dirs as dirs too.
            Interlocked.Increment(ref VolumeInfo.directories);

            if (!Options.DiscardSymLinks)
            {
                symLinkHelper.AddFile(dir.FullName, item.ItemID);
            }

            return(item.ItemID);
        }
Ejemplo n.º 11
0
 abstract void ScanningThreadMain(PlatformIO.DriveInfo drive,
                                  TVolume volume,
                                  BufferedVolumeItemWriter writer);
Ejemplo n.º 12
0
        private void ImportThread(string sourceDbPath,
		                          VolumeDatabase targetDb,
		                          string dbDataPath,
		                          int buferSize)
        {
            Exception fatalError = null;
            bool cancelled = false;

            try {
                // must be the first call within the try block
                targetDb.TransactionBegin(); // locks VolumeDatabase

                if (!File.Exists(sourceDbPath))
                    throw new FileNotFoundException("Source database not found");

                // note:
                // don't use the writer in a using() block here as dispose() would write
                // buffered items after an exception has been thrown.
                BufferedVolumeItemWriter writer = new BufferedVolumeItemWriter(targetDb, true, bufferSize);

                ImportThreadMain(sourceDbPath,
                                 targetDb,
                                 dbDataPath,
                                 writer);

                writer.Close();

                targetDb.TransactionCommit(); // unlocks VolumeDatabase
                importSucceeded = true;

            } catch (Exception ex) {

                Exception cleanupException = null;
                try {
                    targetDb.TransactionRollback();  // unlocks VolumeDatabase

                    foreach (string path in volumeDataPaths)
                        Directory.Delete(path, true);
                } catch (Exception e) {
                    cleanupException = e;
                }

                if (ex is ImportCancelledException) {
                    cancelled = true;
                } else {
                    /* save the error that caused the import to stop (import failure) */
                    fatalError = ex;
                    PostError(ex);

                    Debug.WriteLine("Details for exception in ImportThread():\n" + ex.ToString());
                }

                // in case an error occured while cleaning up,
                // post the error here, _after_ the initial error that made the import fail.
                if (cleanupException != null) {
                    PostError(cleanupException);
                }

            //#if THROW_EXCEPTIONS_ON_ALL_THREADS
            //				  if (!(ex is ScanCancelledException))
            //					  throw;
            //#endif
            } finally {
                isRunning = false;
                PostCompleted(fatalError, cancelled);
            }
        }
Ejemplo n.º 13
0
        // TODO : make this member internally protected in case this language feature has become real
        // see http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=33c53cf6-2709-4cc9-a408-6cafee4313ef
        //protected
        internal abstract void ImportThreadMain(string sourceDbPath,
			                               VolumeDatabase targetDb, 
			                               string dbDataPath,
			                               BufferedVolumeItemWriter writer);
Ejemplo n.º 14
0
            public void InsertSymLinkItems(BufferedVolumeItemWriter writer, long volumeID)
            {
                if (symLinkItems.Count == 0)
                {
                    return;
                }

                /* if scanner has no db associated, just update the counters
                 * and return */
                if (!scanner.HasDB)
                {
                    foreach (SymLinkItem sli in symLinkItems)
                    {
                        if (sli.isDir)
                        {
                            Interlocked.Increment(ref scanner.VolumeInfo.directories);
                        }
                        else
                        {
                            Interlocked.Increment(ref scanner.VolumeInfo.files);
                        }

                        // TODO :
                        // increase totalsize by size of symlinks too? (not size of target!)
                        // or are symlinks as big as dirs, those aren't respected as well..
                        //Interlocked.Add(ref VolumeInfo.size, sli.size);
                    }
                    return;
                }

                // make sure all files/dirs have been written to the database
                // before searching for symlink targets.
                writer.Flush();

                foreach (SymLinkItem sli in symLinkItems)
                {
                    scanner.CheckForCancellationRequest();

                    long itemID;
                    if (!files.TryGetValue(sli.fullTargetPath, out itemID))
                    {
                        /* may throw ScanCancelledException */
                        scanner.SendScannerWarning(string.Format(S._("Failed to resolve target item for symlink '{0}'."),
                                                                 sli.fullPath));
                    }
                    else
                    {
                        SearchCriteriaGroup g = new SearchCriteriaGroup(MatchRule.AllMustMatch);
                        g.AddSearchCriteria(new IDSearchCriteria(volumeID, IDSearchField.VolumeID, CompareOperator.Equal));
                        g.AddSearchCriteria(new IDSearchCriteria(itemID, IDSearchField.ItemID, CompareOperator.Equal));

                        // query target item.
                        // async BeginItemSearch() won't work here
                        // (active transaction prevents other threads from accessing the database)
                        VolumeItem[] queriedItems = scanner.Database.SearchItem(g);

                        FileSystemVolumeItem targetItem = (FileSystemVolumeItem)queriedItems[0];
                        FileSystemVolumeItem newItem;

                        if (targetItem is FileVolumeItem)
                        {
                            newItem = scanner.GetNewVolumeItem <FileVolumeItem>(sli.parentID,
                                                                                sli.name,
                                                                                targetItem.MimeType,
                                                                                targetItem.MetaData,
                                                                                VolumeItemType.FileVolumeItem);

                            ((FileVolumeItem)newItem).SetFileVolumeItemFields(((FileVolumeItem)targetItem).Size,
                                                                              ((FileVolumeItem)targetItem).Hash);

                            Interlocked.Increment(ref scanner.VolumeInfo.files);
                        }
                        else                             // DirectoryVolumeItem
                        {
                            newItem = scanner.GetNewVolumeItem <DirectoryVolumeItem>(sli.parentID,
                                                                                     sli.name,
                                                                                     targetItem.MimeType,
                                                                                     targetItem.MetaData,
                                                                                     VolumeItemType.DirectoryVolumeItem);

                            Interlocked.Increment(ref scanner.VolumeInfo.directories);
                        }

                        newItem.SetFileSystemVolumeItemFields(sli.location,
                                                              targetItem.LastWriteTime,
                                                              targetItem.ItemID);

                        writer.Write(newItem);

                        // TODO :
                        // increase totalsize by size of symlinks too? (not size of target!)
                        // or are symlinks as big as dirs, those aren't respected as well..
                        //Interlocked.Add(ref VolumeInfo.size, sli.size);
                        if (Global.EnableDebugging)
                        {
                            Debug.WriteLine("Successfully resolved and saved symlink item: {0}/{1} -> {2}/{3}",
                                            (sli.location == PATH_SEPARATOR.ToString() ? "" : sli.location),
                                            sli.name,
                                            (targetItem.Location == PATH_SEPARATOR.ToString() ? "" : targetItem.Location),
                                            (targetItem.Name == PATH_SEPARATOR.ToString() ? "" : targetItem.Name));
                        }
                    }             // end if
                }                 // end foreach
            }
Ejemplo n.º 15
0
        private static void ImportFile(IDataReader reader,
		                               long volumeID,
		                               long minFileID,
		                               string rootPath,
		                               MetadataStore metaData,
		                               VolumeDatabase db,
		                               BufferedVolumeItemWriter writer,
		                               long[] counters)
        {
            FileSystemVolumeItem item;

            if ((string)reader["type"] == "directory") {
                item = new DirectoryVolumeItem(db);
                counters[TOTAL_DIRS]++;
            } else {
                item = new FileVolumeItem(db);
                long size = (long)reader["size"];

                ((FileVolumeItem)item).SetFileVolumeItemFields(size, null);
                counters[TOTAL_FILES]++;
                counters[TOTAL_SIZE] += size;
            }

            string path = (string)reader["path"];
            Debug.Assert(path.StartsWith("file://"), "path starts with 'file://'");

            string name = (string)reader["name"];

            string location = DecoderUtility.UrlDecode(path);
            location = location.Substring(rootPath.Length);
            location = location.Substring(0, location.Length - name.Length - 1);

            if (location.Length == 0)
                location = "/";

            long itemID = 2 + (long)reader["id"] - minFileID; // id 1 is the root item
            long parentID = Math.Max(1, 2 + (long)reader["idparent"] - minFileID);

            item.SetFileSystemVolumeItemFields(location,
                                               DateTime.MinValue,
                                               VolumeDatabase.ID_NONE);
            item.SetVolumeItemFields(volumeID,
                                     itemID,
                                     parentID,
                                     name,
                                     Util.ReplaceDBNull<string>(reader["mime"], null),
                                     metaData,
                                     Util.ReplaceDBNull<string>(reader["comment"], null),
                                     null);

            writer.Write(item);
        }
Ejemplo n.º 16
0
        private void ScanningThread(PlatformIO.DriveInfo drive,
                                    TVolume volume,
                                    BufferedVolumeItemWriter writer)
        {
            TVolume   returnVolume = null;
            Exception fatalError   = null;
            bool      cancelled    = false;

            try {
                if (this.HasDB)
                {
                    Database.TransactionBegin();                      // locks VolumeDatabase
                }
                ScanningThreadMain(drive, volume, writer);
                if (this.HasDB)
                {
                    writer.Close();
                    if (!volume.IsInserted)
                    {
                        volume.InsertIntoDB();
                    }

                    returnVolume = volume;

                    database.TransactionCommit();                     // unlocks VolumeDatabase
                }

                //result = ScanningResult.Success;
                scanSucceeded = true;
            } catch (Exception ex) {
                Exception rollbackException = null;
                try {
                    // rollback all database changes
                    if (this.HasDB)
                    {
                        database.TransactionRollback();                         // unlocks VolumeDatabase
                    }
                } catch (Exception e) {
                    rollbackException = e;
                }


                if (ex is ScanCancelledException)
                {
                    //result = ScanningResult.Cancelled;
                    cancelled = true;
                }
                else
                {
                    //result = ScanningResult.FatalError;

                    /* save the error that caused the scanner to stop (scanning failure) */
                    fatalError = ex;
                    //OnError(new ErrorEventArgs(ex));
                    PostError(ex);

                    Debug.WriteLine("Details for exception in ScanningThread():\n" + ex.ToString());
                }

                // in case an error occured while rollig back,
                // post the error here, _after_ the initial error that made the scan fail.
                if (rollbackException != null)
                {
                    //OnError(new ErrorEventArgs(rollbackException));
                    PostError(rollbackException);
                }

//#if THROW_EXCEPTIONS_ON_ALL_THREADS
//				  if (!(ex is ScanCancelledException))
//					  throw;
//#endif
            } finally {
                /*
                 * TODO : unlock db / thread // (in try / catch / PostError !!) */

                //if (result == ScanningResult.Success)
                //	  m_scanSucceeded = true;

                //m_cancellationRequested = false;
                isRunning = false;

                //try { OnScanCompleted(new ScanCompletedEventArgs(result, mediaID, fatalError)); }
                //catch (Exception e) { OnError(new ErrorEventArgs(e)); }

                PostCompleted(returnVolume, fatalError, cancelled);
            }
        }
Ejemplo n.º 17
0
        internal override void ImportThreadMain(string sourceDbPath,
		                                         VolumeDatabase targetDb,
		                                         string dbDataPath,
		                                         BufferedVolumeItemWriter writer)
        {
            string thumbsPath = sourceDbPath + "_thumbs";

            string sqlDisks = "SELECT * FROM disks ORDER BY id";
            string sqlFiles = "SELECT * FROM files WHERE iddisk = {0} ORDER BY iddisk, id";

            using (IDbConnection conn = SqliteDB.Open(sourceDbPath, false)) {

                long totalFiles = CountFiles(conn);
                long fileCounter = 0;

                using (IDbCommand cmdDisks = conn.CreateCommand()) {
                    using (IDbCommand cmdFiles = conn.CreateCommand()) {

                        cmdDisks.CommandText = sqlDisks;

                        using (IDataReader readerDisks = cmdDisks.ExecuteReader()) {
                            while (readerDisks.Read()) {
                                long diskID = (long)readerDisks["id"];
                                long minFileID = GetMinFileID(conn, diskID);
                                string rootPath = "file://" + (string)readerDisks["root"];
                                long volumeID = targetDb.GetNextVolumeID();
                                long[] counters = { 0L, 0L, 0L };

                                string volDBThumbsPath = CreateThumbsDir(dbDataPath, volumeID);

                                cmdFiles.CommandText = string.Format(sqlFiles, diskID);

                                using (IDataReader readerFiles = cmdFiles.ExecuteReader()) {
                                    while (readerFiles.Read()) {
                                        long fileID = (long)readerFiles["id"];

                                        ImportFile(readerFiles,
                                                   volumeID,
                                                   minFileID,
                                                   rootPath,
                                                   ConvertMetaData(conn, fileID),
                                                   targetDb,
                                                   writer,
                                                   counters);

                                        ImportThumb(fileID,
                                                    (2 + fileID - minFileID),
                                                    thumbsPath,
                                                    volDBThumbsPath);

                                        PostProgressUpdate((++fileCounter * 100.0) / totalFiles);
                                        CheckForCancellationRequest();
                                    }
                                }

                                ImportDisk(readerDisks,
                                           volumeID,
                                           targetDb,
                                           counters);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 18
0
        private void RecursiveDump(string rootPath,
                                   DirectoryInfo dir,
                                   BufferedVolumeItemWriter writer,
                                   long parentID)
        {
            CheckForCancellationRequest();

            /* event is called before a _directory_ item is about to be scanned only.
             * it could also be called everytime a _file_ item is about to be scanned,
             * but this could result in a performance loss.
             */
            PostBeforeScanItem(dir.FullName);             //OnBeforeScanItem(new BeforeScanItemEventArgs(dir.FullName));

//			  bool dirIsSymLink = false;
//			  string symLinkTarget = null;
            FileType ft;

            // catch possible FileNotFoundExceptions
            // (e.g. on filesystems with wrong filename encoding or vanishing virtual files in /dev).
            try {
                ft = FileHelper.GetFileType(dir.FullName, false);
            } catch (FileNotFoundException ex) {
                /* may throw ScanCancelledException */
                SendScannerWarning(string.Format(S._("Directory '{0}' not found. (Wrong filename encoding?)"),
                                                 dir.FullName), ex);
                return;
            }

            bool dirIsSymLink = (ft == FileType.SymbolicLink);

            if ((ft != FileType.Directory) && !dirIsSymLink)
            {
                /* may throw ScanCancelledException */
                SendScannerWarning(string.Format(S._("Skipped item '{0}' as it doesn't seem to be a real directory."),
                                                 dir.FullName));
                return;
            }

            if (dirIsSymLink)
            {
                if (!Options.DiscardSymLinks)
                {
                    string symLinkTarget = null;

                    try {
                        // get real path with all symlinks resolved
                        symLinkTarget = FileHelper
                                        .GetCanonicalSymLinkTarget(dir.FullName);
                    } catch (FileNotFoundException) {}

                    // Note:
                    // this check seems to be useless since a broken link
                    // to a directory is identified as a broken link to a _file_ (a few lines below).
                    if (symLinkTarget == null)
                    {
                        /* may throw ScanCancelledException */
                        SendScannerWarning(string.Format(S._("Skipped symlink item '{0}' as the target does not exist."),
                                                         dir.FullName));
                        return;
                    }

                    // skip symlinks outside of rootPath
                    // (in addition, GetLocation()/FixPath() need paths relative to rootPath)
                    if (!symLinkTarget.StartsWith(rootPath))
                    {
                        /* may throw ScanCancelledException */
                        SendScannerWarning(string.Format(S._("Skipped symlink item '{0}' as it appears to point to a different drive ('{1}')."),
                                                         dir.FullName,
                                                         symLinkTarget));
                        return;
                    }

                    symLinkHelper.AddSymLink(dir, symLinkTarget, rootPath, parentID, true);
                }
                /* do not dump symlinks to directories */
                return;
            }

            /* insert dirname */
            long dirID = InsertDir(rootPath, dir, writer, parentID);

            parentID = dirID;
            // TODO : check m_cancel here (?)

//			  /* do not dump symlinks to directories */
//			  if (dirIsSymlink)
//				  return;

            try {
                /* insert files of dir */
                FileInfo[] files = dir.GetFiles();                 /* throws access exceptions (cant access _DIRECTORY_) */
                for (int i = 0; i < files.Length; i++)
                {
                    CheckForCancellationRequest();

//					  bool isRegularFile  = true;
//					  bool isSymLink	  = false;

//#if DEBUG && DEBUG_FILE_VERBOSE
                    if (Global.EnableDebugging)
                    {
                        Debug.WriteLine(string.Format("Indexing file '{0}'", files[i].FullName));
                    }
//#endif
                    // catch possible FileNotFoundExceptions
                    // (e.g. on filesystems with wrong filename encoding or vanishing virtual files in /dev).
                    try {
                        ft = FileHelper.GetFileType(files[i].FullName, false);
                    } catch (FileNotFoundException ex) {
                        /* may throw ScanCancelledException */
                        SendScannerWarning(string.Format(S._("File '{0}' not found. (Wrong filename encoding?)"),
                                                         files[i].FullName), ex);
                        continue;
                    }

                    /* special files (fifos, blockdevices, chardevices) are skipped */
                    bool isRegularFile = (ft == FileType.RegularFile);
                    bool isSymLink     = (ft == FileType.SymbolicLink);

                    if (isRegularFile)
                    {
                        string        mimeType       = null;
                        MetadataStore metaData       = MetadataStore.Empty;
                        string        hash           = null;
                        bool          thumbGenerated = false;

                        FileStream fs = null;
                        try {
                            // OpenRead() must be called _before_ MimeInfo.GetMimeType(),
                            // since this method returns a mimetype even if the file does not exist / can't be accessed.
                            fs = File.OpenRead(files[i].FullName);                             /* throws access/IO exceptions (cant access _FILE_) */

                            mimeType = MimeType.GetMimeTypeForFile(files[i].FullName);

                            if (Options.MetadataProviders != null)
                            {
                                IEnumerable <MetadataItem> items = null;

                                foreach (MetadataProvider mdp in Options.MetadataProviders)
                                {
                                    IEnumerable <MetadataItem> tmp = null;

                                    try {
                                        tmp = mdp.GetMetadata(files[i].FullName, mimeType);
                                    } catch (Exception e) {
                                        /* may throw ScanCancelledException */
                                        SendScannerWarning(string.Format(S._("Extracting metadata from file '{0}' failed. ({1})"),
                                                                         files[i].FullName,
                                                                         e.Message),
                                                           e);
                                    }

                                    if (items == null)
                                    {
                                        items = tmp;
                                    }
                                    else
                                    {
                                        if (tmp != null)
                                        {
                                            items = items.Concat(tmp);
                                        }
                                    }
                                }

                                metaData = new MetadataStore(items);
                            }

                            if (Options.ComputeHashs)
                            {
                                hash = ComputeHash(fs);
                                // TODO : check m_cancel here? hashing can be a lengthy operation on big files.
                            }

                            if (Options.GenerateThumbnails)
                            {
                                thumbGenerated = thumbGen.GenerateThumbnail(files[i], mimeType);
                            }
                        } catch (Exception e) {
                            // ### exception caught: hash, mime and/or metadata may be null
                            // and the thumbnail may not have been generated!
                            if (e is UnauthorizedAccessException || e is IOException)
                            {
                                /* may throw ScanCancelledException */
                                SendScannerWarning(string.Format(S._("Error opening file '{0}', can't retrieve any mime/metadata. ({1})"),
                                                                 files[i].FullName,
                                                                 e.Message),
                                                   e);
                            }
                            else
                            {
                                throw;
                            }
                        } finally {
                            if (fs != null)
                            {
                                fs.Close();
                            }
                        }

                        long fileID = InsertFile(rootPath, files[i], writer, parentID, mimeType, metaData, hash);
                        if (thumbGenerated)
                        {
                            thumbGen.SaveThumbnail(Path.Combine(paths.thumbnailPath, string.Format("{0}.png", fileID)));
                        }
                    }
                    else if (isSymLink)
                    {
                        if (!Options.DiscardSymLinks)
                        {
                            string symLinkTarget = null;

                            try {
                                // get real path with all symlinks resolved
                                symLinkTarget = FileHelper
                                                .GetCanonicalSymLinkTarget(files[i].FullName);
                            } catch (FileNotFoundException) {}

                            if (symLinkTarget == null)
                            {
                                /* may throw ScanCancelledException */
                                SendScannerWarning(string.Format(S._("Skipped symlink item '{0}' as the target does not exist."),
                                                                 files[i].FullName));

                                // skip symlinks outside of rootPath
                                // (in addition, GetLocation()/FixPath() need paths relative to rootPath)
                            }
                            else if (!symLinkTarget.StartsWith(rootPath))
                            {
                                /* may throw ScanCancelledException */
                                SendScannerWarning(string.Format(S._("Skipped symlink item '{0}' as it appears to point to a different drive ('{1}')."),
                                                                 files[i].FullName,
                                                                 symLinkTarget));

                                // skip symlinks pointing to special files (only regular files are indexed)
                            }
                            else if (FileHelper.GetFileType(symLinkTarget, false) != FileType.RegularFile)
                            {
                                /* may throw ScanCancelledException */
                                SendScannerWarning(string.Format(S._("Skipped symlink item '{0}' as it does not point to a regular file ('{1}')."),
                                                                 files[i].FullName,
                                                                 symLinkTarget));
                            }
                            else
                            {
                                symLinkHelper.AddSymLink(files[i], symLinkTarget, rootPath, parentID, false);
                            }
                        }
                    }
                    else
                    {
                        /* may throw ScanCancelledException */
                        SendScannerWarning(string.Format(S._("Skipped item '{0}' as it appears to be some kind of special file."),
                                                         files[i].FullName));
                    }

                    // TODO : check m_cancel here (?)
                }                  // end for

                /* recursively dump subdirs */
                DirectoryInfo[] childDirs = dir.GetDirectories();                 /* throws access exceptions (cant access _DIRECTORY_) */
                for (int i = 0; i < childDirs.Length; i++)
                {
                    RecursiveDump(rootPath, childDirs[i], writer, parentID);
                }
            } catch (UnauthorizedAccessException e) {
                //ScannerWarningEventArgs args = new ScannerWarningEventArgs("Unable to dump dir '" + dir.FullName + "'. (" + e.Message + ")", e);
                //OnScannerWarning(args); // may throw ScanCancelledException

                /* may throw ScanCancelledException */
                SendScannerWarning(string.Format(S._("Unable to dump dir '{0}'. ({1})"),
                                                 dir.FullName,
                                                 e.Message),
                                   e);
            }
        }