Version 7 of Wikit run in a Slave Interpreter on TclHttpd

Updated 2004-05-28 07:53:16

"WhipIt" - Wikit run in a Slave Interpreter on TclHttpd

Since I read the comments below this became an itch I just had to scratch! Jeff Smith

Extracted from the How to grow your own Wiki page.

MDD: What would be really nice would be if someone would create a Starkit that combines tclhttpd and the wikit into one turnkey wiki server. Performance should be better, since you wouldn't have to use CGI.

11apr03 jcw - Yes, that would be cool, but it may need some work (either to make it properly keep state with repeated requests, or to make it work in a slave interp which gets re-inited on each access).

To try "WhipIt" place the following whipit.tcl code into the custom directory of your TclHttpd Starkit or get a ready made starkit, whipit.kit, from [L1 ]. This starkit has a copy of wikit.kit inside and copies it to the outside directory at startup if the wikit.kit file does not exist.

To launch on unix

 # ./tclkit whipit.kit

On Windows

from a dos window

 C:\tclkitsh whipit.kit

from windows explorer

 drag and release whipit.kit on tclkit

Point your browser to

 http://yourhost:8015/wikit/

This provides a nice wrapper around Wikit to allow you to dynamically control it. For example the WIKIT_BASE environment variable is dynamically set per request in the code below. Some ideas for the future

  • A readonly wiki with a seperate database that allows certain pages to be edited by dynamically removing "-readonly" flag for those pages.
  • A database which registers users and allows them to only edit the pages they created or edit pages of people in their group.

************* whipit.tcl ****************************

 #Mount the wikit startkit
 vfs::mk4::Mount [file dir $starkit::topdir]/wikit.kit [file dir $starkit::topdir]/wikit.kit

 set WktDir [file dir $starkit::topdir]/wikit.kit

 # Append wikit library from the mounted wikit starkit to the auto_path
 lappend auto_path [file dir $starkit::topdir]/wikit.kit/lib

 Url_PrefixInstall /wikit [list wikitProc /wikit]

 proc wikitProc {prefix sock suffix} {
         upvar #0 Httpd$sock data
         global env auto_path

      # Set the CGI environment variables

      Cgi_SetEnv $sock $prefix
      set env(PATH_INFO) $suffix
      set env(SCRIPT_NAME) $prefix

      # This sets the WIKIT_BASE environment vaiable dynamically based on
      # the host portion of the url typed in the browser.

      set env(WIKIT_BASE) http://$env(HTTP_HOST)$prefix/

      append data(query) ""

      # Use the Session Module in TclHttpd to create a slave interpreter.
      # A session state array is also created but we don't use it. This
      # maybe of some use if you have a need for a session based wiki.
      #
      # To emulate a CGI environment for Wikit, a slave interpreter is created
      # and then destroyed per request.

      # Destroy any old sessions that are laying around. Interpreters that have
      # been created but for some reason not destroyed. In this instance
      # 2 minutes is the setting.

      Session_Reap 120 Wkt

      # Create a new session.

      set session [Session_Create Wkt 0]

      set html [WktProcess $session $data(query)]

      Httpd_ReturnData $sock text/html $html
      Session_Destroy $session
 }

 proc WktProcess {session query} {
      upvar #0 Session:$session state
      set interp $state(interp)
      global auto_path WktDir

      set WktCGI_LineNumber 0

      set html ""

      # Redirect the read and puts in the slave interpreter
      # that runs Wikit.

      interp eval  $interp {rename puts real_puts}
      interp alias $interp puts {} WktCGI_Puts
      interp hidden $interp
      interp eval $interp {rename read real_read}
      interp alias $interp read {} WktCGI_Read $interp $query

      # Fool wikit to think it is running in it own Starkit so we can copy
      # the first ten pages from wikidoc.tkd

      interp eval $interp [list namespace eval starkit set topdir $WktDir]

      # Following taken from httpd.tcl for getting these variables into
      # a slave interpreter.
      #
      # Transfer the scalar global variables

      foreach var {::v ::auto_path} {
         $interp eval [list set $var [set $var]]
      }

      # Procedure that is run when the slave interpreter does a read.

      proc WktCGI_Read {interp query args} {

            if { [llength $args] == 2 && [lindex $args 0] == "stdin" } {
                return [$interp eval subst $query]
            } else {
                return [$interp eval real_read $args]
            }
      }

      # Precedure that is run when the slave interpreter does a puts.

      proc WktCGI_Puts {args} {
            upvar 1 WktCGI_LineNumber WktCGI_LineNumber
            upvar 1 html html

            incr WktCGI_LineNumber
            if {$WktCGI_LineNumber <= 4} {
                return ""
            } else {
                 append html [lindex $args end]
            }
      }


      # Setup and run Wikit.

      $interp eval {
                    set argv0 tclkit
                    set argv {}
                    set argc 0

                    package require cgi
                    #cgi_debug -on

                    # Work around for getting lassign into the slave interpreter.
                    # From "Practical Programming in Tcl and Tk" Third Edition
                    # by Brent B. Welch page 131.

                    proc lassign {valueList args} {
                         if {[llength $args] == 0 } {
                             error "wrong # args: lassign list varname ?varname ..?"
                         }
                         if {[llength $valueList] == 0} {
                             #Ensure one trip through the foreach loop
                              set valueList [list {}]
                         }
                         uplevel 1 [list foreach $args $valueList {break}]
                         return [lrange $valueList [llength $args] end]
                    }

                    # Source the starkit
                    package require app-wikit
       }
       return $html
 }

**********************************************************************************


Matthias Hoffmann: Which modifications are neccessary to do the same as above, but with a "conventional" tclhttpd-installation (no tclhttpd.kit)?


Category Wikit - Category TclHttpd