Cost of reread a dbo::ptr every time it is loaded (either by an explicit reread or by setting the reread flag of the Wt::Dbo::Session::load to true)
Added by Dottor Hell over 7 years ago
Short version:
Some dbo::ptr data seem to be not consistently updated if changed from another user; using the reread fixes the problem; how much does it cost to reread a dbo::ptr every time that I load (like in Wt::Dbo::Session::load) it, either by an explicit reread or activating the reread flag in Wt::Dbo::Session::load?
The online ref docs say that the value is not necessarily loaded again from the DB, which seems to point to a not excessive waste of DB readings, yet I wonder then why, if the system doesn't load it from the DB, the reread fixes this problem (and, if it reads again the ptr effectively only if 'needed', it doesn't realize that a ptr with some associated obsolete data should anyway be reread).
Long version:
I have built a chat with a ban system, moderator levels and such; when a "moderator" executes a ban or a mute, both his level and the other user's level are checked (so that a moderator cannot ban an admin, for example). To do so I blindly call a wrapper of the load function (DB::Ptr is a wrapper for dbo::ptr and so on...) for both the parts
template <class DBElement, class WidgetClass>
DB::Ptr UserDBSession::safeLoad_withinTransaction(const DB::IdType &id_int, WidgetClass *widget)
{
DB::Ptr p;
try
{
p=this->getSession().load(id_int);
}
catch (DB::ObjectNotFoundException)
{
return DB::Ptr();
}
CATCH_UNEXPECTED_EXCEPTION(this, widget);
return p;
}
Which then I call like this:
DB::Ptr p_ban_creator=session_.safeLoad_withinTransaction(creatorID);
This system includes, obviously, a way for the admin to increase or decrease the level of the other users.
The problem is that when the admin A changes the level of another user X, while this is correctly registered in the DB (I checked opening the DB with an extern program: DB Browser for SQLITE), when the user X tries to ban/mute another user (B), an action which activates the comparison between the levels of X and B, loading the two ptr as shown above, the result is that X's level is still the old level and not the new one (which is in the DB).
Using a reread fixes this, but at this point either there is a specific reason for the error to be there, or as a safe measure I'm supposed to reread the ptr every single time (ie: setting always the reread flag of the ::load function to true).
But I'd like to know if this implies an excessive waste of resources if the reread is, indeed, not needed.
Thanks.
Replies (1)
RE: Cost of reread a dbo::ptr every time it is loaded (either by an explicit reread or by setting the reread flag of the Wt::Dbo::Session::load to true) - Added by Mark Petryk over 7 years ago
I created a form model class that takes care of automatically 'reloading' the ptr object. It does this by running a simple sql query (probably not portable) to check the version of the item on disk vs the version of the item in memory, and if the item in memory is stale, then it automatically reloads it.
Here's the code the runs the sql:
202 template <class C>
203 int FormModel<C>::diskVersion() const
204 {
205 #ifdef DEBUG_TRACE
206 std::cout << __LINE__ << ":" << __FILE__ << " " << std::endl;
207 #endif
208 if( !session() )
209 return -1;
210
211 Wt::Dbo::Transaction t(*session());
212 int version = session()->
213 template query<int>("SELECT version FROM \"" + tableName() + "\"")
214 .where("id=?").bind( item().id() )
215 ;
216
217 return version;
218 }
219
In the case of the Table Views I have a 'refresh' button and/or also an automatic timer to re-query the underlying database for fresh data. And, in the case of the 'timer' the refresh function doesn't fire if the Table View is not presently visible. Data collisions is a real problem, however. I'm working on an 'item-lock' function, that will lock down the items from edit when some other user has the item open - much like the file-lock that operates on a document when some other user has the document open...
The module is here in case you want to poke around on it (it's a work in progress).
https://support.lorimarksolutions.com/wtx/FormModel__imp_8h_source.html