/**
* Inqwell Unique Functions
*
* Generate Unique Ids.
*
* Private & Confidential Copyright © Inqwell Ltd 2004.
* All rights reserved.
*/
package inq.util;
/**
* Generate a new Unique Id for the set given by Name. If the
* specified set does not exist and onDemand
* is true the set will be created with the
* given initValue.
*
* @param Name The set of ids from which the new value
* will be generated.
* @param onDemand If truecreates a set if one
* by the given Name
* does not currently exist. Throws otherwise.
* @param initValue Initial value for sequence if it does not
* currently exist. Defaults to 1
* @param localTxn If true then new Id will be allocated within a
* local transaction. If false then allocation happens in the caller's
* transaction. localTxn=true is the default and is
* preferred if the caller's transaction is long-lived. If the
* caller's transaction is short-lived then using false
* offers the benefit of the id not actually being allocated if the
* transaction fails.
*
* @throws If the set does not exist and onDemand is false;
* if Name is null.
*/
function getUniqueId(string Name,
boolean onDemand = true,
int initValue = 1,
boolean localTxn = true)
{
if (length(Name) == 0 || isnull(Name))
throw("Unique ID Name cannot be null or zero length");
if (localTxn)
{
transaction
{
any ret = call allocateId(Name, onDemand, initValue);
}
}
else
any ret = call allocateId(Name, onDemand, initValue);
ret;
}
local function allocateId(string Name, boolean onDemand, int initValue)
{
// Lock the code block. We do this because we don't want
// one process to incur an exception because of unique key
// violation if there is a collision creating a Name.
lock("__unique" + Name);
// Unless otherwise specified the read() function uses the unique key.
// The key value is "." meaning the stack. The stack contains the Name
// argument and therefore satisfies the field requirements for a
// unique key value.
if (read(Unique, .))
{
// The return value
++Unique.Value;
}
else
{
if (!onDemand)
throw("Unique Id requested for non-existent set " + Name);
any Unique = new(Unique);
Unique.Name = Name;
// We must assign the value before we create the object in the
// transaction, since subsequent mutations are ignored.
// There is a (small) window in which two processes could create
// the same new sequence. However, we have an explicit lock
// protecting this transaction, so everything's OK!
int ret = Unique.Value = initValue;
create(Unique);
// The return value
Unique.Value;
}
}