Forum Discussion

hooleylist's avatar
hooleylist
Icon for Cirrostratus rankCirrostratus
Jun 29, 2010

Unexpected result from foreach loop on 10.2

While testing a simple iRule to print out the contents of an array, I found a weird result when using "foreach {name value} [array get myarray]" on 10.2.0. The unexpected output is bolded below for the 10.2.0 test output. Basically, it looks like the varlist assignment isn't happening correcting when using more than one variable. I tried testing in RULE_INIT and CLIENT_ACCEPTED to see if the issue involved global variables, but saw the bad result in both tests.

Does anyone have a suggestion for what might be causing this? I'll open a case but figured I'd check here as well.

Thanks, Aaron

I tested with an example from the TCL wiki page for arrays:


 From http://www.tcl.tk/man/tcl8.4/TclCmd/array.htmM8
array set colorcount {
    red   1
    green 5
    blue  4
    white 9
}
foreach {color count} [array get colorcount] {
   puts "Color: $color Count: $count" 
}
 => Color: blue Count: 4
    Color: white Count: 9
    Color: green Count: 5
    Color: red Count: 1
foreach color [array names colorcount] {
   puts "Color: $color Count: $colorcount($color)" 
}
 => Color: blue Count: 4
    Color: white Count: 9
    Color: green Count: 5
    Color: red Count: 1

Testing this on tclsh.exe and 9.4.4 return expected results as listed below. However, on 10.2.0, "foreach {color count} [array get colorcount]" returns unexpected results for $color and $count.


when RULE_INIT {
   
   array set colorcount {
      red    1
      green    5
      blue    4
      white    9
   }
   log local0. "\[array size colorcount\]: [array size colorcount]"
   log local0. "\[array get colorcount\]: [array get colorcount]"
   log local0. ""
   log local0. "foreach {color count} \[array get colorcount\]:"
   foreach {color count} [array get colorcount] {
      log local0. "Color: $color Count: $count"
   }
   log local0. ""
   log local0. "foreach color \[array names colorcount\]:"
   foreach color [array names colorcount] {
      log local0. "Color: $color Count: $colorcount($color)" 
   }
}

Output on 10.2.0:

< RULE_INIT >: [array size colorcount]: 4

< RULE_INIT >: [array get colorcount]: blue 4 white 9 green 5 red 1

< RULE_INIT >:

< RULE_INIT >: foreach {color count} [array get colorcount]:

 

< RULE_INIT >: Color: blue Count: blue

 

< RULE_INIT >: Color: 4 Count: 4

 

< RULE_INIT >: Color: white Count: white

 

< RULE_INIT >: Color: 9 Count: 9

< RULE_INIT >:

< RULE_INIT >: foreach color [array names colorcount]:

< RULE_INIT >: Color: blue Count: 4

< RULE_INIT >: Color: white Count: 9

< RULE_INIT >: Color: green Count: 5

< RULE_INIT >: Color: red Count: 1

Output on 9.4.4:

Rule : [array size colorcount]: 4

Rule : [array get colorcount]: blue 4 white 9 green 5 red 1

Rule :

Rule : foreach {color count} [array get colorcount]:

Rule : Color: blue Count: 4

Rule : Color: white Count: 9

Rule : Color: green Count: 5

Rule : Color: red Count: 1

Rule :

Rule : foreach color [array names colorcount]:

Rule : Color: blue Count: 4

Rule : Color: white Count: 9

Rule : Color: green Count: 5

Rule : Color: red Count: 1

Output from Cygwin tclsh.exe:

% array set colorcount {

red 1

green 5

blue 4

white 9

}

% array size colorcount

4

% foreach {color count} [array get colorcount] {

puts "Color: $color Count: $count"

}

Color: blue Count: 4

Color: white Count: 9

Color: green Count: 5

Color: red Count: 1

% foreach color [array names colorcount] {

puts "Color: $color Count: $colorcount($color)"

}

Color: blue Count: 4

Color: white Count: 9

Color: green Count: 5

Color: red Count: 1

The iRule is the exact same on 9.4.4 and 10.2.0:

[hooleya@ltm.9.4.4:Active] log b version|grep Version

BIG-IP Version 9.4.4 94.0

[hooleya@ltm.9.4.4:Active] log b rule hooleya_array_rule list|md5sum

4cda0e55694c49036ac7274a6ec3763f -

[hooleya@ltm.10.2.0:Active] log b version|grep Version

BIG-IP Version 10.2.0 1707.0

[hooleya@ltm.10.2.0:Active] log b rule hooleya_array_rule list|md5sum

4cda0e55694c49036ac7274a6ec3763f -

  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    This is CR140814, affecting 10.1 and 10.2. I do not believe that it is currently fixed in any hotfix.
  • This explains why my code broke and was reporting just as you say.

     

    i changed the references to the second form (requiring another line of code) and it now works.

     

    almost... so i have a side question...

     

     

    for V10 CMP the $:: syntax is supposed to be eliminated, correct?

     

    i can't figure out what the replacement syntax is to make this work. if i just remove the $ it doesn't provide the value of the array element.... code:

     

     

    earlier the array "active_clients" was defined:

     

    when RULE_INIT {

     

    array set ::active_clients { }

     

    }

     

     

    then the routine to display the contents of this array is:

     

     

    foreach key [array names ::active_clients] {

     

    set value $::active_clients($key)

     

    append rpt "$key$value\n"

     

    }

     

     

    how do i do this in the "CMP compatible" form?

     

    thanks so much.
  • use the static namespace. Nat has a good example here: http://devcentral.f5.com/weblogs/jason/archive/2009/05/20/optimize-this-contest-1.aspx Click Here
  • Hi Brad,

     

     

    Your post became corrupted. Can you repost the iRule in [ code ] [/ code ] blocks?

     

     

    Also, the static namespace wouldn't allow you to modify the values after the RULE_INIT event and have those changes sync'ed across multiple TMM instances. If you need to use a globally available array, you can still use $::my_array--it just won't be CMP compatible. You could use the table commands instead for similar functionality that is CMP compatible:

     

     

    http://devcentral.f5.com/wiki/default.aspx/iRules/table

     

     

    Aaron