
Hi, I am not very clear from the spec how to handle contexts - and it would appear that C++ and Java implementations have interpreted it differently. I will try to explain what I think should happen then you can all tell me why I am wrong. If I have omitted the session parameter to get a default session then I get a session with the default context. An implementation (which may or may be adapter based) has a set of contexts that it knows about - each with an implementation-defined type. An implementation-defined context type in turn defines a set of context attribute names that are meaningful to that type The implementation defines one of the contexts types that it knows about as a default type - so the default context is actually a context with the default type. If the default context needs to be modified by the user to be useful - e.g. storing a password - then there is no benefit in using the default context. So the default context should not be modifiable by the user. It may be implemented as a singleton. The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user. The set_defaults call should *not* be in the spec - it is purely an implementation thing. Steve

Steve Fisher wrote:
Hi,
I am not very clear from the spec how to handle contexts - and it would appear that C++ and Java implementations have interpreted it differently.
Could you elaborate on that? What is the difference?
I will try to explain what I think should happen then you can all tell me why I am wrong.
If I have omitted the session parameter to get a default session then I get a session with the default context.
... possibly default contextS.
An implementation (which may or may be adapter based) has a set of contexts that it knows about - each with an implementation-defined type.
An implementation-defined context type in turn defines a set of context attribute names that are meaningful to that type
The implementation defines one of the contexts types that it knows about as a default type - so the default context is actually a context with the default type.
I don't think there is a single default context type. The default session may contain various contexts, or none at all. It may initially contain various default contexts, or none at all.
If the default context needs to be modified by the user to be useful - e.g. storing a password - then there is no benefit in using the default context. So the default context should not be modifiable by the user. It may be implemented as a singleton.
I agree that default contexts should not be modifyable, and unfortunately, there is a way for the user to get at them: session.list_contexts(), which does not specify that copies are returned. Fortunately, session.add_context() specifies that a deep copy of the specified context is added to the session, so a session always contains copies. And if the default session contains default contexts, it should actually contain copies of them. In hindsight, it might have been better to make contexts within sessions unmodifyable, by having list_contexts return copies.
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The set_defaults call should *not* be in the spec - it is purely an implementation thing.
I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API. Ceriel

Quoting [Ceriel Jacobs] (Feb 20 2009):
If the default context needs to be modified by the user to be useful - e.g. storing a password - then there is no benefit in using the default context. So the default context should not be modifiable by the user. It may be implemented as a singleton.
I agree that default contexts should not be modifyable, and unfortunately, there is a way for the user to get at them: session.list_contexts(), which does not specify that copies are returned. Fortunately, session.add_context() specifies that a deep copy of the specified context is added to the session, so a session always contains copies. And if the default session contains default contexts, it should actually contain copies of them. In hindsight, it might have been better to make contexts within sessions unmodifyable, by having list_contexts return copies.
This indeed looks like a spec error to me. A user should NOT be able to change a context which is in use. That was the reson to require a deep copy on add_context. It seems to me that list_contexts should be symmetric, and also return deep copies. If you folx agree, I make this an errata.
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The set_defaults call should *not* be in the spec - it is purely an implementation thing.
I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API.
Calling set_defaults() in the c'tor breaks. That was actually in the spec at some point, but: saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/non-default-proxy.x509"); c.set_defaults (); The c'tor would throw NoSuccess if no default globus proxy exists. Then, how would you create a globus context which points to a non-default proxy location, like above? Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment? Best, Andre. -- Nothing is ever easy.

Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 20 2009): (who quoted Steve Fisher)
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The set_defaults call should *not* be in the spec - it is purely an implementation thing. I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API.
Calling set_defaults() in the c'tor breaks. That was actually in the spec at some point, but:
saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/non-default-proxy.x509"); c.set_defaults ();
Well, calling set_defaults in the constructor IS in the specs, at least it is in the 1.0 version, which is still the official version, is it not? There, it sais in the Notes: if a type is given, then the CONSTRUCTOR internally calls set_defaults().
The c'tor would throw NoSuccess if no default globus proxy exists. Then, how would you create a globus context which points to a non-default proxy location, like above?
I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check? In that case, there is a problem with at least some of the examples in the SAGA specs, see the example on the first page of the "Saga Context Management" paragraph.
Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment?
I guess there is a difference between "" and "klopus" in that "" is IMHO supposed to mean that the Type is not yet specified, whereas "klopus" specifies a Type, on which the constructor will call set_defaults(), which will probably cause an exception. Cheers, Ceriel

Quoting [Ceriel Jacobs] (Feb 25 2009):
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 20 2009): (who quoted Steve Fisher)
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The set_defaults call should *not* be in the spec - it is purely an implementation thing. I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API.
Calling set_defaults() in the c'tor breaks. That was actually in the spec at some point, but:
saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/non-default-proxy.x509"); c.set_defaults ();
Well, calling set_defaults in the constructor IS in the specs, at least it is in the 1.0 version, which is still the official version, is it not? There, it sais in the Notes: if a type is given, then the CONSTRUCTOR internally calls set_defaults().
Right - the errata remove that call.
The c'tor would throw NoSuccess if no default globus proxy exists. Then, how would you create a globus context which points to a non-default proxy location, like above?
I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check?
When else can you check? On setting the attribute would be an option - but throwing there would confuse: the exceptions defined on set_attribute are attribute related, not related to the semantics of the context. One could also check internally at the first time the context is being used, but then it is hard to predict on API level when that exception will come, and again it is probably in a context unrelated to the, uhm, context (pun unintented). So, set_defaults provides a good opportnity to flag any inconsistencies.
In that case, there is a problem with at least some of the examples in the SAGA specs, see the example on the first page of the "Saga Context Management" paragraph.
Right - line 9 and 10 should be exchanged. Thanks.
Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment?
I guess there is a difference between "" and "klopus" in that "" is IMHO supposed to mean that the Type is not yet specified, whereas "klopus" specifies a Type, on which the constructor will call set_defaults(), which will probably cause an exception.
Again, set_defaults() in the c'tor cannot work - you could never create a context with a non-default location for the globus proxy file. Given that, there is not much difference between "" and "klopus", that is what I meant... Best, Andre. -- Nothing is ever easy.

Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 20 2009): (who quoted Steve Fisher)
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The set_defaults call should *not* be in the spec - it is purely an implementation thing. I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API. Calling set_defaults() in the c'tor breaks. That was actually in the spec at some point, but:
saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/non-default-proxy.x509"); c.set_defaults (); Well, calling set_defaults in the constructor IS in the specs, at least it is in the 1.0 version, which is still the official version, is it not? There, it sais in the Notes: if a type is given, then the CONSTRUCTOR internally calls set_defaults().
Right - the errata remove that call.
The c'tor would throw NoSuccess if no default globus proxy exists. Then, how would you create a globus context which points to a non-default proxy location, like above? I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check?
When else can you check? On setting the attribute would be an option - but throwing there would confuse: the exceptions defined on set_attribute are attribute related, not related to the semantics of the context. One could also check internally at the first time the context is being used, but then it is hard to predict on API level when that exception will come, and again it is probably in a context unrelated to the, uhm, context (pun unintented). So, set_defaults provides a good opportnity to flag any inconsistencies.
I would indeed check the first time the context is being used. I don't think it is hard to predict on API level when an exception will come, because virtually all methods can throw a corresponding exception. Also, set_defaults may possibly detect SOME inconsistencies, but certainly not all.
Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment? I guess there is a difference between "" and "klopus" in that "" is IMHO supposed to mean that the Type is not yet specified, whereas "klopus" specifies a Type, on which the constructor will call set_defaults(), which will probably cause an exception.
Again, set_defaults() in the c'tor cannot work - you could never create a context with a non-default location for the globus proxy file.
Indeed, not if you want set_defaults to do all the things you describe. But I don't think set_defaults is the right place. If you set some attributes explicitly, like "UserProxy", or "UserId", or "UserPass", there is no check either. In general, the first time you notice that something is wrong is when you try to actually use the context. I don't see why this should be any different if you use set_defaults. For instance, you could create an ftp context with perfectly reasonable default values for UserId and UserPass, but if you then connect to an ftp server that does not allow anonymous access, you still have a problem. So, I think a cleaner design would be to not have set_defaults, and to have the context constructor set some reasonable default values (if a Type is specified). It would then be up to the user to make sure that the default values actually work. Cheers, Ceriel

Quoting [Ceriel Jacobs] (Feb 25 2009):
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check?
When else can you check? On setting the attribute would be an option - but throwing there would confuse: the exceptions defined on set_attribute are attribute related, not related to the semantics of the context. One could also check internally at the first time the context is being used, but then it is hard to predict on API level when that exception will come, and again it is probably in a context unrelated to the, uhm, context (pun unintented). So, set_defaults provides a good opportnity to flag any inconsistencies.
I would indeed check the first time the context is being used. I don't think it is hard to predict on API level when an exception will come, because virtually all methods can throw a corresponding exception. Also, set_defaults may possibly detect SOME inconsistencies, but certainly not all.
Yes, true, the exceptions listed on set_defaults are almost always listed on other API calls, too (almost though - IncorrectState may be the exception). So, lets try a similar use case to before: 1 saga::context c1 ("ssh"); 2 saga::context c2 ("myproxy"); 3 c2.set_attribute ("Server", "myproxy.teragrid.org/does-not-exist"); 4 5 saga::session s; 6 s.add_context (c1); 7 s.add_context (c2); 8 9 saga::file f (s, "ssh://dead-host.net/data/file"); 10 f.copy ("gridftp://qb.teragrid.org/etc/passwd"); Line 10 would then stumble over the fact that the server I specified for the context does not exist. And an AuthenticationDenied exception would actually fit semantically, too. I agree so far with you. What I don't see is why you have a problem with having set_defaults in the API, as a fixed point to check for that error. Naively, the user could also expect it to get raised on the lines 3, 7, or 9. The calls on line 3 and 7 don't have AuthenticationDenied exception defined. The call on line 9 is not obviously connected to the teragrid. In particular on line 9, the engine may try the myproxy context first, and would raise the misleading AuthenticationDenied exception (*). Also, set_defaults, as motivated earlier, has other uses, too - so it is not like it is going away, really: saga::context c ("globus"); c.set_defaults (); // get info about default globus proxy std::cout << c.get_attribute ("LifeTime"); std::cout << c.get_attribute ("UserID"); std::cout << c.get_attribute ("VO"); without set_defaults, it is totally undefined when these attributes are available. In line 9 above, for example, which is the first 'remote call', the ssh adaptor may succeed, and the myproxy context remains uninitialized, as it's set_defaults() is never called internally. One can very likely achieve a consistent API w/o set_defaults, by defining a couple of semantic changes which address the issues above explicitely, no doubt. I just don't think (a) that this is justified, and (b) that this would really simplify matters. (*) The discussion about exception order chips in here, I know. I assume that the engine would prefer the AuthenticationDenied over the TimeOut of=r NoSuccess exception caused by the dead host. But you can find other examples for other exception ordering policies of course.
Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment?
I guess there is a difference between "" and "klopus" in that "" is IMHO supposed to mean that the Type is not yet specified, whereas "klopus" specifies a Type, on which the constructor will call set_defaults(), which will probably cause an exception.
Again, set_defaults() in the c'tor cannot work - you could never create a context with a non-default location for the globus proxy file.
Indeed, not if you want set_defaults to do all the things you describe. But I don't think set_defaults is the right place. If you set some attributes explicitly, like "UserProxy", or "UserId", or "UserPass", there is no check either.
That is correct. Setting a single attribute may very well leave the context in an undefined state, like: c.set_attribute ("Type", "myroxy"); c.set_attribute ("UserID", "public"); c.set_attribute ("UserPass", "secret"); c.set_attribute ("Server", "some.server.net"); It would not make sense to complain about an invalid UserID before passwd and server are known. That would be like complaining about invalid executable path when creating a job description, before the target host is known... ;-)
In general, the first time you notice that something is wrong is when you try to actually use the context.
You have a very valid point her: even after set_defaults, there is no guarantee that a context is still valid when a remote operation is actually executed. It may have timed out, for example. However, that is what the AuthenticationFailed exception is for, to flag that the context is unusable. The NoSuccess on set_defaults is rather to signal that the context could not even be created in the first place... Cheers, Andre.
I don't see why this should be any different if you use set_defaults. For instance, you could create an ftp context with perfectly reasonable default values for UserId and UserPass, but if you then connect to an ftp server that does not allow anonymous access, you still have a problem. So, I think a cleaner design would be to not have set_defaults, and to have the context constructor set some reasonable default values (if a Type is specified). It would then be up to the user to make sure that the default values actually work.
-- Nothing is ever easy.

Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
Andre Merzky wrote:
I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check? When else can you check? On setting the attribute would be an option - but throwing there would confuse: the exceptions defined on set_attribute are attribute related, not related to the semantics of the context. One could also check internally at the first time the context is being used, but
Quoting [Ceriel Jacobs] (Feb 25 2009): then it is hard to predict on API level when that exception will come, and again it is probably in a context unrelated to the, uhm, context (pun unintented). So, set_defaults provides a good opportnity to flag any inconsistencies. I would indeed check the first time the context is being used. I don't think it is hard to predict on API level when an exception will come, because virtually all methods can throw a corresponding exception. Also, set_defaults may possibly detect SOME inconsistencies, but certainly not all.
Yes, true, the exceptions listed on set_defaults are almost always listed on other API calls, too (almost though - IncorrectState may be the exception).
Yes, but that one is only thrown if the context has an empty Type, which should not be a default, I think.
So, lets try a similar use case to before:
1 saga::context c1 ("ssh"); 2 saga::context c2 ("myproxy"); 3 c2.set_attribute ("Server", "myproxy.teragrid.org/does-not-exist"); 4 5 saga::session s; 6 s.add_context (c1); 7 s.add_context (c2); 8 9 saga::file f (s, "ssh://dead-host.net/data/file"); 10 f.copy ("gridftp://qb.teragrid.org/etc/passwd");
Line 10 would then stumble over the fact that the server I specified for the context does not exist. And an AuthenticationDenied exception would actually fit semantically, too. I agree so far with you.
What I don't see is why you have a problem with having set_defaults in the API, as a fixed point to check for that error.
I am having a (small) problem with that because set_defaults() cannot always check that there actually is an error, because it is the context, in combination with the specific server, which determines if there is an error or not. I can see some, but limited, usefulness in some call to check a context in itself, but set_defaults suggests something else which could just as well (and IS in the SAGA 1.0 specs) be done in the constructor.
Naively, the user could also expect it to get raised on the lines 3, 7, or 9. The calls on line 3 and 7 don't have AuthenticationDenied exception defined. The call on line 9 is not obviously connected to the teragrid. In particular on line 9, the engine may try the myproxy context first, and would raise the misleading AuthenticationDenied exception (*).
Also, set_defaults, as motivated earlier, has other uses, too - so it is not like it is going away, really:
saga::context c ("globus");
c.set_defaults ();
// get info about default globus proxy std::cout << c.get_attribute ("LifeTime"); std::cout << c.get_attribute ("UserID"); std::cout << c.get_attribute ("VO");
without set_defaults, it is totally undefined when these attributes are available.
After calling the constructor? As would be the case for the SAGA 1.0 specs?
One can very likely achieve a consistent API w/o set_defaults, by defining a couple of semantic changes which address the issues above explicitely, no doubt. I just don't think (a) that this is justified, and (b) that this would really simplify matters.
But I think the CURRENT changes with respect to SAGA 1.0 are much bigger. O well, I think I have vented my opinion enough for now ... Ceriel

Quoting [Ceriel Jacobs] (Feb 25 2009):
saga::context c ("globus");
c.set_defaults ();
// get info about default globus proxy std::cout << c.get_attribute ("LifeTime"); std::cout << c.get_attribute ("UserID"); std::cout << c.get_attribute ("VO");
without set_defaults, it is totally undefined when these attributes are available.
After calling the constructor? As would be the case for the SAGA 1.0 specs?
As said: calling set_defaults in the constructor cannot possibly stay in the spec: that breaks in those cases where set_defaults would throw. If the c'tor then throws for a given type, you can't create any context of that type _at_ _all_.
One can very likely achieve a consistent API w/o set_defaults, by defining a couple of semantic changes which address the issues above explicitely, no doubt. I just don't think (a) that this is justified, and (b) that this would really simplify matters.
But I think the CURRENT changes with respect to SAGA 1.0 are much bigger.
Hmm, you mean the ones we have in the errata I assume? Yes, some of them are bigger. However, they are there to fix errors. Any item in particular you are unhappy with? I'll commit the latest state of the errata file to CVS in a minute...
O well, I think I have vented my opinion enough for now ...
Hmm, would you mind if we discuss that on the phone? I agree that we are running in circles somehow, but I would like to get the discussion to a conclusion one way or the other, instead of leaving it open... Can I call you somewhere? Thanks, Andre. -- Nothing is ever easy.

Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
saga::context c ("globus");
c.set_defaults ();
// get info about default globus proxy std::cout << c.get_attribute ("LifeTime"); std::cout << c.get_attribute ("UserID"); std::cout << c.get_attribute ("VO");
without set_defaults, it is totally undefined when these attributes are available. After calling the constructor? As would be the case for the SAGA 1.0 specs?
As said: calling set_defaults in the constructor cannot possibly stay in the spec: that breaks in those cases where set_defaults would throw. If the c'tor then throws for a given type, you can't create any context of that type _at_ _all_.
That's one reason why I think set_defaults should not be in the API, and should not throw. Instead, the constructor should set suitable defaults, if it can. If it does not recognize the Type, it can throw an exception, but only then. Other errors will turn up when the context is used.
One can very likely achieve a consistent API w/o set_defaults, by defining a couple of semantic changes which address the issues above explicitely, no doubt. I just don't think (a) that this is justified, and (b) that this would really simplify matters. But I think the CURRENT changes with respect to SAGA 1.0 are much bigger.
Hmm, you mean the ones we have in the errata I assume? Yes, some of them are bigger. However, they are there to fix errors.
No, I mean the change that set_defaults is not to be called anymore from the constructor. That is quite a big change, that may affect all SAGA applications. I don't know if SAGA applications usually call set_defaults(), since SAGA 1.0 specifies that it is called from the constructor, if a Type is specified.
O well, I think I have vented my opinion enough for now ...
Hmm, would you mind if we discuss that on the phone? I agree that we are running in circles somehow, but I would like to get the discussion to a conclusion one way or the other, instead of leaving it open... Can I call you somewhere?
Of course you can call me, you know the number (since it was yours as well for a while :-) But this is not just between you and me, although it may seem that way now. We both live in European time:-) Maybe this discussion prompts some more opinions. Cheers, Ceriel

Quoting [Ceriel Jacobs] (Feb 25 2009):
Date: Wed, 25 Feb 2009 15:49:18 +0100 From: Ceriel Jacobs <ceriel@cs.vu.nl> To: Andre Merzky <andre@merzky.net> CC: Steve Fisher <dr.s.m.fisher@gmail.com>, SAGA RG <saga-rg@ogf.org> Subject: Re: [SAGA-RG] Context and Session thoughts
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
saga::context c ("globus");
c.set_defaults ();
// get info about default globus proxy std::cout << c.get_attribute ("LifeTime"); std::cout << c.get_attribute ("UserID"); std::cout << c.get_attribute ("VO");
without set_defaults, it is totally undefined when these attributes are available. After calling the constructor? As would be the case for the SAGA 1.0 specs?
As said: calling set_defaults in the constructor cannot possibly stay in the spec: that breaks in those cases where set_defaults would throw. If the c'tor then throws for a given type, you can't create any context of that type _at_ _all_.
That's one reason why I think set_defaults should not be in the API, and should not throw. Instead, the constructor should set suitable defaults, if it can. If it does not recognize the Type, it can throw an exception, but only then. Other errors will turn up when the context is used.
Ah, got it now I think, thanks for bearing with me. So, setting the defaults in the c'tor would not throw anymore. The following would then still not work: saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/<F2>does-not-exist"); // get info about default globus proxy std::cout << c.get_attribute ("LifeTime"); std::cout << c.get_attribute ("UserID"); std::cout << c.get_attribute ("VO"); but that might be acceptable.
One can very likely achieve a consistent API w/o set_defaults, by defining a couple of semantic changes which address the issues above explicitely, no doubt. I just don't think (a) that this is justified, and (b) that this would really simplify matters. But I think the CURRENT changes with respect to SAGA 1.0 are much bigger.
Hmm, you mean the ones we have in the errata I assume? Yes, some of them are bigger. However, they are there to fix errors.
No, I mean the change that set_defaults is not to be called anymore from the constructor. That is quite a big change, that may affect all SAGA applications. I don't know if SAGA applications usually call set_defaults(), since SAGA 1.0 specifies that it is called from the constructor, if a Type is specified.
Well, for those applications which _do_ call set_defaults() anywhere, removing that call would be an equally big change - so that does not help us to decide either way I guess...
O well, I think I have vented my opinion enough for now ...
Hmm, would you mind if we discuss that on the phone? I agree that we are running in circles somehow, but I would like to get the discussion to a conclusion one way or the other, instead of leaving it open... Can I call you somewhere?
Of course you can call me, you know the number (since it was yours as well for a while :-)
You sincerely overestimate my memory, and my ability to keep track of phone numbers! :-) But anyway, found it online.
But this is not just between you and me, although it may seem that way now. We both live in European time:-) Maybe this discussion prompts some more opinions.
I would be delighted to hear them! I am known to be stubborn unless there are at least two opposing opinions (*) ;-) Cheers, Andre (*) This is an endless source of grief for my wife, you see? :-P -- Nothing is ever easy.

Perhaps this is something we could discuss next week in Catania 2009/2/25 Ceriel Jacobs <ceriel@cs.vu.nl>:
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 20 2009):
(who quoted Steve Fisher)
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The set_defaults call should *not* be in the spec - it is purely an implementation thing.
I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API.
Calling set_defaults() in the c'tor breaks. That was actually in the spec at some point, but:
saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/non-default-proxy.x509"); c.set_defaults ();
Well, calling set_defaults in the constructor IS in the specs, at least it is in the 1.0 version, which is still the official version, is it not? There, it sais in the Notes: if a type is given, then the CONSTRUCTOR internally calls set_defaults().
Right - the errata remove that call.
The c'tor would throw NoSuccess if no default globus proxy exists. Then, how would you create a globus context which points to a non-default proxy location, like above?
I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check?
When else can you check? On setting the attribute would be an option - but throwing there would confuse: the exceptions defined on set_attribute are attribute related, not related to the semantics of the context. One could also check internally at the first time the context is being used, but then it is hard to predict on API level when that exception will come, and again it is probably in a context unrelated to the, uhm, context (pun unintented). So, set_defaults provides a good opportnity to flag any inconsistencies.
I would indeed check the first time the context is being used. I don't think it is hard to predict on API level when an exception will come, because virtually all methods can throw a corresponding exception. Also, set_defaults may possibly detect SOME inconsistencies, but certainly not all.
Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment?
I guess there is a difference between "" and "klopus" in that "" is IMHO supposed to mean that the Type is not yet specified, whereas "klopus" specifies a Type, on which the constructor will call set_defaults(), which will probably cause an exception.
Again, set_defaults() in the c'tor cannot work - you could never create a context with a non-default location for the globus proxy file.
Indeed, not if you want set_defaults to do all the things you describe. But I don't think set_defaults is the right place. If you set some attributes explicitly, like "UserProxy", or "UserId", or "UserPass", there is no check either. In general, the first time you notice that something is wrong is when you try to actually use the context. I don't see why this should be any different if you use set_defaults. For instance, you could create an ftp context with perfectly reasonable default values for UserId and UserPass, but if you then connect to an ftp server that does not allow anonymous access, you still have a problem. So, I think a cleaner design would be to not have set_defaults, and to have the context constructor set some reasonable default values (if a Type is specified). It would then be up to the user to make sure that the default values actually work.
Cheers, Ceriel

Most certainly :-) Quoting [Steve Fisher] (Feb 25 2009):
Date: Wed, 25 Feb 2009 13:01:32 +0000 Subject: Re: [SAGA-RG] Context and Session thoughts From: Steve Fisher <dr.s.m.fisher@gmail.com> To: Ceriel Jacobs <ceriel@cs.vu.nl> Cc: Andre Merzky <andre@merzky.net>, SAGA RG <saga-rg@ogf.org>
Perhaps this is something we could discuss next week in Catania
2009/2/25 Ceriel Jacobs <ceriel@cs.vu.nl>:
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 25 2009):
Andre Merzky wrote:
Quoting [Ceriel Jacobs] (Feb 20 2009):
(who quoted Steve Fisher)
> > The user can also create a context with a type known to him and to the > implementation. He may need to set attributes of this context before > it can be used. The implementation must not modify any attributes - > though the constructor may set attributes to sensible defaults which > can then be modified by the user. > > The set_defaults call should *not* be in the spec - it is purely an > implementation thing.
I think I agree with that. It is a pity that the Context constructor has a default value "" for the context type. IMHO, the Type attribute should only have read access and be set by the Context constructor, which should then also call set_defaults, which then does not have to be in the API.
Calling set_defaults() in the c'tor breaks. That was actually in the spec at some point, but:
saga::context c ("globus"); c.set_attribute ("UserProxy", "/tmp/non-default-proxy.x509"); c.set_defaults ();
Well, calling set_defaults in the constructor IS in the specs, at least it is in the 1.0 version, which is still the official version, is it not? There, it sais in the Notes: if a type is given, then the CONSTRUCTOR internally calls set_defaults().
Right - the errata remove that call.
The c'tor would throw NoSuccess if no default globus proxy exists. Then, how would you create a globus context which points to a non-default proxy location, like above?
I don't know that the c'tor would throw NoSuccess. Maybe a default UserProxy file does not exist, but is set_defaults() the right time to check?
When else can you check? On setting the attribute would be an option - but throwing there would confuse: the exceptions defined on set_attribute are attribute related, not related to the semantics of the context. One could also check internally at the first time the context is being used, but then it is hard to predict on API level when that exception will come, and again it is probably in a context unrelated to the, uhm, context (pun unintented). So, set_defaults provides a good opportnity to flag any inconsistencies.
I would indeed check the first time the context is being used. I don't think it is hard to predict on API level when an exception will come, because virtually all methods can throw a corresponding exception. Also, set_defaults may possibly detect SOME inconsistencies, but certainly not all.
Yes, one could argue if an empty type on context creation makes sense, or if one should mandate a valid string. Given that an empty string is a 'valid' string in most languages, that is not much different from other invalid strings like 'klopus'. We have defined error conditions for calling set_defaults() on invalid context attributes. I don't think that this is a big problem at the moment?
I guess there is a difference between "" and "klopus" in that "" is IMHO supposed to mean that the Type is not yet specified, whereas "klopus" specifies a Type, on which the constructor will call set_defaults(), which will probably cause an exception.
Again, set_defaults() in the c'tor cannot work - you could never create a context with a non-default location for the globus proxy file.
Indeed, not if you want set_defaults to do all the things you describe. But I don't think set_defaults is the right place. If you set some attributes explicitly, like "UserProxy", or "UserId", or "UserPass", there is no check either. In general, the first time you notice that something is wrong is when you try to actually use the context. I don't see why this should be any different if you use set_defaults. For instance, you could create an ftp context with perfectly reasonable default values for UserId and UserPass, but if you then connect to an ftp server that does not allow anonymous access, you still have a problem. So, I think a cleaner design would be to not have set_defaults, and to have the context constructor set some reasonable default values (if a Type is specified). It would then be up to the user to make sure that the default values actually work.
Cheers, Ceriel
-- Nothing is ever easy.

Hi Steve, Quoting [Steve Fisher] (Feb 19 2009):
Hi,
I am not very clear from the spec how to handle contexts - and it would appear that C++ and Java implementations have interpreted it differently. I will try to explain what I think should happen then you can all tell me why I am wrong.
If I have omitted the session parameter to get a default session then I get a session with the default context.
An implementation (which may or may be adapter based) has a set of contexts that it knows about - each with an implementation-defined type.
Not that for a single (impl defined) context type, multiple default contexts may exist.
An implementation-defined context type in turn defines a set of context attribute names that are meaningful to that type
The implementation defines one of the contexts types that it knows about as a default type - so the default context is actually a context with the default type.
No, not really. A default context is a context which can be established by the implementation without any user intervention. As such, it has a full set of attributes. For example, a globus adaptor may implement the detection of two default contexts. For the first one, it may set UserProxy to the value of the applications X509_PROXY env variable, for the second one it may set UserProxy to /tmp/x509_<uid> with the applications running user id uid. That way, the saga objects in the default session can perform operations on the globus backend with either one of these contexts (assumed that they are valid, and differ). What context type is supported by the adaptor ('globus'), and what information are used to find default contexts (environment, default file location + uid) need to be documented by the implementation. Anyway, those contexts get attached to the default session. BTW: saga::context c ('globus'); c.set_defaults (); will yield one of the default globus contexts - which one is up to the implementation. In general, I assume that one set of adaptors will provide one default context - the above example is somewhat arbitrary, but hopefully illustrates things.
If the default context needs to be modified by the user to be useful - e.g. storing a password - then there is no benefit in using the default context. So the default context should not be modifiable by the user. It may be implemented as a singleton.
Default contexts do not _need_ to be modified by the end user. OTOH, users _can_ modify them, to change parameters. As an example: saga::context c ('globus'); c.set_defaults (); c.set_attribute ("LifeTime", "30"); would set the lifetime of a default globus context to 30 seconds (or whatever). I doubt that this is a useful scenario, but you get the idea. Basically, you can create a default context, and derive a customized one.
The user can also create a context with a type known to him and to the implementation. He may need to set attributes of this context before it can be used. The implementation must not modify any attributes - though the constructor may set attributes to sensible defaults which can then be modified by the user.
The c'tor is, by definition, not setting attributes (apart from the given 'Type'. Otherwise, your description above is correct: the user creates a context with a type known to him and to the implementation, and then likely needs to set attributes in order to obtain a useful context.
The set_defaults call should *not* be in the spec - it is purely an implementation thing.
Sorry, I disagree: it is supposed to take the burden from the end user to know what default can be set. It has nothing to do with the creation of default contexts for the default session: that is completely done in the background, within the implementation. You could consider 'set_defaults' as a way to sensibly initialize a context's attributes. Hope that helps, Andre.
Steve
-- Nothing is ever easy.
participants (3)
-
Andre Merzky
-
Ceriel Jacobs
-
Steve Fisher