1# $Id$
2
3package require ctable_client
4package require st_client
5
6namespace eval ::stapi {
7  # shared://port/[dir/]table[/stuff][?stuff]
8  # options:
9  #   -build dir
10  #      Specify path to ctable build directory
11  #
12  variable shared_serial 0
13  variable shared_build_dir ""
14
15  proc connect_shared {table_path {address ""} args} {
16    variable shared_serial
17    variable shared_build_dir
18
19    if {[info exists shared_build_dir] && "$shared_build_dir" != ""} {
20      set opts(-build) $shared_build_dir
21    }
22
23    array set opts $args
24
25    if {"$address" == ""} {
26      set host localhost
27      set port ""
28    } elseif {![regexp {^(.*):(.*)$} $address _ host port]} {
29      set host localhost
30      set port $address
31    }
32
33    if {"$host" != "localhost" && "$host" != "127.0.0.1"} {
34      return -code error "Can not make a shared connection to a remote server"
35    }
36
37    if {"$port" == ""} {
38      set address $host
39    } else {
40      set address $host:$port
41    }
42
43    set uri ctable://$address/$table_path
44
45    set ns ::stapi::shared[incr shared_serial]
46
47    # insert handler proc (below) into namespace, and create the namespace
48    namespace eval $ns [list proc handler {args} [info body shared_handler]]
49
50    remote_ctable $uri ${ns}::master
51    set handle [${ns}::master attach [pid]]
52    array set prop [${ns}::master getprop]
53
54    if {[info exist opts(-build)]} {
55      if {[lsearch $::auto_path $opts(-build)] == -1} {
56	lappend ::auto_path $opts(-build)
57      }
58    }
59
60    namespace eval :: [list package require [string totitle $prop(extension)]]
61    $prop(type) create ${ns}::reader reader $handle
62
63    # Everything's been successfully completed, remember that in the created
64    # namespace.
65    set ${ns}::handle $handle
66    set ${ns}::table $prop(type)
67    set ${ns}::attached 1
68    return ${ns}::handler
69  }
70  register shared connect_shared
71
72  # Simple handler, most commands are passed straight to the master.
73  #
74  # Note cheesy object model!
75  #
76  # This executes in the stapi::sharedN namespace created in connect_shared,
77  # never in this namespace, so references to "reader" and "master" are
78  # the two stapi objects created there.
79  proc shared_handler {args} {
80    set method [lindex $args 0]
81    variable attached
82    switch -glob -- [lindex $args 0] {
83      search* {
84	#puts "\nrunning shared_handler search, '[namespace which reader] $args'"
85	catch {uplevel 1 [namespace which reader] $args} catchResult catchOptions
86
87	#puts "shared_handler search ran, args '$args' result '$catchResult', options $catchOptions\n"
88	dict incr catchOptions -level 1
89	return -options $catchOptions $catchResult
90      }
91      destroy {
92	if {$attached} {
93	  master destroy
94	}
95	reader destroy
96      }
97      detach {
98	if {$attached} {
99	  master destroy
100	  set attached 0
101	}
102      }
103      default {
104	if {$attached} {
105	  #puts "\nrunning shared_handler default case, args '$args'"
106	  catch {uplevel 1 [namespace which master] $args} catchResult catchOptions
107	  #puts "shared_handler default case ran, args '$args' result '$catchResult', options $catchOptions\n"
108	  dict incr catchOptions -level 1
109	  return -options $catchOptions $catchResult
110	} else {
111	  return -code error "Detached shared table can only 'search' and 'destroy'"
112	}
113      }
114    }
115  }
116}
117
118package provide st_shared 1.13.12
119
120# vim: set ts=8 sw=4 sts=4 noet :
121