Ns adp include

From AOLserver Wiki
Revision as of 07:59, 14 June 2010 by Akhassin (talk | contribs)
Jump to navigation Jump to search

Man page: http://aolserver.com/man/4.0/tcl/ns_adp_include.html


NAME

ns_adp_include - Parse an ADP file with the generated output written to the adp buffer

SYNOPSIS

ns_adp_include ?-cache seconds |-nocache? file ?arg arg ...?

DESCRIPTION

This command reads file and parses its contents as an ADP with the generated output written to the adp buffer and returns the adp return value (i.e. from return, ns_adp_return or the last tcl command in the adp) to the caller. file is relative to the caller's directory unless an absolute pathname is used. Tcl commands in the ADP are evaluated in a new scope one level below the caller just like when calling a proc. Optional arguments can be passed which are accessed using ns_adp_argc, ns_adp_argv and ns_adp_bind_args commands in the callee.
The optional -cache seconds argument specifies the time to cache the results of execution (i.e. the output written to the adp buffer). Output generated by any scripts and included ADPs is saved for subsequent requests except ns_adp_included blocks that specify the -nocache switch as part of the ns_adp_include command. The use of -cache and -nocache can be used to increase performance of ADP used to generated a mix of personalized, non-cacheable, content and shared content which changes more slowly. Under high load, the performance improvement can be substaintial, especially in cases where the cached content is the result of accessing a slow databases or web services. See the EXAMPLES section for an example of using cached output.
Note that ADP streaming cannot be turned on using ns_adp_stream from within an ADP executed with the ns_adp_include command.
ADPs can be nested by including each other up to the maximum of 256 levels deep.
This command is only available from an ADP page or script. Use ns_adp_parse to parse ADPs from outside the context of an ADP.

EXAMPLES

    ###
    ### Example #1: Callee writes the output directly to ADP output buffer, also using passed arguments.
    ###

    # In a.adp:
    <% ns_adp_include b.adp Bob%>

    # In b.adp:
    <% ns_adp_puts "Hello, [ns_adp_argv 1 world]!" %>

    ###
    ### Example #2: Caller writes the adp return value to ADP buffer.
    ###

    # In a.adp:
    <% ns_adp_puts [ns_adp_include b.adp] %>

    # In b.adp:
    <% return "Hello, [ns_adp_argv 1 world]!" %>

    ###
    ### Example #3: The following example demonstrates using the -cache and -nocache options to enhance
    ###             performance through caching execution output. 

    # In top.adp:
    <% ns_adp_include -cache 60 cached.adp %>

    # In cached.adp:
    <%
      ns_adp_puts "Time at cache: [ns_time]"
      ns_adp_include -nocache nocache.adp
    %>

    # In nocache.adp:
    <% ns_adp_puts "Time now: [ns_time]" %>

    # The output of cached.adp will only update once every 60 seconds except for the portion
    # that is the output of nocache.adp, which will be executed on each request,
    # even though it's included within cached.adp.

NOTES

With the new output caching in AOLserver 4.5, there is now a three-tier caching system for adp files - cache of static text blocks, cache of parsed adp scripts and resulting tcl byte-code and cache of execution/output - implemented as follows:
  • Each thread/interpreter maintains a cache of ADP code which includes the result of parsing adp tags and byte-code compiling (but not executing) the resulting tcl code
  • Plus the per-interpreter cache includes pointers to text regions in a shared area (tied to a specific virtual server). When all threads no longer point to the shared text, it's free'd from memory.
  • When enabled, the output cache is simply the replacement of what would have been per-interp byte code blocks with pointers to combined runs of text. The output cache is shared.
  • Files on disk are checked on each request, whether output caching is enabled or not, via a stat call. On Unix the key in the cache is device/inode (which allows the same file pointed by multiple symlinks to be only read once) and on Windows it's the filename.
  • If the file on disk has changed, byte-code, text regions and output caches are flushed and regenerated.
  • The cache is keyed to both the inode/filename and the adp arguments in the ns_adp_include call.
  • It is not possible to change the time-to-live (ttl) for a cache entry once it is generated - if you have two files that include the same adp with different ttl, the first file to be accessed will determine the ttl. -cache 0 will still use the previously cached output if the previously set ttl hasn't expired (it might be helpful if a value of 0 would actually flush the cache without recreating it, so that database-change-triggered code could invalidate the cache without having to know how long it should be cached for again). If you omit -cache or use -nocache, then the previously cached output is not used (it might be helpful to support a value of -1 to mean the same as omitting -cache)
  • You can force a given request to ignore all cache directives and execute all includes with ns_adp_ctl cache 0 (or ns_adp_ctl nocache 1 in NaviServer).
Since ns_adp_include adp caching is rather useful outside of adp pages as well, the following wrapper procedure can be used both in an adp and outside of one to include an adp file with output caching
    proc am_adp_include {args} {
    #
    # Last Modified:    2010-06-13
    # Last Modified By: Alex Hisen
    # Original Author:  Alex Nisenboim
    #
    # Usage :  am_adp_include ?-cache ttl | -nocache? adpfile ?arg1? ?arg2? ...
    #        
    # Synopis: Works like ns_adp_include, but can be called outside of an ADP. Also there is 
    #          a new option for ttl parameter that could be convenient (see below).
    #          This proc automatically determines whether it's being executed inside an ADP
    #          and if so, it works as a drop-in replacement for ns_adp_include - i.e. it
    #          returns the return value of the adp file and writes the parsed result to the adp buffer.
    #          If executed outside of an ADP, the return value is discarded and the
    #          parsed result is returned.
    # 
    # Input  : 
    #          ?-cache ttl | -nocache?   -  optional switch. Opting for -cache will cause using the cached 
    #                                       value unless it is older then ttl. Note that providing ttl == -1 
    #                                       effectively means -nocache,  but otherwise ttl must be positive 
    #                                       integer, just like in ns_adp_include. If cache is disabled for 
    #                                       duration of the current connection (with am_adp_disableCache),
    #                                       the specified -cache value will be ignored.
    #
    #          adpfile                   -  mandatory parameter which is the ADP filename. 
    #                                       It could have absolute or relative path. If 
    #                                       called from an ADP  it is assumed to be relative to 
    #                                       the adp current working directory.
    #                                       If called not from an ADP and has a relative or volumerelative 
    #                                       path then adpfile is assumed to be relative to the  
    #                                       pageroot i.e. the output of ns_url2file command. 
    #         
    #          ?arg1? ?arg2? ...         -  optional parameters that are to be passed to the ADP.             
    #      
    #
    
        
        # manually parse args for improved performance 
        set nargs [llength $args]       
        if { $nargs == 0 } {
            error "wrong # args: should be \"am_adp_include ?-cache ttl | -nocache? adpfile ?arg1? ?arg2? ...  \"" "" ""
        } else {
            if {[string match "-cache*" $args]} {
                set inputSwitch "-cache"
                set ttl [lindex $args 1]
                if {[string equal "-1" $ttl]} {
                    set inputSwitch "-nocache"
                    set ttl ""
                }
                set filename [lindex $args 2]
                if {[string equal "" $filename]} {
                    error "wrong # args:  should be \"am_adp_include ?-cache ttl | -nocache? adpfile ?arg1? ?arg2? ... \"" "" ""
                } else {
                    set adpfile [am_normalizeFileName $filename] 
                }
                set adpargs [lrange $args 3 end] 
            } elseif {[string match "-nocache*" $args]} {
                set inputSwitch "-nocache"
                set adpfile [am_normalizeFileName [lindex $args 1]] 
                set adpargs [lrange $args 2 end] 
                set ttl ""
            } else {
                set inputSwitch ""
                set adpfile [am_normalizeFileName [lindex $args 0]] 
                set adpargs [lrange $args 1 end]
                set ttl ""
            }
        }
        
        set parsedResult [ns_adp_parse -savedresult returnValue -string "<% ns_adp_include $inputSwitch $ttl [list $adpfile] $adpargs %>"]
        if {![catch {ns_adp_argc}]} {
            #meaning we are in an ADP
            ns_adp_puts -nonewline $parsedResult
            return $returnValue
        }
        return $parsedResult
    }

SEE ALSO

ns_adp_abort, ns_adp_append, ns_adp_argc, ns_adp_argv, ns_adp_bind_args, ns_adp_break, ns_adp_debug, ns_adp_debuginit, ns_adp_dir, ns_adp_dump, ns_adp_eval, ns_adp_exception, ns_adp_mime, ns_adp_mimetype, ns_adp_parse, ns_adp_puts, ns_adp_registeradp, ns_adp_registerproc, ns_adp_registertag, ns_adp_return, ns_adp_safeeval, ns_adp_stats, ns_adp_stream, ns_adp_tell, ns_adp_trunc