~ubuntu-branches/ubuntu/precise/ubuntuone-client/precise

« back to all changes in this revision

Viewing changes to ubuntuone/platform/windows/filesystem_notifications.py

  • Committer: Package Import Robot
  • Author(s): Rodney Dawes
  • Date: 2011-12-21 15:46:25 UTC
  • mfrom: (1.1.56)
  • Revision ID: package-import@ubuntu.com-20111221154625-ujvunri4frsecj2k
Tags: 2.99.0-0ubuntu1
* New upstream release.
  - Verify timestamp to avoid invalid auth failures (LP: #692597)
  - Files in new UDFs not uploaded due to filtering (LP: #869920)
* debian/patches:
  - Remove upstreamed patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
90
90
  2: IN_DELETE,
91
91
  3: IN_MODIFY,
92
92
  4: IN_MOVED_FROM,
93
 
  5: IN_MOVED_TO}
 
93
  5: IN_MOVED_TO,
 
94
}
 
95
 
 
96
# a map of the actions to names so that we have better logs.
 
97
WINDOWS_ACTIONS_NAMES = {
 
98
  1: 'IN_CREATE',
 
99
  2: 'IN_DELETE',
 
100
  3: 'IN_MODIFY',
 
101
  4: 'IN_MOVED_FROM',
 
102
  5: 'IN_MOVED_TO',
 
103
}
94
104
 
95
105
# translates quickly the event and it's is_dir state to our standard events
96
106
NAME_TRANSLATIONS = {
118
128
 
119
129
THREADPOOL_MAX = 20
120
130
 
 
131
 
121
132
# The implementation of the code that is provided as the pyinotify substitute
122
133
class Watch(object):
123
134
    """Implement the same functions as pyinotify.Watch."""
143
154
        self._watch_handle = None
144
155
        # remember the subdirs we have so that when we have a delete we can
145
156
        # check if it was a remove
146
 
        self._subdirs = []
 
157
        self._subdirs = set()
147
158
        # ensure that we work with an abspath and that we can deal with
148
159
        # long paths over 260 chars.
149
160
        if not path.endswith(os.path.sep):
157
168
        self._watch_stopped_deferred = defer.Deferred()
158
169
 
159
170
    @is_valid_windows_path(path_indexes=[1])
 
171
    def _update_subdirs(self, path, event):
 
172
        """Adds the path to the internal subdirs.
 
173
 
 
174
        The given path is considered to be a path and therefore this
 
175
        will not be checked.
 
176
        """
 
177
        if WINDOWS_ACTIONS[event] == IN_CREATE:
 
178
            self._subdirs.add(path)
 
179
        elif WINDOWS_ACTIONS[event] == IN_DELETE and\
 
180
                path in self._subdirs:
 
181
            self._subdirs.remove(path)
 
182
 
 
183
    @is_valid_windows_path(path_indexes=[1])
160
184
    def _path_is_dir(self, path):
161
185
        """Check if the path is a dir and update the local subdir list."""
162
 
        self.log.debug('Testing if path %r is a dir', path)
 
186
 
 
187
        # The logic of this function is the following:
 
188
        # 1. ReadDirectoryChangesW changes does not send if a path
 
189
        # is a new dir or not.
 
190
        # 2. We keep track of subdirs that in self._subdir.
 
191
        # 3. We check if a path is a dir by:
 
192
        #    * Asking the os if the path exists.
 
193
        #    * Finding the path in self._subdirs
 
194
 
163
195
        is_dir = False
164
196
        if os.path.exists(path):
165
197
            is_dir = os.path.isdir(path)
166
198
        else:
167
 
            self.log.debug('Path "%s" was deleted subdirs are %s.',
168
 
                path, self._subdirs)
169
 
            # we removed the path, we look in the internal list
170
 
            if path in self._subdirs:
171
 
                is_dir = True
172
 
                self._subdirs.remove(path)
173
 
        if is_dir:
174
 
            self.log.debug('Adding %s to subdirs %s', path, self._subdirs)
175
 
            self._subdirs.append(path)
 
199
            # path does not exists, was it in the internal list?
 
200
            is_dir = path in self._subdirs
 
201
        self.log.debug('Is path %r a dir? %s', path, is_dir)
176
202
        return is_dir
177
203
 
178
204
    def _process_events(self, events):
191
217
            # makes the multiplatform better, linux was first :P
192
218
            syncdaemon_path = get_syncdaemon_valid_path(
193
219
                                        os.path.join(self._path, file_name))
194
 
            is_dir = self._path_is_dir(os.path.join(self._path, file_name))
 
220
            full_dir_path = os.path.join(self._path, file_name)
 
221
            is_dir = self._path_is_dir(full_dir_path)
195
222
            if is_dir:
196
 
                self._subdirs.append(file_name)
 
223
                # we need to update the list of subdirs that we have
 
224
                self._update_subdirs(full_dir_path, action)
197
225
            mask = WINDOWS_ACTIONS[action]
198
226
            head, tail = os.path.split(file_name)
199
227
            if is_dir:
221
249
            # add the event only if we do not have an exclude filter or
222
250
            # the exclude filter returns False, that is, the event will not
223
251
            # be excluded
224
 
            self.log.debug('Event is %s.', event)
 
252
            self.log.debug('Pushing event %r to processor.', event)
225
253
            self._processor(event)
226
254
 
227
255
    def _call_deferred(self, f, *args):
292
320
            data = GetOverlappedResult(handle, self._overlapped, True)
293
321
            # lets ead the data and store it in the results
294
322
            events = FILE_NOTIFY_INFORMATION(buf, data)
295
 
            self.log.debug('Events from ReadDirectoryChangesW are %s', events)
 
323
            self.log.debug('Got from ReadDirectoryChangesW %r.',
 
324
                    [(WINDOWS_ACTIONS_NAMES[action], path) for action, path in
 
325
                        events])
296
326
            reactor.callFromThread(self._process_events, events)
297
327
 
298
328
    @is_valid_windows_path(path_indexes=[1])
319
349
        for current_child in os.listdir(self._path):
320
350
            full_child_path = os.path.join(self._path, current_child)
321
351
            if os.path.isdir(full_child_path):
322
 
                self._subdirs.append(full_child_path)
 
352
                self._subdirs.add(full_child_path)
323
353
        # start to diff threads, one to watch the path, the other to
324
354
        # process the events.
325
355
        self.log.debug('Start watching path.')
332
362
        self.log.info('Stop watching %s', self._path)
333
363
        SetEvent(self._wait_stop)
334
364
        self._watching = False
335
 
        self._subdirs = []
 
365
        self._subdirs = set()
336
366
        return self.stopped
337
367
 
338
368
    def update(self, mask, auto_add=False):
419
449
                                          mask, auto_add, self._processor)
420
450
        d = self._wdm[self._wd_count].start_watching()
421
451
        self._wd_count += 1
422
 
        self.log.debug('Watch count increased to %s', self._wd_count)
423
452
        return d
424
453
 
425
454
    @is_valid_windows_path(path_indexes=[1])
497
526
    def __init__(self, monitor, ignore_config=None):
498
527
        # XXX: avoid circular imports.
499
528
        from ubuntuone.syncdaemon.filesystem_notifications import (
500
 
            GeneralINotifyProcessor
501
 
        )
 
529
            GeneralINotifyProcessor)
502
530
        self.general_processor = GeneralINotifyProcessor(monitor,
503
531
            self.handle_dir_delete, NAME_TRANSLATIONS,
504
532
            self.platform_is_ignored, IN_IGNORED, ignore_config=ignore_config)