2011-08-26 22 views
8

Me gustaría sondear el sistema de archivos en busca de archivos o subdirectorios cambiados, agregados o eliminados. Todos los cambios deben detectarse rápidamente pero sin ejercer presión sobre la máquina. El sistema operativo es Windows> = Vista, la parte observada es un directorio local.¿Cómo debo sondear una gran cantidad de archivos para cambios?

Normalmente, recurriría a un FileSystemWatcher, pero esto dio lugar a problemas con otros programas que intentaron mirar el mismo lugar (de forma destacada, Windows Explorer). Además, escuché que FSW no es realmente confiable incluso para carpetas locales y con un gran buffer.

El problema principal que tengo es que la cantidad de archivos y directorios puede ser muy grande (adivinar 7 dígitos). Simplemente ejecutar un control de todos los archivos cada segundo afectó notablemente a mi máquina.

Mi siguiente idea fue verificar diferentes partes de todo el árbol por segundo para reducir el impacto general, y posiblemente agregar un tipo de heurística, como revisar los archivos que cambian frecuentemente en una sucesión más rápida.

Me pregunto si hay patrones para este tipo de problema, o si alguien tiene experiencia con esta situación.

+0

¿Todas las subcarpetas están en una sola raíz? ¿Qué tipo de problemas tienes con Windows Explorer? Aquí hay un patrón para asegurarse de no perder ningún mensaje. http://stackoverflow.com/questions/4967095/c-predict-file-system-events-on-folder-delete/4968391#4968391 – adrianm

+0

@adrianm: Sí, la misma raíz. --- Explorer no actualizó su vista cuando se modificó una carpeta supervisada, supongo porque FSW robó sus eventos. – mafu

Respuesta

3

Hemos implementado una característica similar, usando C#. El FileSystemWatcher era ineficiente con grandes árboles de directorios.

Nuestra alternativa, se utiliza FSNodes, una estructura creada por nosotros, usando las siguientes llamadas a la API de Windows:

[StructLayout(LayoutKind.Sequential)] 
     private struct FILETIME 
    { 
     public uint dwLowDateTime; 
     public uint dwHighDateTime; 
    }; 

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
     private struct WIN32_FIND_DATA 
    { 
     public FileAttributes dwFileAttributes; 
     public FILETIME ftCreationTime; 
     public FILETIME ftLastAccessTime; 
     public FILETIME ftLastWriteTime; 
     public uint nFileSizeHigh; 
     public uint nFileSizeLow; 
     public int dwReserved0; 
     public int dwReserved1; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)] 
     public string cFileName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)] 
     public string cAlternate; 
    } 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool FindClose(IntPtr hFindFile); 

    [DllImport("kernel32", CharSet=CharSet.Unicode)] 
    private static extern IntPtr FindFirstFile(
     string lpFileName, out WIN32_FIND_DATA lpFindFileData); 

    [DllImport("kernel32", CharSet=CharSet.Unicode)] 
    private static extern bool FindNextFile(
     IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData); 

Lo que hacemos es un procesamiento estática. Guardamos un árbol de metadatos en el disco y comparamos el árbol de directorios almacenados con el cargado, buscando modificado (basado en su sello de tiempo (más rápido), o en el hash del archivo). Además, podemos administrar archivos eliminados, agregados y movidos, incluso modificados con movimiento (también basados ​​en el hash del archivo).

Esta implementación se mezcló con un daemon que la ejecutó cada POLL_TIME, era válida para nosotros. Espero eso ayude.

+0

¿Podría explicarme un poco sobre cómo está utilizando las llamadas a la API de Win32? – Cocowalla

+0

'FindFirstFile' busca en un directorio un archivo o subdirectorio con un nombre que coincida con un nombre específico (o un nombre parcial si se usan comodines). 'FindNextFile' continúa una búsqueda de archivos desde una llamada anterior a la función' FindFirstFile' o 'FindFirstFileEx'. Cierra un identificador de búsqueda de archivos abierto por las funciones 'FindFirstFile' (y otras). Recomiendo una búsqueda en Google para entender mejor la API. –

0

Para entornos * nix puede usar inotify https://github.com/rvoicilas/inotify-tools/wiki/, que funcionó muy bien en mi limitada investigación sobre el mismo. Puede que exista una versión que funcione con Windows con la que tengo menos experiencia ... la búsqueda en Google rápida me llevó a un clon de Java llamado jnotify http://jnotify.sourceforge.net/ que se anuncia para que funcione en Windows, por lo que podría valer la pena intentarlo.

Cuestiones relacionadas