Tideway Community Forum

forgot password?
   
 
search within lists?
Posted: 03 December 2008 07:47 PM   [ Ignore ]  
Newbie
Rank
Total Posts:  3
Joined  2008-02-05

Hi. I’d like to be able to search for specific items within a list variable, in order to create a sub-list. In the below example, the goal is to create a list called dev_hosts containing only those hosts from all_hosts that have “dev” in the string.

all_hosts := ["db_dev1",
              
"db_dev2",
              
"db_prd1",
              
"db_prd2",
              
"db_uat1",
              
"db_uat2"];

where the goal is to wind up with a list like this:

dev_hosts :=             ["db_dev1",
                          
"db_dev2"]

The only smart way to do this, that I know of, is to iterate through each item in the main list and add it to the sub-list if it matches that regex, thusly:

dev_hosts := [];

for 
host in all_hosts do
    if 
regex.extract(hostregex "dev"then
        dev_hosts 
:= dev_hosts [host];
    
end if;
end for; 

Is there a quicker way to do this with the “search” function? i.e. something like this:

dev_hosts := search(in all_hosts ... something); 

I tried regex.extractAll on the main list, in the hopes that it would return another list, but I got an ECA error. :( regex.extractAll appears to want only a string input.

Profile
 
 
Posted: 04 December 2008 10:09 AM   [ Ignore ]   [ # 1 ]  
Administrator
Rank
Total Posts:  4
Joined  2008-02-14

Where did your list come from in the first place? Presumably not from a static list in the pattern body? Wherever it came from, perhaps you could have filtered it before you got it? I’d be interested to hear what the intent of this pattern is.

If you really do have a list to filter in TPL, you can’t do much better than the for loop you suggest. You should, however, use “matches” or “has substring” rather than regex.extract, since you don’t need to use the result of the match:

for host in all_hosts do
    if 
host matches regex "dev" then
        
... 
or
for host in all_hosts do
    if 
host has substring "dev" then
        
... 

Both of those are a bit more efficient than doing a regex extraction then throwing the result away.

Profile
 
 
Posted: 04 December 2008 10:20 AM   [ Ignore ]   [ # 2 ]  
Administrator
Avatar
RankRankRankRank
Total Posts:  130
Joined  2008-01-25

Morning Colin

First point is that no, regex.extractAll() isn’t going to help here, the regex functions process single strings.

I think there is some confusion about the difference between a list of strings and a list of nodes.

If you have pulled the list of names from some text or configuration file then you will have to process it as a list of strings. In this case the for loop approach to filter the list is what you want.

However if you are pulling a list of Host nodes from the datastore remember that a variable in TPL can also be a handle to the node, so in this case you will have a list of nodes. The important thing about a list of nodes is that it can be passed to the search service and you could then filter on any of the attributes or relationships.

Can you post the rest of the TPL so we can see where the list comes from and advise?

In the general case it’s a lot easier if you are finding nodes, filtering them and then updating or linking them if you keep them as a list of nodes rather than extracting a name, filtering that and then searching for the nodes with that name.

Profile
 
 
Posted: 04 December 2008 01:52 PM   [ Ignore ]   [ # 3 ]  
Newbie
Rank
Total Posts:  3
Joined  2008-02-05

Good morning again! (5:30am here) Thanks for your help, guys. The sad news is that the list has always been a list before I can get my hands on it. It’s actually the web_sites_list generated via xpath.evaluate on the MetaBase.xml file for IIS. Its function is analogous to grepping out the VSites in httpd.conf – one can see what web sites are served by this particular IIS server. Here’s that snippet of IIS.tpl:

website_bindings := xpath.evaluate(metabase_file.contentraw"/configuration/MBProperty/IIsWebServer/@ServerBindings");
                    
                    
// Iterate over the bindings and extract the name of the website that the binding corresponds to.
                    
for binding in website_bindings do
                    
                        
websites := xpath.evaluate(metabase_file.contentraw"/configuration/MBProperty/IIsWebServer[@ServerBindings = '" binding "']/@ServerComment");

                        for 
website in websites do

                            
// For each website found check if it is already in the list, if not then add it to the string 
                            // list and list.                        
                            
if not(website in web_sitesthen
                                log
.debug("Added &#xwe;bsite% to web_sites list.");
                                
web_sites := "&#xwe;bsites%, &#xwe;bsite%";
                                
web_sites_list := web_sites_list [website];
                            
end if;

                        
end for;
                        
                    
end for; 

So in this particular case, I can see exactly how many instances of the “Cleaner” application are in existence, because the web_sites_list will have several entries, like “CleanerDEV”,“CleanerQAS”,“CleanerPRD” and so on. The instance names of the Cleaner application are always the three letters after the word “Cleaner” in each item in the web_sites_list attribute. So the intent really in my original post was to simply search that list for the word “Cleaner”, then iterate through that subset creating BusinessApplicationInstance nodes for DEV,QAS,PRD, etc. Here’s my more-or-less actual code:

type := "Cleaner";
  
log.info("triggered Cleaner");
  
  
web_sis := search(SoftwareInstance 
  where type 
"Microsoft IIS Service" and web_sites_list has substring "Cleaner");
  
      
instances := [];
    for 
web_si in web_sis do
        
siteslist := web_si.web_sites_list;
        for 
site in siteslist do
            if 
site matches "(?i)Cleaner" then
             site_instance 
:= regex.extract(site,
                              
regex "(?<=Cleaner)(\w{3})"raw'\1');
            if 
not site_instance then 
                
continue;
            
end if;
                         if 
site_instance not in instances then
                 instances 
:= instances [site_instance];
             
end if;
                        
end if;
        
end for;
    
end for;
  
    if 
instances then
    
for instance in instances
        bai_name 
:= "&#xty;pe% &#xin;stance%";
        
model.BusinessApplicationInstance(name := bai_name,
                          
type := type
                          
... and so on); 

I don’t particularly like this method because web_sites_list can sometimes be dozens of items, and I perceive that looping through each one is inefficient. I guess this is the only way to go…?

Profile
 
 
Posted: 04 December 2008 03:43 PM   [ Ignore ]   [ # 4 ]  
Administrator
Avatar
RankRankRankRank
Total Posts:  130
Joined  2008-01-25

In this case the for loop is the way to go.

A couple of other thoughts. The IIS SI will have 2 attributes on, one is a concatenated string (web_sites) and one is a list (web_site_list). If you are wanting to trigger where any of the entries has the substring “Cleaner” I’d use the string (web_sites).

The other thing you need to remember is what happens if the list of hosted websites change. The pattern you are building also needs to remove the BAI that is no longer there. The usual technique here is
+ search for a list of connected BAIs at the start of the pattern
+ work out which BAIs still exist
+ call model.BAI on those that exist to confirm their existence
+ call model.destroy() on those that no longer exist to remove them from the model

Are you in the situation where there are a number of webservers providing this application in a load balanced/round robin/fail over approach? If there are then you are probably better building a second order SI to represent all the servers providing that website and modelling the BAI off that, the model will be more stable.

This was the approach I recommended over in this thread on the Nov 4th, and I’ve attached the two structure sketches below.

Image Attachments
teleflora_website.pngteleflora_website2.png
Profile