Homepage › Clovertech Forums › Read Only Archives › Cloverleaf › Tcl Library › global variables.
- This topic has 23 replies, 7 voices, and was last updated 14 years, 11 months ago by Kevan Riley.
-
CreatorTopic
-
April 8, 2008 at 7:00 pm #49960Kevin CristParticipant
How can I access from within a tps tclproc the global variable for the current site my tclproc is running in? Thanks!
-
CreatorTopic
-
AuthorReplies
-
-
April 8, 2008 at 7:37 pm #64261Max Drown (Infor)Keymaster
Here is a common line from many tps scripts: Code:global HciSite HciSiteDir HciProcessesDir HciConnName HciRootDir ibdir
You can then access the variable in the normal way like maybe “puts $HciSiteDir”.
-- Max Drown (Infor)
-
April 9, 2008 at 3:53 pm #64262Charlie BursellParticipant
If you remember that the global area is simply a namespace you can access them without declaring as global as long as you provide the full path to the variable. For example: $::HciSiteDir
-
October 15, 2008 at 4:15 pm #64263Todd HorstParticipant
So does each thread have thier own global section? Can you share globals between threads, processes, sites? At what level does tcl get loaded and therefore is the ceiling for sharing globals? I created 2 scripts to share a global between two threads and it didnt work. Here was my setup
Script 1:
global testvar
set testvar “Some Value”
Script 2:
global testvar
echo $testvar
I would expect this to spit out “Some Value”, instead i get a tcl error saying its an undefined variable.
Any ideas?
-
October 15, 2008 at 5:26 pm #64264Charlie BursellParticipant
Each interpreter has it’s own global area. Anything defined outside of a process is, by definition global. A running engine has three interpreters, one for the IB Protocol Thread, one for the OB Protocol Thread and another for the Xlate Thread. SO as long as a proc shares the same interpreter it can share globals. This is basic Tcl stuff covered quite well in Brent Welch’s book
-
October 15, 2008 at 5:54 pm #64265Todd HorstParticipant
Im able to set a variable and use it in two procs if its set up like this, all in the same file: set var1 “some value”
proc 1 {} {
global var1
echo $var1
}
proc 2 {} {
global var1
echo $var1
}
I then place these procs in the TPS Outbound Data field. Im guessing this works because everytime it runs the proc its sourcing the file and therefore defining the var1 variable no matter which proc it wants to call.
What im looking for is a global variable that is maintained. So for example. 3 threads could share the same variable globally, but all 3 threads have a proc from a different file. If the variable didnt exitst yet any of the three could create it, but once it existed, any of the three could access it.
So here is a more accurate description of my scenario. Each time a message goes through it should echo “some value”, and it will for test1, but for test2 it will say its undefined:
File1:
set testvar2 “some value”
proc test1 { args } {
keylget args MODE mode ;# Fetch mode
global testvar2
set dispList {} ;# Nothing to return
switch -exact — $mode {
run {
echo $testvar2
# ‘run’ mode always has a MSGID; fetch and process it
keylget args MSGID mh
lappend dispList “CONTINUE $mh”
}
}
return $dispList
}
file 2:
proc test2 { args } {
keylget args MODE mode ;# Fetch mode
global testvar2
set dispList {} ;# Nothing to return
switch -exact — $mode {
run {
echo $testvar2
# ‘run’ mode always has a MSGID; fetch and process it
keylget args MSGID mh
lappend dispList “CONTINUE $mh”
}
}
return $dispList
}
-
October 15, 2008 at 7:12 pm #64266Charlie BursellParticipant
Take a look at the recover_33 procs to see how globals are shared there -
October 16, 2008 at 11:12 am #64267Todd HorstParticipant
Right, and thats how i started my scripts initially but i cannot get it to work. If you take the following 2 procs, save them to a file (can be one or two files) then create 2 threads. Then on the first thread on the outbound tab set tps outbound data proc to the 1st proc and on the 2nd thread set same field to the 2nd proc. Now start up the first thread. Now start up the second thread.
It will give you a “can’t read “gvar”: no such variable'”.
Any ideas on how to get it to work would be nice, If you can fix the code that would be better…
proc test1 { args } {
keylget args MODE mode ;# Fetch mode
global gvar
set dispList {} ;# Nothing to return
set gvar “heyyou”
switch -exact — $mode {
start {
echo $gvar
}
run {
keylget args MSGID mh
lappend dispList “CONTINUE $mh”
}
shutdown {
echo $gvar
}
}
return $dispList
}
proc test2 { args } {
keylget args MODE mode ;# Fetch mode
set dispList {} ;# Nothing to return
global gvar
switch -exact — $mode {
start {
echo $gvar
}
run {
# ‘run’ mode always has a MSGID; fetch and process it
keylget args MSGID mh
lappend dispList “CONTINUE $mh”
}
shutdown {
echo $gvar
}
}
return $dispList
}
-
October 16, 2008 at 12:17 pm #64268Charlie BursellParticipant
Ah, but that is your problem, two thread. I said there are at least three interpreters, one for each Protocol Thread and one for the Xlate thread. I you define two threads, each will have it’s own interpreter. You cannot share globals across interpreters. -
October 16, 2008 at 12:30 pm #64269Todd HorstParticipant
Okay, That was my underlining question. At what level the tcl runs at, and your answer is that each thread has 3 instances of tcl running, IB OB and XLATE. So a multiple thread variable is not possible. This is fine, i was just curious if it was possible.
My main reason if everyone was curious is that i wanted to share an odbc persistent connection to a server among several threads. This way we could limit the connections coming out, and maximizing a connections throughput instead of many small (sometimes inactive) odbc connections.
Thanks charlie
-
October 16, 2008 at 1:06 pm #64270Kevan RileyParticipant
There are two ways I know of to “share” information (like an ODBC handle) between threads. One is to write it to a file, and read it from there. You would need to clean up your file when you close the handle or in teh shutdown part of the thread that creates the handle. the other is through message metadata USERDATA. You can use the message to carry your information to the next thread by storing it in the USERDATA and then reading it in the dest. thread. Kevan Riley
AHS-IS
-
October 16, 2008 at 1:16 pm #64271Todd HorstParticipant
yeh, i was thinking more your second approach. Set up a odbc thread that connected to a server and then send all my messages to that thread. Routing to specific procs would be determined by its meta data. So the message comes in, i read meta data, call a sub proc in a namespace that write it to the correct table, or performs and needed modifications before writting to a common table…whatever the case demanded.
The benifit of the impossibility of a site global is that it would be much more orginized and readable. So we are able to have each thread do specific tasks for its needs.
I realize the true global could present issues with variable overwrites, but with some management and orginization thats pretty easily solved. Not to mention that most people that would globals would understand the concept and its complications.
Besides any other language you look at his the same issue, which really i wouldnt call and issue, but rather a feature.
Thanks for your suggestion Kevan.
-
October 16, 2008 at 1:47 pm #64272Kevan RileyParticipant
If you wanted to get really clever you could craft a proc that hides the metadata reading and writing and make it function more or less like the “global” command. Especially since you are mostly just reading it, and not changing it. Make it a proc in a library and “package require” it. That would hide all of the “ugliness” of putting and getting to/from USERDATA. You would have to pass the message handle, a key name, and optionally a value to set. The return value would be whatever is set. eg. something like this
# set ODBC connection handle to metatdata
# where:
# $mh is your message handle
# ODBC_CH is you key in the metadata USERDATA
# $ODBC_ch is the connection handle variable
set null [MetaGlobal $mh ODBC_CH $ODBCch]
# read ODBC connection handle from metadata
set ODBCch [MetaGlobal $mh ODBC_CH]
if you want to do it right and handle errors, make the call something like this:
if {[catch {MetaGlobal $mh ODBC_CH $ODBCch} result]} {
echo “Error: MetaGlobal store failed with error: $result”
# handle error!
}
unset result
and
if {[catch {MetaGlobal $mh ODBC_CH} result]} {
echo “Error: MetaGlobal fetch failed with error: $result”
# handle error!
} else {
set ODBCch $result
}
unset result
Kevan Riley
AHS-IS
-
October 16, 2008 at 1:50 pm #64273Kevan RileyParticipant
The previous is an example of calling the proc, not the proc its self, -
August 27, 2009 at 8:20 pm #64274Troy MortonParticipant
Is there anywhere that all the global Tcl variables available in the engine are documented? I couldn’t find anything in the manuals when searching for “global HciConnName”. It would be nice to have a table of all the global variables established by the engine interpreter and what they contain.
Troy
-
October 19, 2009 at 2:36 pm #64275Todd HorstParticipantCode:
proc globalpat {args} {
foreach pattern $args {
set varnames [info globals $pattern]
if {[llength $varnames] != 0} {
echo $varnames
}
}
}globalpat *
Found this on the internet-> i agree it should be documented. i was looking for a way now to retrieve the threads process name, thought it would be in global, but it is not.
-
October 19, 2009 at 3:58 pm #64276Troy MortonParticipant
Here is how I’ve been able to get the Cloverleaf Engine process name from within Tcl.
-
October 19, 2009 at 6:06 pm #64277Russ RossParticipant
Troy Morton asked:
[code]Is there anywhere that all the global Tcl variables available in the engine are documented?Is there anywhere that all the global Tcl variables available in the engine are documented?Russ Ross
RussRoss318@gmail.com -
October 19, 2009 at 8:48 pm #64278Charlie BursellParticipant
Why jump through all these hoops? 🙂
set HciProcess [file tail [pwd]] from a running engine
grep protocol NetConfig | cut ……
Troy Morton wrote:Here is how I’ve been able to get the Cloverleaf Engine process name from within Tcl.
-
October 19, 2009 at 8:56 pm #64279Troy MortonParticipant
I knew you’d jump in with a one-liner, Charlie.
-
October 19, 2009 at 8:59 pm #64280Charlie BursellParticipant
We didn’t make that a global because it is readily available via the command I gave you.
Of course you are free to modify $HCIROOT/tcl/lib/cloverleaf/init.tcl at you site and add it 😀
-
October 19, 2009 at 9:07 pm #64281Troy MortonParticipant
Charlie, did you notice your last post was your 666th post.
-
October 19, 2009 at 10:27 pm #64282Charlie BursellParticipant
I’m a pretty spooky guy 😈 😈
-
October 20, 2009 at 3:34 pm #64283Kevan RileyParticipant
try:
puts “[info globals]”
Kevan Riley
AHS-IS
-
-
AuthorReplies
- The forum ‘Tcl Library’ is closed to new topics and replies.