Forum OpenACS Development: Using the function "ad_set_client_property".

Request notifications

Hi,

I have the following problem/doubt:

In order to avoid long URL's (and to make compatible the application with IE), I'm trying to use for some specially big variables the functions "ad_set_client_property"/"ad_get_client_property" instead of "export_vars".

The problem is that if I set with "ad_set_client_property" a lot of session variables, the values of some of these are lost.

The question are:

1) Is the problem above related with the util_memoize's size cache (and solved through the kernel parameter Caching/MaxSize)?

2) As I'm newbie and in special with the cache topics, I was trying to read something about it, and I found the following forum's entry: http://openacs.org/forums/message-view?message_id=1163553 . There, there is a phrase of Don that attracted my attention: "Long-term, I'd get rid of util_memoize entirely".
Under the light of this prhase, is some advice to come when it is wanted to pass variables of big size between pages?

Thanks a lot for the help.

Jorge.

Collapse
Posted by Dave Bauer on
Maybe you can describe more clearly what you are trying to accomplish. Why are you passing huge variables between pages like this?
Collapse
Posted by Jorge Couchet on
Hi Dave,

I have a chain of 12 form's, each one receiving values from the precedent one, and I'm not using the wizard. Some of the variables are huge because are observations from the user (that can have any length).
Between each chain's step I'm using something as the following:

*********************************

-on_submit {

set newpage "add_neuron?[export_vars -override {{return_url $current}} { var1,...varn return_url }]"

ad_returnredirect $newpage

ad_script_abort
}

*********************************

At the final step I have a huge URL that works fine with Mozilla but not with IE.

Thanks a lot!

Jorge.

Collapse
Posted by Dave Bauer on
I suggest you just store the data in the database between each step.
Collapse
Posted by Jorge Couchet on
Indeed, that was my first option. But, I began to look for in the forums and found the following entry: http://openacs.org/forums/message-view?message_id=110868

As consequence I am trying to implement the advice from the forum's entry, but I have the problem previously mentioned (some values are lost).

Thanks a lot!

Jorge.

Collapse
Posted by Michael Hinds on
Hi Jorge,

I don't think you want to be distracted by discussions about caching! Go with your first instinct of saving to the database. That's what it's there for ;-)

The 2083 IE limit problem only affects URLs, so if your forms use the "post" method instead of "get" you can save as much data as you like.

Collapse
Posted by Jorge Couchet on
Hi Michael,

Indeed, I am already using the data base :-)

Thanks to you and Dave for the help!

Jorge.

Collapse
Posted by Tom Jackson on
Go with your first instinct of saving to the database. That's what it's there for...

Good advice. One problem of passing variable from page to page is that you have to reverify them, if that is important to you, but you still have to process them on every page. If you setup a storage method, then you can also use it to pass information that users shouldn't be allowed to set. Overall, it should be easier to manage the page flow if you only have to deal with the new information.

Collapse
Posted by Jorge Couchet on
Tom, thanks for the new approach!
Collapse
Posted by Jorge Couchet on
Well,

The problem with ad_set_client_property (some session variable's values are lost), indeed was solved increasing the kernel parameter Caching/MaxSize's default value.

Now I have two solutions implemented:

a) Using the database in order to save temporary values
b) Using the ad_set_client_property (with MaxSize increased)

Pros/cons of both solutions: I suppose that I get more performance with "b" (in special if it's using the switch "-persistent f"), and the solution "a" is more secure (I do not have the risk of reaching MaxSize and losing some values again).

Regards,

Jorge.

Collapse
Posted by Andrew Piskorski on
So ad_set_client_property is implemented with ns_cache? Yes, I see that it is so (via util_memoize_seed). Is that really appropriate?

Seems to me that client properties should have their own cache, not the util_memoize cache, which is bounded on time but not on size. Does ns_cache support that style of use? (Or, perhaps keep the space bound, but make sure it's very large, and separate from whatever cache util_memoize uses?) You want non-persistent client properties to expire after a time, but while they're active you don't want AOLserver to throw them out just because they're large, right? Thoughts?

I'm not clear though, what happens if non-persistent client properties are evicted from the cache? Or if the AOLserver restarts, for that matter? What will the Tcl code and end user see?

Collapse
Posted by Tom Jackson on
Well, util_memoize isn't storage. If you can't guarantee a particular lifetime for the data, it isn't really a programming model. I can't think of a single reason to use util_memoize for storing a single user's data. Data like this is essentially private and shouldn't be stored in a global structure. The closest concept is a session variable, which should be stored somewhere for a guaranteed length of time, or until the session is expired by client or server. But if the data is personally valuable, maybe it should be stored so that the user can decide to either commit it to the larger database, delete it, or just let it stay around for a later decision. Caching should probably not be part of this process, as caching implies that there is a master copy somewhere.
Collapse
Posted by Jorge Couchet on
Hi,

In order to guarantee the permanence of the data I'm using the database. I have created the following table:

------ *******************************************
------ *******************************************
------ start SESSION_VARIABLES
------ *******************************************
------ *******************************************

-- start table SESSION_VARIABLES

CREATE TABLE session_variables (
session_id integer,
module_id varchar,
var_name varchar,
var_value varchar CONSTRAINT session_variables_var_value_nn
NOT NULL,
CONSTRAINT session_variables_pk
PRIMARY KEY(session_id, module_id, var_name)
);

COMMENT ON TABLE session_variables IS '
The table holds session variables. The programmer is in charge to delete the variables rows, if not the data is holded permanently.
';

COMMENT ON COLUMN session_variables.session_id IS '
The session ID of the user (obtained with the command [ad_conn session_id]).
';

COMMENT ON COLUMN session_variables.module_id IS '
The package key plus the package id ( "package_key_[ad_conn package_id]").
';

-- end table SESSION_VARIABLES

------ *******************************************
------ *******************************************
------ end SESSION_VARIABLES
------ *******************************************
------ *******************************************

I don't know if there is a better model, but this one is working fine to me.

Regards,

Jorge.

Collapse
Posted by Dave Bauer on
If you are going to do it use "text" not varchar, varchar has limits just like the URL.

Although you don't need to bother that's what sec_session_properties is for!

\d sec_session_properties
Table "public.sec_session_properties"
Column | Type | Modifiers
----------------+-----------------------+-----------
session_id | integer | not null
module | character varying(50) | not null
property_name | character varying(50) | not null
property_value | text |
secure_p | boolean |
last_hit | integer | not null
Indexes:
"sec_session_properties_pkey" PRIMARY KEY, btree (session_id, module, prope\
rty_name)
"sec_property_names" btree (property_name)

This is where ad_set_client_property values are stored.

All you data should be in here all the time. I guess the bug is that you can get a partial result from ad_get_client_property is the cache is full? But you should always be able to get it back out of the database.

Collapse
Posted by Jorge Couchet on
Hi Dave,

Indeed, the problem would seem to happen when the cache is full (at least it is solved when I have increased the kernel parameter MaxSize).

"But you should always be able to get it back out of the database": this means that I must explicitly query he table sec_session_properties (in order to avoid the error -lost values- that I get using ad_get_client_property)?

Thanks a lot for your help!

Jorge.

Collapse
Posted by Tom Jackson on

Caching session data is probably a bug. One reason to place session data into the database is so that you can transparently move from one front-end server to multiple servers. It isn't expensive if you have few users, and if you have many, another front-end server shouldn't be expensive either.

Caching should really be reserved for shared data. Even dynamic data can be cached for a short period of time. I imagine that you could cache most website front pages and index pages for a few minutes at least without any impact on the dynamic appearance of the site.

And if you can't turn off caching during development, why not just pull out a gun and get it over with? Turning on caching is like turning off logging. Maybe another concept is that you shouldn't have to test your package to see if it fails when using a cache. If the cache is not your code, it probably points to a bug in the code using a cache.

Maybe there is another way of putting it: don't cache inputs or intermediate results. Cache results which are likely to be valid for a useful amount of time.