Monitoring changes on folder with lot of subfolders?

Viewed 143

I've been working on a Dropbox indicator for Wingpanel and one of the features I've been trying to implement is a list of recent activity, that is, a list of the most recent modified/created files.

I know we do have inotify. However, it has two limitations:

  1. it doesn't watch for changes in subfolder;
  2. there is a max number of folders you can watch at once.

So, my approach is the following one: I run through the entire tree structure comparing modification dates of each folder. If some change is detected I emit a signal and stop. However, in order to avoid freezing the GUI while performing this search, I have to execute it in another thread.

So, my indicator runs this search at every 3s. It has worked just fine for me. However, some users have pointed out a Segmentation Fault error exactly while this search is being executed. In a specific case, the folder structure has like 23k files and folders.

Does anyone have a better solution? Thank you all in advance!

I post my code below.

The following code is executed at every 3s and it creates a new Thread where I perform the looking for changes.

private async bool core () throws ThreadError {
        // Do not create a new Thread if there is another
        if (is_working == false) {
            is_working = true;
            SourceFunc callback = core.callback;

            ThreadFunc<bool> run = () => {
                File dir_root = File.new_for_path (path);
                try {
                    FileInfo info = dir_root.query_info ("*", 0);
                    string iso = info.get_modification_time().to_iso8601();
                    GLib.DateTime file_modification_date = new GLib.DateTime.from_iso8601 (iso, null);

                    // Check if the root dir has changed
                    if (last_check_date.compare (file_modification_date) == -1) {
                        is_working = false;
                        // emitting change signal
                        changed (info);
                    } else {
                        compare_modification_date (path, last_check_date);
                        is_working = false;
                    }

                    last_check_date = new DateTime.now_local ();
                    Idle.add ((owned)callback);

                    return true;

                } catch (Error e) {
                    print ("Error getting info: %s",e.message);
                    return false;
                }

            };

            new Thread<bool>("compare-dir", run);
            yield;
        }

        return true;
    }

The code below is the recursive function that does the job of comparing modification dates.

private void compare_modification_date (string dir_path, GLib.DateTime d) {
        File dir = File.new_for_path (dir_path);
        //
            try {
                FileEnumerator files = dir.enumerate_children("*", FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
                FileInfo info = files.next_file (null);
                while(info != null) {
                    if(info.get_file_type() == FileType.DIRECTORY && !info.get_name().has_prefix(".") ) {
                         string iso = info.get_modification_time().to_iso8601();
                         GLib.DateTime file_modification_date = new GLib.DateTime.from_iso8601 (iso, null);

                         if (d.compare(file_modification_date) == -1) {
                             print ("The dir %s has been modified.", info.get_name());
                             // emitting change signal
                             changed (info);
                             break;
                         } else {
                             compare_modification_date(dir_path+"/"+info.get_name(), d);
                             info =files.next_file (null);
                         }
                     } else {
                         info = files.next_file(null);
                     }
                }
            } catch (Error e) {
                print ("Error comparing dates:%s", e.message);
            }
     }

}

0 Answers
Related