Thursday, December 8, 2016

Incremental Naming

I had a discussion yesterday about incremental naming.  A discussion that started after my post about reservations and verifications.
My colleague stated that reservations are not needed for the incremental naming to work and that rather the verification had a bigger role in it.

It ended up in a debate where both have a point.  So how does incremental naming work ?

Incremental naming

What is incremental naming

That's pretty simple :

You create a name that contains a number and we want to increments that number, something like :
  • myvolume001
  • myvolume002
  • myvolume003 
Now, that number does not necessarily need to be on the end, although that's the most obvious one, if you ask me.  You could still create something like :
  • myvolume001_production
  • myvolume002_production
  • myvolume003_production
However, as you notice, the assumption would then be that you are adding a fixed suffix to it.

Only on object string fields

If you are about to fill in a field that is bound to an object, let's say the "name" field of the command "create volume".  You might notice the ellipsis-button (3 dots) on the field.


I you click on that button, you will enter the "incremental naming" window.

This window explains the entire working of the incremental naming : RTFM : "The incremental naming wizard is based on a search for an existing volume"

Step 1 : The search

You search for an existing volume.  Now how you search is really important.  We want an incremental number in the end, so that's what we need to look for.
Let's assume we want a naming conventions like "myvolume###" where the ### stands for 3 numbers.   
This means we need to search for this specific format.  Now, when it comes to "create volume" and this specific naming convention, it's your lucky day, as for volumes, there is an existing filter called "filter volumes with a numeric suffix", and the numeric suffix in the filter just happens to be a 3 digit number.
Let's have a look a this filter :
SELECT

    volume.name,
    vserver.name AS 'vserver.name',
    cluster.primary_address AS 'vserver.cluster.primary_address'

FROM

    cm_storage.volume,
    cm_storage.vserver,
    cm_storage.cluster

WHERE

    vserver.id = volume.vserver_id
    AND cluster.id = vserver.cluster_id
    AND volume.name REGEXP '^${vol_name}[0-9][0-9][0-9]$'
    AND vserver.name = '${vserver_name}'
    AND (

        cluster.name = '${cluster_name}'
        OR cluster.primary_address = '${cluster_name}'

    )

ORDER BY
    volume.name DESC
As you can see, it's just a regular volume search, but it's adding one more query
volume.name REGEXP '^${vol_name}[0-9][0-9][0-9]$'

The REGEXP operator is a perfect fit for our goal.  It allows us to filter based on a regular expression.  Now if you are not familiar with regular expressions, you are missing out !  Once you get the hang of regular expressions, the possibilities on endless.  Personally I always use http://www.regexr.com to test my regular expressions.  Now let's analyze this regex. (feel free to use the regexr.com site to analyze if for you)
^${vol_name}[0-9][0-9][0-9]$

Let's first handle the ${vol_name}, this is our variable, in our case it would have been replaced by 'myvolume'.  So our actual regex would be :
^myvolume[0-9][0-9][0-9]$

it starts with a '^' : this means "begin of string", so it checks that there is nothing before it. it ends with a '$' : this means "end of string", so it checks that there is nothing after it. Why is this needed ?  Well, regular expressions are flexible.  for example :
^top$ => would exactly match "top" and nothing else, while if we drop the '^' top$ => would also match "stop" or "laptop", and if we drop the '$', now we would have top => this would match every word with "top" in it, whether in the beginning, the middle or the end.
this leaves us with the square brackets [0-9].  When you put something between square brackets, it's an "OR" operator.  For example 
[abc] => this will match an "a", "b" or "c".  But only one of it.  
st[aeiou]p => this wil match stap, step, stip, stop and stup.
Now to make our lives easier, the regex dev-team built in sequences like [0-9], this is the same as [0123456789].  Same is for [a-z] or [A-Z] and you can combine them like [a-zA-Z].
So our final analysis is that ^myvolume[0-9][0-9][0-9]$ will match the word "myvolume" with 3 numeric digits at the end.  Do you want only 2 digits ?  Well, just clone the filter and change it to your needs.  ^${vol_name}[0-9][0-9]$ would be only 2 digits, but I assume you already figured that one out on your own.
One last remark, notice that the filter is ordering "name DESC", it is ordering the results descending, and this is alphabetically, but that sufficient for us.  The filter will take the highest on top, that's the one we want, as we want to increment the number of the latest/highest.

Step 2 : what if no result was found

If no result was found, you will need to set the starting value.  That's the next step.  If no volume is found, we set the default value, in our example we set it to "myvolume001".

Step 3 : increment

Now, assuming a result wás found, then this function will pick the first item of the result (the highest remember), find the number at the end of the string, increment it (default is by 1, but you can change that, see screenshot) and return that as the new name.
Optionally you can say that your naming convention has a fixed suffix (like the '_production' in my previous example).  Then the incrementing will happen as follows : It will remove the suffix first, find the number at the end, increment the number and then re-add the suffix.

Reservations

So that was simple right. So what was all the fuss about this discussion and whether reservations have a part in it or not.

Well, here is the deal :
For your first increment (let's say, myvolume003 existed in the database), there will not be a problem.  The search will return the highest (myvolume003), the increment will happen (myvolume004), everybody happy.
Now, if your command supports reservations (see a previous post in this blog), like our example 'create volume', then WFA will add your newly created volume to the database cache (kind of... see previous post), and the next time (for example in the same workflow), another increment has to happen (example : you want to create 10 volumes), the search will return your newly created volume on top (myvolume004) and the increment can happen again (005), and again and again.
But, if your command does NOT support reservations (maybe a custom command), then your newly created 'something' will not be added to the database cache, this means your command will keep incrementing from the first one that was found in the database.  The first increment will work, but all subsequent increments not. Of course if you wait a while and your datasource picks up the changes, you can increment again.
So the discussion was : 
  • yes, the first increment will always work, if that fits your needs, fine.
  • the second increment will only work if your command handles reservations.
So looping (repeat rows) to create multiple object with incremental naming will only work if your create-command support reservations (most built-in commands do, by the way).

Verifications

One final word on verifications.  Verifications are used to check if a reservation has been discovered by a datasource, and marking this as complete.

But, verification are also used to detect collisions.  Assume you want to create a volume that already exists.  During the planning phase (before anything was executed), the verification SQL code in the command 'create volume' will detect that the volume already exists and will throw an exception.

Conclusion

If you ever create your own commands, make sure you implement reservations & verifications.

No comments :

Post a Comment