Hi,

nobody complained, therefore I think we should commit this to cvs. I am not sure, if it is better to remove the (commented) debug code now or later (don't know if someone tested this patch, Here it works fine. But for a final test I need someone with this patch on MP).

Maik



Maik Justus schrieb am 28.01.2007 21:49:
Hi,

sorry, the first sentence in the description was wrong. It should look like this:
What the patch does:
Every time a path is stored in a path-cache of a property node, the referenced node adds a link to this path-cache. Therefore a node knows all other nodes, which references him in their path-cache.


Maik Justus schrieb am 28.01.2007 21:37:
Hi,

here is a patch, which adds remove functionality to the patch cache (hash-table) of the property tree.
What the patch does:
Every time a path is stored in a path-cache of a property node, the referenced hash table adds a link to this path-cache. Therefore a node knows all other nodes, which references him in their path-cache. If a node is removed, it and all children tell all patch-caches, which link to them, to delete this entries. Therefore it is save now, to address a node by its name, even if a node with the same name was deleted before (e.g. the AI/ tree is very dynamic).

The property tree is a very central part of flightgear. Therefore I decided to comment out my debug outputs instead of deleting them (maybe it's easier to check the functionality of the patch). Even the _value member of SGPropertyNode::hash_table is only for the debug output.

If noone complains, I will post a patch without the debug stuff to be committed to cvs soon.

(With this patch and the multiplayer patch (in cvs) aerotow should work stable over the net).

Maik

Maik Justus schrieb am 22.01.2007 01:21:
Hi just to clarify:

if I wrote delete, I meant not delete as cpp defines delete. I thought of removing a node.

Maik

Maik Justus schrieb am 22.01.2007 01:11:
Hi,

the patch-cache of the property tree is not designed for node-deleting. But the multiplayer code deletes nodes deletes nodes very often. If you access such nodes by name, which is necessary to acces multiplayer-nodes (you can not store a pointer, tho node could be deleted meanwhile), you often get a pointer to a already deleted node. As a result, aerotowing often fails, if one player was removed from the multiplayer list for a short time. As an ugly fix, you can switch off the path cache and aerotow works as expected. As a solution I think of a vector of path caches at every node, which stores all path caches, if they are pointing to this node. If a node is removed, all linked path caches get this information and the link can be deleted. This must be done for all child-nodes, too. (one question: which member of SGPropertyNode is called if a node is removed from the tree?)

Maik


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel


Index: props.cxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/props/props.cxx,v
retrieving revision 1.26
diff -u -p -r1.26 props.cxx
--- props.cxx   22 Oct 2006 13:08:09 -0000      1.26
+++ props.cxx   28 Jan 2007 20:18:53 -0000
@@ -909,6 +909,19 @@ SGPropertyNode::getChildren (const char 
   return children;
 }
 
+void
+SGPropertyNode::removeTreeFromPathCaches()
+{
+  //if(_linkedNodes.size())  cout<<"removing tree from "<< _linkedNodes.size() 
<<" path caches '"<<getPath()<<"'" << endl;
+  for(unsigned i=0; i<_linkedNodes.size(); i++)
+  {
+    _linkedNodes[i]->eraseNodeByPtr(this);
+  }
+  _linkedNodes.clear();
+  for (unsigned i = 0; i < _children.size(); ++i)
+    _children[i]->removeTreeFromPathCaches();
+}
+
 
 /**
  * Remove child by position.
@@ -931,6 +944,7 @@ SGPropertyNode::removeChild (int pos, bo
      _path_cache->erase(node->getName()); // EMH - TODO: Take "index" into 
account!
   node->setAttribute(REMOVED, true);
   node->clearValue();
+  node->removeTreeFromPathCaches();
   fireChildRemoved(node);
   return node;
 }
@@ -967,6 +981,29 @@ SGPropertyNode::removeChildren (const ch
 }
 
 
+  /**
+   * remove a linked node
+   */
+bool
+SGPropertyNode::removeLinkedNode (SGHashTable_ptr node)
+{
+  //cout<<"trying to remove a linked Node of '"<<getPath()<<"', linked by 
'"<<node->_value->getPath()<<"':";
+  for(unsigned i=0; i<_linkedNodes.size(); i++)
+  {
+    if (_linkedNodes[i]==node)
+    {
+      vector<SGHashTable_ptr>::iterator it = _linkedNodes.begin();
+      it += i;
+      _linkedNodes.erase(it);
+      //cout <<"ok"<<endl;
+      return true;
+    }
+  }
+  //cout <<"error, not found!"<<endl;
+  return false;
+}
+
+
 const char *
 SGPropertyNode::getDisplayName (bool simplify) const
 {
@@ -1741,8 +1778,7 @@ SGPropertyNode *
 SGPropertyNode::getNode (const char * relative_path, bool create)
 {
   if (_path_cache == 0)
-    _path_cache = new hash_table;
-
+    _path_cache = new hash_table(this);
   SGPropertyNode * result = _path_cache->get(relative_path);
   if (result == 0) {
     vector<PathComponent> components;
@@ -2210,11 +2246,17 @@ SGPropertyNode::hash_table::bucket::eras
   }
 }
 
-
+/*
 SGPropertyNode::hash_table::hash_table ()
   : _data_length(0),
     _data(0)
 {
+}*/
+SGPropertyNode::hash_table::hash_table (SGPropertyNode * value)
+  : _data_length(0),
+    _data(0)
+{
+  _value=value;
 }
 
 SGPropertyNode::hash_table::~hash_table ()
@@ -2254,6 +2296,8 @@ SGPropertyNode::hash_table::put (const c
   }
   entry * e = _data[index]->get_entry(key, true);
   e->set_value(value);
+  value->addLinkedNode(this);
+  //cout<<"adding linked Note '"<<_value->getPath() <<"' to 
'"<<value->getPath()<<"'"<<endl;
 }
 
 void
@@ -2264,7 +2308,39 @@ SGPropertyNode::hash_table::erase (const
   unsigned int index = hashcode(key) % _data_length;
   if (_data[index] == 0)
     return;
+  _data[index]->get_entry(key, true)->get_value()->removeLinkedNode(this);
   _data[index]->erase(key);
+  _data[index]=0;
+}
+
+bool
+SGPropertyNode::hash_table::bucket::eraseNodeByPtr(SGPropertyNode * value)
+{
+  int i;
+  for (i = 0; i < _length; i++) {
+    if (_entries[i]->get_value()==value)
+    {
+      for (++i; i < _length; i++) {
+        _entries[i-1] = _entries[i];
+      }
+      _length--;
+      return true;
+    }
+  }
+  return false;
+}
+
+
+bool
+SGPropertyNode::hash_table::eraseNodeByPtr(SGPropertyNode * value)
+{
+  unsigned int d;
+  //cout<<"deleting '"<<value->getPath()<<"' at '"<<_value->getPath()<<"':";
+
+  for (d = 0; d < _data_length; d++)
+    if(_data[d])  if(_data[d]->eraseNodeByPtr(value)) {/*cout << 
"ok!"<<endl;*/return true;}
+  //cout<<"error!"<<endl;
+  return false;
 }
 
 unsigned int
Index: props.hxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/props/props.hxx,v
retrieving revision 1.18
diff -u -p -r1.18 props.hxx
--- props.hxx   14 Mar 2006 15:55:24 -0000      1.18
+++ props.hxx   28 Jan 2007 20:18:56 -0000
@@ -457,7 +457,8 @@ private:
 class SGPropertyNode;
 typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
 typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
-
+//class hash_table;
+//typedef SGSharedPtr<hash_table> SGHashTable_ptr;
 
 /**
  * The property change listener interface.
@@ -489,6 +490,7 @@ private:
  */
 class SGPropertyNode : public SGReferenced
 {
+
 public:
 
   /**
@@ -781,7 +783,7 @@ public:
    * Set a single mode attribute for the property node.
    */
   void setAttribute (Attribute attr, bool state) {
-    (state ? _attr |= attr : _attr &= ~attr);
+    (state ? _attr |= attr : _attr &= ~attr);//hier auch die Child
   }
 
 
@@ -1134,6 +1136,13 @@ public:
   void clearValue ();
 
 
+  /**
+   * tell all linked nodes (path cache entries) that
+   * this node and all childes are removed
+   */
+  void removeTreeFromPathCaches();
+
+
 protected:
 
   void fireValueChanged (SGPropertyNode * node);
@@ -1184,6 +1193,7 @@ private:
 
 
   class hash_table;
+  typedef hash_table*  SGHashTable_ptr;
 
   int _index;
   string _name;
@@ -1193,6 +1203,7 @@ private:
   SGPropertyNode * _parent;
   vector<SGPropertyNode_ptr> _children;
   vector<SGPropertyNode_ptr> _removedChildren;
+  vector<SGHashTable_ptr> _linkedNodes;//by hash
   mutable string _path;
   mutable string _buffer;
   hash_table * _path_cache;
@@ -1222,10 +1233,28 @@ private:
 
   vector <SGPropertyChangeListener *> * _listeners;
 
+public:
+  //
+  // linked nodes (this nodes have references to this Node in their hash table)
+  //
+
 
+    /**
+   * add a linked node (a Hash Table o another Node which references this node)
+   */
+  void addLinkedNode (const SGHashTable_ptr node) { 
_linkedNodes.push_back(node); }
+
+
+  /**
+   * remove a linked node (a Hash Table o another Node which references this 
node)
+   */
+  bool  removeLinkedNode (SGHashTable_ptr node);
+
+
+private:
 
   /**
-   * A very simple hash table with no remove functionality.
+   * A very simple hash table with remove functionality.
    */
   class hash_table {
   public:
@@ -1256,6 +1285,7 @@ private:
       ~bucket ();
       entry * get_entry (const char * key, bool create = false);
       void erase(const char * key);
+      bool eraseNodeByPtr(SGPropertyNode * value);
     private:
       int _length;
       entry ** _entries;
@@ -1263,11 +1293,13 @@ private:
 
     friend class bucket;
 
-    hash_table ();
+    hash_table (SGPropertyNode * value);
+    SGPropertyNode * _value; //only for debug
     ~hash_table ();
     SGPropertyNode * get (const char * key);
     void put (const char * key, SGPropertyNode * value);
     void erase(const char * key);
+    bool eraseNodeByPtr(SGPropertyNode * value);
 
   private:
     unsigned int hashcode (const char * key);
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to