Index: openacs-4/packages/acs-tcl/tcl/site-nodes-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/site-nodes-init.tcl,v
diff -u -r1.3 -r1.4
--- openacs-4/packages/acs-tcl/tcl/site-nodes-init.tcl 10 Sep 2002 22:22:14 -0000 1.3
+++ openacs-4/packages/acs-tcl/tcl/site-nodes-init.tcl 27 Nov 2003 15:25:18 -0000 1.4
@@ -6,4 +6,6 @@
}
+nsv_set site_nodes_mutex mutex [ns_mutex create]
+
site_node::init_cache
Index: openacs-4/packages/acs-tcl/tcl/site-nodes-procs-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/site-nodes-procs-oracle.xql,v
diff -u -r1.16 -r1.17
--- openacs-4/packages/acs-tcl/tcl/site-nodes-procs-oracle.xql 30 Sep 2003 12:10:03 -0000 1.16
+++ openacs-4/packages/acs-tcl/tcl/site-nodes-procs-oracle.xql 27 Nov 2003 15:25:18 -0000 1.17
@@ -9,52 +9,47 @@
-
+
- select site_node.url(site_nodes.node_id) as url,
- site_nodes.node_id,
- site_nodes.parent_id,
- site_nodes.name,
- site_nodes.directory_p,
- site_nodes.pattern_p,
- site_nodes.object_id,
- (select acs_objects.object_type
- from acs_objects
- where acs_objects.object_id = site_nodes.object_id) as object_type,
- apm_packages.package_key,
- apm_packages.package_id,
- apm_packages.instance_name,
- apm_package_types.package_type
- from site_nodes,
- apm_packages,
- apm_package_types
- where site_nodes.object_id = apm_packages.package_id(+)
- and apm_package_types.package_key (+) = apm_packages.package_key
+ select n.node_id,
+ n.parent_id,
+ n.name,
+ n.directory_p,
+ n.pattern_p,
+ n.object_id,
+ p.package_key,
+ p.package_id,
+ p.instance_name,
+ t.package_type
+ from apm_packages p,
+ apm_package_types t,
+ (select node_id, parent_id, name, directory_p, pattern_p, object_id,
+ rownum as nodes_rownum
+ from site_nodes
+ connect by parent_id = prior node_id
+ start with node_id = :node_id) n
+ where n.object_id = p.package_id(+)
+ and t.package_key (+) = p.package_key
+ order by n.nodes_rownum
- select site_node.url(site_nodes.node_id) as url,
- site_nodes.node_id,
- site_nodes.parent_id,
- site_nodes.name,
- site_nodes.directory_p,
- site_nodes.pattern_p,
- site_nodes.object_id,
- (select acs_objects.object_type
- from acs_objects
- where acs_objects.object_id = site_nodes.object_id) as object_type,
- apm_packages.package_key,
- apm_packages.package_id,
- apm_packages.instance_name,
- apm_package_types.package_type
- from site_nodes,
- apm_packages,
- apm_package_types
- where site_nodes.node_id = :node_id
- and site_nodes.object_id = apm_packages.package_id (+)
- and apm_package_types.package_key (+) = apm_packages.package_key
+ select n.node_id,
+ n.parent_id,
+ n.name,
+ n.directory_p,
+ n.pattern_p,
+ n.object_id,
+ p.package_key,
+ p.package_id,
+ p.instance_name,
+ t.package_type
+ from apm_packages p, apm_package_types t, site_nodes n
+ where n.node_id = :node_id
+ and n.object_id = p.package_id(+)
+ and t.package_key (+) = p.package_key
Index: openacs-4/packages/acs-tcl/tcl/site-nodes-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/site-nodes-procs-postgresql.xql,v
diff -u -r1.17 -r1.18
--- openacs-4/packages/acs-tcl/tcl/site-nodes-procs-postgresql.xql 28 Aug 2003 09:41:43 -0000 1.17
+++ openacs-4/packages/acs-tcl/tcl/site-nodes-procs-postgresql.xql 27 Nov 2003 15:25:18 -0000 1.18
@@ -9,48 +9,43 @@
-
+
- select site_node__url(site_nodes.node_id) as url,
- site_nodes.node_id,
- site_nodes.parent_id,
- site_nodes.name,
- site_nodes.directory_p,
- site_nodes.pattern_p,
- site_nodes.object_id,
- (select acs_objects.object_type
- from acs_objects
- where acs_objects.object_id = site_nodes.object_id) as object_type,
- apm_packages.package_key,
- apm_packages.package_id,
- apm_packages.instance_name,
- apm_package_types.package_type
- from site_nodes left join
- apm_packages on site_nodes.object_id = apm_packages.package_id left join
- apm_package_types using (package_key)
+ select n.node_id,
+ n.parent_id,
+ n.name,
+ n.directory_p,
+ n.pattern_p,
+ n.object_id,
+ p.package_key,
+ p.package_id,
+ p.instance_name,
+ t.package_type
+ from site_nodes n left join
+ apm_packages p on n.object_id = p.package_id left join
+ apm_package_types t using (package_key)
+ where n.tree_sortkey between site_node_get_tree_sortkey(:node_id)
+ and tree_right(site_node_get_tree_sortkey(:node_id))
+ order by n.tree_sortkey
- select site_node__url(site_nodes.node_id) as url,
- site_nodes.node_id,
- site_nodes.parent_id,
- site_nodes.name,
- site_nodes.directory_p,
- site_nodes.pattern_p,
- site_nodes.object_id,
- (select acs_objects.object_type
- from acs_objects
- where acs_objects.object_id = site_nodes.object_id) as object_type,
- apm_packages.package_key,
- apm_packages.package_id,
- apm_packages.instance_name,
- apm_package_types.package_type
- from site_nodes left join
- apm_packages on site_nodes.object_id = apm_packages.package_id left join
- apm_package_types using (package_key)
- where site_nodes.node_id = :node_id
+ select n.node_id,
+ n.parent_id,
+ n.name,
+ n.directory_p,
+ n.pattern_p,
+ n.object_id,
+ p.package_key,
+ p.package_id,
+ p.instance_name,
+ t.package_type
+ from site_nodes n left join
+ apm_packages p on n.object_id = p.package_id left join
+ apm_package_types t using (package_key)
+ where n.node_id = :node_id
Index: openacs-4/packages/acs-tcl/tcl/site-nodes-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/site-nodes-procs.tcl,v
diff -u -r1.47 -r1.48
--- openacs-4/packages/acs-tcl/tcl/site-nodes-procs.tcl 25 Nov 2003 04:13:47 -0000 1.47
+++ openacs-4/packages/acs-tcl/tcl/site-nodes-procs.tcl 27 Nov 2003 15:25:18 -0000 1.48
@@ -65,14 +65,7 @@
db_dml rename_node {}
- # Unset all cache entries under the old path
- foreach name [nsv_array names site_nodes "${node_url}*"] {
- nsv_unset site_nodes $name
- }
-
- foreach node_id [concat $node_id $child_node_ids] {
- update_cache -node_id $node_id
- }
+ update_cache -sync_children -node_id $node_id
}
ad_proc -public site_node::instantiate_and_mount {
@@ -162,33 +155,82 @@
ad_proc -private site_node::init_cache {} {
initialize the site node cache
} {
- nsv_array reset site_nodes [list]
- nsv_array reset site_node_urls [list]
-
- db_foreach select_site_nodes {} -column_array node {
- nsv_set site_nodes $node(url) [array get node]
- nsv_set site_node_urls $node(node_id) $node(url)
- }
-
+ set root_node_id [db_string get_root_node_id {}]
+ site_node::update_cache -sync_children -node_id $root_node_id
}
ad_proc -private site_node::update_cache {
+ {-sync_children:boolean}
{-node_id:required}
} {
- if { [db_0or1row select_site_node {} -column_array node] } {
- nsv_set site_nodes $node(url) [array get node]
- nsv_set site_node_urls $node(node_id) $node(url)
+ Brings the in memory copy of the site nodes hierarchy in sync with the
+ database version. Only updates the given node and its children.
+} {
+ # don't let any other thread try to do a concurrent update
+ # until cache is fully updated
+ ns_mutex lock [nsv_get site_nodes_mutex mutex]
- } else {
- set url [get_url -node_id $node_id]
+ with_finally -code {
- if {[nsv_exists site_nodes $url]} {
- nsv_unset site_nodes $url
- }
+ array set nodes [nsv_array get site_nodes]
+ array set urls [nsv_array get site_node_urls]
- if {[nsv_exists site_node_urls $node_id]} {
- nsv_unset site_node_urls $node_id
- }
+ if {[catch {set old_url $urls($node_id)}]} {
+ set old_url ""
+ }
+
+ if { ![empty_string_p $old_url] } {
+ # unset old nodes-subtree
+ if { $sync_children_p } {
+ array unset nodes "${old_url}*"
+ } else {
+ array unset nodes $old_url
+ }
+ }
+
+ # Note that in the queries below, we use connect by instead of site_node.url
+ # to get the URLs. This is less expensive.
+
+ if { $sync_children_p } {
+ set query_name select_child_site_nodes
+ } else {
+ set query_name select_site_node
+ }
+
+ db_foreach $query_name {} {
+ if {[empty_string_p $parent_id]} {
+ # url of root node
+ set url "/"
+ } else {
+ # append directory to url of parent node
+ set url $urls($parent_id)
+ append url $name
+ if { $directory_p == "t" } { append url "/" }
+ }
+ # save new url
+ set urls($node_id) $url
+
+ if { [empty_string_p package_id] } {
+ set object_type ""
+ } else {
+ set object_type "apm_package"
+ }
+
+ # save new node
+ set nodes($url) \
+ [list url $url node_id $node_id parent_id $parent_id name $name \
+ directory_p $directory_p pattern_p $pattern_p \
+ object_id $object_id object_type $object_type \
+ package_key $package_key package_id $package_id \
+ instance_name $instance_name package_type $package_type]
+ }
+
+ # update arrays
+ nsv_array reset site_nodes [array get nodes]
+ nsv_array reset site_node_urls [array get urls]
+
+ } -finally {
+ ns_mutex unlock [nsv_get site_nodes_mutex mutex]
}
}
Index: openacs-4/packages/acs-tcl/tcl/site-nodes-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/site-nodes-procs.xql,v
diff -u -r1.6 -r1.7
--- openacs-4/packages/acs-tcl/tcl/site-nodes-procs.xql 28 Aug 2003 09:41:43 -0000 1.6
+++ openacs-4/packages/acs-tcl/tcl/site-nodes-procs.xql 27 Nov 2003 15:25:18 -0000 1.7
@@ -25,4 +25,12 @@
+
+
+ select node_id
+ from site_nodes
+ where parent_id is null
+
+
+
Index: openacs-4/packages/acs-tcl/tcl/utilities-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/utilities-procs.tcl,v
diff -u -r1.58 -r1.59
--- openacs-4/packages/acs-tcl/tcl/utilities-procs.tcl 10 Nov 2003 17:23:02 -0000 1.58
+++ openacs-4/packages/acs-tcl/tcl/utilities-procs.tcl 27 Nov 2003 15:25:18 -0000 1.59
@@ -4107,6 +4107,59 @@
return [string range [sec_random_token] 0 $length]
}
+ad_proc -public with_finally {
+ -code:required
+ -finally:required
+} {
+ Execute CODE, then execute cleanup code FINALLY.
+ If CODE completes normally, its value is returned after
+ executing FINALLY.
+ If CODE exits non-locally (as with error or return), FINALLY
+ is executed anyway.
+
+ @param code Code to be executed that could throw and error
+ @param finally Cleanup code to be executed even if an error occurs
+} {
+ global errorInfo errorCode
+
+ # Execute CODE.
+ set return_code [catch {uplevel $code} string]
+ set s_errorInfo $errorInfo
+ set s_errorCode $errorCode
+
+ # As promised, always execute FINALLY. If FINALLY throws an
+ # error, Tcl will propagate it the usual way. If FINALLY contains
+ # stuff like break or continue, the result is undefined.
+ uplevel $finally
+
+ switch $return_code {
+ 0 {
+ # CODE executed without a non-local exit -- return what it
+ # evaluated to.
+ return $string
+ }
+ 1 {
+ # Error
+ return -code error -errorinfo $s_errorInfo -errorcode $s_errorCode $string
+ }
+ 2 {
+ # Return from the caller.
+ return -code return $string
+ }
+ 3 {
+ # break
+ return -code break
+ }
+ 4 {
+ # continue
+ return -code continue
+ }
+ default {
+ return -code $return_code $string
+ }
+ }
+}
+
ad_proc util_background_exec {
{-pass_vars ""}
{-name:required}
Index: openacs-4/packages/acs-tcl/tcl/test/site-nodes-test-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/test/site-nodes-test-procs.tcl,v
diff -u -r1.2 -r1.3
--- openacs-4/packages/acs-tcl/tcl/test/site-nodes-test-procs.tcl 25 Nov 2003 04:13:48 -0000 1.2
+++ openacs-4/packages/acs-tcl/tcl/test/site-nodes-test-procs.tcl 27 Nov 2003 15:24:46 -0000 1.3
@@ -8,6 +8,85 @@
aa_register_case -cats {
script
+} site_node_update_cache {
+ Test site_node::update_cache
+} {
+ aa_run_with_teardown -rollback -test_code {
+ # 1) mount /doc1 /doc2 /doc1/doc3
+ set doc1_name [ad_generate_random_string]
+ set doc2_name [ad_generate_random_string]
+ set doc3_name [ad_generate_random_string]
+ set node1_pkg_id [site_node::instantiate_and_mount \
+ -node_name $doc1_name \
+ -package_key acs-core-docs]
+ set node1_node_id [site_node::get_node_id -url "/$doc1_name"]
+ set node2_pkg_id [site_node::instantiate_and_mount \
+ -node_name $doc2_name \
+ -package_key acs-core-docs]
+ set node2_node_id [site_node::get_node_id -url "/$doc2_name"]
+ set node3_pkg_id [site_node::instantiate_and_mount \
+ -parent_node_id $node1_node_id \
+ -node_name $doc3_name \
+ -package_key acs-core-docs]
+ set node3_node_id [site_node::get_node_id -url "/$doc1_name/$doc3_name"]
+ set root_node_id [site_node::get_node_id -url /]
+ aa_equals "Verify url /doc1 for node1" [site_node::get_url -node_id $node1_node_id] "/$doc1_name/"
+ aa_equals "Verify url /doc1/doc3 for node3" [site_node::get_url -node_id $node3_node_id] "/$doc1_name/$doc3_name/"
+ aa_equals "Verify url /doc2 for node2" [site_node::get_url -node_id $node2_node_id] "/$doc2_name/"
+ # 2) rename /doc1 => doc4: Test /doc4 /doc4/doc3 /doc2
+ set doc4_name [ad_generate_random_string]
+ site_node::rename -node_id $node1_node_id -name $doc4_name
+ aa_equals "Check new url /doc4" [site_node::get_node_id -url "/$doc4_name"] $node1_node_id
+ aa_equals "Check new url /doc4/doc3" [site_node::get_node_id -url "/$doc4_name/$doc3_name"] $node3_node_id
+ aa_equals "Check old url /doc2" [site_node::get_node_id -url "/$doc2_name"] $node2_node_id
+ aa_equals "Make sure old url /doc1 now matches /" [site_node::get_node_id -url "/$doc1_name/"] $root_node_id
+ aa_equals "Make sure old url /doc1/doc3 now matches /" [site_node::get_node_id -url "/$doc1_name/$doc3_name/"] $root_node_id
+ aa_equals "Verify url /doc4 for node1" [site_node::get_url -node_id $node1_node_id] "/$doc4_name/"
+ aa_equals "Verify url /doc4/doc3 for node3" [site_node::get_url -node_id $node3_node_id] "/$doc4_name/$doc3_name/"
+ aa_equals "Verify url /doc2 for node2" [site_node::get_url -node_id $node2_node_id] "/$doc2_name/"
+ # 3) rename /node4 => doc5 without updating children in the cache: Test /doc5 /doc4/doc3 /doc2
+ set doc5_name [ad_generate_random_string]
+ db_dml rename_node1 {
+ update site_nodes
+ set name = :doc5_name
+ where node_id = :node1_node_id
+ }
+ site_node::update_cache -node_id $node1_node_id
+ aa_equals "Check url /doc5" [site_node::get_node_id -url "/$doc5_name"] $node1_node_id
+ aa_equals "Check url /doc4/doc3" [site_node::get_node_id -url "/$doc4_name/$doc3_name"] $node3_node_id
+ aa_equals "Check url /doc2" [site_node::get_node_id -url "/$doc2_name"] $node2_node_id
+ aa_equals "Make sure old url /doc1 now matches /" [site_node::get_node_id -url "/$doc1_name/"] $root_node_id
+ aa_equals "Make sure old url /doc1/doc3 now matches /" [site_node::get_node_id -url "/$doc1_name/$doc3_name/"] $root_node_id
+ aa_equals "Make sure old url /doc4 now matches /" [site_node::get_node_id -url "/$doc4_name/"] $root_node_id
+ aa_equals "Make sure url /doc5/doc3 now matches /doc5" [site_node::get_node_id -url "/$doc5_name/$doc3_name/"] $node1_node_id
+ aa_equals "Verify url /doc5 for node1" [site_node::get_url -node_id $node1_node_id] "/$doc5_name/"
+ aa_equals "Verify url /doc4/doc3 for node3" [site_node::get_url -node_id $node3_node_id] "/$doc4_name/$doc3_name/"
+ aa_equals "Verify url /doc2 for node2" [site_node::get_url -node_id $node2_node_id] "/$doc2_name/"
+ # 4) init_cache: Test /doc5 /doc5/doc3 /doc2
+ site_node::init_cache
+ aa_equals "Check url /doc5" [site_node::get_node_id -url "/$doc5_name"] $node1_node_id
+ aa_equals "Check url /doc5/doc3" [site_node::get_node_id -url "/$doc5_name/$doc3_name"] $node3_node_id
+ aa_equals "Check url /doc2" [site_node::get_node_id -url "/$doc2_name"] $node2_node_id
+ aa_equals "Make sure old url /doc1 now matches" [site_node::get_node_id -url "/$doc1_name/"] $root_node_id
+ aa_equals "Make sure old url /doc1/doc3 now matches" [site_node::get_node_id -url "/$doc1_name/$doc3_name/"] $root_node_id
+ aa_equals "Make sure old url /doc4 now matches" [site_node::get_node_id -url "/$doc4_name/"] $root_node_id
+ aa_equals "Make sure old url /doc4/doc3 now matches" [site_node::get_node_id -url "/$doc4_name/$doc3_name/"] $root_node_id
+ aa_equals "Verify url /doc5 for node1" [site_node::get_url -node_id $node1_node_id] "/$doc5_name/"
+ aa_equals "Verify url /doc5/doc3 for node3" [site_node::get_url -node_id $node3_node_id] "/$doc5_name/$doc3_name/"
+ aa_equals "Verify url /doc2 for node2" [site_node::get_url -node_id $node2_node_id] "/$doc2_name/"
+ # 5) delete doc3: Test /doc5 /doc2, nonexisting /doc5/doc3
+ site_node::unmount -node_id $node3_node_id
+ site_node::delete -node_id $node3_node_id
+ aa_equals "Check url /doc5" [site_node::get_node_id -url "/$doc5_name"] $node1_node_id
+ aa_equals "Check url /doc2" [site_node::get_node_id -url "/$doc2_name"] $node2_node_id
+ aa_equals "Make sure old url /doc5/doc3 now matches /doc5" [site_node::get_node_id -url "/$doc5_name/$doc3_name/"] $node1_node_id
+ aa_equals "Verify url /doc5 for node1" [site_node::get_url -node_id $node1_node_id] "/$doc5_name/"
+ aa_equals "Verify url /doc2 for node2" [site_node::get_url -node_id $node2_node_id] "/$doc2_name/"
+ }
+}
+
+aa_register_case -cats {
+ script
} site_node_closest_ancestor_package {
Test site_node::closest_ancestor_package
} {