db4o Developer Community
Developer Community db4o open source object database, native to Java and .NET
Register   |  Login
  Search
  • Forums
  • Documentation
  • Resources
  • Downloads
  • Blogs
  • About
Unanswered Active Topics Forums
Forums > English Forums > db4o User Forum
More on transactions and threads
Last Post 01 Aug 2002 08:29 AM by Newsgroup Import. 11 Replies.
AddThis - Bookmarking and Sharing Button Printer Friendly
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Author Messages
Newsgroup Import
New Member
New Member
Newsgroup Import

--
28 Jul 2002 01:55 PM  
This message was imported from the former db4o newsgroup.

Rickard and Martin,
thanks a lot for your comments.

Sorry for not joining the discussion but I was away from the net
for two days.

I really like the idea of per-thread transactions and per-thread
reference management but since the current behaviour also makes
sense for some applications, I think we should consider to support
both behaviour modes.

Just brainstorming a little, I can think of the following two
possibilities:
(1.) Add a configuration feature "transactionPerThread(true)"
(2.) Add the possibility to open multiple clients (== transactions)
on the same ObjectContainer. Communication should take place locally,
not over a socket. Every "Client" would have its individual transaction
and its individual reference management. Staying with the current naming
convention, the method could be:
ExtDb4o.openClient(ObjectContainer onObjectContainer);

Although I really like version (1) for it's elegance, version (2) would
be more flexible, since it also allows to work with two different
transactions from within the same thread. We could also support nested
transactions with the same interface.
If Rickard really needs a "thread-transaction" it wouldn't be too
complex to implement
ExtDb4o.getClient(ObjectContainer onObjectContainer):
  - look up current thread and ObjectContainer in a Map
  - if not found, call the above local openClient and store both to the Map

Both above options would require very similar overall code. It would
be nice if we could provide the simplest and most intuitive interface.


Some comments to your statements:


> The way I would see it happening is a thread has access to both the main
> repository and a temporary repository. As existing objects are queried they
> are copied to the temporary repository. New objects are created in the
> temporary repository. Once the transaction is commited the temporary
> repository is purged into the main repository, and a new temporary
> repository is created.

What we are currently doing:
- Queries run against the main repository only, and they don't take the
modifications on your local "temporary" objects into account at all.
- Upon calls to ObjectContainer set(), temporary objects are added to
the transaction's reference space in the main repository.
The modified copies are only visible to the individual transaction and
the changes will be visible in queries executed by the transactions.
- Upon commit, the changes also become visible to other transactions.
- commit() does not purge local data. Instead we use weak references
and objects get garbage collected automatically. However our internal
WeakReference collector does not have it's own thread and it only polls
the ReferenceQueue in calls to set() and get(), so calling
ExtObjectContainer#purge() will often help to free memory.

We urgently need a refresh() call but deactivate() and activate()
can be currently used as a workaround.



> Carl bonus points to you if you stumble upon eXcelon's "forward caching"
> algorithm that they market as their "patented" node caching solution;)

It's implementing S.O.D.A. and only S.O.D.A. right now but I love leading
the discussion with you, so we can implement this theme in the best way
possible, when the time comes. Thanks for the pointer to eXcelon.

Our db4o clients simply cache everything.


> The temporary cache/repository should be able to be turned on and off as
> necessary. I would want to specify whether the thread would be "read-only"
> to optimize memory/resources.

The additional overhead by the db4o cache shouldn't make such a big
difference. I think we will have to talk about additional built-in
caching strategies when the UpdateListener is implemented.



> Is it possible to implement copy-on-write? I.e. copies are only made
> if changes are only made? Do you have any hooks for that? (I guess
> this is one place where JDO does have a point, since that can be
> easily hooked there).

No, I am afraid we don't have any chances for copy-on-write in db4o.
No bytecode-enhancement == no hooks at all.



> I would prefer standard optimistic transaction semantics, i.e. if you
> change an object and another transaction also changed and committed
> changes then the transactions rollbacks. This is definitely the
> *proper way*, and you can look that up in any database book if you
> don't believe me ;-)

I don't believe you. :-)

Without having really tried this out, I have hopes that a messaging
system, that allows to detect conflicts individually, can work even
better.



> I just realized that it is enough if each transaction get its own
> copy, and that if no transaction is running then the main repository
> copy would be used. That way you would get proper read-committed
> semantics in transactions, but would not get the overhead (CPU-wise
> and memory-wise) of copying objects when transactions are not used
> during read operations (which at least for me is the vast majority of
> operations).

Currently it's either copying-all or not-copying-anything and I think
I would want to leave it at that. I don't like all this
"makeTransactional"- and "makeNonTransactional"-fuss that JDO proposes.

I think applications should solve the memory-footprint-problem
themselves by sharing one read-only transaction and by using
individual write transactions.

You could handle identity problems by using the internal db4o ID.

You could "replace" existing objects by using
ExtObjectContainer#bind(Object, id).
(== makeTransactional()  :-) )

You could remove an instantiated object from the reference system
with ExtObjectContainer#purge(Object).
(== makeNonTransactional() :-) )


Kind regards,
Carl
Newsgroup Import
New Member
New Member
Newsgroup Import

--
28 Jul 2002 10:03 PM  
This message was imported from the former db4o newsgroup.

Carl Rosenberger wrote:
> Just brainstorming a little, I can think of the following two
> possibilities:
> (1.) Add a configuration feature "transactionPerThread(true)"
> (2.) Add the possibility to open multiple clients (== transactions)
> on the same ObjectContainer. Communication should take place locally,
> not over a socket. Every "Client" would have its individual transaction
> and its individual reference management. Staying with the current naming
> convention, the method could be:
> ExtDb4o.openClient(ObjectContainer onObjectContainer);

If 2. then beware of the fact that my servlet will be doing this on each 
page request, maybe multiple times. The operation needs to be fast.

I would advice against the connection=transaction idea. It has been 
abandoned in JDBC, and for good reasons. It makes more sense to manage 
transactions as a full-blown object on its own, which is *using* 
connections that can be associated or dis-associated with transactions, 
over time. Again, look at the JTA and JDBC API's for hints and ideas on 
this. In fact, if you could make db4o a resource that can be used by JTA 
that would be awesome, especially in a J2EE/EJB setting.

> Although I really like version (1) for it's elegance, version (2) would
> be more flexible, since it also allows to work with two different
> transactions from within the same thread. 

Why would anyone want to do this!? That would be really confusing I think.

> We could also support nested
> transactions with the same interface.
> If Rickard really needs a "thread-transaction" it wouldn't be too
> complex to implement
> ExtDb4o.getClient(ObjectContainer onObjectContainer):
>   - look up current thread and ObjectContainer in a Map
>   - if not found, call the above local openClient and store both to the Map

I would call the above "Transaction.begin()" followed by "openClient()". 
This would then mimic how JTA/JDBC works where you do 
"UserTransaction.begin()" followed by "DataSource.getConnection()".

> 
> 
>>I would prefer standard optimistic transaction semantics, i.e. if you
>>change an object and another transaction also changed and committed
>>changes then the transactions rollbacks. This is definitely the
>>*proper way*, and you can look that up in any database book if you
>>don't believe me ;-)
> 
> I don't believe you. :-)
> 
> Without having really tried this out, I have hopes that a messaging
> system, that allows to detect conflicts individually, can work even
> better.

How? The basic problem is that you have changes that have been made in 
two concurrent transactions. Only one of them is allowed to be "ok". The 
standard solution is to let the transaction that finishes last rollback. 
This is how all other database engines work (AFAIK).+

> 
> Currently it's either copying-all or not-copying-anything and I think
> I would want to leave it at that. I don't like all this
> "makeTransactional"- and "makeNonTransactional"-fuss that JDO proposes.

Well, don't you have a "begin()" call? You really need to. And if so, 
not calling it would amount to not having a transaction and hence going 
to the main repository. I.e. read-transactions simply "do nothing", 
whereas write-transactions need to delineate the block to commit atomically.

> I think applications should solve the memory-footprint-problem
> themselves by sharing one read-only transaction and by using
> individual write transactions.

That sucks. To start with you'd have to have a Transaction object, and 
then it'd have to be shared using statics, and then you have to figure 
out who starts it to begin with, and then you need to continually commit 
it in order to get access to changes from other transactions. Yeuch.

/Rickard
Newsgroup Import
New Member
New Member
Newsgroup Import

--
29 Jul 2002 05:25 AM  
This message was imported from the former db4o newsgroup.

Rickard berg wrote:
> If 2. then beware of the fact that my servlet will be doing this on each
> page request, maybe multiple times. The operation needs to be fast.

Speed wouldn't be a problem at all but I think it does make sense to
continue the discussion, maybe we get some more ideas.

There will always be a conflict between two possible goals:
"Can we do this simpler than everyone else?"
"Is there a standard we can stick to?"


> I would advice against the connection=transaction idea. It has been
> abandoned in JDBC, and for good reasons. It makes more sense to manage
> transactions as a full-blown object on its own, which is *using*
> connections that can be associated or dis-associated with transactions,
> over time. Again, look at the JTA and JDBC API's for hints and ideas on
> this. In fact, if you could make db4o a resource that can be used by JTA
> that would be awesome, especially in a J2EE/EJB setting.

Thinking this over I do feel that ObjectContainer==Transaction makes our
engine easier to handle than thread==transaction. Nearly all
ExtObjectContainer methods like bind, getByID, getID ... are always
in a transactional context. I think it is easier to understand, if the
same ObjectContainer object delivers the same query results, no matter
which thread accesses it. The additional benefit is obvious, if you
write objects back: You are in full control which ObjectContainer
(possible version) you use.

The major problem that necessarily lead to the separation of
connections and transactions for JDBC:
JDBC connections usually are remote over multiple software layers and
it takes time to build them up and to close them. We would not be facing
the same problem since we would use the same socket connection or only
one additional local cache in the same VM.
Nested transactions on JDBC system necessarily run on the server.
Possibly we can do a lot on the client side.


My proposed "ExtDb4o.openClient(masterObjectContainer)" would be similar
to a JTA "TransactionManager#begin()". It would be fast and it would use
the same socket as the masterObjectContainer.


Maybe the method will look better if I change the name:
  public ObjectContainer ObjectContainer#begin()


Of course it would be desirable to make an implementation of the complete
JTA API possible on top of our solution.


> > Although I really like version (1) for it's elegance, version (2) would
> > be more flexible, since it also allows to work with two different
> > transactions from within the same thread.
>
> Why would anyone want to do this!? That would be really confusing I think.

Two examples:
(1.) In long complicated business processes that are likely to run against
locking problems it sometimes makes sense to try and execute and *commit*
parts of a bigger process, one after the other. The "main process" would
not be committed to keep objects locked.

(2.) Maybe you would like to work against different stored versions of an
object from within the same thread.


> >>I would prefer standard optimistic transaction semantics, i.e. if you
> >>change an object and another transaction also changed and committed
> >>changes then the transactions rollbacks. This is definitely the
> >>*proper way*, and you can look that up in any database book if you
> >>don't believe me ;-)
> >
> > I don't believe you. :-)
> >
> > Without having really tried this out, I have hopes that a messaging
> > system, that allows to detect conflicts individually, can work even
> > better.
>
> How? The basic problem is that you have changes that have been made in
> two concurrent transactions. Only one of them is allowed to be "ok". The
> standard solution is to let the transaction that finishes last rollback.
> This is how all other database engines work (AFAIK).+

Concurrencies could be detected long before the commit, if two transactions
call ObjectContainer#set() with the same object. In this case you could
notify the object itself with a callback method or some other listener
object that you would register.

For db4o we want a one-commit-at-a-time logic. The commit of concurrenct
modifications could again notify all objects that are part of a conflict
or a listener.

If the object (or the listener) could solve the conflict, it could return
an "everything O.K." response and both transactions could be committed
in spite of the conflict.


> > 
> > Currently it's either copying-all or not-copying-anything and I think
> > I would want to leave it at that. I don't like all this
> > "makeTransactional"- and "makeNonTransactional"-fuss that JDO proposes.
>
> Well, don't you have a "begin()" call?

No. ObjectContainers always are transactional.
Opening the ObjectContainer is the begin() call.


> > I think applications should solve the memory-footprint-problem
> > themselves by sharing one read-only transaction and by using
> > individual write transactions.
>
> That sucks. To start with you'd have to have a Transaction object, and
> then it'd have to be shared using statics, and then you have to figure
> out who starts it to begin with, and then you need to continually commit
> it in order to get access to changes from other transactions. Yeuch.

O.K.
Agreed.

We will find your thread-transactions somewhere.


Kind regards,
Carl
Newsgroup Import
New Member
New Member
Newsgroup Import

--
29 Jul 2002 06:19 AM  
This message was imported from the former db4o newsgroup.

Carl Rosenberger wrote:
> There will always be a conflict between two possible goals:
> "Can we do this simpler than everyone else?"
> "Is there a standard we can stick to?"

When it comes to transactions it would be dangerous, IMHO, to start 
inventing ones own semantics of how it should work. The basics of how 
this works is pretty well defined these days, so sticking with that is 
recommended. IMHO.

> Thinking this over I do feel that ObjectContainer==Transaction makes our
> engine easier to handle than thread==transaction. 

Not when you're in a strictly server-mode. Then you want to be able to 
hold on to ObjectContainer's and begin/commit blocks of actions against 
it. What you are saying is that there's always a transaction running. 
IMHO that's bad, as there's just no need for it (usually) when you're 
doing read-only ops, which usually is the most common case (generalizing 
wildly here).

> Nearly all
> ExtObjectContainer methods like bind, getByID, getID ... are always
> in a transactional context. I think it is easier to understand, if the
> same ObjectContainer object delivers the same query results, no matter
> which thread accesses it. 

Why not rename it to Transaction then? ;-)

So, let me get this straight. If you have two clients, if the first one 
modifies an object, when will the other see it? Immediately? What if the 
first one is using it? Then, let's say that it sees one version and 
decides to change it. But, then the other one has changed it so that the 
decision to change it is based on the wrong information, resulting in 
possibly corrupt data.

If a transaction has begun, and an object has been read, then it should 
not change until the transaction is committed or rollbacked. But, if you 
*do* want to read the committed state, then how would you handle that? 
Since you're always in a transaction with your proposed scheme, you'd 
have to commit/rollback it just to get the latest state of the repository.

That's bad. It is better to use explicit transaction demarcation, which 
solves the above dilemma: no transaction -> get repository (good for 
read), transaction started -> get own copy, which will stay the same 
until commit/rollback.

> The major problem that necessarily lead to the separation of
> connections and transactions for JDBC:
> JDBC connections usually are remote over multiple software layers and
> it takes time to build them up and to close them. We would not be facing
> the same problem since we would use the same socket connection or only
> one additional local cache in the same VM.
> Nested transactions on JDBC system necessarily run on the server.
> Possibly we can do a lot on the client side.

That is not the primary reason. The primary reason, as I see it, is that 
connections are system resources, and transactions are application 
resources that you use to define your application logic. I don't care 
how system resources are managed, whereas I am very concerned with how 
transactions are managed (when they begin/end).

> My proposed "ExtDb4o.openClient(masterObjectContainer)" would be similar
> to a JTA "TransactionManager#begin()". It would be fast and it would use
> the same socket as the masterObjectContainer.

Would the master container correspond to "no transaction", i.e. main 
repository? If so, then that's good. It's still a bit too different from 
normal transaction API's for my taste, but at least you can get somewhat 
the same behaviour.

> Two examples:
> (1.) In long complicated business processes that are likely to run against
> locking problems it sometimes makes sense to try and execute and *commit*
> parts of a bigger process, one after the other. The "main process" would
> not be committed to keep objects locked.

Isn't that nested transactions?

> (2.) Maybe you would like to work against different stored versions of an
> object from within the same thread.

I see. That would correspond to TransactionManager.suspend()/resume() in 
JTA I think.

> Concurrencies could be detected long before the commit, if two transactions
> call ObjectContainer#set() with the same object. 

Scenario:
1) Tx 1 starts
2) Tx 2 starts
3) Tx 1 updates object A
4) Tx 2 updates object A.
5) Tx 1 rollbacks
6) Rx 2 commits successfully.

This shows that while there is a conflict at 4, tx 2 should not rollback 
since the conflict had been resolved by 6 due to tx 1 rollbacking. I.e. 
premature conflict checking cannot be done in this case. Did you have 
any other scenario in mind that could be solved prematurely?

> For db4o we want a one-commit-at-a-time logic. The commit of concurrenct
> modifications could again notify all objects that are part of a conflict
> or a listener.

Well, isn't this simply commit() throwing a RollbackException or 
similar? That's how JTA does it, and I'd recommend it. In JTA you can 
also register a Synchronization listener to explicitly handle 
commit/rollback, which sounds similar to what you want.

>>>
>>>Currently it's either copying-all or not-copying-anything and I think
>>>I would want to leave it at that. I don't like all this
>>>"makeTransactional"- and "makeNonTransactional"-fuss that JDO proposes.
>>
>>Well, don't you have a "begin()" call?
> 
> No. ObjectContainers always are transactional.
> Opening the ObjectContainer is the begin() call.

See above question: how does containers get the updated state from other 
containers? It sounds like clients should not hold on to 
ObjectContainers very long. They more or less have to be discarded after 
each operation, or you will be working on stale data.

/Rickard
Newsgroup Import
New Member
New Member
Newsgroup Import

--
29 Jul 2002 06:40 PM  
This message was imported from the former db4o newsgroup.

> My proposed "ExtDb4o.openClient(masterObjectContainer)" would be similar
> to a JTA "TransactionManager#begin()". It would be fast and it would use
> the same socket as the masterObjectContainer.
>
> Maybe the method will look better if I change the name:
>  public ObjectContainer ObjectContainer#begin()
>

Symantically, I would vote the method to be either:

    ExtDb4o.openTransaction(masterObjectContainer)
or
    ObjectContainer.newTransaction()

Esspecially, if the former is the desired approach, as "client" would be
easily confused as in "client/server" which is not the case.

> Nearly all
> ExtObjectContainer methods like bind, getByID, getID ... are always
> in a transactional context. I think it is easier to understand, if the
> same ObjectContainer object delivers the same query results, no matter
> which thread accesses it.

I vote for keeping the ObjectContainer interface central to all
transactions. The db4o API is elegant in its reuse of the one interfaces.
The interopability between functionality is merely one or two method calls,
which is really quite brilliant. Plus one interface, fast time getting your
hands wet. This is a hallmark of this product and why I've moved towards.

There is risk of turning the simplicity into another Java-bless
specification. While I'm a fan of standards, and a not of vendor lock in, a)
db4o is unique in many regards to most OODBMSs, and b) sometimes the
praticality of a spec is poor (i.e. more specs should support the "Ext"
concept of db4o, if you don't need it, don't worry about it).

> Would the master container correspond to "no transaction", i.e. main
> repository? If so, then that's good. It's still a bit too different from
> normal transaction API's for my taste, but at least you can get somewhat
> the same behaviour.

I would think that the master container would function exactly as db4o does
today, otherwise you're looking at a serious break in compatibility. The
master container would work in its own transaction, essentially
"single-user" mode (for lack of terminology). Now interestingly how would
you handle this situation:

1) masterDb4o = Db4o.openFile();
2) masterDb4o.set() (begining a transaction);
3) transactionDb4o = ExtDb4o.openTransaction(masterDb4o);

Would transactionDb4o be:

a) Not allowed, throwing an exception. Essentially forcing you choose a
model single-user mode. Benefits is this is coded defensively to prevent
confused symantics.

b) transactionDb4o, becomes a nested transaction. This is kind of elegent
too, and multiple calls to openTransaction() would continue to nest the
transactions. The standard nested transaction rules would apply.

c) transactionDb4o, becomes an independent transaction competing with the
masterDb4o transaction. This would be a poor choice I think, but I offer it
for discussion.

> Scenario:
> 1) Tx 1 starts
> 2) Tx 2 starts
> 3) Tx 1 updates object A
> 4) Tx 2 updates object A.
> 5) Tx 1 rollbacks
> 6) Rx 2 commits successfully.
>
> This shows that while there is a conflict at 4, tx 2 should not rollback
> since the conflict had been resolved by 6 due to tx 1 rollbacking. I.e.
> premature conflict checking cannot be done in this case. Did you have
> any other scenario in mind that could be solved prematurely?

Carl, are you suggesting that once 4 occurs Listeners on Transaction 1 & 2
would be notified of the change, and have an opportunity to either rollback
or proceed based on their implementation? I like this opposed to the
Exception on commit which could be too late. I feel that unlike a relational
database, the potential for a large object models become part of a complex
transactions more likely in db4o. I can picture a deep tree becoming
involved in a large transaction and rollbacks being more of an occurance.

I guess it also depends at what granularity to block a transaction, object
or field level. It could also be argued that some objects should have their
fields treated atomically, while others would be independent. Example time:

A cheap DateTimeStruct object (for lack of a clever example) should be
atomic...

class DateTimeStruct {

  Date thisDate;
  Time thisTime;

  class Date {
  	int year;
      int month;
      int day;
  }

  class Time {
    int hours;
    int minutes;
    int seconds;
  }
}

Changing one field essentially changes the definition of this object it is
no longer the same.

Where as (another lame example)...

class BusinessUnit {

  Collection Employees;

}

Changing the Employee in the Collection should not mark this object as
changed.

Perhaps this logic already exists in the current db4o implementation, in
which case its a good review;) But either a way to mark fields as being
atomic, or perhaps better to use the equals() & hashCode() methods in
comparison. Again perhaps db4o already does this...

I am sure there is more rambling to do...
Martin


------------------------ Yahoo! Groups Sponsor ---------------------~-->
Will You Find True Love?
Will You Meet the One?
Free Love Reading by phone!
http://us.click.yahoo.com/7dY7FD/R_ZEAA/Ey.GAA/PhFolB/TM
---------------------------------------------------------------------~->

To unsubscribe from this group, send an email to:
db4o_unmoderated-unsubscribe@yahoogroups.com

 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
Newsgroup Import
New Member
New Member
Newsgroup Import

--
31 Jul 2002 06:46 AM  
This message was imported from the former db4o newsgroup.

Rickard berg wrote:
> When it comes to transactions it would be dangerous, IMHO, to start
> inventing ones own semantics of how it should work. The basics of how
> this works is pretty well defined these days, so sticking with that is
> recommended. IMHO.

If we would have been sticking with "well defined these days" we
would have been doing SQL / ODMG / JDO. :-)

I don't like the idea of bloating db4o with additional necessary
packages and I don't like the idea of making the implementation
dependant on other monster specifications that we can only support
to some percentage.

Martin's last posting has summed the goal up quite nicely:
(1.) We want to stay supersimple.
(2.) We want to make the support of other specifications possible
but we don't ruin the lean interface of our core engine with them.

Shortly you will see a JDO implementation built upon db4o.
(not by us)

In this manner we should build the basis for a JTA implementation
on top of db4o.

The worst thing we can do would be to add tons of badly-named methods
that we would have to carry along for backwards compatibility. From
this point of view the "configureTransactionPerThread" approach may
be the best.


> > Thinking this over I do feel that ObjectContainer==Transaction makes our
> > engine easier to handle than thread==transaction.
>
> Not when you're in a strictly server-mode. Then you want to be able to
> hold on to ObjectContainer's and begin/commit blocks of actions against
> it. What you are saying is that there's always a transaction running.
> IMHO that's bad, as there's just no need for it (usually) when you're
> doing read-only ops, which usually is the most common case (generalizing
> wildly here).

I don't understand this argument but maybe you can enlighten me.
What's so bad about always having a transaction running?
It doesn't take away any ressources.


> So, let me get this straight. If you have two clients, if the first one
> modifies an object, when will the other see it? Immediately?

The second client does not see anything until it loads/reloads objects.
During loading (ObjectContainer#activate(), ObjectSet#next()) it only
sees committed changes.


> What if the
> first one is using it? Then, let's say that it sees one version and
> decides to change it. But, then the other one has changed it so that the
> decision to change it is based on the wrong information, resulting in
> possibly corrupt data.

Yes, we want two mechanisms to prevent this:
(1.) change notification
(2.) locking


> If a transaction has begun, and an object has been read, then it should
> not change until the transaction is committed or rollbacked. But, if you
> *do* want to read the committed state, then how would you handle that?

You would have to open another transaction and get the object by ID.


> Since you're always in a transaction with your proposed scheme, you'd
> have to commit/rollback it just to get the latest state of the repository.

No, the above will do.


> That's bad. It is better to use explicit transaction demarcation, which
> solves the above dilemma: no transaction -> get repository (good for
> read), transaction started -> get own copy, which will stay the same
> until commit/rollback.

What would be the right behaviour if ObjectContainer#set() would be
called in a context without a transaction?


> > My proposed "ExtDb4o.openClient(masterObjectContainer)" would be similar
> > to a JTA "TransactionManager#begin()". It would be fast and it would use
> > the same socket as the masterObjectContainer.
>
> Would the master container correspond to "no transaction", i.e. main
> repository? If so, then that's good. It's still a bit too different from
> normal transaction API's for my taste, but at least you can get somewhat
> the same behaviour.

It's no problem at all to get the same behaviour with all the
proposed alternatives. The points we are discussing here are:

- How would the API look nice?
- Can we adher to an existing standard?


> > (1.) In long complicated business processes that are likely to run against
> > locking problems it sometimes makes sense to try and execute and *commit*
> > parts of a bigger process, one after the other. The "main process" would
> > not be committed to keep objects locked.
>
> Isn't that nested transactions?

I don't think that there are too many database implementations that
- support nested transactions
- and allow the individual commit of nested transactions
- and make the commit visible outside of the master transaction

Reading through the JTA specification, I think the behaviour of
nested transactions is unspecified. :-)


> > (2.) Maybe you would like to work against different stored versions of an
> > object from within the same thread.
>
> I see. That would correspond to TransactionManager.suspend()/resume() in
> JTA I think.

Yup, in principle.
The behaviour would be easy to understand in an SQL implementation, since
you would always be rereading the complete data.
For db4o it would mean that there would always be a non-transactional cache
(before begin, for suspend/resume) and a transactional cache associated with
every thread.
...too complex and too difficult to understand.


Principles that can easily be communicated:
(1.) "Every ObjectContainer has it's own cache and transaction."
(2.) "Every thread has it's own cache and transaction."

We would have to stay compatible with the existing implementation.
That would mean the existing behaviour would have to remain and
alternate behaviour would have to be a configuration option.


> > Concurrencies could be detected long before the commit, if two transactions
> > call ObjectContainer#set() with the same object.
>
> Scenario:
> 1) Tx 1 starts
> 2) Tx 2 starts
> 3) Tx 1 updates object A
> 4) Tx 2 updates object A.
> 5) Tx 1 rollbacks
> 6) Rx 2 commits successfully.
>
> This shows that while there is a conflict at 4, tx 2 should not rollback
> since the conflict had been resolved by 6 due to tx 1 rollbacking. I.e.
> premature conflict checking cannot be done in this case. Did you have
> any other scenario in mind that could be solved prematurely?

Thanks for the input!

Possibly an early pre-commit notification upon the change itself
may not be such a good idea.

However a two-stage notification could be nice:
(1.) "Just about to commit. Is this O.K. with you others?"
(2.) "Just committed. Check your concurrencies."

Looking at this (1.) isn't nice either, since it would have to
wait for all other clients to respond.


> > For db4o we want a one-commit-at-a-time logic. The commit of concurrenct
> > modifications could again notify all objects that are part of a conflict
> > or a listener.
>
> Well, isn't this simply commit() throwing a RollbackException or
> similar? That's how JTA does it, and I'd recommend it. In JTA you can
> also register a Synchronization listener to explicitly handle
> commit/rollback, which sounds similar to what you want.

I do want an additional feature:
Notification about committed objects.
Other transactions could reread values and adjust their behaviour
while running. This would have interfer with locking in some sort:
Maybe a call to ObjectContainer#set() would acquire a non-blocking
write-lock that would need to be refreshed, in case another transaction
has commit the object in the meanwhile.


> > No. ObjectContainers always are transactional.
> > Opening the ObjectContainer is the begin() call.
>
> See above question: how does containers get the updated state from other
> containers? It sounds like clients should not hold on to
> ObjectContainers very long. They more or less have to be discarded after
> each operation, or you will be working on stale data.

I would like to handle this with:
- a refresh call
- commit notification to trigger the refresh

Does this sound feasible?


Kind regards,
Carl
Newsgroup Import
New Member
New Member
Newsgroup Import

--
31 Jul 2002 07:30 AM  
This message was imported from the former db4o newsgroup.

Martin Crawford wrote:
> Symantically, I would vote the method to be either:
>
>     ExtDb4o.openTransaction(masterObjectContainer)
> or
>     ObjectContainer.newTransaction()
>
> Esspecially, if the former is the desired approach, as "client" would be
> easily confused as in "client/server" which is not the case.

Thanks for your feedback.

I have come back to favour a configurable per-thread transaction,
since it requires the least changes to our existing
class/interface/method zoo.

It would also behave very nicely in our servlet interface, without
having to touch a line of application code.


> I vote for keeping the ObjectContainer interface central to all
> transactions. The db4o API is elegant in its reuse of the one interfaces.
> The interopability between functionality is merely one or two method calls,
> which is really quite brilliant. Plus one interface, fast time getting your
> hands wet. This is a hallmark of this product and why I've moved towards.

Thanks!
Yeah, no JTA full bloat with TransactionManagers and special
Transaction objects at this point in time.


> I would think that the master container would function exactly as db4o does
> today, otherwise you're looking at a serious break in compatibility. The
> master container would work in its own transaction, essentially
> "single-user" mode (for lack of terminology). Now interestingly how would
> you handle this situation:
>
> 1) masterDb4o = Db4o.openFile();
> 2) masterDb4o.set() (begining a transaction);
> 3) transactionDb4o = ExtDb4o.openTransaction(masterDb4o);
>
> Would transactionDb4o be:
>
> a) Not allowed, throwing an exception. Essentially forcing you choose a
> model single-user mode. Benefits is this is coded defensively to prevent
> confused symantics.
>
> b) transactionDb4o, becomes a nested transaction. This is kind of elegent
> too, and multiple calls to openTransaction() would continue to nest the
> transactions. The standard nested transaction rules would apply.
>
> c) transactionDb4o, becomes an independent transaction competing with the
> masterDb4o transaction. This would be a poor choice I think, but I offer it
> for discussion.

I favour totally staying away from nested transactions at this point
in time.


> > Scenario:
> > 1) Tx 1 starts
> > 2) Tx 2 starts
> > 3) Tx 1 updates object A
> > 4) Tx 2 updates object A.
> > 5) Tx 1 rollbacks
> > 6) Rx 2 commits successfully.
>
> Carl, are you suggesting that once 4 occurs Listeners on Transaction 1 & 2
> would be notified of the change, and have an opportunity to either rollback
> or proceed based on their implementation?

Yes, that was the idea.

I think what we want is some kind of non-exclusive update lock
that becomes exclusive against older versions of the same object,
as soon as the first transaction is successful to commit.

In principle the functionality is already present in the engine,
since all calls to ObjectContainer#set() already write the modified
object to the database file and store the pointer indirection for
a future commit. We would only need to open this information to
the public interface and maybe send notification messages.


> I like this opposed to the
> Exception on commit which could be too late. I feel that unlike a relational
> database, the potential for a large object models become part of a complex
> transactions more likely in db4o. I can picture a deep tree becoming
> involved in a large transaction and rollbacks being more of an occurance.

Exactly that is the problem in a complex object network.

As Rickard correctly points out though, there is no useful
action to be taken, if another client modifies the same
object.

- You are not even sure, if the other transaction will commit.
- You can't reread the object yet.

Very early messages only seem useful if you have some kind
of hierarchy between modification processes. Something like
"the higher level lock in the object hierarchy gets the
higher priority to commit"

...we will stay away from wild stuff like that for another
5 years, I hope.


> I guess it also depends at what granularity to block a transaction, object
> or field level.

I think object level locking is what we can implement nicely and
quickly since our core engine works with object IDs everywhere.


> It could also be argued that some objects should have their
> fields treated atomically, while others would be independent. Example time:
>
> A cheap DateTimeStruct object (for lack of a clever example) should be
> atomic...
>
> class DateTimeStruct {
>
>   Date thisDate;
>   Time thisTime;
>
>   class Date {
>   int year;
>       int month;
>       int day;
>   }
>
>   class Time {
>     int hours;
>     int minutes;
>     int seconds;
>   }
> }
>
> Changing one field essentially changes the definition of this object it is
> no longer the same.

OK, but I am afraid there is no way to automatically detect what
"belongs" to an object and what doesn't.

I have been thinking of some sort of "domain definition", possibly
from the top, with a depth attribute:

#defineDomain(DateTimeStruct.class, 2);

This would not only be nice for locking, it could also be used
for cascaded activation, cascaded updates and cascaded deletes.

...future music.


For the time being I think it would be sufficient to allow a
manual #lock(Object, depth) call. I will write a posting on
locking immediately after this one.


> I am sure there is more rambling to do...

I am buzzing with ideas and I hope some of them are good.

Doing some brainstorming, it seems extremely simple to
allow server-side code execution in a client-server environment.

It really is tempting to implement the "this one is easy" features
first but I know enhanced query functionality is the
one-and-most-important key for more success right now.

It will be needed for JDO and it could also start someone off
to implement SQL for S.O.D.A.


Kind regards,
Carl
Newsgroup Import
New Member
New Member
Newsgroup Import

--
01 Aug 2002 12:08 AM  
This message was imported from the former db4o newsgroup.

Carl Rosenberger wrote:
> If we would have been sticking with "well defined these days" we
> would have been doing SQL / ODMG / JDO. :-)

So you want to make a system that uses transactions, but noone will 
understand because you redefined what a transaction is?  Hm...

>>>Thinking this over I do feel that ObjectContainer==Transaction makes our
>>>engine easier to handle than thread==transaction.
>>
>>Not when you're in a strictly server-mode. Then you want to be able to
>>hold on to ObjectContainer's and begin/commit blocks of actions against
>>it. What you are saying is that there's always a transaction running.
>>IMHO that's bad, as there's just no need for it (usually) when you're
>>doing read-only ops, which usually is the most common case (generalizing
>>wildly here).
> 
> I don't understand this argument but maybe you can enlighten me.
> What's so bad about always having a transaction running?
> It doesn't take away any ressources.

No, but you need to explicitly stop/start it in order to reload state 
from the main repository. That's bad. Should I reload now.. or now... or 
maybe now... hm.. maybe always, just in case... if you don't have any 
transaction you should be running directly on the main repository so 
there's never any problem with stale data.

>>So, let me get this straight. If you have two clients, if the first one
>>modifies an object, when will the other see it? Immediately?
> 
> The second client does not see anything until it loads/reloads objects.
> During loading (ObjectContainer#activate(), ObjectSet#next()) it only
> sees committed changes.

Exactly. And that's the problem. You'd want to avoid constantly 
reloading objects for read-transactions, in case the repository was updated.

> Yes, we want two mechanisms to prevent this:
> (1.) change notification
> (2.) locking

If you do 2) then you have pessimistic locking, which leads to 
deadlocks. And what are you going to do with 1)? Not a lot you can do I 
think.

>>If a transaction has begun, and an object has been read, then it should
>>not change until the transaction is committed or rollbacked. But, if you
>>*do* want to read the committed state, then how would you handle that?
> 
> You would have to open another transaction and get the object by ID.

Exactly. Which is the problem. Previously you said that read-operations 
should share one "read-transaction", but then there's the issue of 
updating it. Which needs to take place pretty much all the time in order 
to be sure we have the latest state. Which is bad. It is better to 
simply use no transaction and then get the main repository. Then you'll 
be sure that you got the right one, without any hassles of reloading.

>>Since you're always in a transaction with your proposed scheme, you'd
>>have to commit/rollback it just to get the latest state of the repository.
> 
> No, the above will do.

You said reload it, or open another transaction and get it by ID. Same 
thing different name, just as bad.

>>That's bad. It is better to use explicit transaction demarcation, which
>>solves the above dilemma: no transaction -> get repository (good for
>>read), transaction started -> get own copy, which will stay the same
>>until commit/rollback.
> 
> What would be the right behaviour if ObjectContainer#set() would be
> called in a context without a transaction?

Set the main repository object directly. Other users that didn't use 
transactions will see the change directly.

> It's no problem at all to get the same behaviour with all the
> proposed alternatives. The points we are discussing here are:
> 
> - How would the API look nice?
> - Can we adher to an existing standard?

No, that's definitely not the issue. The issue is basic semantics. If 
you do implement what you've been outlining, I know db4o is not for me 
because it'll be a nightmare to manage the state, having to reload them 
all the time.

> I don't think that there are too many database implementations that
> - support nested transactions
> - and allow the individual commit of nested transactions
> - and make the commit visible outside of the master transaction
> 
> Reading through the JTA specification, I think the behaviour of
> nested transactions is unspecified. :-)

Yes, so this particular bit is up for interpretation. But this is a 
minor issue in comparison with the normal semantics of the transactions 
in db4o.

> Yup, in principle.
> The behaviour would be easy to understand in an SQL implementation, since
> you would always be rereading the complete data.
> For db4o it would mean that there would always be a non-transactional cache
> (before begin, for suspend/resume) and a transactional cache associated with
> every thread.
> ...too complex and too difficult to understand.

IMHO that's the right way to do it, and no I don't find that difficult 
to understand. Except, the cache is not associated with the thread, it's 
associated with the transaction. I still want a separate notion of 
transaction (i.e. transaction != thread). You'll need it for the 
suspend/resume thing if nothing else.

> Principles that can easily be communicated:
> (1.) "Every ObjectContainer has it's own cache and transaction."
> (2.) "Every thread has it's own cache and transaction."
> 
> We would have to stay compatible with the existing implementation.
> That would mean the existing behaviour would have to remain and
> alternate behaviour would have to be a configuration option.

Sure, that should be doable. But in the long run I think it's more 
important to get it right than stay backward compatible.

> Possibly an early pre-commit notification upon the change itself
> may not be such a good idea.
> 
> However a two-stage notification could be nice:
> (1.) "Just about to commit. Is this O.K. with you others?"
> (2.) "Just committed. Check your concurrencies."
> 
> Looking at this (1.) isn't nice either, since it would have to
> wait for all other clients to respond.

1 seems to be similar to how the Synchronization interface in JTA works. 
And 2 should be done by the database. I don't care as a user.

> I do want an additional feature:
> Notification about committed objects.
> Other transactions could reread values and adjust their behaviour
> while running. 

Too complicated. If that's the reason to use commit notifications then 
it's better that you have the no-transaction option and automatically 
let clients using that see the committed objects. Same thing, but less 
hassle for the clients (since they don't have to do the notification 
listening and explicit reload). What you're talking about should be 
internal to the database.

> This would have interfer with locking in some sort:
> Maybe a call to ObjectContainer#set() would acquire a non-blocking
> write-lock that would need to be refreshed, in case another transaction
> has commit the object in the meanwhile.

As outlined, optimistic transaction management does not use "locks". It 
uses "object use tags" more like, which are checked at commit. Tthe 
easiest way is to get a timestamp at the acquisition of the object and 
check against it when committing. If same timestamp, then no other tx 
changed it. If not same timestamp, then it was changed concurrently, and 
the tx should rollback.

>>See above question: how does containers get the updated state from other
>>containers? It sounds like clients should not hold on to
>>ObjectContainers very long. They more or less have to be discarded after
>>each operation, or you will be working on stale data.
> 
> 
> I would like to handle this with:
> - a refresh call
> - commit notification to trigger the refresh
> 
> Does this sound feasible?

Feasible, yes, but see comments above. I want this to be automatic, and 
(FWIW I guess) this is how other transactional resources work (that I've 
seen).

/Rickard
Newsgroup Import
New Member
New Member
Newsgroup Import

--
01 Aug 2002 05:22 AM  
This message was imported from the former db4o newsgroup.

Rickard berg wrote:
[JTA compliance]
> > If we would have been sticking with "well defined these days" we
> > would have been doing SQL / ODMG / JDO. :-)
>
> So you want to make a system that uses transactions, but noone will
> understand because you redefined what a transaction is?

No. I think we fully agree what a transaction is. I am listening to
all suggestions, what to associate a transaction with and when the
time comes for implementation, hopefully the best choice can be taken.


[explicit transaction begin]
> > I don't understand this argument but maybe you can enlighten me.
> > What's so bad about always having a transaction running?
> > It doesn't take away any ressources.
>
> No, but you need to explicitly stop/start it in order to reload state
> from the main repository. That's bad. Should I reload now.. or now... or
> maybe now... hm.. maybe always, just in case... if you don't have any
> transaction you should be running directly on the main repository so
> there's never any problem with stale data.

Using objects on an SQL database you are always working with stale objects,
unless you have some sort of automatic cache refresh implemented in the
framework. Can you enlighten me on the mechanisms that products of the
kind use?

When we discuss non-transactional behaviour, we clearly have to separate
two setups:
(1) A single-VM system with multiple transactions.
(2) A client/server system.

For (1) I can imagine an automatic refresh mechanism to be reasonably
performant.
For (2) I don't think an automatic push of all modified objects to the
client will perform nicely, even if it is limited to the objects that are
instantiated on the client.

I am sure that I want db4o to behave in exactly the same way in both
scenarios (1) and (2).


Here is an example, just to get clear how "working on the main repository"
would look like:
- thread 1 is running in non-transactional mode
- thread 2 has modified some objects and commits them
- Now the system has to find out which objects have been committed
by thread 2 which are also instantiated for thread 1 (or any other
non-transactional thread). All these objects in thread 1 would need to be
completely reloaded from the database file.

Hey, I don't think I would like that behaviour, definitely not as a default.
Imagine some sort of tree structure that is displayed in a Swing JTree.
Obviously it could break.
Imagine a model behind a servlet application where a currently displayed
HTML page corresponds to an object. What would happen if some attributes
of the object have been deleted by thread 2?

Turning on automatic refresh may be an option for special usecases
but I am certain that I don't want it as a default setting after
opening an ObjectContainer.


> > The second client does not see anything until it loads/reloads objects.
> > During loading (ObjectContainer#activate(), ObjectSet#next()) it only
> > sees committed changes.
>
> Exactly. And that's the problem. You'd want to avoid constantly
> reloading objects for read-transactions, in case the repository was updated.

Yes, but you don't need to constantly reload objects.
Your objects are consistent.

If you want some sort of real-time display, you will need to
work with a change-notification listener anyway.

In case you want to write back objects to the database,
the lock-design I have posted yesterday will tell you
that your objects are stale.


> > Yes, we want two mechanisms to prevent this:
> > (1.) change notification
> > (2.) locking
>
> If you do 2) then you have pessimistic locking, which leads to
> deadlocks. And what are you going to do with 1)? Not a lot you can do I
> think.

O.K. "lock" might be the wrong terminology.
What I want to do is to "tag" objects as modified.
Any suggestions for a better naming?
setModified ? markDirty ? setDirty ?

The behaviour is not pessimistic at all, since it does not
prevent other transactions from committing. It only:
- allows to detect other "locks" or "dirty-tags" by other transactions
- performs a check on commit and the commit will fail, if a "dirty"
object was committed by another transaction after my transaction
has read it.


What's so bad about change notification?
It would allow to reread an object.
A global refresh would work in exactly this way:
Iterate through all the changed objects and refresh them.
If you wish, you can implement your "non-transactional"
behaviour easily with this mechanism.


> You said reload it, or open another transaction and get it by ID. Same
> thing different name, just as bad.

No, completely different thing, different usecase.
Reloading an object will traverse all attributes and refresh them.
It may even be possible to do this with objects that are embedded
into some GUI logic.

Opening another transaction and getting the object by ID will
give you a *different instance*, a second object.


> > What would be the right behaviour if ObjectContainer#set() would be
> > called in a context without a transaction?
>
> Set the main repository object directly. Other users that didn't use
> transactions will see the change directly.

That's bad, since it's likely to produce corrupt and inconsistent data.
How would you suggest to handle this with internal logic in our
write-to-file mechanism? Use a transaction and commit after every #set() ?

Consider "see the change directly" in a multi-user environment with
10 clients in non-transactional mode. Hey, I would need to push the
complete object to all clients over TCP.

As a default? Not an option!

This would also be inconsistent with the current behaviour.

Just from a strategical point of view, the default behaviour needs to
do caching. Imagine someone evaluating db4o and forgetting to call
begin() (which would be normal). His immediate experience would be
"This thing is darn slow. I don't think it works".

I prefer people playing with auto-refresh, after they have some
confidence.


> No, that's definitely not the issue. The issue is basic semantics. If
> you do implement what you've been outlining, I know db4o is not for me
> because it'll be a nightmare to manage the state, having to reload them
> all the time.

I guess you're a candidate for auto-refresh then.


[two caches, transactional and non-transactional]
> IMHO that's the right way to do it, and no I don't find that difficult
> to understand. Except, the cache is not associated with the thread, it's
> associated with the transaction. I still want a separate notion of
> transaction (i.e. transaction != thread). You'll need it for the
> suspend/resume thing if nothing else.

No.
If someone wants to build JTA on top of db4o, I think he can do this
by working with two transactions or by turning autorefresh on an off.

JTA with it's suspend() and resume() comes from SQL, where you always
read and write data with SQL and you can modify what you read and write.
You don't have a cached state of objects on your client that you have
to worry about from a database point of view.

For db4o suspend() would be awkward and difficult to define.
What should happen:
- reload all objects immediately?
- upon reloading parts of objects, read beside the transaction?
(super-inconsistent)
- receive reloading events from commits of other transactions?
(super-inconsistent and will randomly kill your changes)


> > We would have to stay compatible with the existing implementation.
> > That would mean the existing behaviour would have to remain and
> > alternate behaviour would have to be a configuration option.
>
> Sure, that should be doable. But in the long run I think it's more
> important to get it right than stay backward compatible.

No doubt!

In the long run we want to do this right and experience shows that
we are bound to do something wrong this first time. I don't see
the necessity to alternate the current behaviour though.


> > However a two-stage notification could be nice:
> > (1.) "Just about to commit. Is this O.K. with you others?"
> > (2.) "Just committed. Check your concurrencies."
> >
> > Looking at this (1.) isn't nice either, since it would have to
> > wait for all other clients to respond.
>
> 1 seems to be similar to how the Synchronization interface in JTA works.

No.
JTA synchronisation only notifies listeners that a transaction
has just committed.

We want to notify listeners about *all committed objects*.


> And 2 should be done by the database. I don't care as a user.

Auto-refresh, just for you.
It will work nicely in a single VM.

To simulate your non-transactional-mode, we will also need a
mechanism to share a transaction/object cache between two
ObjectContainer threads. I think this will work in exactly the
way you want.


> > This would have interfer with locking in some sort:
> > Maybe a call to ObjectContainer#set() would acquire a non-blocking
> > write-lock that would need to be refreshed, in case another transaction
> > has commit the object in the meanwhile.
>
> As outlined, optimistic transaction management does not use "locks". It
> uses "object use tags" more like, which are checked at commit.

O.K., yeah, that's what I meant:
"dirty tags" are easier to understand since I don't want to block anyone.


> Tthe
> easiest way is to get a timestamp at the acquisition of the object and
> check against it when committing. If same timestamp, then no other tx
> changed it. If not same timestamp, then it was changed concurrently, and
> the tx should rollback.

Yup, I think I outlined this in my other mail.


Are we approaching eachother with our ideas?


Thank you very much for your time and your feedback, Rickard.


Kind regards,
Carl
Newsgroup Import
New Member
New Member
Newsgroup Import

--
01 Aug 2002 05:46 AM  
This message was imported from the former db4o newsgroup.

Carl Rosenberger wrote:
> Using objects on an SQL database you are always working with stale objects,
> unless you have some sort of automatic cache refresh implemented in the
> framework. Can you enlighten me on the mechanisms that products of the
> kind use?

But now you are not comparing the same things. You are the database, not 
the application layer. Of course my objects will be stale if I put it on 
top of SQL. I'd have to refresh somehow. But, if the comparison is to be 
fair, not only do I have to refresh from the database, I have to refresh 
the database itself.

However, I do see your point that in this case the application and the 
database are very tight together so it's hard to determine where one end 
and the other start.

> When we discuss non-transactional behaviour, we clearly have to separate
> two setups:
> (1) A single-VM system with multiple transactions.
> (2) A client/server system.
> 
> For (1) I can imagine an automatic refresh mechanism to be reasonably
> performant.
> For (2) I don't think an automatic push of all modified objects to the
> client will perform nicely, even if it is limited to the objects that are
> instantiated on the client.

For 2) it doesn't have to send the object itself. It just have to say 
"these objects should be purged from the cache", so that they are 
reloaded when used. Although maybe it goes back to the point that you 
don't have any ways to intercept usage, hence must update the objects 
directly.. hm...

> Hey, I don't think I would like that behaviour, definitely not as a default.
> Imagine some sort of tree structure that is displayed in a Swing JTree.
> Obviously it could break.
> Imagine a model behind a servlet application where a currently displayed
> HTML page corresponds to an object. What would happen if some attributes
> of the object have been deleted by thread 2?

That's a good point. No, you're right, one would want to specifically 
say refresh then. But, it needs to be triggered in order to avoid having 
to refresh it randomly. Hm.. but then the notification thingy you 
outlined does make sense...

> If you want some sort of real-time display, you will need to
> work with a change-notification listener anyway.
> 
> In case you want to write back objects to the database,
> the lock-design I have posted yesterday will tell you
> that your objects are stale.

Good point.

> O.K. "lock" might be the wrong terminology.
> What I want to do is to "tag" objects as modified.
> Any suggestions for a better naming?
> setModified ? markDirty ? setDirty ?

Ok, I see what you mean.

> The behaviour is not pessimistic at all, since it does not
> prevent other transactions from committing. It only:
> - allows to detect other "locks" or "dirty-tags" by other transactions
> - performs a check on commit and the commit will fail, if a "dirty"
> object was committed by another transaction after my transaction
> has read it.

Yup, that's how it should work.

> What's so bad about change notification?
> It would allow to reread an object.
> A global refresh would work in exactly this way:
> Iterate through all the changed objects and refresh them.
> If you wish, you can implement your "non-transactional"
> behaviour easily with this mechanism.

You're correct. As long as it's performant it may just be the way to go 
really.

>>You said reload it, or open another transaction and get it by ID. Same
>>thing different name, just as bad.
> 
> No, completely different thing, different usecase.
> Reloading an object will traverse all attributes and refresh them.
> It may even be possible to do this with objects that are embedded
> into some GUI logic.

I'd get that automatically through my AOP framework. But yes, that'd be 
the basic idea.

> That's bad, since it's likely to produce corrupt and inconsistent data.

Which is the reason you don't want to not use transactions for 
write-operations :-)

> How would you suggest to handle this with internal logic in our
> write-to-file mechanism? Use a transaction and commit after every #set() ?

Pretty much.

> Consider "see the change directly" in a multi-user environment with
> 10 clients in non-transactional mode. Hey, I would need to push the
> complete object to all clients over TCP.
> 
> As a default? Not an option!

Point taken.

> This would also be inconsistent with the current behaviour.
> 
> Just from a strategical point of view, the default behaviour needs to
> do caching. Imagine someone evaluating db4o and forgetting to call
> begin() (which would be normal). His immediate experience would be
> "This thing is darn slow. I don't think it works".

That's pretty much how most EJB reviews have been done, and yes, it's 
frustrating.

>>No, that's definitely not the issue. The issue is basic semantics. If
>>you do implement what you've been outlining, I know db4o is not for me
>>because it'll be a nightmare to manage the state, having to reload them
>>all the time.
> 
> I guess you're a candidate for auto-refresh then.

Maybe. Having thought about it some, your case for explicitly reloading 
read-transactions is good. I don't want the servlets to have the model 
change during rendering. That'd be.. bad.

> For db4o suspend() would be awkward and difficult to define.
> What should happen:
> - reload all objects immediately?
> - upon reloading parts of objects, read beside the transaction?
> (super-inconsistent)
> - receive reloading events from commits of other transactions?
> (super-inconsistent and will randomly kill your changes)

Ok, points taken.

> We want to notify listeners about *all committed objects*.

You mean, which objects were committed?

>>And 2 should be done by the database. I don't care as a user.
> 
> Auto-refresh, just for you.
> It will work nicely in a single VM.

:-)

> Are we approaching eachother with our ideas?

Done deal :-)

/Rickard

-- 
Rickard berg
Senselogic


To unsubscribe from this group, send an email to:
db4o_unmoderated-unsubscribe@yahoogroups.com

 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
Newsgroup Import
New Member
New Member
Newsgroup Import

--
01 Aug 2002 07:18 AM  
This message was imported from the former db4o newsgroup.

> When we discuss non-transactional behaviour, we clearly have to separate
> two setups:
> (1) A single-VM system with multiple transactions.
> (2) A client/server system.
>
> For (1) I can imagine an automatic refresh mechanism to be reasonably
> performant.
> For (2) I don't think an automatic push of all modified objects to the
> client will perform nicely, even if it is limited to the objects that are
> instantiated on the client.
>
> I am sure that I want db4o to behave in exactly the same way in both
>scenarios (1) and (2).
>

I would have to agree, Carl, that an application using db4o in 1) would
really want to have an "auto-refresh", while 2) would want to control what
gets refreshed. Could it be covered with the following two things (one I
believe has been touched upon before):

- Listener for commit changes
  perhaps being passed an ObejctSet of the objects effected in the commit
  and optimized to have only those objects that might require a refresh
because
  they are in the local cache

- Config method where you can turn on auto-refresh, but default to off
(ooops, consider this one a summary for later points in your email;)


To unsubscribe from this group, send an email to:
db4o_unmoderated-unsubscribe@yahoogroups.com

 

Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
Newsgroup Import
New Member
New Member
Newsgroup Import

--
01 Aug 2002 08:29 AM  
This message was imported from the former db4o newsgroup.

Martin Crawford wrote:
> > (1) A single-VM system with multiple transactions.
> > (2) A client/server system.
>
> I would have to agree, Carl, that an application using db4o in 1) would
> really want to have an "auto-refresh", while 2) would want to control what
> gets refreshed. Could it be covered with the following two things (one I
> believe has been touched upon before):
>
> - Listener for commit changes
>   perhaps being passed an ObejctSet of the objects effected in the commit
>   and optimized to have only those objects that might require a refresh
> because
>   they are in the local cache
>
> - Config method where you can turn on auto-refresh, but default to off
> (ooops, consider this one a summary for later points in your email;)

Perfect, Martin.

That's exactly how we will do it.
It's nice to see that we are thinking in the same direction.

Kind regards,
Carl
You are not authorized to post a reply.
Forums > English Forums > db4o User Forum

Active Forums 4.2
Close
Copyright ©2000-2010 by Versant Corp.
Privacy Policy