Torque objects as currently written will not work well in a cache.  The
objects are not thread-safe.  there are cases where the objects are
generally used in as read-only or you are only using the simple bean
properties that map the db columns, that you may be able to get away
with caching them, but in general it cannot be done.  

john mcnally

Kelvin Tan wrote:
> 
> I've been thinking about this, and I'll here are my thoughts of how to
> approach this. If it's ok, I'll go ahead and work on it.
> 
> The test case I produced is just one situation in which saving would fail in
> a multithreaded environment. Imagine if in between modifications to an
> object's member collection, another thread invokes the equivalent of
> getCivPeoples() in the test case, replacing the object's member collection.
> Oblivious to this, the original thread continues modification of the member
> collection. However, the Vector object that the original thread modifies is
> now defunct. The object no longer has a reference to it, and all
> modifications are lost.
> 
> One solution, then, would be to ensure that the get method for the member
> collection does not succeed if any modifications have been performed to the
> Vector representing the member collection, either throwing an exception, or
> maybe just waiting (which is probably a bad idea). This can be implemented
> by
> 
> 1) creating a class which extends Vector, and provides access to modCount
> (number of modified elements in the Vector). This is currently a protected
> variable.
> 2) modify the BaseXXX template to use this modified Vector instead of a
> normal one
> 3) adding a boolean flag for each collection, whether it has been modified
> (using modCount)
> 4) modifying get{Collection} to check for the boolean flag, and maybe throw
> an exception if it's true
> 
> Kelvin
> 
> ----- Original Message -----
> From: Kelvin Tan <[EMAIL PROTECTED]>
> To: Turbine Users List <[EMAIL PROTECTED]>
> Sent: Saturday, December 08, 2001 11:58 AM
> Subject: Re: [Torque] Failed testcase
> 
> > > On 12/7/01 9:52 PM, "Kelvin Tan" <[EMAIL PROTECTED]> wrote:
> > >
> > > > Neglected to mention that this is with the CVS version checked out on
> > Dec 7
> > > > itself.
> > >
> > > You've got the testcase, now you get to figure out what's wrong :-)
> > >
> > > I don't know off the top of my head what the problem is.
> >
> > I think I do. As I mentioned, I believe it's because of the way Torque
> > caches the previous Criteria's result, and then attempts to use that to
> save
> > to the database.
> >
> > Using the testcase example:
> >
> > Within BaseCivilization,
> >
> > Calling getCivPeoples(Criteria criteria) assigns a vector collCivPeoples
> as
> > the result of the doSelect, and returns this vector.
> >
> > In save(DBConnection dbCon),
> >
> >           if (collCivPeoples != null )
> >           {
> >               for (int i=0; i<collCivPeoples.size(); i++)
> >               {
> >                   ((CivPeople)collCivPeoples.get(i)).save(dbCon);
> >               }
> >           }
> >
> > basically using the results of the doSelect as the basis for saving, which
> > makes sense since modifications to an object's member collections should
> be
> > saved when an object is saved.
> >
> > The trouble, of course, arrives when, in between an object being modified
> > and the save, getCivPeoples(Criteria criteria) is called, essentially
> > setting the vector collCivPeoples to a new value (depending on the
> criteria)
> > and wiping out all modifications.
> >
> > This problem will not arise if application-level caching is not performed,
> > since Torque itself doesn't do any caching, everytime a doSelect is
> called,
> > a new Civilization object is created with its own collCivPeoples. In the
> > case when it is used in conjunction with a cache like Turbine's global
> > cache, then this will pose a problem.
> >
> > Kelvin
> >
> > >
> > >
> > > > ----- Original Message -----
> > > > From: Kelvin Tan <[EMAIL PROTECTED]>
> > > > To: <[EMAIL PROTECTED]>
> > > > Sent: Friday, December 07, 2001 6:11 PM
> > > > Subject: [Torque] Failed testcase
> > > >
> > > >
> > > > The testcase I've submitted below fails. The problem, I think, is that
> > > > before a save() is called on an object whose collection has been
> > modified,
> > > > the modification is basically lost because of the way Torque caches
> the
> > > > previous Criteria's dbhit. Attention to Line 1 and Line 2.
> > > >
> > > > This situation would be possible in a high-load environment with lots
> of
> > > > concurrent hits.
> > > >
> > > > public class TorqueRunner
> > > > {
> > > >   /**
> > > >    * Category used for logging in the runtime test class.
> > > >    */
> > > >   private static Category cat =
> > > >           Category.getInstance(TorqueRunner.class.getName());
> > > >
> > > >   public static void main(String[] args)
> > > >           throws TorqueException, Exception
> > > >   {
> > > >       String configurationFile = "/schema/Torque.properties";
> > > >
> > > >       // initializing Torque
> > > >       try
> > > >       {
> > > >           Torque.init(configurationFile);
> > > >       }
> > > >       catch (Exception e)
> > > >       {
> > > >           throw new TorqueException("Can't initialize Torque!", e);
> > > >       }
> > > >
> > > >       // run the tests
> > > >       TorqueRunner tr = new TorqueRunner();
> > > >
> > > >       //tr.insertData();
> > > >       //tr.retrieveData();
> > > >       tr.test();
> > > >       Runtime.getRuntime().exit(0);
> > > >   }
> > > >
> > > >   private void test() throws Exception
> > > >   {
> > > >       Civilization civ = new Civilization();
> > > >       civ.setCivId("1");
> > > >       civ.setName("Civilization");
> > > >       civ.save();
> > > >
> > > >       int newCivPeopleSize = civ.getCivPeoples(new Criteria()).size();
> > > >
> > > >       CivPeople cp = new CivPeople();
> > > >       cp.setCivId(civ.getCivId());
> > > >       People p = new People();
> > > >       p.setPeopleId("1");
> > > >       p.setName("peoplename");
> > > >       p.save();
> > > >       cp.setPeopleId(p.getPeopleId());
> > > >       //cp.save(); // Line 1
> > > >       civ.addCivPeople(cp);
> > > >       civ.getCivPeoples(new Criteria()).size(); // Line 2
> > > >       civ.save();
> > > >       civ = (Civilization)
> > CivilizationPeer.doSelect(civ).firstElement();
> > > >       int newerCivPeopleSize = civ.getCivPeoples(new
> Criteria()).size();
> > > >       if (newerCivPeopleSize != (newCivPeopleSize + 1))
> > > >           throw new Exception("Added people not reflected! Expected:"
> > > >                               + (newCivPeopleSize + 1) + " but was:"
> > > >                               + newerCivPeopleSize);
> > > >   }
> > > > }
> > > >
> > > >
> > > > Regards,
> > > > Kelvin Tan
> > > >
> > > > Relevanz Pte Ltd
> > > > http://www.relevanz.com
> > > >
> > > > 180B Bencoolen St.
> > > > The Bencoolen, #04-01
> > > > S(189648)
> > > >
> > > > Tel: 238 6229
> > > > Fax: 337 4417
> > > >
> > > >
> > > >
> > > >
> > > > --
> > > > To unsubscribe, e-mail:
> > <mailto:[EMAIL PROTECTED]>
> > > > For additional commands, e-mail:
> > <mailto:[EMAIL PROTECTED]>
> > >
> > >
> > > --
> > > To unsubscribe, e-mail:
> > <mailto:[EMAIL PROTECTED]>
> > > For additional commands, e-mail:
> > <mailto:[EMAIL PROTECTED]>
> > >
> >
> >
> > --
> > To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
> >
> 
> --
> To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to