示例#1
0
        /// <summary>
        /// The actual internal folder scan implementation.
        /// </summary>
        private void InternalScan()
        {
            if (isDisposed)
            {
                return;
            }

            try
            {
                if (Interlocked.Increment(ref scanning) > 1)
                {
                    return;     // Don't allow multiple parallel scans
                }
                Dictionary <AppRef, AppPackageInfo> newPackages = new Dictionary <AppRef, AppPackageInfo>();
                string[] files;

                files = Helper.GetFilesByPattern(packageFolder + "*.zip", SearchOption.TopDirectoryOnly);
                foreach (string file in files)
                {
                    bool isRetry = false;

retry:
                    try
                    {
                        int size;

                        using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
                            size = (int)fs.Length;

                        using (AppPackage package = AppPackage.Open(file))
                            newPackages.Add(package.AppRef, new AppPackageInfo(package.AppRef,
                                                                               Path.GetFileName(file),
                                                                               file,
                                                                               package.MD5,
                                                                               size,
                                                                               File.GetLastWriteTimeUtc(file)));
                    }
                    catch (FileNotFoundException e)
                    {
                        SysLog.LogErrorStackDump("{0}", e.Message);
                    }
                    catch (DirectoryNotFoundException e)
                    {
                        SysLog.LogErrorStackDump("{0}", e.Message);
                    }
                    catch (IOException e)
                    {
                        // I've run into trouble where we've gotten notifications from the
                        // file watcher while a new file is still locked for writing.  In
                        // this situation, I'm going to wait a bit and then retry the
                        // operation once.

                        if (!isRetry)
                        {
                            Thread.Sleep(RetryTime);
                            isRetry = true;
                            goto retry;
                        }

                        SysLog.LogErrorStackDump("{0}", e.Message);
                    }
                    catch (Exception e)
                    {
                        SysLog.LogErrorStackDump("Error [{0}] loading application package [{1}].", e.Message, file);
                    }
                }

                // Determine if there have been any changes to the set of
                // application packages and then update the cached package set
                // and then raise the change event if there were any changes.

                bool changed = false;

                using (TimedLock.Lock(syncLock))
                {
                    foreach (var info in newPackages.Values)
                    {
                        if (!packages.ContainsKey(info.AppRef))
                        {
                            changed = true;
                            break;
                        }
                        else
                        {
                            var orgInfo = packages[info.AppRef];

                            if (info.FileName != orgInfo.FileName ||
                                !Helper.ArrayEquals(info.MD5, orgInfo.MD5))
                            {
                                changed = true;
                                break;
                            }
                        }
                    }

                    if (!changed)
                    {
                        foreach (AppPackageInfo info in packages.Values)
                        {
                            if (!newPackages.ContainsKey(info.AppRef))
                            {
                                changed = true;
                                break;
                            }
                        }
                    }

                    if (changed)
                    {
                        packages = newPackages;
                    }
                }

                if (changed)
                {
                    RaiseChangeEvent();
                }
            }
            finally
            {
                Interlocked.Decrement(ref scanning);
            }
        }