With version 10.1, we've given the session table some long-sought functionality, and revamped its iRules interface completely to give users a new, cleaner, full-featured way to keep track of global data. We are very proud to introduce the table command...

  1. Basics
  2. New Ways To Set Data
  3. New Ways To Alter Data
  4. Data Expiration
  5. Advanced Data Expiration
  6. Subtables
  7. Counting
  8. The Fine Print
  9. Examples

In this second part of the series on the usage of the new table command, we discuss ways to assign data to the session table.

New Ways To Set Data

The session add command will always set a value associated with a key, overwriting anything that was there before it. If you are keeping track of the last URI that a user visited, for example, then this isn't a problem: the new URI value in the table overwrites the old one. But if you were trying to roll your own type of persistence, then this behavior is less good. (In reality, you should use the persist command for this sort of thing, as it's designed to handle situations like this. I'm just using persistence as a concrete example.) You might try to write an iRule that looks something like:

set newpmbr [session lookup uie $key]
if { $newpmbr == {} } {
    session add uie $key $curpmbr
} else {
    pool [LB::server pool] member $newpmbr

Makes sense: use an existing entry if there is one, or add one if not. But what happens if two connections come in at very close to the same time? The first one will do a lookup, see that there's no entry in the table, and start to add an entry. But since there are now multiple processors working at the same time, the second connection could do its lookup after the first connection did its lookup, but before the first connection added an entry. If that happens, both connections will act as if they are the first, and they could go to different servers! Oops!

To address problems like that, we've added two other ways to add data to the session table:

table set $key $data
table add $key $data
table replace $key $data
  • table set acts just like session add does: if the key doesn't already exist in the table, it adds the entry, and if it does exist, it overwrites what's there.
  • table add won't overwrite an existing entry, it will only add an entry if the key doesn't already exist.
  • table replace is the opposite: it will only update an existing entry. If the key doesn't already exist in the session table, it does not add a new entry.

If you've seen memcache, then this syntax will seem very familiar to you. But if you haven't, and you don't want to have three different commands in your iRules that all set data, you can instead supply flags to the table set command that provide the exact same behavior.

  • table set -excl is equivalent to table add.
  • table set -mustexist is equivalent to table replace.

Some users might prefer one way over the other, and using the flags might be more obvious to a newcomer over the more subtle set/add/replace distinction. But they really are just synonyms.

Also, even though it's not shown right here, all of these commands take an optional timeout, as well as many other parameters. The examples of table command syntax in this series won't give a complete command set, so we can focus on just one feature at a time, and won't strictly follow the usual syntax conventions.  A complete syntax reference can be found in the iRules Wiki.

With these commands, we can now rewrite the above example in a way that will actually work:

set newpmbr [table add $key $curpmbr]
if { $newpmbr != $curpmbr } {
    pool [LB::server pool] member $newpmbr

(Note that this isn’t a complete example of persistence, because things like timeout handling and persistence for different pools aren’t covered.)

Because table add will never overwrite an existing entry, it doesn't matter how many connections happen at the same time. The first one will always win and write its pool member to the session table entry, and all the other connections will get that pool member as a result of the table add command.  Note that no matter if the table add command wrote the entry or not, it returns the value of the entry, so all connections accessing this session table entry will get the same result, no matter which one was first

Continue reading part three in the series: New Ways To Alter Data