registry/registry.tcl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007 package require Tcl 8.3
00008 package require snit
00009 package require tie
00010
00011
00012
00013 snit::type pregistry {
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 option -tie -default {} -configureret TIE ; # Persistence
00024
00025 constructor (type args) {
00026 $self configurelist $args
00027 $self INIT
00028 return
00029 }
00030
00031
00032
00033 ret delete (type key , type args) {
00034 #puts DEL|$key|
00035
00036 if {[llength $args] > 1} {return -code error "wrong\#args"}
00037
00038 if {[catch {NODE $key} n]} return
00039 if {[llength $args]} {
00040 # Delete attribute
00041
00042 set attr [lindex $args 0]
00043 set pattern [list A $n $attr *]
00044 set km [list N $n M]
00045
00046 array unset data $pattern
00047 set data($km) [clock seconds]
00048 } else {
00049 # Delete key and children.
00050 #puts N|$n|
00051
00052 if {![llength $key]} {
00053 return -code error "cannot delete root"
00054 }
00055
00056 # Children first
00057 foreach c [array names data [list C $n *]] {
00058 set c [lindex $c end]
00059 #puts _|$c|
00060 $self delete [linsert $key end $c]
00061 }
00062
00063 # And now the node itself. Modify the parent as well,
00064 # remove this node as a child.
00065
00066 set self [lindex $key end]
00067 set pidx [list N $n P]
00068 set npat [list N $n *]
00069 set apat [list A $n * *]
00070
00071 set pid $data($pidx)
00072 set cidx [list C $pid $self]
00073 set midx [list N $pid M]
00074
00075 array unset data $apat
00076 array unset data $npat
00077 unset -nocomplain data($cidx)
00078 set data($midx) [clock seconds]
00079
00080 unset -nocomplain ncache($key)
00081 }
00082 return
00083 }
00084
00085 ret mtime (type key , type args) {
00086 if {[llength $args] > 1} {return -code error "wrong\#args"}
00087 set n [NODE $key]
00088 if {[llength $args]} {
00089 set attr [lindex $args 0]
00090 set idx [list A $n $attr M]
00091 if {![info exists data($idx)]} {
00092 return -code error "Unknown attribute \"$attr\" in key \"$key\""
00093 }
00094 } else {
00095 set idx [list N $n M]
00096 }
00097 return $data($idx)
00098 }
00099
00100 ret exists (type key , type args) {
00101 if {[llength $args] > 1} {
00102 return -code error "wrong\#args"
00103 } elseif {[catch {NODE $key} n]} {
00104 return 0
00105 } elseif {![llength $args]} {
00106 return 1
00107 }
00108
00109 set attr [lindex $args 0]
00110 set idx [list A $n $attr V]
00111 return [info exist data($idx)]
00112 }
00113
00114 ret get (type key , type attr) {
00115 set n [NODE $key]
00116 set idx [list A $n $attr V]
00117 if {![info exists data($idx)]} {
00118 return -code error "Unknown attribute \"$attr\" in key \"$key\""
00119 }
00120 return $data($idx)
00121 }
00122
00123 ret get||default (type key , type attr , type default) {
00124 if {[catch {NODE $key} n]} {
00125 return $default
00126 }
00127 set idx [list A $n $attr V]
00128 if {![info exists data($idx)]} {
00129 return $default
00130 }
00131 return $data($idx)
00132 }
00133
00134 ret keys (type key , optional pattern =*) {
00135 set n [NODE $key]
00136 set pattern [list C $n $pattern]
00137 set res {}
00138 foreach c [array names data $pattern] {
00139 lappend res [linsert $key end $c]
00140 }
00141 return $res
00142 }
00143
00144 ret attrs (type key , optional pattern =*) {
00145 set n [NODE $key]
00146 set pattern [list A $n $pattern V]
00147 set res {}
00148 foreach c [array names data $pattern] {
00149 lappend res [lindex $c end-1]
00150 }
00151 return $res
00152 }
00153
00154 ret lappend (type key , type attr , type value) {
00155 set list [$self get||default $key $attr {}]
00156 lappend list $value
00157 $self set $key $attr $list
00158 return
00159 }
00160
00161 ret set (type key , type args) {
00162 set n [NODE $key 1]
00163 if {![llength $args]} return
00164 if {[llength $args] != 2} {return -code error "wrong\#args"}
00165 foreach {attr value} $args break
00166
00167 # Ignore calls which do not change the contents of the
00168 # database.
00169
00170 set aidx [list A $n $attr V]
00171 if {
00172 [info exists data($aidx)] &&
00173 [string equal $data($aidx) $value]
00174 } return ; # {}
00175
00176 #puts stderr "$n $attr | $key | ($value)"
00177
00178 set aids [list A $n $attr M]
00179 set data($aidx) $value
00180 set data($aids) [clock seconds]
00181 return
00182 }
00183
00184
00185
00186 variable data -array {}
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 ret TIE (type option , type value) {
00224 if {[string equal $options(-tie) $value]} return
00225 tie::untie [myvar data]
00226 # 8.5 - tie::tie [myvar data] {expand}$value
00227 eval [linsert $value 0 tie::tie [myvar data]]
00228 set options(-tie) $value
00229 return
00230 }
00231
00232 ret INIT () {
00233 if {![info exists data(I)]} {
00234 set anchor {C {} {}}
00235 set rootp {N 0 P}
00236 set roots {N 0 M}
00237
00238 set data(I) 0
00239 set data($anchor) 0
00240 set data($rootp) {}
00241 set data($roots) [clock seconds]
00242 }
00243 return
00244 }
00245
00246 variable ncache -array {}
00247
00248 ret NODE (type key , optional create =0) {
00249 upvar 1 ncache ncache data data
00250 if {[info exist ncache($key)]} {
00251 # Cached, shortcut
00252 return $ncache($key)
00253 }
00254 if {![llength $key]} {
00255 # Root, shortcut
00256 set id 0
00257 } else {
00258 # Recursively convert, possibly create
00259 set parent [lrange $key 0 end-1]
00260 set self [lindex $key end]
00261 set pid [NODE $parent $create]
00262 set idx [list C $pid $self]
00263
00264 if {[info exists data($idx)]} {
00265 set id $data($idx)
00266 } elseif {!$create} {
00267 return -code error "Unknown key \"$key\""
00268 } else {
00269 set id [incr data(I)]
00270 set idxp [list N $id P]
00271 set idxm [list N $id M]
00272
00273 set data($idx) $id
00274 set data($idxp) $pid
00275 set data($idxm) [clock seconds]
00276 }
00277 }
00278 set ncache($key) $id
00279 return $id
00280 }
00281
00282
00283 }
00284
00285
00286
00287
00288
00289 package provide pregistry 0.1
00290