From: Adriano d. S. F. <adr...@gm...> - 2011-03-25 17:30:57
|
On 25-03-2011 14:21, Dimitry Sibiryakov wrote: > 25.03.2011 18:07, Adriano dos Santos Fernandes wrote: >> Also, let say external code receives an engine IAttachment which was >> registered in yvalve and now has a handle. Then external code starts to >> use this handle and start new transaction with legacy API. > > Why the code would like to do such stupid things?.. It can start new transaction using > received IAttachment. And to accomplish that it doesn't need it's handle. > It's always easy to ask people they need to: 1) Wait for the creators of the library they use to release new version, rewritten for a new API or 2) Convert they existing code with use official till now Firebird API to use new API Right? Adriano PS: I'm not going to continue replying to such stupidities everytime... I have better things to do, sorry. |
From: Dimitry S. <sd...@ib...> - 2011-03-25 17:46:03
|
25.03.2011 18:30, Adriano dos Santos Fernandes wrote: > It's always easy to ask people they need to: > > 1) Wait for the creators of the library they use to release new version, > rewritten for a new API > or > 2) Convert they existing code with use official till now Firebird API to > use new API > > Right? Right. Because a) no existing code exists yet; b) before such code appear, new API will become years old. You are too optimistic about external datasource feature. BLOB filter API exists from the beginning. How many third-party BLOB filters you know? UDF API is even older. How many years passed before libraries like rfunc stop crashing server?.. It was a joke: rfunc still do that. -- SY, SD. |
From: Alex P. <pes...@ma...> - 2011-03-27 12:04:22
|
On 03/25/11 20:45, Dimitry Sibiryakov wrote: > 25.03.2011 18:30, Adriano dos Santos Fernandes wrote: >> It's always easy to ask people they need to: >> >> 1) Wait for the creators of the library they use to release new version, >> rewritten for a new API >> or >> 2) Convert they existing code with use official till now Firebird API to >> use new API >> >> Right? > Right. Because a) no existing code exists yet; b) before such code appear, new API will > become years old. > You are too optimistic about external datasource feature. BLOB filter API exists from > the beginning. How many third-party BLOB filters you know? UDF API is even older. How many > years passed before libraries like rfunc stop crashing server?.. It was a joke: rfunc > still do that. Guys, I suppose you are both somewhat right. I know that Adriano expects that some people will convert there existing code to run in external engines. It's possible, though I do not expect massive things. And certainly if we make it possible to use old ISC API in external engines (moreover, this does not seem to be a big problem), such conversion looks easier. |
From: Alex P. <pes...@ma...> - 2011-03-25 18:40:53
|
> In my new version of why.cpp things like CAttachment (C*) classes gone > in favor of YAttachment (Y*) objects. Things are much simple and > effective, became directly usable without legacy handles, may use the > same API (semantics defined in yvalve) for client and external code > running on the server. > Adriano, sorry - it's too late here now and I can't give complete full answer right now. If your modifications: 1. Do not take new special measures (like IYvalveManagement interface) to coordinate between engine and yvalve. 2. Do not break reference counters functionality. I see no problems with them. If not - please delay them till the end of discussion. |
From: Alex P. <pes...@ma...> - 2011-03-27 13:11:18
|
On 03/25/11 20:07, Adriano dos Santos Fernandes wrote: > On 25-03-2011 13:48, Alex Peshkoff wrote: >> On 03/25/11 18:59, Adriano dos Santos Fernandes wrote: >>> On 25-03-2011 05:27, Alex Peshkoff wrote: >>>> On 03/24/11 20:28, Adriano dos Santos Fernandes wrote: >>>>> On 24-03-2011 12:53, Alex Peshkoff wrote: >>>>>> On 03/24/11 18:09, Adriano dos Santos Fernandes wrote: >>>>>>> On 24-03-2011 11:59, Alex Peshkoff wrote: >>>>>>>> May be you have forgotten - one of my proposals is to not pass external >>>>>>>> handles in attach/startTransaction call. And do not pass them into >>>>>>>> engine in any way. Cause with new API we have much better way to access >>>>>>>> current context. >>>>>>>> >>>>>>> If your approach is about don't be able to use current Firebird API with >>>>>>> external attachments and transactions (initiated by client or >>>>>>> internally), I'm sorry but I can't consider it as usable. >>>>>> May be you've missed in the thread 'Refcounted API objects': >>>>>> >>>>>> We really need converter from ISC API to new interface. If in external >>>>>> engines we >>>>>> add 2 special handle values - current connection and current >>>>>> transaction, this will solve backward compatibility problem in all places. >>>>>> >>>>> Single handle meaning different things when used in different moments >>>>> smells like fire to me. >>>> Yes, probably you are right. Even if we take into an account existence >>>> of current_user and current_role variables - I agree that this is >>>> another usage. >>>> >>>> But no matter of that fact delivering of original ISC handles into >>>> engine is also bad idea. And one of the reasons for it - in many cases >>>> there will be nothing to deliver. Server with new interface will work >>>> without ISC handles at all, therefore to support old API in external >>>> engines you will anyway have to create a kind of pseudo ISC handle. >>>> There is absolutely no crime in it - just make it possible to ask API >>>> converter: I have IAttacment* (or ITransaction*), please create handle >>>> for it. >>>> >>> This seems ok. >>> >>> What I had in mind: >>> - Yvalve handles are mapped to Yvalve objects (YAttachment, YTransaction). >>> - We add new API function that translate Yvalve pointer to handle: >>> fb_get_handle(IInterface*, int type) >>> >>> And with your suggestion, then we add a way to make the Yvalve to create >>> a Yvalve object from a provider object, so external code always access >>> provider objects via Yvalve objects. And since external code now >>> receives a Yvalve object, it can gets its legacy handle with fb_get_handle. >> Now (I talk about SVN state) external code receives ISC handle. But I >> suggest you to remove this hack from the code and when external engines >> need to access current attachment/transaction (let me call this pair >> context later), make them work using engine directly, without yValve. >> >> I know your mind that all calls must pass through yValve. But I have not >> seen any explanation of this requirement. The only reason I remember is >> 'other types of providers need access to this calls'. But this >> requirement is rather strange. Let's take a look at SP. It executes some >> SQL operators, and (I hope) nobody requires this calls to go to yValve. > Yvalve defines Firebird API requirements, may check handles (objects > too), may do extra things. With VTable-based API checking handles makes almost no sense. If we reached some function (it's virtual function) in the object, this means that a region of memory where user's pointer to that interface points has correct VTable. That is ehough guarantee that the object is OK. > Don't make sense to move this type of functionality to each provider. > If we talk about checking objects - hmm, only provider itself can check his own object. What about extra things - this depends upon what extra things to be done. > Also, let say external code receives an engine IAttachment which was > registered in yvalve and now has a handle. Then external code starts to > use this handle and start new transaction with legacy API. If this > IAttachment is not from yvalve, now yvalve gained another responsibility > which is to coordinate engine provider objects. If external code start transaction, using legacy handle created for current attachment, then isc_start_transaction(legHandle) will find IAttachment* curAtt, appropriate for that legHandle, and call curAtt->startTransaction(). Certainly, if curAtt is not yValve's but engine's object, this means that transaction is started not under yvalve control. And telling true I see absolutely no problems that this transaction did not pass through yValve. > Let yvalve coordinate yvalve objects. Let! (but also let engine coordinate engine objects) > In my new version of why.cpp things like CAttachment (C*) classes gone > in favor of YAttachment (Y*) objects. Things are much simple and > effective, became directly usable without legacy handles, may use the > same API (semantics defined in yvalve) for client and external code > running on the server. > Looks like I totally agree with mentioned changes. I suppose you also have a module to translate ISC API calls? >> Now imagine that instead direct >> >> INSERT INTO SOME_TABLES(SOME_INT) VALUES(123); >> >> Now let's rewrite this slightly. >> >> EXECUTE STATEMENT 'INSERT INTO SOME_TABLES(SOME_INT) VALUES(123)'; >> >> Should it pass through yValve? What's a difference with previous case? >> And finally let's imagine that some external engine executes same >> statement in current context. What's the difference between stored >> procedure, execute statement and external engine (working with current >> context) that in some cases SQL operator must pass go to yValve, but in >> others - not? >> > This is pure internal command, has nothing to do with API, so it may > execute without yvalve like any other internal command. If it's an > external datasource, it must be created by yvalve cause it may go to > another provider. Yes. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-27 16:04:08
|
On 27-03-2011 10:11, Alex Peshkoff wrote: >>> >>> I know your mind that all calls must pass through yValve. But I have not >>> seen any explanation of this requirement. The only reason I remember is >>> 'other types of providers need access to this calls'. But this >>> requirement is rather strange. Let's take a look at SP. It executes some >>> SQL operators, and (I hope) nobody requires this calls to go to yValve. >> Yvalve defines Firebird API requirements, may check handles (objects >> too), may do extra things. > > With VTable-based API checking handles makes almost no sense. If we > reached some function (it's virtual function) in the object, this means > that a region of memory where user's pointer to that interface points > has correct VTable. That is ehough guarantee that the object is OK. > Not true. Let say I have: IAttachment* attachment = ...; // attachment from yvalve ITransaction* transaction = ...; // transaction from provider or any other instance of an ITransaction And we call attachment->createBlob(transaction, ...); Yvalve would use the transaction as an YTransaction, and it obviously is not. >> Don't make sense to move this type of functionality to each provider. >> > > If we talk about checking objects - hmm, only provider itself can check > his own object. > What about extra things - this depends upon what extra things to be done. > And this where yvalve objects enter again. For user, it's always used. And we expect that yvalve is correct, so each provider don't need to do this type of checks. >> Also, let say external code receives an engine IAttachment which was >> registered in yvalve and now has a handle. Then external code starts to >> use this handle and start new transaction with legacy API. If this >> IAttachment is not from yvalve, now yvalve gained another responsibility >> which is to coordinate engine provider objects. > > If external code start transaction, using legacy handle created for > current attachment, then isc_start_transaction(legHandle) will find > IAttachment* curAtt, appropriate for that legHandle, and call > curAtt->startTransaction(). Certainly, if curAtt is not yValve's but > engine's object, this means that transaction is started not under yvalve > control. And telling true I see absolutely no problems that this > transaction did not pass through yValve. > I do not agree this is easy or make code simple. Using "YObjects" in the yvalve makes sense, and this case introduces an exception that makes things harder. >> Let yvalve coordinate yvalve objects. > > Let! (but also let engine coordinate engine objects) > >> In my new version of why.cpp things like CAttachment (C*) classes gone >> in favor of YAttachment (Y*) objects. Things are much simple and >> effective, became directly usable without legacy handles, may use the >> same API (semantics defined in yvalve) for client and external code >> running on the server. >> > > Looks like I totally agree with mentioned changes. I suppose you also > have a module to translate ISC API calls? > Not yet. Currently it pass all tcs tests and has published the dispatcher provider, so the client can use the objects directly. I'll make it available for review. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-28 09:11:01
|
On 03/27/11 20:03, Adriano dos Santos Fernandes wrote: > On 27-03-2011 10:11, Alex Peshkoff wrote: >>>> I know your mind that all calls must pass through yValve. But I have not >>>> seen any explanation of this requirement. The only reason I remember is >>>> 'other types of providers need access to this calls'. But this >>>> requirement is rather strange. Let's take a look at SP. It executes some >>>> SQL operators, and (I hope) nobody requires this calls to go to yValve. >>> Yvalve defines Firebird API requirements, may check handles (objects >>> too), may do extra things. >> With VTable-based API checking handles makes almost no sense. If we >> reached some function (it's virtual function) in the object, this means >> that a region of memory where user's pointer to that interface points >> has correct VTable. That is ehough guarantee that the object is OK. >> > Not true. > > Let say I have: > IAttachment* attachment = ...; // attachment from yvalve > ITransaction* transaction = ...; // transaction from provider or any > other instance of an ITransaction > > And we call attachment->createBlob(transaction, ...); > > Yvalve would use the transaction as an YTransaction, and it obviously is > not. > This need happened due to my attempt to emulate old ISC API too careful :-) All the cases when we need both attachment & transaction are due to my wrong understanding (when writing interfaces for yvalve) of how should multiDb transaction work. Such transaction should have same interface as single database one, but absolutely other implementation. This implementation is provider-independent, therefore can be placed in master interface. startMultiDbTransaction() creates a container holding pairs - IAttachment* which started transaction and started ITransaction*. All functions like createBlob() go to ITransaction. Normal implementation ignores IAttachment* parameter. MultiDb implementation searchs in internal container for appropriate IAttachment* and calls same function for found transaction. No more casts - and therefore no need in additonal checks. And yes - one can safely mix attachments, created by different providers, in such MultiDb transaction. I.e. I still do not see where do we need to do additional checks. >>> Also, let say external code receives an engine IAttachment which was >>> registered in yvalve and now has a handle. Then external code starts to >>> use this handle and start new transaction with legacy API. If this >>> IAttachment is not from yvalve, now yvalve gained another responsibility >>> which is to coordinate engine provider objects. >> If external code start transaction, using legacy handle created for >> current attachment, then isc_start_transaction(legHandle) will find >> IAttachment* curAtt, appropriate for that legHandle, and call >> curAtt->startTransaction(). Certainly, if curAtt is not yValve's but >> engine's object, this means that transaction is started not under yvalve >> control. And telling true I see absolutely no problems that this >> transaction did not pass through yValve. >> > I do not agree this is easy or make code simple. Many times simpler than adding artificial yValve control interface. > Using "YObjects" in the > yvalve makes sense, and this case introduces an exception that makes > things harder. I do not understand what this phrase about? What "YObjects", how makes sense? Your solution to pass pointers to yValve objects into engine when working with ISC API was unavoidable hack when using ISC API. With new providers interfaces we should avoid such hacks. Removing old (or new) hacks is one of the reasons to add new interface. I do not understand why do you protect that old hack so intensively, and try to push it into new code. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-28 14:28:49
|
On 28-03-2011 06:10, Alex Peshkoff wrote: > > This need happened due to my attempt to emulate old ISC API too careful :-) > All the cases when we need both attachment & transaction are due to my > wrong understanding (when writing interfaces for yvalve) of how should > multiDb transaction work. > Such transaction should have same interface as single database one, but > absolutely other implementation. This implementation is > provider-independent, therefore can be placed in master interface. > startMultiDbTransaction() creates a container holding pairs - > IAttachment* which started transaction and started ITransaction*. All > functions like createBlob() go to ITransaction. Normal implementation > ignores IAttachment* parameter. MultiDb implementation searchs in > internal container for appropriate IAttachment* and calls same function > for found transaction. No more casts - and therefore no need in > additonal checks. And yes - one can safely mix attachments, created by > different providers, in such MultiDb transaction. > > I.e. I still do not see where do we need to do additional checks. > The scheme of put openBlob and others in transaction was very evil, and complete different than the way others things worked. With it, you created this notion of passing a null attachment. But you would need it in multidb transactions, then, you would still need the casts, and at the same time make programs difficult to change from single to multidb transactions if needed. >>>> Also, let say external code receives an engine IAttachment which was >>>> registered in yvalve and now has a handle. Then external code starts to >>>> use this handle and start new transaction with legacy API. If this >>>> IAttachment is not from yvalve, now yvalve gained another responsibility >>>> which is to coordinate engine provider objects. >>> If external code start transaction, using legacy handle created for >>> current attachment, then isc_start_transaction(legHandle) will find >>> IAttachment* curAtt, appropriate for that legHandle, and call >>> curAtt->startTransaction(). Certainly, if curAtt is not yValve's but >>> engine's object, this means that transaction is started not under yvalve >>> control. And telling true I see absolutely no problems that this >>> transaction did not pass through yValve. >>> >> I do not agree this is easy or make code simple. > > Many times simpler than adding artificial yValve control interface. > It's becoming difficult to discuss with you cause you change your opinions everytime. Yesterday you said: ------------------ > In my new version of why.cpp things like CAttachment (C*) classes gone > > in favor of YAttachment (Y*) objects. Things are much simple and > > effective, became directly usable without legacy handles, may use the > > same API (semantics defined in yvalve) for client and external code > > running on the server. > > Looks like I totally agree with mentioned changes. I suppose you also have a module to translate ISC API calls? ------------------ You also agreed with these now "artificial yValve control interface" a number of times, and also disagreed with them a number of times.... >> Using "YObjects" in the >> yvalve makes sense, and this case introduces an exception that makes >> things harder. > > I do not understand what this phrase about? What "YObjects", how makes > sense? > > Your solution to pass pointers to yValve objects into engine when > working with ISC API was unavoidable hack when using ISC API. With new > providers interfaces we should avoid such hacks. Removing old (or new) > hacks is one of the reasons to add new interface. I do not understand > why do you protect that old hack so intensively, and try to push it into > new code. > I don't know exactly what are you talking about. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-28 14:42:03
|
Adriano! > It's becoming difficult to discuss with you cause you change your > opinions everytime. Yesterday you said: > > ------------------ >> In my new version of why.cpp things like CAttachment (C*) classes gone >>> in favor of YAttachment (Y*) objects. Things are much simple and >>> effective, became directly usable without legacy handles, may use the >>> same API (semantics defined in yvalve) for client and external code >>> running on the server. >>> > Looks like I totally agree with mentioned changes. I suppose you also > have a module to translate ISC API calls? Stop! Where do you see here something like "yValve control interface"? I agreed with MENTIONED changes, namely: 1. new Y* objects, usable without legacy handles. 2. MAY use same API for client and external code running on the server. With this I do agree. If your new objects require yValve control interface - sorry, it was not MENTIONED here. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-28 15:16:43
|
On 28-03-2011 11:41, Alex Peshkoff wrote: > Adriano! >> It's becoming difficult to discuss with you cause you change your >> opinions everytime. Yesterday you said: >> >> ------------------ >>> In my new version of why.cpp things like CAttachment (C*) classes gone >>>> in favor of YAttachment (Y*) objects. Things are much simple and >>>> effective, became directly usable without legacy handles, may use the >>>> same API (semantics defined in yvalve) for client and external code >>>> running on the server. >>>> >> Looks like I totally agree with mentioned changes. I suppose you also >> have a module to translate ISC API calls? > > Stop! Where do you see here something like "yValve control interface"? > I agreed with MENTIONED changes, namely: > > 1. new Y* objects, usable without legacy handles. > 2. MAY use same API for client and external code running on the server. > > With this I do agree. If your new objects require yValve control > interface - sorry, it was not MENTIONED here. > Of course, as I already explained more than one times, "YObjects" are substitutes to current C* internal yvalve objects and are what I suppose you call "yValve control interface", otherwise would have no sense to create them. And as is yvalve resposability to do some things (multidb transactions being one of them, more many things I already talked about), it's of course better to have user using YValve objects than providers directly. And back when Dmitry was discussing about the same things (to not use providers directly), you were with some doubts but never was against it nor provided a good reason to do the contrary. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-28 14:52:25
|
On 03/28/11 18:28, Adriano dos Santos Fernandes wrote: > On 28-03-2011 06:10, Alex Peshkoff wrote: >> This need happened due to my attempt to emulate old ISC API too careful :-) >> All the cases when we need both attachment & transaction are due to my >> wrong understanding (when writing interfaces for yvalve) of how should >> multiDb transaction work. >> Such transaction should have same interface as single database one, but >> absolutely other implementation. This implementation is >> provider-independent, therefore can be placed in master interface. >> startMultiDbTransaction() creates a container holding pairs - >> IAttachment* which started transaction and started ITransaction*. All >> functions like createBlob() go to ITransaction. Normal implementation >> ignores IAttachment* parameter. MultiDb implementation searchs in >> internal container for appropriate IAttachment* and calls same function >> for found transaction. No more casts - and therefore no need in >> additonal checks. And yes - one can safely mix attachments, created by >> different providers, in such MultiDb transaction. >> >> I.e. I still do not see where do we need to do additional checks. >> > The scheme of put openBlob and others in transaction was very evil, and > complete different than the way others things worked. What others things? Why evil? When was openBlob in transaction? > With it, you created this notion of passing a null attachment. ??? > But you > would need it in multidb transactions, then, you would still need the > casts, With described approach I will not need casts. > and at the same time make programs difficult to change from > single to multidb transactions if needed. > There will be absolutely no difference in program when changing from single to multiDbTransactions. Except the start of transaction itself - but one will anyway need to have >1 attachment, i.e. changes here are unavoidable. When multidb transaction is started, one will work with it in exactly same way as with single db. It's same interface, just different implementations. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-28 15:04:41
|
On 28-03-2011 11:52, Alex Peshkoff wrote: > On 03/28/11 18:28, Adriano dos Santos Fernandes wrote: >> On 28-03-2011 06:10, Alex Peshkoff wrote: >>> This need happened due to my attempt to emulate old ISC API too careful :-) >>> All the cases when we need both attachment & transaction are due to my >>> wrong understanding (when writing interfaces for yvalve) of how should >>> multiDb transaction work. >>> Such transaction should have same interface as single database one, but >>> absolutely other implementation. This implementation is >>> provider-independent, therefore can be placed in master interface. >>> startMultiDbTransaction() creates a container holding pairs - >>> IAttachment* which started transaction and started ITransaction*. All >>> functions like createBlob() go to ITransaction. Normal implementation >>> ignores IAttachment* parameter. MultiDb implementation searchs in >>> internal container for appropriate IAttachment* and calls same function >>> for found transaction. No more casts - and therefore no need in >>> additonal checks. And yes - one can safely mix attachments, created by >>> different providers, in such MultiDb transaction. >>> >>> I.e. I still do not see where do we need to do additional checks. >>> >> The scheme of put openBlob and others in transaction was very evil, and >> complete different than the way others things worked. > > What others things? Why evil? > When was openBlob in transaction? >> With it, you created this notion of passing a null attachment. > > ??? > --------------------- Revision: 52587 http://firebird.svn.sourceforge.net/firebird/?rev=52587&view=rev Author: asfernandes Date: 2011-03-21 21:56:47 +0000 (Mon, 21 Mar 2011) Log Message: ----------- Move transactRequest, createBlob, openBlob, getSlice, putSlice and ddl from ITransaction to IAttachment. It's better to have one standard than two, and "ddl" was broken from API POV. So make the IAttachment always the caller, explicit or implicit (via IStatement or IRequest), and pass the ITransaction as parameter. --------------------- What you were doing was to make possible to call transaction->createBlob(..., attachment = NULL) for single transactions, but sure this is impossible to work with multidb transactions. So you needed the IAttachment for them, and it would be need to be casted as we were talking. Also, engine was receiving a bogus IAttachment and just validating it. >> But you >> would need it in multidb transactions, then, you would still need the >> casts, > > With described approach I will not need casts. > >> and at the same time make programs difficult to change from >> single to multidb transactions if needed. >> > > There will be absolutely no difference in program when changing from > single to multiDbTransactions. > Except the start of transaction itself - but one will anyway need to > have >1 attachment, i.e. changes here are unavoidable. When multidb > transaction is started, one will work with it in exactly same way as > with single db. It's same interface, just different implementations. > As I said above, multidb transaction can't receive a null attachment and work before my change, but this worked with singledb transction. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-30 10:53:31
|
On 03/28/11 19:04, Adriano dos Santos Fernandes wrote: > > --------------------- > Revision: 52587 > http://firebird.svn.sourceforge.net/firebird/?rev=52587&view=rev > Author: asfernandes > Date: 2011-03-21 21:56:47 +0000 (Mon, 21 Mar 2011) > > Log Message: > ----------- > Move transactRequest, createBlob, openBlob, getSlice, putSlice and ddl > from ITransaction to IAttachment. > > It's better to have one standard than two, and "ddl" was broken from API > POV. > So make the IAttachment always the caller, explicit or implicit (via > IStatement or IRequest), and pass the ITransaction as parameter. > --------------------- > > What you were doing was to make possible to call > transaction->createBlob(..., attachment = NULL) for single transactions, > but sure this is impossible to work with multidb transactions. Definitely yes. I've blindly kept ISC API functionality, I was wrong. But I do not see big need in moving this calls from ITransaction to IAttachment. What did you achieve with it? > So you needed the IAttachment for them, and it would be need to be > casted as we were talking. No, there is no need in casts. Instead I suggest to keep openBlob in ITransaction. SingleDB implementation stores a pointer to an YAttachment in which it was started. Let it be: YAttachment* myAttachment; Therefore: YTransaction::openBlob(BLOB_ID_TYPE blobId, IAttachment* att) { if (myAttachment == att) { next->openBlob(bolbId, myAttachment->next); return; } // raise error } Multi DB transaction stores pairs (IAttachment*, ITransaction*). Lete it be: Array<Pair<IAttachment*, ITransaction*> > pairs; And: MultiTransaction::openBlob(BLOB_ID_TYPE blobId, IAttachment* att) { for (i=0; I<pairs.count(); ++i) { if (pairs[i].left == att) { pairs[i].right->openBlob(bolbId, att); return; } } // raise error } That's all - and no casts. |
From: Vlad K. <hv...@us...> - 2011-03-28 18:18:54
|
Let me comment a bit. >>>> If external code start transaction, using legacy handle created for >>>> current attachment, then isc_start_transaction(legHandle) will find >>>> IAttachment* curAtt, appropriate for that legHandle, and call >>>> curAtt->startTransaction(). Certainly, if curAtt is not yValve's but >>>> engine's object, this means that transaction is started not under yvalve >>>> control. And telling true I see absolutely no problems that this >>>> transaction did not pass through yValve. >>>> >>> I do not agree this is easy or make code simple. >> >> Many times simpler than adding artificial yValve control interface. >> > It's becoming difficult to discuss with you cause you change your > opinions everytime. Yesterday you said: > > ------------------ >> In my new version of why.cpp things like CAttachment (C*) classes gone >> > in favor of YAttachment (Y*) objects. Things are much simple and >> > effective, became directly usable without legacy handles, may use the >> > same API (semantics defined in yvalve) for client and external code >> > running on the server. >> > > Looks like I totally agree with mentioned changes. I suppose you also > have a module to translate ISC API calls? > ------------------ > > You also agreed with these now "artificial yValve control interface" a > number of times, and also disagreed with them a number of times.... Alex (and me) disagree with IProviderManagement interface. >> Your solution to pass pointers to yValve objects into engine when >> working with ISC API was unavoidable hack when using ISC API. With new >> providers interfaces we should avoid such hacks. Removing old (or new) >> hacks is one of the reasons to add new interface. I do not understand >> why do you protect that old hack so intensively, and try to push it into >> new code. >> > I don't know exactly what are you talking about. I believe Alex means FB_API_HANDLE Attachment::att_public_handle, and FB_API_HANDLE jrd_tra::tra_public_handle Regards, Vlad |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-28 18:47:59
|
On 28-03-2011 15:18, Vlad Khorsun wrote: > Let me comment a bit. > >>>>> If external code start transaction, using legacy handle created for >>>>> current attachment, then isc_start_transaction(legHandle) will find >>>>> IAttachment* curAtt, appropriate for that legHandle, and call >>>>> curAtt->startTransaction(). Certainly, if curAtt is not yValve's but >>>>> engine's object, this means that transaction is started not under yvalve >>>>> control. And telling true I see absolutely no problems that this >>>>> transaction did not pass through yValve. >>>>> >>>> I do not agree this is easy or make code simple. >>> >>> Many times simpler than adding artificial yValve control interface. >>> >> It's becoming difficult to discuss with you cause you change your >> opinions everytime. Yesterday you said: >> >> ------------------ >>> In my new version of why.cpp things like CAttachment (C*) classes gone >>>> in favor of YAttachment (Y*) objects. Things are much simple and >>>> effective, became directly usable without legacy handles, may use the >>>> same API (semantics defined in yvalve) for client and external code >>>> running on the server. >>>> >> Looks like I totally agree with mentioned changes. I suppose you also >> have a module to translate ISC API calls? >> ------------------ >> >> You also agreed with these now "artificial yValve control interface" a >> number of times, and also disagreed with them a number of times.... > > Alex (and me) disagree with IProviderManagement interface. > >>> Your solution to pass pointers to yValve objects into engine when >>> working with ISC API was unavoidable hack when using ISC API. With new >>> providers interfaces we should avoid such hacks. Removing old (or new) >>> hacks is one of the reasons to add new interface. I do not understand >>> why do you protect that old hack so intensively, and try to push it into >>> new code. >>> >> I don't know exactly what are you talking about. > > I believe Alex means > > FB_API_HANDLE Attachment::att_public_handle, and > FB_API_HANDLE jrd_tra::tra_public_handle > > Looks like you miss the place I liked the solution to make the engine call the yvalve to register handles. Of course, yvalve must publish yvalve objects for external usage. This still lacks support for providers wanting to do some sort of chaining. But this is another problem, and would be necessary to investigate separated if required. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-24 09:14:27
|
On 03/23/11 17:29, Adriano dos Santos Fernandes wrote: >> Adriano, are you serious that all described here is simpler than proxy >> objects in engine? :-) >> > I'm *sure* it is. I showed you ~15 lines of code, against > addRefs/releases around by Firebird and all-over-the-world users code. Most of addRef/release in firebird are done using smart pointers. Therefore this is not a problem. What about users code - if user is not going to use an object in complex MT environment he need not care about reference counters at all. May be you did not pay attention, but detach, commit and all other calls, closing handle, perform release automatically on successful completion. In MT environment existing inside exported object reference counters will just help to minimize user code - remember your own words that if someone needs MT safety he will have to completely implement logic himself without reference counters? > And, BTW, it will not crash when the engine is unloaded, like I said in > the another message. Answered in other thread. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-24 13:51:02
|
On 24-03-2011 06:14, Alex Peshkoff wrote: > On 03/23/11 17:29, Adriano dos Santos Fernandes wrote: >>> Adriano, are you serious that all described here is simpler than proxy >>> objects in engine? :-) >>> >> I'm *sure* it is. I showed you ~15 lines of code, against >> addRefs/releases around by Firebird and all-over-the-world users code. > > Most of addRef/release in firebird are done using smart pointers. > Therefore this is not a problem. > Of course it is. Currently why.cpp is completely unnecessarily overloaded by RefPtrs, References, etc. I'm rewriting it in much simple way. > What about users code - if user is not going to use an object in complex > MT environment he need not care about reference counters at all. May be > you did not pay attention, but detach, commit and all other calls, > closing handle, perform release automatically on successful completion. > > In MT environment existing inside exported object reference counters > will just help to minimize user code - remember your own words that if > someone needs MT safety he will have to completely implement logic > himself without reference counters? > Please let me know, with details, what *user* problem you want to solve making *user* call addRef in his MT program. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-24 14:08:33
|
On 03/24/11 16:50, Adriano dos Santos Fernandes wrote: > On 24-03-2011 06:14, Alex Peshkoff wrote: >> On 03/23/11 17:29, Adriano dos Santos Fernandes wrote: >>>> Adriano, are you serious that all described here is simpler than proxy >>>> objects in engine? :-) >>>> >>> I'm *sure* it is. I showed you ~15 lines of code, against >>> addRefs/releases around by Firebird and all-over-the-world users code. >> Most of addRef/release in firebird are done using smart pointers. >> Therefore this is not a problem. >> > Of course it is. Currently why.cpp is completely unnecessarily > overloaded by RefPtrs, References, etc. I'm rewriting it in much simple way. > Adriano PLEASE do not hurry too much. We still have no decision on a problem... >> What about users code - if user is not going to use an object in complex >> MT environment he need not care about reference counters at all. May be >> you did not pay attention, but detach, commit and all other calls, >> closing handle, perform release automatically on successful completion. >> >> In MT environment existing inside exported object reference counters >> will just help to minimize user code - remember your own words that if >> someone needs MT safety he will have to completely implement logic >> himself without reference counters? >> > Please let me know, with details, what *user* problem you want to solve > making *user* call addRef in his MT program. Big desire to recommend you to read microsoft's com-related documentation :-) In 2 words problem is as follows - avoid segfault when pointer to already non-existing interface is used. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-24 14:17:36
|
On 24-03-2011 11:08, Alex Peshkoff wrote: > On 03/24/11 16:50, Adriano dos Santos Fernandes wrote: >> On 24-03-2011 06:14, Alex Peshkoff wrote: >>> On 03/23/11 17:29, Adriano dos Santos Fernandes wrote: >>>>> Adriano, are you serious that all described here is simpler than proxy >>>>> objects in engine? :-) >>>>> >>>> I'm *sure* it is. I showed you ~15 lines of code, against >>>> addRefs/releases around by Firebird and all-over-the-world users code. >>> Most of addRef/release in firebird are done using smart pointers. >>> Therefore this is not a problem. >>> >> Of course it is. Currently why.cpp is completely unnecessarily >> overloaded by RefPtrs, References, etc. I'm rewriting it in much simple way. >> > > Adriano PLEASE do not hurry too much. > We still have no decision on a problem... > It's does not include remotion of your beloved refcounters... :) yet. It's just new implementation, a simple (it don't need to not be) framework to use the providers in more modern way. >>> What about users code - if user is not going to use an object in complex >>> MT environment he need not care about reference counters at all. May be >>> you did not pay attention, but detach, commit and all other calls, >>> closing handle, perform release automatically on successful completion. >>> >>> In MT environment existing inside exported object reference counters >>> will just help to minimize user code - remember your own words that if >>> someone needs MT safety he will have to completely implement logic >>> himself without reference counters? >>> >> Please let me know, with details, what *user* problem you want to solve >> making *user* call addRef in his MT program. > > Big desire to recommend you to read microsoft's com-related > documentation :-) > In 2 words problem is as follows - avoid segfault when pointer to > already non-existing interface is used. > Alex, how (or better saying, what)? What problem are you solving from user POV? Please let me know what type of usage of addRef will solve users problems, and what problems are these. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-24 14:36:24
|
On 03/24/11 17:17, Adriano dos Santos Fernandes wrote: > On 24-03-2011 11:08, Alex Peshkoff wrote: >> On 03/24/11 16:50, Adriano dos Santos Fernandes wrote: >>> On 24-03-2011 06:14, Alex Peshkoff wrote: >>>> On 03/23/11 17:29, Adriano dos Santos Fernandes wrote: >>>>>> Adriano, are you serious that all described here is simpler than proxy >>>>>> objects in engine? :-) >>>>>> >>>>> I'm *sure* it is. I showed you ~15 lines of code, against >>>>> addRefs/releases around by Firebird and all-over-the-world users code. >>>> Most of addRef/release in firebird are done using smart pointers. >>>> Therefore this is not a problem. >>>> >>> Of course it is. Currently why.cpp is completely unnecessarily >>> overloaded by RefPtrs, References, etc. I'm rewriting it in much simple way. >>> >> Adriano PLEASE do not hurry too much. >> We still have no decision on a problem... >> > It's does not include remotion of your beloved refcounters... :) yet. > It's just new implementation, a simple (it don't need to not be) > framework to use the providers in more modern way. > >>>> What about users code - if user is not going to use an object in complex >>>> MT environment he need not care about reference counters at all. May be >>>> you did not pay attention, but detach, commit and all other calls, >>>> closing handle, perform release automatically on successful completion. >>>> >>>> In MT environment existing inside exported object reference counters >>>> will just help to minimize user code - remember your own words that if >>>> someone needs MT safety he will have to completely implement logic >>>> himself without reference counters? >>>> >>> Please let me know, with details, what *user* problem you want to solve >>> making *user* call addRef in his MT program. >> Big desire to recommend you to read microsoft's com-related >> documentation :-) >> In 2 words problem is as follows - avoid segfault when pointer to >> already non-existing interface is used. >> > Alex, how (or better saying, what)? What problem are you solving from > user POV? > > Please let me know what type of usage of addRef will solve users > problems, and what problems are these. Well, an example. I have database attachment and want to use it in some background thread. Attachment may be closed at some random moment. I have a choice - check some flags before each use of it (and anyway have problems - may be it was closed at some point before that check and actual use) or add reference to it and use without risk of segfault. Certainly, I must check status vector after each operation, and after getting 'invalid handle value' return from the thread. But checking status is anyway good style, therefore with reference counter in attachment handle I write code for that thread as if I'm the owner of an attachment. And I'm really one of it's owners after addRef() call! |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-24 14:50:24
|
On 24-03-2011 11:36, Alex Peshkoff wrote: > > Well, an example. > > I have database attachment and want to use it in some background thread. > Attachment may be closed at some random moment. I have a choice - check > some flags before each use of it (and anyway have problems - may be it > was closed at some point before that check and actual use) or add > reference to it and use without risk of segfault. Certainly, I must > check status vector after each operation, and after getting 'invalid > handle value' return from the thread. But checking status is anyway good > style, therefore with reference counter in attachment handle I write > code for that thread as if I'm the owner of an attachment. And I'm > really one of it's owners after addRef() call! > And let me say why it don't work. User first get a pointer (refcount = 1) from Firebird. Then he may use it and "close at some random moment". So let say, he has two threads: T1: globalObj->addRef(); T1: globalObj->doSomething(); T1: globalObj->release(); T2: globalObj->release(); Nothing prevent the random moment to call T2 release first than T1 addRef. So it will segfault, because the release will wipe toe object from memory. So you may do some extra addRef and fake the system. But then you don't need any of them, and would just handle it without a public interface baggage that serves nothing. You see, reference counting alone don't solve the user problem. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-24 14:56:44
|
On 03/24/11 17:50, Adriano dos Santos Fernandes wrote: > On 24-03-2011 11:36, Alex Peshkoff wrote: >> Well, an example. >> >> I have database attachment and want to use it in some background thread. >> Attachment may be closed at some random moment. I have a choice - check >> some flags before each use of it (and anyway have problems - may be it >> was closed at some point before that check and actual use) or add >> reference to it and use without risk of segfault. Certainly, I must >> check status vector after each operation, and after getting 'invalid >> handle value' return from the thread. But checking status is anyway good >> style, therefore with reference counter in attachment handle I write >> code for that thread as if I'm the owner of an attachment. And I'm >> really one of it's owners after addRef() call! >> > And let me say why it don't work. > > User first get a pointer (refcount = 1) from Firebird. > > Then he may use it and "close at some random moment". So let say, he has > two threads: > > T1: globalObj->addRef(); > T1: globalObj->doSomething(); > T1: globalObj->release(); > > T2: globalObj->release(); > > Nothing prevent the random moment to call T2 release first than T1 > addRef. So it will segfault, because the release will wipe toe object > from memory. > > So you may do some extra addRef and fake the system. But then you don't > need any of them, and would just handle it without a public interface > baggage that serves nothing. > > You see, reference counting alone don't solve the user problem. When used wrong - yes, do not. But if: T1: globalObj->addRef(); T1: start T2 /* that's using globalObj */ It's OK. BTW, it's present in MS docs - "You must also call AddRef on a pointer before passing it ....". |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-24 15:07:46
|
On 24-03-2011 11:56, Alex Peshkoff wrote: >> >> You see, reference counting alone don't solve the user problem. > > When used wrong - yes, do not. But if: > > T1: globalObj->addRef(); > T1: start T2 /* that's using globalObj */ > > It's OK. BTW, it's present in MS docs - "You must also call AddRef on a > pointer before passing it ....". > Reference counting is overloaded to make this work. With a single atomic variable user fix the problem without need a polluted API. It's user responsibility to use pointers before free them, and I showed you can't fix user mistakes. Adriano |
From: Alex P. <pes...@ma...> - 2011-03-24 15:50:49
|
On 03/24/11 18:07, Adriano dos Santos Fernandes wrote: > On 24-03-2011 11:56, Alex Peshkoff wrote: >>> You see, reference counting alone don't solve the user problem. >> When used wrong - yes, do not. But if: >> >> T1: globalObj->addRef(); >> T1: start T2 /* that's using globalObj */ >> >> It's OK. BTW, it's present in MS docs - "You must also call AddRef on a >> pointer before passing it ....". >> > Reference counting is overloaded to make this work. Sorry, it's just words... > With a single atomic > variable user fix the problem without need a polluted API. > Reference counter is really not more than atomic counter. > It's user responsibility to use pointers before free them, and I showed > you can't fix user mistakes. Certainly not. I never pretended to fix user mistakes. What can be done - is help to avoid them. And providing functions, familiar to many people in other products, is good way to do it. I do not understand what do you want to show. You say that use of refcounted API is polluted and overloaded. But it is used in IT world, and it is used actively. Even forgetting OLE2 - OOO is also using it. Before saying "I want to suggest something new" it's very good idea to look around - what do other people do? And before calling everything you do not like for some reason 'ugly, polluted and overloaded' try to explain - why? I agree that there may be other methods to make pointers stable in MT world. One of them is to say - we do not care about this, it's user responsibility. As for me it's much better to have required support (and pay attention - traditional for interfaces). Certainly, if you can suggest other approach, which does not let people make errors - let's go with it. But please make it not limited with C++ only. Currently I prefer to stay with traditional reference counters because: 1. They are familiar to a lot of programmers - just say 'please work with fb3 handles like OLE2 objects when MT safety is needed', and at least 70% of people will understand what you mean. 2. They do what they are supposed to do - help people work with our API in MT safe way. 3. They are very simple to implement. |
From: Adriano d. S. F. <adr...@gm...> - 2011-03-24 17:15:35
|
On 24-03-2011 12:50, Alex Peshkoff wrote: > On 03/24/11 18:07, Adriano dos Santos Fernandes wrote: >> On 24-03-2011 11:56, Alex Peshkoff wrote: >>>> You see, reference counting alone don't solve the user problem. >>> When used wrong - yes, do not. But if: >>> >>> T1: globalObj->addRef(); >>> T1: start T2 /* that's using globalObj */ >>> >>> It's OK. BTW, it's present in MS docs - "You must also call AddRef on a >>> pointer before passing it ....". >>> >> Reference counting is overloaded to make this work. > > Sorry, it's just words... > >> With a single atomic >> variable user fix the problem without need a polluted API. >> > > Reference counter is really not more than atomic counter. > >> It's user responsibility to use pointers before free them, and I showed >> you can't fix user mistakes. > > Certainly not. I never pretended to fix user mistakes. > What can be done - is help to avoid them. And providing functions, > familiar to many people in other products, is good way to do it. > > I do not understand what do you want to show. You say that use of > refcounted API is polluted and overloaded. But it is used in IT world, > and it is used actively. Even forgetting OLE2 - OOO is also using it. > Before saying "I want to suggest something new" it's very good idea to > look around - what do other people do? And before calling everything you > do not like for some reason 'ugly, polluted and overloaded' try to > explain - why? > This is from wikipedia: "One primary motivation for reference counting in COM is to enable interoperability across different programming languages and runtime systems. A client need only know how to invoke object methods in order to manage object life cycle; thus, the client is completely abstracted from whatever memory allocator the implementation of the COM object uses. As a typical example, a Visual Basic program using a COM object is agnostic towards whether that object was allocated (and must later be deallocated) by a C++ allocator or another Visual Basic component. However, this support for heterogeneity has a major cost: it requires correct reference count management by all parties involved. While high-level languages like Visual Basic manage reference counts automatically, C/C++ programmers are entrusted to increment and decrement reference counts at the appropriate time. C++ programs can and should avoid the task of managing reference counts manually by using smart pointers. Bugs caused by incorrect reference counting in COM systems are notoriously hard to resolve, especially because the error may occur in an opaque, third-party component. Microsoft has abandoned reference counting in favor of tracing garbage collection for the .NET Framework." I would add that COM dates 1990 decade, and reference counting is abandoned in new environments. Do I suggest we add garbage collection to Firebird API? Of course, no. I'm just saying we should add nothing there as there are nothing to care about. And we known the first paragraph is solvable by simple "disposable" approach. > I agree that there may be other methods to make pointers stable in MT > world. One of them is to say - we do not care about this, it's user > responsibility. As for me it's much better to have required support (and > pay attention - traditional for interfaces). Certainly, if you can > suggest other approach, which does not let people make errors - let's go > with it. But please make it not limited with C++ only. > As also said in the wikipedia snippet, it's difficult to make reference count work manually, in languages like C and non-C++ languages expected to use our API. You also said about user don't need to call it, as then only a single release is going to destroy the object. So, we're adding nothing except a complication. I prefer much more things that consistent fail in dev environment than ones that works in dev and may fail in production. Do you like counters and they solve internal problems in good way, go on and use them. But this is not necessary and is evil in our API. > Currently I prefer to stay with traditional reference counters because: > 1. They are familiar to a lot of programmers - just say 'please work > with fb3 handles like OLE2 objects when MT safety is needed', and at > least 70% of people will understand what you mean. > 2. They do what they are supposed to do - help people work with our API > in MT safe way. > 3. They are very simple to implement. > You list only the "pros". What about the cons: they are obsolete (1990), complicated (without smart pointers), bugged (reference cycles) and unnecessary (as I showed in my example, user still need to care when an object is live). Adriano |