Forum Discussion

Robert_Reznicek's avatar
Robert_Reznicek
Icon for Nimbostratus rankNimbostratus
Apr 15, 2010

Assigning array to another array

Hello, is it somehow possible to fill one array (temporary) and then assign this whole array to another array? I would need to do something like this:


set tempArr(x1) "valueA"
set tempArr(x2) "valueB"
.
.
unset ::arr
set ::arr tempArr
unset tempArr
I need this, because there are thousands of entries in the array and filling the target array directly would take too much time. Or is there any other possibility how to solve this? Thank you

8 Replies

  • Hi Robert,

     

     

    Are you wanting to copy an array to another array? If so, something like this should work:

     

     

    Create a new array with keys 1 and 2

     

    % array set array1 {key1 val1 key2 val2}

     

     

    Dump the array contents

     

    % array get array1

     

    key1 val1 key2 val2

     

     

    Get the array size

     

    % array size array1

     

    2

     

     

    Create a new array with the contents of $array1

     

    % array set array2 [array get array1]

     

     

    Dump the array contents

     

    % array get array2

     

    key1 val1 key2 val2

     

     

    Aaron
  • Hi Aaron,

     

     

    this is exactly what I needed.

     

    I'm using this in a reverse proxy implementation, so in the array there are thousands of URLs. Our idea was, that editing this array (adding, removing, modifying hosts) must lead to delay in processing of new connections, in case we are not using a temporary array. Surprisingly, when I unset the array first and then fill it with new content (thousands of items), all the connections are processed correctly. Is it possible, that the connections are queued and processed when the array is fully loaded?
  • What are you doing with the URLs in the array? Are you using them for URI based persistence for web caches? If so, you might be better off using CARP like persistence:

     

     

    SOL11362: Overview of the CARP hash algorithm

     

    https://support.f5.com/kb/en-us/solutions/public/11000/300/sol11362.html

     

     

    If this doesn't work for your scenario, can you provide more background on it?

     

     

    Thanks, Aaron
  • I'm using these URLs for matching the correct backend servers. I took this ProxyPass iRule: http://devcentral.f5.com/Wiki/default.aspx/iRules/proxypass.html and rewrote it, so the connection is forwarded directly to backend server, rather then to assigned pool. I also modified matching of the correct server - I'm using array, rather then the external datagroup file (because of performance issues)

    the format of array is:

     
     key name                    item1               item2          
      external_url {internal_url internal_host_ip } 
     

    I'm using two iRules, one for filling of the array (it works together with bash script, which generates the data group) and the second which acts as the reverse proxy.

    When the data group is modified, i need to run an iRule, which creates array from items in the iRule. During this, the array needs to be cleared and then filled again. My concern is, that when this array is unset and before it is filled again (processing of too many items in the data group takes some time), there must be some delay in processing of new connections. But surprisingly, when performing tests, no connection ends with error, during the time, when the array is refilled.

    Robert

  • Okay, I understand a bit more on the scenario and your question:

     

     

     

    When I unset the array first and then fill it with new content (thousands of items), all the connections are processed correctly. Is it possible, that the connections are queued and processed when the array is fully loaded?

     

     

     

    Unfortunately, I don't know the answer. If TMM did queue the connections while loading the array, a watchdog process could potentially kill TMM if it doesn't respond to heartbeats. So I'm not sure this is an ideal option.

     

     

    Maybe Spark or someone else with more definitive knowledge could respond?

     

     

    On another note, are you seeing a significant decrease in performance when using the datagroup directly compared with the array? If so, how have you been testing this?

     

     

    Aaron
  • Thank you guys, this is exactly what I needed to know.

    I don't have any performance issues with reading of the entries from the external datagroup, but there is limitation with processing of the entries, so I'm forced to create loop, which is searching for best match. This is slowing down the whole process.

    The datagroup has this format:

     external_host1/path1 internal_host1 node_IP
    external_host1/path2/levelX internal_host2 node_IP
    external_host1/path3 internal_host3 node_IP
    

    I need to compare URL with all entries from this file (1st field) and to find best match. When using loop lsearch the performance is poor so we are using multidimensional array, where the first field acts as key name and the rest of the line as it's values. When using this method, the performance is much better:

                  ...
    set url_host [HTTP::host]
    set url_path [URI::path [HTTP::uri]]
                  ...
    set url $url_host$url_path
                  ...
    if {[info exists ::ppass($url)]} {
    log local0. "DEBUG: Found"
    set line $::ppass($url)
    } else { ...
     
  • What limitation did you run into with processing the datagroup entries? Are you trying to do an exact match on the first field of the datagroup? If so, you should be able to use findclass (or in 10.x the class command) to do this search against the datagroup and not use a loop or array.

     

     

    Aaron
  • Hi Aaron,

     

    the difference in performance between querying the datagroup directly (using findclass or lsearch) and querying the array is significant. Please see the results:

     

    - datagroup:

     

    +-> HTTP_REQUEST 64 total 0 fail 0 abort

     

    | | Cycles (min, avg, max) = (56620837, 121340405, 183729519)

     

     

    - array:

     

    +-> HTTP_RESPONSE 64 total 0 fail 0 abort

     

    | | Cycles (min, avg, max) = (62009, 87091, 474018)

     

     

    I suppose this is because findclass and lsearch must go trough all entries to find a match, but when using my method I'm asking for exact match - determining whether the entry exists:

     

    if {[info exists ::ppass($url)

     

     

    and assigning the value:

     

    set line $::ppass($url)

     

     

    Because I didn't find how to use the similar method to ask the datagroup directly, I'm using the array.

     

     

    Thank you,

     

    Robert