Author: bargull
Date: 2007-09-15 12:47:13 -0700 (Sat, 15 Sep 2007)
New Revision: 6496

Modified:
   openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzDatapointer.lzs
   openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzParsedPath.lzs
Log:
Change 20070915-bargull-2 by [EMAIL PROTECTED] on 2007-09-15 21:39:09
    in /home/Admin/src/svn/openlaszlo/branches/legals
    for http://svn.openlaszlo.org/openlaszlo/branches/legals

Summary: Fix for memory leak in LzParsedPath

New Features:

Bugs Fixed:
LPP-4214 - "LzDatapointer#ppcache" leaks memory

Technical Reviewer: hminsky
QA Reviewer: ptw
Doc Reviewer: (pending)

Documentation:
Added "getContext()" to LzParsedPath which replaces the direct access to 
"context"-member of "LzParsedPath". 
With this change the "context"-member of LzParsedPath is only used for 
"new"-datasets (xpath:"new:/foo/bar").
This API-Change was necessary, because LzParsedPath was holding a reference to 
a dataset through his "context"-member,
but even if this dataset was destroyed, the reference was not cleared.
This led to two bugs:
1. it was preventing garbage-collection
2. when a user created a new dataset with the same name, cached LzParsedPaths 
were still pointing to the old dataset, 
    which gave some strange errors i.e. when a user used xpath:"ds:/foo/text()" 
(cached) this gave the old results, 
    but xpath:"ds:/foo" (non-cached) and then a LzDatapointer#getNodeText() 
gave new results. 
    For better understanding of this issue, please see the attached testcase at 
LPP-4214.

Release Notes:

Details:
The marked memory leaks in the testcase are covered by LPP-4688

Tests:
Testcase is attached at LPP-4214



Modified: openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzDatapointer.lzs
===================================================================
--- openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzDatapointer.lzs   
2007-09-15 19:44:42 UTC (rev 6495)
+++ openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzDatapointer.lzs   
2007-09-15 19:47:13 UTC (rev 6496)
@@ -232,7 +232,8 @@
   */
 function xpathQuery ( p ){ 
     var pp = this.parsePath ( p );
-    var nodes = this.__LZgetNodes( pp , pp.context ? pp.context : this.p);
+    var ppcontext = pp.getContext(this);
+    var nodes = this.__LZgetNodes( pp , ppcontext ? ppcontext : this.p);
     if ( ! nodes ) return null;
 
     if ( pp.aggOperator != null ){
@@ -343,10 +344,11 @@
 
     this.xpath = p;
     this.parsedPath = this.parsePath( p );
+    var ppcontext = this.parsedPath.getContext(this);
     
     if ( this.rerunxpath && 
          this.parsedPath.hasDotDot && 
-         !this.parsedPath.context  ){
+         !ppcontext  ){
         //ruh roh
         this.__LZspecialDotDot = true;
     } else {
@@ -356,7 +358,7 @@
     }
 
     if ( canvas.__LZoldOnData ){
-        if ( this.parsedPath.context && ! this.parsedPath.selectors.length &&
+        if ( ppcontext && ! this.parsedPath.selectors.length &&
             !this.rerunxpath ){
             this.__LZspecialOndata = true;
         } else if ( this.__LZspecialOndata ){
@@ -364,7 +366,7 @@
         }
     }
 
-    this.setDataContext( this.parsedPath.context );
+    this.setDataContext( ppcontext );
 
     return  this.runXPath(  );
 }
@@ -578,13 +580,8 @@
 function parsePath ( pa ){
     if (pa instanceof LzDatapath) pa = pa.xpath;
     var q = this.ppcache[ pa ];
-    if ( q ) {
-        var l = q['islocaldata'] 
-        if (l) {
-            q.context = this.getLocalDataContext(l);
-        } 
-    } else {
-        var q = new LzParsedPath( pa, this);
+    if (q == null) {
+        q = new LzParsedPath(pa, this);
         this.ppcache[ pa ] = q;
     }
     return q;

Modified: openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzParsedPath.lzs
===================================================================
--- openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzParsedPath.lzs    
2007-09-15 19:44:42 UTC (rev 6495)
+++ openlaszlo/branches/legals/WEB-INF/lps/lfc/data/LzParsedPath.lzs    
2007-09-15 19:47:13 UTC (rev 6496)
@@ -13,6 +13,120 @@
   */
 class LzParsedPath {
 
+  /** 
+    * The xpath for this LzParsedPath
+    * 
+    * @access private
+    */
+  var path = null;
+  
+  /** 
+    * Array containing selector-operations for this LzParsedPath
+    * 
+    * @access private
+    */
+  var selectors = null;
+  
+  /** 
+    * Pointer to the dataset (if part of the path) otherwise null
+    * (currently only used for "new"-datasets, see deprecated message)
+    * 
+    * @access private
+    * @deprecated may lead to memory leaks (LPP-4214)
+    */
+  var context = null;
+  
+  /** 
+    * Name of the dataset (if part of the path)
+    * 
+    * @access private
+    */
+  var dsetname = null;
+  
+  /** 
+    * Name of the datasource (if part of the path)
+    * 
+    * @access private
+    */
+  var dsrcname = null;
+  
+  /** 
+    * Array containing the path to the local-dataset
+    * 
+    * @access private
+    */
+  var islocaldata = null;
+  
+  /* Parsing information */
+  
+  /** 
+    * One of: "nodeName", "__LZgetText", "serialize", "attributes" 
+    * or "attributes.xxx" with 'xxx' as an attribute-name
+    * 
+    * @access private
+    */
+  var operator = null;
+  
+  /** 
+    * One of: "position" or "last" 
+    * 
+    * @access private
+    */
+  var aggOperator = null;
+  
+  /** 
+    * null or 0
+    * 
+    * @access private
+    */
+  var operatorArgs = null;
+  
+  /** 
+    * true if terminal operator is a attribute-selector, otherwise false
+    * 
+    * @access private
+    */
+  var hasAttrOper = false;
+  
+  /** 
+    * true if path contains a attribute-predicate
+    * 
+    * @access private
+    */
+  var hasOpSelector = false;
+  
+  /** 
+    * true if path contains ".." or "//", otherwise false
+    * 
+    * @access private
+    */
+  var hasDotDot = false;
+  
+  /** 
+    * Return the context for this LzParsedPath
+    * Should be used instead of accessing directly the deprecated field 
context. 
+    *
+    * @access private
+    */
+  function getContext ( dp ) {
+      if (this.context != null) {
+          return this.context;
+      } else {
+          if (this.islocaldata != null) {
+              return dp.getLocalDataContext(this.islocaldata);
+          } else {
+              if (this.dsrcname != null) {
+                  return (canvas[ this.dsrcname ])[ this.dsetname ];
+              } else {
+                  if (this.dsetname != null) {
+                      return canvas.datasets[ this.dsetname ];
+                  }
+              }
+          }
+      }
+      return null;
+  }
+  
   function initialize ( pa, node ){
     //split context part
     this.path = pa;
@@ -32,10 +146,11 @@
             if (dsrc == 'local') {
                 nowarn=true;
                 this.islocaldata = dset.split('.');
-                this.context = node.getLocalDataContext(this.islocaldata);
             } else {
                 //we have a datasource and a dataset
-                this.context =canvas[ dsrc ] [ dset ]; 
+                nowarn = ((canvas[ dsrc ])[ dset ] != null);
+                this.dsrcname = dsrc;
+                this.dsetname = dset;
             }
         } else {
             var name = LzParsedPath.trim( sourceparts[ 0 ] );
@@ -48,10 +163,11 @@
                 this.islocaldata = true; 
         */
             } else {
-                this.context =  canvas.datasets[ name ];
+                nowarn = (canvas.datasets[ name ] != null);
+                this.dsetname = name;
             }
         }
-        if ( this.context == null && nowarn != true){
+        if (nowarn != true){
             if ($debug) {
                 Debug.error( "couldn't find dataset for %w", pa );
             }
@@ -207,7 +323,6 @@
     //this.operator = "t" , "n" , or "a" plus "." and the attribute name 
     //text, name or attribute, respectively
 }
-var operatorArgs = null;
 
 /**
   * @access private


_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins

Reply via email to