Author: dmeyer
Date: Fri Feb 17 19:56:27 2006
New Revision: 1186

Modified:
   trunk/WIP/vfs/src/client.py
   trunk/WIP/vfs/src/db.py
   trunk/WIP/vfs/src/item.py
   trunk/WIP/vfs/src/monitor.py
   trunk/WIP/vfs/src/parser.py
   trunk/WIP/vfs/src/query.py
   trunk/WIP/vfs/src/server.py

Log:
more updates

Modified: trunk/WIP/vfs/src/client.py
==============================================================================
--- trunk/WIP/vfs/src/client.py (original)
+++ trunk/WIP/vfs/src/client.py Fri Feb 17 19:56:27 2006
@@ -59,11 +59,11 @@
         db = os.path.abspath(db)
         # monitor function from the server to start a new monitor for a query
         self._server = ipc.IPCClient('vfs').get_object('vfs')(db)
-        self.monitor = self._server.monitor
+        self._server_monitor = self._server.monitor
         # read only version of the database
         self.database = Database(db, self)
         # connect to server notifications
-        self._server.connect(self)
+        self.id = self._server.connect(self, self._vfs_notify)
         # internal list of active queries
         self._queries = []
         # internal list of items to update
@@ -81,31 +81,19 @@
         """
         Return an object for the given filename.
         """
-        result = Query(self, filename=os.path.realpath(filename))
-        return result.get()[0]
-
-
-    def vfs_request(self, id):
-        return self._server.vfs_request(id, __ipc_noproxy_result=True,
-                                        __ipc_noproxy_args=True)
+        return Query(self, filename=os.path.realpath(filename)).result
 
 
     def query(self, **query):
         result = Query(self, **query)
         self._queries.append(weakref(result))
-        # start the remote query 100 ms seconds later. It is faster
-        # that way because a) ipc takes some time and b) it avoids
-        # doing the same stuff at the same time
-
-        # TODO: create a client id to avoid sending self.notify to the
-        # client at this point.
         if 'parent' in query:
             query['parent'] = query['parent']._vfs_id
-        OneShotTimer(self.monitor, self.notify, result.id,
-                     **query).start(0.1)
+        OneShotTimer(self._server_monitor, self.id, result.id, query,
+                     __ipc_noproxy_args=True, __ipc_oneway=True).start(0.01)
         return result
-        
     
+
 #     def query(self, **query):
 #         """
 #         Do a query to the databse. This will return a Query object.
@@ -130,13 +118,22 @@
 #         return result
 
 
-    def notify(self, id, msg, *args, **kwargs):
+    def _vfs_request(self, filename):
+        """
+        Request information about a filename.
+        """
+        return self._server.request(filename, __ipc_noproxy_result=True,
+                                    __ipc_noproxy_args=True)
+
+
+    def _vfs_notify(self, id, msg, *args, **kwargs):
         """
         Internal notification callback from the server. The Monitor does not
         has a reference to the Query because this would result in circular
         dependencies. So this function is needed to find the correct Query
         for a request.
         """
+        print 'NOTIFY', id, msg
         for query in self._queries:
             if query and query.id == id:
                 if hasattr(query, '_vfs_%s' % msg):
@@ -145,37 +142,37 @@
                 
                 log.error('Error: unknown message from server: %s' % msg)
                 return
-            
+
         # not found, possibly already deleted, check for dead weakrefs
         for query in self._queries[:]:
             if not query:
                 self._queries.remove(query)
 
 
-    def update(self, item=None):
-        """
-        Update item in next main loop interation.
-        """
-        if not item:
-            # do the update now
-            items = []
-            for i in self._changed:
-                changes = {}
-                for var in i.changes:
-                    changes[var] = i[var]
-                i.changes = []
-                items.append((i.dbid, changes))
-            self._changed = []
-            self._server.update(items, __ipc_oneway=True, 
__ipc_noproxy_args=True)
-            return
-
-        if not self._changed:
-            # register timer to do the changes
-            OneShotTimer(self.update).start(0.1)
-        self._changed.append(item)
+#     def update(self, item=None):
+#         """
+#         Update item in next main loop interation.
+#         """
+#         if not item:
+#             # do the update now
+#             items = []
+#             for i in self._changed:
+#                 changes = {}
+#                 for var in i.changes:
+#                     changes[var] = i[var]
+#                 i.changes = []
+#                 items.append((i.dbid, changes))
+#             self._changed = []
+#             self._server.update(items, __ipc_oneway=True, 
__ipc_noproxy_args=True)
+#             return
+
+#         if not self._changed:
+#             # register timer to do the changes
+#             OneShotTimer(self.update).start(0.1)
+#         self._changed.append(item)
 
         
-    def __str__(self):
+    def __repr__(self):
         """
         Convert object to string (usefull for debugging)
         """

Modified: trunk/WIP/vfs/src/db.py
==============================================================================
--- trunk/WIP/vfs/src/db.py     (original)
+++ trunk/WIP/vfs/src/db.py     Fri Feb 17 19:56:27 2006
@@ -43,14 +43,15 @@
 from kaa.base import db
 from kaa.base.db import *
 
-# kaa.vfs imports
-import item
-
 # get logging object
 log = logging.getLogger('vfs')
 
 MAX_BUFFER_CHANGES = 20
 
+# Item generation mapping
+from item import Directory as create_dir
+from item import File as create_file
+
 class Mountpoint(object):
     """
     Internal class for mountpoints. More a list of attributes important
@@ -112,25 +113,25 @@
         return True
 
 
-    def item(self):
-        """
-        Get the id of the mountpoint. This functions needs the database
-        and _must_ be called from the same thread as the db itself.
-        Return the root item for the mountpoint.
-        """
-        if not self.id:
-             return None
-        media = self.db.query(type='media', id=self.id[1])
-        content = media[0]['content']
-        if content == 'file':
-            # a simple data dir
-            current = self.db.query(type="dir", name='', parent=self.id)[0]
-            return item.create(current, None, self)
-        # a track of something else
-        return [ item.create(x, self, self) for x in \
-                 self.db.query(type='track_%s' % content, parent=self.id) ]
-        # TODO: support other media
-        return None
+#     def item(self):
+#         """
+#         Get the id of the mountpoint. This functions needs the database
+#         and _must_ be called from the same thread as the db itself.
+#         Return the root item for the mountpoint.
+#         """
+#         if not self.id:
+#              return None
+#         media = self.db.query(type='media', id=self.id[1])
+#         content = media[0]['content']
+#         if content == 'file':
+#             # a simple data dir
+#             current = self.db.query(type="dir", name='', parent=self.id)[0]
+#             return item.create(current, None, self)
+#         # a track of something else
+#         return [ item.create(x, self, self) for x in \
+#                  self.db.query(type='track_%s' % content, parent=self.id) ]
+#         # TODO: support other media
+#         return None
 
         
     def __str__(self):
@@ -245,24 +246,24 @@
         if dirname == media.directory:
             # we know that '/' is in the db
             current = self._db.query(type="dir", name='', parent=media.id)[0]
-            return item.create_dir(current, media)
+            return create_dir(current, media)
 
         parent = self._get_dir(os.path.dirname(dirname), media)
         name = os.path.basename(dirname)
 
         if not parent._vfs_id:
-            return item.create_dir(name, parent)
+            return create_dir(name, parent)
             
         current = self._db.query(type="dir", name=name, parent=parent._vfs_id)
         if not current and self.client:
-            return item.create_dir(name, parent)
+            return create_dir(name, parent)
 
         if not current:
             current = self._db.add_object("dir", name=name, 
parent=parent._vfs_id)
             self._db.commit()
         else:
             current = current[0]
-        return item.create_dir(current, parent)
+        return create_dir(current, parent)
 
 
     def commit(self):
@@ -270,6 +271,10 @@
         Commit changes to the database. All changes in the internal list
         are done first.
         """
+        if not self.changes:
+            return
+
+        print 'COMMIT'
         t1 = time.time()
         changes = self.changes
         for function, arg1, args, kwargs in self.changes:
@@ -296,9 +301,9 @@
         commit is called just after this function is called.
         """
         log.debug('DELETE %s' % entry)
-        for child in self._db.query(parent = (entry['type'], entry['id'])):
+        for child in self._db.query(parent = entry._vfs_id):
             self._delete(child)
-        self._db.delete_object((entry['type'], entry['id']))
+        self._db.delete_object((entry._vfs_id))
 
 
     def _query_dir(self, parent):
@@ -306,11 +311,11 @@
         A query to get all files in a directory.
         """
         dirname = parent.filename[:-1]
-        items = [ item.create_file(f, parent) for f in \
+        items = [ create_file(f, parent) for f in \
                   self._db.query(parent = parent._vfs_id) ]
         # sort items based on url. The listdir is also sorted, that makes
         # checking much faster
-        items.sort(lambda x,y: cmp(x.url, y.url))
+        items.sort(lambda x,y: cmp(x._vfs_name, y._vfs_name))
 
         # TODO: this could block for cdrom drives and network filesystems. 
Maybe
         # put the listdir in a thread
@@ -319,16 +324,17 @@
         # it scan time or something like that. Also make it an option so the
         # user can turn the feature off.
         pos = -1
+
         for pos, (f, overlay) in enumerate(parent._vfs_listdir()):
             if pos == len(items):
                 # new file at the end
                 if os.path.isdir(parent.filename + f):
                     if not overlay:
-                        items.append(item.create_dir(f, parent))
+                        items.append(create_dir(f, parent))
                     continue
-                items.append(item.create_file(f, parent, overlay))
+                items.append(create_file(f, parent, overlay))
                 continue
-            while f > items[pos].url:
+            while f > items[pos]._vfs_name:
                 # file deleted
                 i = items[pos]
                 items.remove(i)
@@ -338,15 +344,15 @@
                     # list. It will be deleted right before the next commit.
                     self.changes.append((self._delete, i, [], {}))
                 # delete
-            if f == items[pos].url:
+            if f == items[pos]._vfs_name:
                 # same file
                 continue
             # new file
             if os.path.isdir(parent.filename + f):
                 if not overlay:
-                    items.append(item.create_dir(f, parent))
+                    items.insert(pos, create_dir(f, parent))
                 continue
-            items.insert(pos, item.create_file(f, parent, overlay))
+            items.insert(pos, create_file(f, parent, overlay))
 
         if pos + 1 < len(items):
             # deleted files at the end
@@ -359,6 +365,7 @@
         if self.changes:
             # need commit because some items were deleted from the db
             self.commit()
+        items.sort(lambda x,y: cmp(x.url, y.url))
         return items
 
 
@@ -379,6 +386,10 @@
         Internal query function inside the thread. This function will use the
         corrent internal query function based on special keywords.
         """
+        print 'QUERY', query
+        # make sure db is ok
+        self.commit()
+        
         if 'filename' in query and len(query) == 1:
             # return item for filename, can't be in overlay
             filename = query['filename']
@@ -396,8 +407,8 @@
                     # entry is in the db
                     basename = e[0]
             if os.path.isdir(filename):
-                return item.create_dir(basename, parent)
-            return item.create_file(basename, parent)
+                return create_dir(basename, parent)
+            return create_file(basename, parent)
 
 
         if 'id' in query and len(query) == 1:
@@ -412,17 +423,17 @@
                         break
                 else:
                     raise AttributeError('bad media %s' % i['parent'])
-                return item.create_dir(i, m)
+                return create_dir(i, m)
             # query for parent
             parent = self.query(id=i['parent'])
             if i['type'] == 'dir':
                 # it is a directory, make a dir item
-                return item.create_dir(i, parent)
+                return create_dir(i, parent)
             if parent._vfs_isdir:
                 # parent is dir, this item is not
-                return item.create_file(i, parent)
+                return create_file(i, parent)
             # neither dir nor file, something else
-            return item.create_item(i, parent)
+            return create_item(i, parent)
 
             
         if 'parent' in query and len(query) == 1:
@@ -450,13 +461,13 @@
             parent = self.query(id=r['parent'])
             if r['type'] == 'dir':
                 # it is a directory, make a dir item
-                result.append(item.create_dir(r, parent))
+                result.append(create_dir(r, parent))
             elif parent._vfs_isdir:
                 # parent is dir, this item is not
-                result.append(item.create_file(r, parent))
+                result.append(create_file(r, parent))
             else:
                 # neither dir nor file, something else
-                result.append(item.create_item(r, parent))
+                result.append(create_item(r, parent))
         return result
 
 

Modified: trunk/WIP/vfs/src/item.py
==============================================================================
--- trunk/WIP/vfs/src/item.py   (original)
+++ trunk/WIP/vfs/src/item.py   Fri Feb 17 19:56:27 2006
@@ -34,6 +34,7 @@
 
 
 import os
+import stat
 
 UNKNOWN = -1
 
@@ -55,6 +56,7 @@
         self._vfs_media = media
         self._vfs_isdir = False
         self._vfs_changes = []
+        self._vfs_name = data['name']
 
 
     def __repr__(self):
@@ -74,6 +76,17 @@
         # get db
         return self._vfs_media.client
 
+    def _vfs_mtime(self):
+        # return mtime
+        return 0
+
+    def _vfs_changed(self):
+        return self._vfs_mtime() != self._vfs_data['mtime']
+
+
+    def _vfs_tree(self):
+        return ParentIterator(self)
+
     
     def getattr(self, key):
         # FIXME: make sure we have db data
@@ -94,7 +107,22 @@
     def keys(self):
         return self._vfs_data.keys()
 
-    
+
+class ParentIterator(object):
+
+    def __init__(self, item):
+        self.item = item
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if not self.item:
+            raise StopIteration
+        ret = self.item
+        self.item = self.item._vfs_parent
+        return ret
+
 class Directory(Item):
     """
     A directory based item.
@@ -110,6 +138,8 @@
             id = None
             self.filename = parent.filename + data + '/' 
             data = { 'name': data, 'mtime': UNKNOWN }
+            if parent and parent._vfs_id:
+                data['parent_type'], data['parent_id'] = parent._vfs_id
             media = parent._vfs_media
         elif isinstance(parent, Directory):
             # db data
@@ -131,8 +161,8 @@
     def listdir(self):
         if not self._vfs_id:
             # item is not in db, request information now
-            
self._vfs_database_update(self._vfs_db().vfs_request(self.filename[:-1]))
-        return self._vfs_db().query(parent=self).get()
+            
self._vfs_database_update(self._vfs_db()._vfs_request(self.filename[:-1]))
+        return self._vfs_db().query(parent=self)
         
 
     def _vfs_listdir(self):
@@ -151,6 +181,32 @@
         result += [ ( x, False ) for x in listdir if not x.startswith('.') ]
         result.sort(lambda x,y: cmp(x[0], y[0]))
         return result
+
+
+    def _vfs_os_listdir(self):
+        if hasattr(self, '_vfs_os_listdir_cache'):
+            return self._vfs_os_listdir_cache
+        
+        try:
+            result = [ (x, self.filename + x) for x in 
os.listdir(self.filename)
+                       if not x.startswith('.') ]
+        except OSError:
+            return []
+
+        media = self._vfs_media
+        overlay = media.overlay + '/' + self.filename[len(media.directory):]
+        try:
+            result += [ ( x, overlay + x ) for x in os.listdir(overlay) \
+                        if not x.startswith('.') and not x in listdir ]
+        except OSError:
+            pass
+        self._vfs_os_listdir_cache = result
+        return result
+        
+    def _vfs_mtime(self):
+        # TODO: add overlay dir to mtime
+        return os.stat(self.filename)[stat.ST_MTIME]
+    
         
 #     def listdir(self):
 #         """
@@ -196,6 +252,8 @@
             id = None
             self.filename = parent.filename + data
             data = { 'name': data, 'mtime': UNKNOWN }
+            if parent and parent._vfs_id:
+                data['parent_type'], data['parent_id'] = parent._vfs_id
             media = parent._vfs_media
         elif isinstance(parent, Directory):
             # db data
@@ -207,6 +265,21 @@
         self._vfs_overlay = overlay
 
 
+    def _vfs_mtime(self):
+        # mtime is the the mtime for all files having the same
+        # base. E.g. the mtime of foo.jpg is the sum of the
+        # mtimeof foo.jpg and foo.jpg.xml or for foo.mp3 the
+        # mtime is the sum of foo.mp3 and foo.jpg.
+        search = self._vfs_data['name']
+        if search.rfind('.') > 0:
+            search = search[:search.rfind('.')]
+        mtime = 0
+        for basename, filename in self._vfs_parent._vfs_os_listdir():
+            if basename.startswith(search):
+                mtime += os.stat(filename)[stat.ST_MTIME]
+        return mtime
+
+
     def __repr__(self):
         """
         Convert object to string (usefull for debugging)
@@ -219,15 +292,3 @@
 
 # make it possible to override these
 
-def create_dir(data, parent):
-    """
-    Create a Directory item.
-    """
-    return Directory(data, parent)
-
-    
-def create_file(data, parent, overlay=False):
-    """
-    Create a File item.
-    """
-    return File(data, parent, overlay)

Modified: trunk/WIP/vfs/src/monitor.py
==============================================================================
--- trunk/WIP/vfs/src/monitor.py        (original)
+++ trunk/WIP/vfs/src/monitor.py        Fri Feb 17 19:56:27 2006
@@ -38,7 +38,7 @@
 
 # kaa imports
 from kaa.base.weakref import weakref
-from kaa.notifier import OneShotTimer, WeakTimer
+from kaa.notifier import OneShotTimer, WeakTimer, Timer, execute_in_timer
 
 # kaa.vfs imports
 import parser
@@ -55,7 +55,7 @@
         self.id = id
 
     def __call__(self, *args, **kwargs):
-        self.remote(self.id, __ipc_oneway=True, *args, **kwargs)
+        self.remote(self.id, __ipc_oneway=True, __ipc_noproxy_args=True, 
*args, **kwargs)
 
 
 class Monitor(object):
@@ -71,46 +71,79 @@
         self._db = db
         self._query = query
         self._checker = None
-        if self._query.has_key('dirname') and \
-           (not self._query.has_key('recursive') or not 
self._query['recursive']):
-            # TODO: use inotify for monitoring, this will also fix the
-            # problem when files grow because they are copied right
-            # now and the first time we had no real information
-            dirname = self._query['dirname']
-            for m in self._db._mountpoints:
-                if dirname.startswith(m.directory):
-                    break
-            WeakTimer(self.check, dirname, m).start(1)
-        if self._query.has_key('device'):
-            # monitor a media
-            # TODO: support other stuff except cdrom
-            # FIXME: support removing the monitor :)
-            cdrom.monitor(query['device'], weakref(self), db, self._server)
-            
+        self.items = self._db.query(**self._query)
+        self._scan(True)
+        self._poll()
+
+#         if self._query.has_key('dirname') and \
+#            (not self._query.has_key('recursive') or not 
self._query['recursive']):
+#             # TODO: use inotify for monitoring, this will also fix the
+#             # problem when files grow because they are copied right
+#             # now and the first time we had no real information
+#             dirname = self._query['dirname']
+#             for m in self._db._mountpoints:
+#                 if dirname.startswith(m.directory):
+#                     break
+#             WeakTimer(self.check, dirname, m).start(1)
+#         if self._query.has_key('device'):
+#             # monitor a media
+#             # TODO: support other stuff except cdrom
+#             # FIXME: support removing the monitor :)
+#             cdrom.monitor(query['device'], weakref(self), db, self._server)
             
-    def check(self, dirname, mountpoint):
+
+    @execute_in_timer(WeakTimer, 1)
+    def _poll(self):
         if self._checker:
             # still checking
             return True
-        current = util.listdir(dirname, mountpoint)
+        current = self._db.query(**self._query)
         if len(current) != len(self.items):
-            OneShotTimer(self.update, True).start(0)
+            self.callback('changed')
+            self.items = current
+            self._scan()
             return True
-        for pos, url in enumerate(current):
-            if self.items[pos].url != url:
-                OneShotTimer(self.update, True).start(0)
+        for pos, c in enumerate(current):
+            if self.items[pos].url != c.url:
+                self.items = current
+                self._scan()
+                self.callback('changed')
                 return True
         return True
 
 
-    def update(self, send_checked=True):
-        to_check = []
-        import time
-        t1 = time.time()
-        self.items = self._db.query(**self._query)
-        print 'monitor query took', time.time() - t1
+    def _scan(self, notify=False):
+        self._scan_step(self.items[:], [], notify)
+
+        
+    @execute_in_timer(Timer, 0.001, type='once')
+    def _scan_step(self, items, changed, notify):
+        """
+        Find changed items in 'items' and add them to changed.
+        """
+        if not items:
+            self._update(changed, notify)
+            return False
+        c = 0
+        while items:
+            c += 1
+            if c > 20:
+                return True
+            i = items.pop(0)
+            # FIXME: check parents
+            if i._vfs_changed():
+                changed.append(weakref(i))
+        return True
+
+
+    def _update(self, changed, notify):
+        self._checker = weakref(parser.Checker(weakref(self), self._db, 
changed, notify))
+
 
-        return
+    def send_update(self, changed):
+        changed = [ (x.url, x._vfs_data) for x in changed ]
+        changed.sort(lambda x,y: cmp(x[0], y[0]))
+        self.callback('updated', changed)
     
     #     if self._query.has_key('device'):
 #             log.info('unable to update device query, just send notification 
here')
@@ -164,9 +197,9 @@
 #             self.callback('checked')
 
 
-    def __str__(self):
+    def __repr__(self):
         return '<vfs.Monitor for %s>' % self._query
 
 
     def __del__(self):
-        log.debug('del %s' % self)
+        log.debug('del %s', repr(self))

Modified: trunk/WIP/vfs/src/parser.py
==============================================================================
--- trunk/WIP/vfs/src/parser.py (original)
+++ trunk/WIP/vfs/src/parser.py Fri Feb 17 19:56:27 2006
@@ -48,37 +48,9 @@
 # get logging object
 log = logging.getLogger('vfs')
 
-def get_mtime(item):
-    if not item.filename:
-        log.info('no filename == no mtime :(')
-        return 0
-    if not item._vfs_parent:
-        log.info('no parent == no mtime :(')
-        return 0
-
-    if item._vfs_isdir:
-        # TODO: add overlay dir to mtime
-        return os.stat(item.filename)[stat.ST_MTIME]
-
-    # mtime is the the mtime for all files having the same
-    # base. E.g. the mtime of foo.jpg is the sum of the
-    # mtimeof foo.jpg and foo.jpg.xml or for foo.mp3 the
-    # mtime is the sum of foo.mp3 and foo.jpg.
-
-    search = item.basename
-    if search.rfind('.') > 0:
-        search = search[:search.rfind('.')]
-
-    mtime = 0
-    for basename, url in item.parent.os_listdir():
-        if basename.startswith(search):
-            mtime += os.stat(url[5:])[stat.ST_MTIME]
-    return mtime
-
-
 def parse(db, item, store=False):
     print 'check', item
-    mtime = get_mtime(item)
+    mtime = item._vfs_mtime()
     if not mtime:
         log.info('oops, no mtime %s' % item)
         return
@@ -140,30 +112,46 @@
 
 
 class Checker(object):
-    def __init__(self, monitor, db, items):
+    def __init__(self, monitor, db, items, notify):
         self.monitor = monitor
         self.db = db
         self.items = items
         self.max = len(items)
         self.pos = 0
+        self.updated = []
+        self.do_notify = notify
         Timer(self.check).start(0.01)
 
 
     def check(self):
 
+        if self.items:
+            self.pos += 1
+            item = self.items[0]
+            self.items = self.items[1:]
+            if item:
+                self.notify('progress', self.pos, self.max, item.url)
+                parse(self.db, item)
+                if item._vfs_id:
+                    self.monitor.send_update([item])
+                else:
+                    self.updated.append(item)
+
         if not self.items:
             self.db.commit()
             if self.monitor:
+                self.monitor.callback('changed')
+            if self.monitor and self.do_notify:
                 self.monitor.callback('checked')
-            if self.monitor:
-                self.monitor.update(False)
+
+        updated = []
+        while self.updated and self.updated[0]._vfs_id:
+            updated.append(self.updated.pop(0))
+        if updated:
+            self.monitor.send_update(updated)
+
+        if not self.items:
             return False
-        self.pos += 1
-        item = self.items[0]
-        self.items = self.items[1:]
-        if item:
-            self.notify('progress', self.pos, self.max, item.url)
-            parse(self.db, item)
         return True
 
 

Modified: trunk/WIP/vfs/src/query.py
==============================================================================
--- trunk/WIP/vfs/src/query.py  (original)
+++ trunk/WIP/vfs/src/query.py  Fri Feb 17 19:56:27 2006
@@ -57,28 +57,15 @@
         self._query = query
         self._monitor = None
         self._client = client
-        self._result = []
-        result = self._client.database.query(**query)
-        if isinstance(result, list):
-            for r in result:
-                self._result.append(r)
-        else:
-            self._result.append(result)
-    
-
-    def get(self):
-        """
-        Get the result of the query.
-        """
-        if self._query.has_key('device'):
-            return self._result
-        return self._result[:]
 
+        self.result = self._client.database.query(**query)
+    
 
     def _vfs_connect(self, monitor):
         """
         Connect message from server.
         """
+        print 'CONNECT', monitor
         self._monitor = monitor
 
 
@@ -94,74 +81,42 @@
         """
         Checked message from server.
         """
-        # The server checked the query, we should redo the query
-        # to get possible updates.
-        result = self._client.database.query(**self._query)
-        log.info('check db results against current list of items')
-        
-        if self._query.has_key('device'):
-            self._result = result
-            self._result.db = self._client
-            self.signals['changed'].emit()
-            return
-        
-        changed = False
-        if not result or not hasattr(result[0], 'url'):
-            # normal string results
-            if result != self._result:
-                self._result = result
-                self.signals['changed'].emit()
-            self.signals['up-to-date'].emit()
-            return
-
-        # check old and new item lists. Both lists are sorted, so
-        # checking can be done with simple cmp of the urls.
-        for pos, dbitem in enumerate(result):
-            if not len(self._result) > pos:
-                # change the internal db of the item to out client
-                dbitem.db = self._client
-                self._result.append(dbitem)
-                changed = True
-                continue
-            current = self._result[pos]
-            while current and dbitem.url > current.url:
-                self._result.remove(current)
-                if len(self._result) > pos:
-                    current = self._result[pos]
-                else:
-                    current = None
-                changed = True
-            if current and dbitem.url == current.url:
-                if current.data['mtime'] != dbitem.data['mtime'] or \
-                   current.dbid != dbitem.dbid:
-                    changed = True
-                    current.data = dbitem.data
-                    current.dbid = dbitem.dbid
-                # TODO: this is not 100% correct. Maybe the parent changed, or
-                # the parent of the parent and we have now a new cover
-                current.parent = dbitem.parent
-                continue
-            # change the internal db of the item to out client
-            dbitem.db = self._client
-            changed = True
-            self._result.insert(pos, dbitem)
-
-        if len(self._result) > pos + 1:
-            changed = True
-            self._result = self._result[:pos+1]
-
-        if changed:
-            # send changed signal
-            log.debug('db has changed for %s, send signal %s'\
-                      % (self._query, self.signals['changed']._callbacks))
-            self.signals['changed'].emit()
-        # send up-to-date signal
-        self.signals['up-to-date'].emit()
+        return
+
+
+    def _vfs_updated(self, items):
+        """
+        Checked message from server.
+        """
+        print 'UPDATE'
+        url, data = items.pop(0)
+        for r in self.result:
+            if r.url == url:
+                r._vfs_database_update(data)
+                if not items:
+                    break
+                url, data = items.pop(0)
+        if items:
+            log.error('not all items found')
 
 
-    def __str__(self):
+    def _vfs_changed(self):
+        self.result = self._client.database.query(**self._query)
+
+        
+    def __repr__(self):
         """
         Convert object to string (usefull for debugging)
         """
         return '<vfs.Client.Query for %s>' % self._query
 
+
+    def __del__(self):
+        """
+        Memory debug
+        """
+        print 'del', repr(self)
+
+
+    def __iter__(self):
+        return self.result.__iter__()

Modified: trunk/WIP/vfs/src/server.py
==============================================================================
--- trunk/WIP/vfs/src/server.py (original)
+++ trunk/WIP/vfs/src/server.py Fri Feb 17 19:56:27 2006
@@ -59,7 +59,8 @@
     """
     def __init__(self, dbdir):
         self._db = Database(dbdir, None)
-
+        self._next_client = 0
+        
         # files
         
         self.register_file_type_attrs("video",
@@ -104,7 +105,7 @@
 
         # list of current clients
         self._clients = []
-
+        
         # add root mountpoint
         self.add_mountpoint(None, '/')
         self.set_mountpoint('/', 'kaa.vfs.root')
@@ -131,18 +132,23 @@
         return self._db.register_object_type_attrs('track_%s' % name, **kwargs)
 
 
-    def monitor(self, callback, id, **query):
+    def monitor(self, client_id, request_id, query):
         """
         Create a monitor object to monitor a query for a client.
         """
+        print 'MONITOR', client_id, request_id, query
         if 'parent' in query:
             type, id = query['parent']
             query['parent'] = self._db.query(type=type, id=id)[0]
 
-        monitor = Monitor(callback, self._db, self, id, query)
+        for id, client, callback in self._clients:
+            if id == client_id:
+                break
+        else:
+            raise AttributeError('Unknown client id %s', client_id)
+        monitor = Monitor(callback, self._db, self, request_id, query)
         log.debug('create %s' % monitor)
-        callback(id, 'connect', monitor)
-        monitor.update()
+        callback(request_id, 'connect', monitor)
         return None
     
 
@@ -151,7 +157,7 @@
         Add a mountpoint to the system.
         """
         if self._db.add_mountpoint(device, directory):
-            for client in self._clients:
+            for id, client, notification in self._clients:
                 client.database.add_mountpoint(device, directory, 
__ipc_oneway=True)
 
 
@@ -160,20 +166,22 @@
         Set mountpoint to the given name (e.g. load media)
         """
         if self._db.set_mountpoint(directory, name):
-            for client in self._clients:
+            for id, client, notification in self._clients:
                 client.database.set_mountpoint(directory, name)
             return True
         return False
 
         
-    def connect(self, client):
+    def connect(self, client, callback):
         """
         Connect a new client to the server.
         """
-        self._clients.append(client)
+        self._next_client += 1
+        self._clients.append((self._next_client, client, callback))
         for device, directory, name in self._db.get_mountpoints():
             client.database.add_mountpoint(device, directory)
             client.database.set_mountpoint(directory, name)
+        return self._next_client
 
 
     def update(self, items):
@@ -186,13 +194,14 @@
         self._db.commit()
 
         
-    def vfs_request(self, filename):
+    def request(self, filename):
         self._db.commit()
         data = self._db.query(filename=filename)
         items = []
-        while not data._vfs_id:
-            items.append(data)
-            data = data._vfs_parent
+        for i in data._vfs_tree():
+            if i._vfs_id:
+                break
+            items.append(i)
         while items:
             parser.parse(self._db, items.pop(), store=True)
         self._db.commit()


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to