// Group: Individual File Management Functions // __________________________________________________________________________ /* Function: PickFileSource * * Returns a <FileSource> that is available to be scanned for files and its corresponding <FileSourceAdder>, or false if there * aren't any. You must pass them to <ReleaseFileSource()> when done. * * If this function returns false it doesn't mean that there are no unscanned <FileSources> remaining, as it may be requiring * some to be scanned sequentially to prevent multiple sources on the same disk from being scanned at the same time. So * while this function may return null while a particular <FileSource> is being scanned, it may return another one after it's * released. */ protected bool PickFileSource(out FileSource fileSource, out FileSourceAdder fileSourceAdder) { lock (accessLock) { for (int i = 0; i < fileSources.Count; i++) { if (fileSourcesClaimed[i] == false) { fileSource = fileSources[i]; if (fileSource is FileSources.Folder) { string folderPrefix = (fileSource as FileSources.Folder).Path.Prefix; if (folderPrefixesClaimed.Contains(folderPrefix) == false) { fileSourcesClaimed[i] = true; folderPrefixesClaimed.Add(folderPrefix); fileSourceAdder = fileSource.CreateAdderProcess(); fileSourceAdders[i] = fileSourceAdder; return(true); } } else // not a folder { fileSourcesClaimed[i] = true; fileSourceAdder = fileSource.CreateAdderProcess(); fileSourceAdders[i] = fileSourceAdder; return(true); } } } } fileSource = null; fileSourceAdder = null; return(false); }
/* Function: AddFileSource * Adds a file source to the list. This can only be called before the <Engine.Instance> is started, not while it is running. */ public void AddFileSource(FileSource source) { lock (accessLock) { fileSources.Add(source); } }
// Group: Group File Management Functions // __________________________________________________________________________ /* Function: WorkOnAddingAllFiles * * Works on the task of going through all the files in all the <FileSources> and calling <AddOrUpdateFile()> on each one. * This is a parallelizable task, so multiple threads can call this function and they will divide up the work until it's done. * * The function returns when there is no more work for this thread to do. If this is the only thread working on it then the * task is complete, but if there are multiple threads, the task is only complete after they all return. An individual thread * may return prior to that point. */ public void WorkOnAddingAllFiles(CancelDelegate cancelDelegate) { string claimedFolderPrefix = null; Monitor.Enter(accessLock); bool locked = true; try { for (;;) { FileSource claimedFileSource = null; if (cancelDelegate()) { return; } // If we have a claimed folder prefix, try to find another file source with the same one. if (claimedFolderPrefix != null) { foreach (FileSource fileSource in fileSources) { if (fileSource is FileSources.Folder && fileSource.Claimed == false && fileSource.AllFilesAdded == false && String.Compare(claimedFolderPrefix, (fileSource as FileSources.Folder).Path.Prefix, true) == 0) { claimedFileSource = fileSource; fileSource.Claimed = true; break; } } if (claimedFileSource == null) { claimedFolderPrefixes.Remove(claimedFolderPrefix); claimedFolderPrefix = null; } } // If that didn't work, either because we didn't have a claimed folder prefix or there were no more available, // claim the first untaken file source there is. If it's a folder file source, claim its prefix as well, but ignore it if the // prefix was already claimed because it wouldn't benefit from parallelization. if (claimedFileSource == null) { foreach (FileSource fileSource in fileSources) { if (fileSource is FileSources.Folder) { if (fileSource.AllFilesAdded == false && fileSource.Claimed == false && claimedFolderPrefixes.Contains((fileSource as FileSources.Folder).Path.Prefix) == false) { claimedFileSource = fileSource; fileSource.Claimed = true; claimedFolderPrefix = (fileSource as FileSources.Folder).Path.Prefix; claimedFolderPrefixes.Add(claimedFolderPrefix); break; } } else if (fileSource.AllFilesAdded == false && fileSource.Claimed == false) { claimedFileSource = fileSource; fileSource.Claimed = true; break; } } } // If that didn't work either it means there are no available file sources left so we can quit. if (claimedFileSource == null) { return; } // Now release the lock while we work on it. Monitor.Exit(accessLock); locked = false; claimedFileSource.AddAllFiles(cancelDelegate); // If it failed because of the cancelDelegate AllFilesAdded will be false. Monitor.Enter(accessLock); locked = true; claimedFileSource.Claimed = false; } // for } // try finally { if (locked) { Monitor.Exit(accessLock); } } }