Global Channels

The use of a PSL global channel is a design advantage for a KM where an external process is used to access the application.

For such applications the least performance-effective method is to repeatedly launch it via PSL system or execute to collect each query. The more effect method is to use PSL popen() to create a local channel to the executable, use PSL write() to send commands to the executable, and to use PSL read() to get data from the application. This local channel allows repeated commands to be sent to the executable, and permits the channel to stay open, thus avoiding the cost of process spawning. If only a collector parameter is using the channel, it can remain a local channel.

If more than one PSL process needs to get information from or to the application, this is not efficient. A local channel can be accessed only by the PSL process that spawned the child via the PSL popen function. In this case the more performance effective approach is to use the PSL share function to convert the local channel to a global channel. The global channel idea involves only creating a single child process.

Global Channels

A global channel is typically a pipe into an interactive process. This child process can be as simple as a system command shell, a commandline tool or a self-written application.

The use of PSL global channels is effective for performance improvement only when the required conditions arise involving multiple PSL scripts and multiple child processes. The channel is an internal agent data structure and has no actual physical run time presence on the computer.

The use of the global channel has a performance advantage in that it allows one child process to be used by multiple PSL processes.

Creating Shared Channel

After you have created a channel and you want to use it in multiple PSL processes, the process that created the channel will have to share it.

Using the share() Command

Sharing a channel means giving it a name and placing that name in the PATROL Shared Memory space from the VM (instead of the process memory area). This process is done with the share() command, and it does all of this for you.

When using shared channels, only one subprocess will answer all requests from a number of PSL processes. This can be very good for performance (applied to a KM that works on Oracle, this can mean one connection per Oracle instance, instead of one connection per parameter in the KM).

Shared Channel Locking

Since multiple processes can occur simultaneously over a shared channel, it can be desirable to introduce channel locking in your KM design. Sometimes it is not harmful if a command is messed up in the channel, and mostly you can detect that this mess-up occurred when you read the output of the channel. In some cases, it is not allowed to happen. If such is the case, you will have to lock() the channel.

When you lock() a channel, it will be locked for a certain PSL process. When you implement locking, you normally lock the channel before writing to it; and you unlock it after you read the output from the channel.

If another process wants to write to the channel, it waits until it can acquire a lock on the channel (when the process occupying the channel unlocks it). If no process is using the channel at the point of request, it will immediately get the lock. You will also have to implement timeouts on the lock so that a process will not be able to get the channel for an infinite time. This will block the channel, and your KM will stop responding.

Be careful when using shared channels in menu commands. The user is used to getting immediate feedback when executing a menu command. If the execution goes over the same channel that you're monitoring, a user issuing many menu commands will influence the monitoring part of your KM (if the user gets the lock all the time). Another possibility is that the user might not get the lock at all (or within an acceptable time interval). The user's perception will be that the KM performs badly; therefore, it's advisable to execute menu commands as one-time commands.

Channel Example

Although channels are quite obvious to work with, it seems that a lot of developers find it difficult to get started with them. The following example does not only show how to create channels, but also how you could use channels to communicate to other processes and do something useful. These examples will pass a job where extended regular expressions are needed to PERL. The two programs below work in tandem and communicate over a channel.

PSL Program

function chan grep(channel, pattern, text)
{
local lter , eot , len , data;
# Used by the perl script
filter ="\n@#!FILTER!#@";
eot="\n@#!EOT!#@\n";
if ( chan exists(channel))
{
# Make sure noone will use the channel while we are
lock("chan_grep_".channel);
# Write the lter de nition , the text and the EOT
# message. It would be possible to have multiple
# lter conditions
# But you will need to learn regular expressions.
write(channel, lter.pattern."\n".text.eot);
# After EOT, perl script will return the length of the output
len=trim(readln(channel),"\r\n");
# If there is more than 0 to read, get it ...
if ( len>0)
{
data=read(channel,len);
}
# Free the lock
unlock("chan_grep_".channel); g
}
return(data);
}
chan=popen("OS","perl /tmp/xxx.pl");
text="1: aaa bbb ccc\n2: aaa xxx ccc\n3: aaa bbb ccc\n";
output=chan grep(chan,"xxx",text);
print("\nOutput 1 =".output);
output=chan grep(chan,"bbb",text);
print("\nOutput 2 =".output);
output=chan grep(chan,"xyz",text);
print("\nOutput 3 =".output);
close(chan);

Perl Program

$j=1;
while (<STDIN>)
{
if (/ˆ @#!FILTER!#@ns (. )/)
{
$filter =$1;
}
elsif (/ $ lter /)
{
$output.=$ ;
}
elsif (/ˆ @#!EOT!#@/)
{
print length($output)."\n".$output;
$output="";
}
}

Channel Pitfalls

The following are a few drawbacks that might occur with channels.

Shared channels not closed

If a KM is unloaded, the shared channels that were opened by that KM will remain open. Therefore it is a good coding practice to see if a certain "share" already exists when the channel is established. It is possible that the KM was unloaded and reloaded. Since it is not possible to clean up at unload time, the KM should at least clean up at reload time.

Channel synchronization

Let's first explain the issue with channel synchronization. For example: you are using popen(), read() and write() to simulate an interactive telnet session and have a function (below) which submits a command to the telnet session and returns the response. After the channel is open, you call this function several times in succession.

function mcomm(channel,command)
{
write(channel,command."\n");
output=read(channel);
return(output);
}
a=mcomm(handle,"echo apple");
b=mcomm(handle,"echo banana");
c=mcomm(handle,"echo pear");

Normally you would expect that

a = apple

b = banana

c = pear

What you might see is :

a =

b = apple

banana

c = pear

or

a =

b =

c = apple

banana

pear

Definitely this is an indication about a synchronization issue in the channel communication.

What you want to do is force read() to wait but also allow for the case where the submitted command might not return any output.

As with any component that communicates with another component, you have to define some type of protocol.

By adding a minor convention to your code you can make the communication more stable. The "trick" is to wait until you get a termination signal... (In this case a very bizarre piece of text). Of course the end-of-output could also be signalled by a prompt or something else. If the sender can tell you how many bytes it will send, you could determine the end-of-output by counting the number of returned bytes. One of the possible ways of getting it done is shown below:

function mcomm(channel,command)
{
local data,output;
output=""; term="@@<at:var at:name="_THE_END_" />@@";
term cmd="echo\necho ".term."\n";
term cmd="echo\necho ".term."\n";
write(channel,command."\n".term cmd);
write(channel,command."\n".term cmd);
while (data=read(channel))
{
output=output.data;
if ( grep("ˆ".term."$",output))
{
output=replace(output,term."\n","");
last;
}
}
return(output);
}

Depending on the product you are talking to, there might be other and better solutions.






Was this page helpful? Yes No Submitting... Thank you

Comments