Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Stephen Deasey
On 5/30/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> 
> Am 30.05.2005 um 12:23 schrieb Stephen Deasey:
> 
> >
> > The other option is -eightbit:flag syntax.  It's not perfect, but it's
> > better than nested lists and has ~5 years of usage in the ACS behind
> > it.
> >
> 
> Another try (I can't just let go) ...
> 
> I do not see much sense in trying to keep the Tcl argument list
> format under all costs. Give me a good reason why we should do that?
> Anyways, we are about to define a new "proc"-type of command
> (ns_proc) aren't we? What is the sense then to force ourselves
> to the old format?
> 
> Why don't we *extend* Tcl-proc arg-treatment like this:
> 
> {name typecheck ?default_value?}
> 
> This is *not* Tcl-proc compatible but *is* in the spirit of
> the language. The "typecheck" above can/will be definitely
> a list of one or more elements, depending on the check itself.
> The typecheck is *forced*. You must give a type. If you need
> no checking at all use "string" which will cover all possiblities.
> By *forcing* the type-check, many of the programming
> errors and double-checks in the procedure itself can be saved.
> 
> Also, all people needing no extra checking can always use plain Tcl-proc
> calls. Others who'd need checking would use exteneded ns_proc syntax.
> This is pretty clear and I see no problems with that at all.
> 
> For example:
> ns_parseargs {{-retries int 0} {-blockcopy flag} {device string}
> args}
> 
> or
> ns_proc dosomething {{-retries int 0} {-blockcopy flag} {device
> string}} {
># ...
> }
> 
> The most natural Tcl-way is to use lists. We've seen that the
> desperate try to keep the Tcl-proc syntax leads to too complicated
> nested lists which humans are not easily assembling.
> So, this is a plain list which is easy to write and read by humans.
> 
> We can evolve typecheck over time to include more elaborate
> tests, but a handful of those (string, int, flag, bool, list) are most
> useful and complete for about all the needs I can think of
> at the moment.
> 
> What is wrong with that (except that it perhaps does not follow
> openacs model)?


ns_proc test {{-flag f}} {
if {$flag} {
ns_log notice ok
}
}

test -flag t ;# ok
test -flag true ;# ok
test -flag yes ;# ok
test -flag 1 ;# ok

The result of the expression passed to Tcl's if is converted to
boolean so there's no need to use [string is true $x].   The
difference between '-flag' and '-flag t' is two characters -- I don't
think it's worth it.

As I mentioned before, in general I think it's a bad idea to create
boolean flags as it makes it cumbersome to call such a proc where the
flag is computed.  e.g.:

if {$x} {
foo -flag ...
} else {
  foo ...
}

It gets really ugly when there are multiple flags.  I added boolean
flags to the C implementation as there is already existing code which
uses them which could benefit from the arg parsing.


Regarding the 'oneof' type, maybe what's actually needed is some
syntactic sugar?  e.g. something like:

proc assert_oneof {varname list} {
upvar $varname x
if {![lsearch -exact $list $x]} {
error "assertion failed: $varname must be one of $list"
}
}

proc test {{x foo}} {
assert_oneof x {foo bar baz}
...
}


The disadvantage of extending the proc syntax as you've suggested
above is that users are then forced to always provide a type, even if
it's just the 'null' type, string.  This kind of type checking is
likely to be the exception rather than the rule, but I imagine option
parsing will be quite common.  The ordering of the default argument
has changed which is incompatible with what the programmer expects
from standard proc usage, even if the mechanical incompatibility does
not matter.

The oneof check shows that things will get more complicated than
simple 'is int', 'is bool' checks.  Min and max range checks on
integers would be nice, regexp checks on strings would be cool etc...

What about applying more than one check to an arg?  There would need
to be syntax for it as you can't specify the arg more than once as you
can specify multiple assertions.

Other languages solve this with assertions or pre-conditions and
post-conditions, and that feels more like what we're doing here.  Tcl
*does* have type checking: an integer argument passed to a proc which
is then passed to the expr command will cause a conversion failure if
the value is 'foo'.  The type checking on the proc argument will just
cause the failure earlier (and will result in double-checking).

What we're catching here are programmer errors.  Checking is more
urgently required for malicious attacks.  You really want to be able
to say something like:

ns_queryget -assert int -- life 42

It was always in the back of my mind that we needed some kind of
unified checking mechanism to handle both procs and ns_queryget (and
forms, as in Vlad's nstk).  Rather than shoe-horn the type checking of
proc into the proc args, perhaps it would be better to u

Re: [naviserver-devel] Re: RFE #1202462

2005-06-01 Thread Stephen Deasey
On 5/30/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> 
> Am 30.05.2005 um 12:01 schrieb Stephen Deasey:
> 
> >
> > What's the return value of Ns_FSOpen?
> >
> 
> Something that can be fed to Ns_FSRead and/or Ns_FSClose
> for example. I haven't started the implementation yet
> but this is first what comes to mind.
> 
> Presumably, it will be Tcl_Channel in VFS or a regular
> OS filehandle w/o VFS.


The return type would be unknown unless the caller also used #ifdef?

The issue is not preferring open over Tcl_VFSOpen, and it's not mmap
per se.  mmap is just one example of a function which requires a file
descriptor or real files in the file system.  sendfile is another, as
are readv/writev, epoll, kqueue, inotify, etc.

The Tcl VFS is a lowest common denominator abstraction over file
systems.  It provides the common things, but can't provide
implementations of everything, nor can it return a useful file
descriptor from a Tcl_Channel, at least in the case where everything
is contained within one big file.  I think Ns_TclGetOpenFd is going to
fail.

I don't see anything wrong with using Tcl_VFS* directly to read the
config file, write to a log file etc., and the tcl commands in
nsd/tclfile.c should be replaced by simple Tcl wrappers anyway.  It's
the stuff in nsd/fastpath.c that's important.  File descriptors need
to be available for use with modern, high performance system calls
with a minimum of conditional compilation/execution.

This also has the potential to be a never-ending bug hunt.  Absolutely
every call to the file system has to be converted to Tcl_VFS* or
Ns_VFS*, including all modules and the libraries they wrap, or people
will be surprised...


I'm not against this feature, but it's pretty esoteric and the
implementation is invasive so the quality bar needs to be set high. 
I'm sure you can do it  :-)



Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Vlad Seryakov
To be as much close to current Tcl convention in proc syntax we can add 
optional type AFTER default value


ns_proc test { {-flag 0 flag} {-list a oneof {a b c}} {-name ""} { value 
"" } } {

}

This way i do not have to remember 2 different ways to provide default 
value and if i want type checking, i will give optional typoe, if not 
then no type cheking.


Stephen Deasey wrote:

On 5/30/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:


Am 30.05.2005 um 12:23 schrieb Stephen Deasey:



The other option is -eightbit:flag syntax.  It's not perfect, but it's
better than nested lists and has ~5 years of usage in the ACS behind
it.



Another try (I can't just let go) ...

I do not see much sense in trying to keep the Tcl argument list
format under all costs. Give me a good reason why we should do that?
Anyways, we are about to define a new "proc"-type of command
(ns_proc) aren't we? What is the sense then to force ourselves
to the old format?

Why don't we *extend* Tcl-proc arg-treatment like this:

   {name typecheck ?default_value?}

This is *not* Tcl-proc compatible but *is* in the spirit of
the language. The "typecheck" above can/will be definitely
a list of one or more elements, depending on the check itself.
The typecheck is *forced*. You must give a type. If you need
no checking at all use "string" which will cover all possiblities.
By *forcing* the type-check, many of the programming
errors and double-checks in the procedure itself can be saved.

Also, all people needing no extra checking can always use plain Tcl-proc
calls. Others who'd need checking would use exteneded ns_proc syntax.
This is pretty clear and I see no problems with that at all.

For example:
   ns_parseargs {{-retries int 0} {-blockcopy flag} {device string}
args}

or
   ns_proc dosomething {{-retries int 0} {-blockcopy flag} {device
string}} {
  # ...
   }

The most natural Tcl-way is to use lists. We've seen that the
desperate try to keep the Tcl-proc syntax leads to too complicated
nested lists which humans are not easily assembling.
So, this is a plain list which is easy to write and read by humans.

We can evolve typecheck over time to include more elaborate
tests, but a handful of those (string, int, flag, bool, list) are most
useful and complete for about all the needs I can think of
at the moment.

What is wrong with that (except that it perhaps does not follow
openacs model)?




ns_proc test {{-flag f}} {
if {$flag} {
ns_log notice ok
}
}

test -flag t ;# ok
test -flag true ;# ok
test -flag yes ;# ok
test -flag 1 ;# ok

The result of the expression passed to Tcl's if is converted to
boolean so there's no need to use [string is true $x].   The
difference between '-flag' and '-flag t' is two characters -- I don't
think it's worth it.

As I mentioned before, in general I think it's a bad idea to create
boolean flags as it makes it cumbersome to call such a proc where the
flag is computed.  e.g.:

if {$x} {
foo -flag ...
} else {
  foo ...
}

It gets really ugly when there are multiple flags.  I added boolean
flags to the C implementation as there is already existing code which
uses them which could benefit from the arg parsing.


Regarding the 'oneof' type, maybe what's actually needed is some
syntactic sugar?  e.g. something like:

proc assert_oneof {varname list} {
upvar $varname x
if {![lsearch -exact $list $x]} {
error "assertion failed: $varname must be one of $list"
}
}

proc test {{x foo}} {
assert_oneof x {foo bar baz}
...
}


The disadvantage of extending the proc syntax as you've suggested
above is that users are then forced to always provide a type, even if
it's just the 'null' type, string.  This kind of type checking is
likely to be the exception rather than the rule, but I imagine option
parsing will be quite common.  The ordering of the default argument
has changed which is incompatible with what the programmer expects
from standard proc usage, even if the mechanical incompatibility does
not matter.

The oneof check shows that things will get more complicated than
simple 'is int', 'is bool' checks.  Min and max range checks on
integers would be nice, regexp checks on strings would be cool etc...

What about applying more than one check to an arg?  There would need
to be syntax for it as you can't specify the arg more than once as you
can specify multiple assertions.

Other languages solve this with assertions or pre-conditions and
post-conditions, and that feels more like what we're doing here.  Tcl
*does* have type checking: an integer argument passed to a proc which
is then passed to the expr command will cause a conversion failure if
the value is 'foo'.  The type checking on the proc argument will just
cause the failure earlier (and will result in double-checking).

What we're catching here are programmer errors.  Checking is more
urgently required for malicious attacks.  You really want to be able
to say something like:

ns_queryget -assert int -- li

Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 15:45 schrieb Vlad Seryakov:

To be as much close to current Tcl convention in proc syntax we can  
add optional type AFTER default value


ns_proc test { {-flag 0 flag} {-list a oneof {a b c}} {-name ""}  
{ value "" } } {

}

This way i do not have to remember 2 different ways to provide  
default value and if i want type checking, i will give optional  
typoe, if not then no type cheking.


The only side-effect is of course that you'd need to give the default
argument if you need type-checking. I believe I can live with that.

Zoran



Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 13:24 schrieb Stephen Deasey:


 So, how
about assertions?



Good.

So, that means we scratch the idea of putting it in the
proc/ns_proc syntax and keep it as is, i.e. we parse-out
only the options from the argument list and do no extra
type checking there. Type-checking would be implemented
as a separate command then.

I understand the blues with the boolean arguments and
I am willing to scratch them from the specs. So, if you
need "-dothat" you'd be actually saying "-dothat true"
or "-dothat false".

All that leaves us with the ns_parseargs pretty much as
it is now, or?

Apropos assertions:
http://www.tcl.tk/cgi-bin/tct/tip/53.html

This was withdrawn because of the fact that it already
exist in tcllib. So, there is very little to do except
"package req tcllib" and use what's there.

Zoran




Re: [naviserver-devel] Re: RFE #1202462

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 14:10 schrieb Stephen Deasey:


On 5/30/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:



Am 30.05.2005 um 12:01 schrieb Stephen Deasey:




What's the return value of Ns_FSOpen?




Something that can be fed to Ns_FSRead and/or Ns_FSClose
for example. I haven't started the implementation yet
but this is first what comes to mind.

Presumably, it will be Tcl_Channel in VFS or a regular
OS filehandle w/o VFS.




The return type would be unknown unless the caller also used #ifdef?


The return value is of course opaque and should be returned
to the FS abstraction layer. But I read on...



I don't see anything wrong with using Tcl_VFS* directly to read the
config file, write to a log file etc., and the tcl commands in
nsd/tclfile.c should be replaced by simple Tcl wrappers anyway.  It's
the stuff in nsd/fastpath.c that's important.  File descriptors need
to be available for use with modern, high performance system calls
with a minimum of conditional compilation/execution.

This also has the potential to be a never-ending bug hunt.  Absolutely
every call to the file system has to be converted to Tcl_VFS* or
Ns_VFS*, including all modules and the libraries they wrap, or people
will be surprised...



I'm not against this feature, but it's pretty esoteric and the
implementation is invasive so the quality bar needs to be set high.
I'm sure you can do it  :-)



Of course, all you say holds. If you need to go to the max when
accesing files, then Tcl VFS will not be the fastest kid on the block.

But what about this: we make a Ns_FS wrappers and put them in place,
even in the fastpath and adp code. We also add Ns_FSGetOSHandle which
will then return invalid handle to the caller if the file is not located
on the native filesystem. This is trivial and costs no performance.
Now, the caller can accomodate for that and decide what to do.
A very good example is the actual fastpath code which does the same
with the mmap. It works-around the fact that mmap is not defined in
the server config and uses simple open/read/close sequence.

This way you'd be free to add whatever fancy roaring implementation
(kaio for example) to get the max-speed, if you like.
We need only cover access to files, no sockets, pipes, etc.
What we'd need is just a handful of calls:

  open, close, stat, seek, read, write, opendir, readdir, closedir,  
getcwd


(did I forgot something?)

Most of them would use the opaque file-handle from which you can
obtain the OS handle to make any private speed optimizations. If the
handle cannot be obtained, then you provide the best-effort fallback.

What would/could be wrong with that?

Zoran



Re: [naviserver-devel] Re: RFE #1202462

2005-06-01 Thread Stephen Deasey
On 6/1/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> 
> Am 01.06.2005 um 14:10 schrieb Stephen Deasey:
> 
> > On 5/30/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> >
> >>
> >> Am 30.05.2005 um 12:01 schrieb Stephen Deasey:
> >>
> >>
> >>>
> >>> What's the return value of Ns_FSOpen?
> >>>
> >>>
> >>
> >> Something that can be fed to Ns_FSRead and/or Ns_FSClose
> >> for example. I haven't started the implementation yet
> >> but this is first what comes to mind.
> >>
> >> Presumably, it will be Tcl_Channel in VFS or a regular
> >> OS filehandle w/o VFS.
> >>
> >
> >
> > The return type would be unknown unless the caller also used #ifdef?
> 
> The return value is of course opaque and should be returned
> to the FS abstraction layer. But I read on...
> 
> >
> > I don't see anything wrong with using Tcl_VFS* directly to read the
> > config file, write to a log file etc., and the tcl commands in
> > nsd/tclfile.c should be replaced by simple Tcl wrappers anyway.  It's
> > the stuff in nsd/fastpath.c that's important.  File descriptors need
> > to be available for use with modern, high performance system calls
> > with a minimum of conditional compilation/execution.
> >
> > This also has the potential to be a never-ending bug hunt.  Absolutely
> > every call to the file system has to be converted to Tcl_VFS* or
> > Ns_VFS*, including all modules and the libraries they wrap, or people
> > will be surprised...
> 
> > I'm not against this feature, but it's pretty esoteric and the
> > implementation is invasive so the quality bar needs to be set high.
> > I'm sure you can do it  :-)
> >
> 
> Of course, all you say holds. If you need to go to the max when
> accesing files, then Tcl VFS will not be the fastest kid on the block.
> 
> But what about this: we make a Ns_FS wrappers and put them in place,
> even in the fastpath and adp code. We also add Ns_FSGetOSHandle which
> will then return invalid handle to the caller if the file is not located
> on the native filesystem. This is trivial and costs no performance.
> Now, the caller can accomodate for that and decide what to do.
> A very good example is the actual fastpath code which does the same
> with the mmap. It works-around the fact that mmap is not defined in
> the server config and uses simple open/read/close sequence.
> 
> This way you'd be free to add whatever fancy roaring implementation
> (kaio for example) to get the max-speed, if you like.
> We need only cover access to files, no sockets, pipes, etc.
> What we'd need is just a handful of calls:
> 
>open, close, stat, seek, read, write, opendir, readdir, closedir,
> getcwd
> 
> (did I forgot something?)
> 
> Most of them would use the opaque file-handle from which you can
> obtain the OS handle to make any private speed optimizations. If the
> handle cannot be obtained, then you provide the best-effort fallback.
> 
> What would/could be wrong with that?


Sounds good.



Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Stephen Deasey
On 6/1/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> 
> Am 01.06.2005 um 13:24 schrieb Stephen Deasey:
> 
> >  So, how
> > about assertions?
> >
> 
> Good.
> 
> So, that means we scratch the idea of putting it in the
> proc/ns_proc syntax and keep it as is, i.e. we parse-out
> only the options from the argument list and do no extra
> type checking there. Type-checking would be implemented
> as a separate command then.
> 
> I understand the blues with the boolean arguments and
> I am willing to scratch them from the specs. So, if you
> need "-dothat" you'd be actually saying "-dothat true"
> or "-dothat false".
> 
> All that leaves us with the ns_parseargs pretty much as
> it is now, or?
> 
> Apropos assertions:
>  http://www.tcl.tk/cgi-bin/tct/tip/53.html
> 
> This was withdrawn because of the fact that it already
> exist in tcllib. So, there is very little to do except
> "package req tcllib" and use what's there.


Looks good.  For program bug detection, use tcllib assertions in
cooperation with the option parsing we have now.  For input
validation, some other mechanism should be used.



Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 21:30 schrieb Stephen Deasey:


 For input
validation, some other mechanism should be used.



Input of what kind? From Tcl or from C?
Do you mean form-input? Why you can't apply the
tcllib assertion on form-input, if this is what you mean?

Zoran




Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Stephen Deasey
On 6/1/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> 
> Am 01.06.2005 um 21:30 schrieb Stephen Deasey:
> 
> >  For input
> > validation, some other mechanism should be used.
> >
> 
> Input of what kind? From Tcl or from C?
> Do you mean form-input? Why you can't apply the
> tcllib assertion on form-input, if this is what you mean?


One of the features of tcllib assertions is that you can turn them
off, or into no-ops when in production mode, just like standard C
assertions.  That's a useful feature, but not when you're checking
form input!



Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 22:23 schrieb Stephen Deasey:


 That's a useful feature, but not when you're checking
form input!


Why not? 
 



Re: [naviserver-devel] Re: RFE #1202462

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 21:27 schrieb Stephen Deasey:



Sounds good.



OK. I will start the work and give diffs for review when I come
to some point.

Zoran




Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Stephen Deasey
On 6/1/05, Zoran Vasiljevic <[EMAIL PROTECTED]> wrote:
> 
> Am 01.06.2005 um 22:23 schrieb Stephen Deasey:
> 
> >  That's a useful feature, but not when you're checking
> > form input!
> 
> Why not?


Because form input always needs to be checked.  You can't declare it
debugged and turn off exception checking.  People will continue to
feed your program broken/malicious input.



Re: [Re: Re: [naviserver-devel] ns_parseargs example]

2005-06-01 Thread Zoran Vasiljevic

Am 01.06.2005 um 22:50 schrieb Stephen Deasey:



Because form input always needs to be checked.  You can't declare it
debugged and turn off exception checking.  People will continue to
feed your program broken/malicious input.



Ah, this is what you mean! What about fixing tcllib to allow two
types of asserts? The one with off/on switch and the one without?
I haven't looked into there, but this can't be rocket science.

Zoran