Safe OCCI createStatelessConnectionPool usage
I've been working a bit with Oracle's OCCI (the C++ API for Oracle Database), and stateless connection pools in particular.
I've noticed a particular behaviour that's important to be aware of when creating the connection pool (using the oracle::occi::Environment method "createStatelessConnectionPool"). The problem is that this call will fail if you have some kind of conenction or TNS error, leaving you with an unusable and invalid pool.
To give a concrete example, if you create a connection pool like this:
scPool = env->createStatelessConnectionPool(...
what I find is that if the database is down (for example), this call with throw a TNS error like ORA-12541: TNS:no listener, and the scPool object is invalid (but not a null reference).
if you attempt to use the pool thereafter, e.g.:
if (scPool) cout << "MaxConn=" << scPool->getMaxConnections() << endl;
then firstly "if (scPool) .." wont protect you (because its not null), and the getMaxConnections method call will throw an uncatchable segmentation fault (this is Linux x86 I'm using)
The workaround of course is to null your scPool if you catch the TNS error, and then if you want a robust application that must keep running even if the connection pool is not created, everytime you try and get a connection from the pool you should also first check to see if you have a pool object to use (and if not, try and create it again).
Tortuous to say the least!
I would have expected that the desired behaviour should be for createStatelessConnectionPool to return a valid connection pool even if connections are not possible at that point in time, and that for the TNS errors to be only thrown if and when you try and get a connection from the pool.
Anyone have a view? ... bug, ER or expected?
12-Feb, an update: I've since discovered that this behaviour is true only if you set a "minumum connections" >0 for the pool. If you set "minumum connections"==0, then the behaviour is as I would expect - the pool is created without error, but you may hit an error when attempting to get a connection from the pool.
read more and comment..
Handling range parameters in Bash
I've come across a few occasions where I wanted to specify a "range parameter" for Bash scripts. Like "1..4" meaning do for 1,2,3 and 4.
Here's a simple trick that uses the (relatively obscure) variable expansion and substring replacement capabilities of the shell.
#!/bin/bash
v_range="1..3" # or you could have taken it as a script parameter
v_start=${v_range%%.*} # chomp everything from the left-most matching "."
v_end=${v_range##*.} # chomp everything up to the right-most matching "."
The repeated %% and ## basically mean you will get a "greedy" match, so you can say "1..4" or "1....5"; it doesn't matter how many repeats you have of the range delimiter. Of course, you can choose other delimiters such as a hyphen, as in "5-10", if you wish.
Now that you have extracted the start and end indices, you can then loop or whatever to your hearts content:
for ((a=v_start; a <= v_end ; a++))
do
echo "Looping with a=$a"
done
For more information on variable expansion, see 9.3 in the Advanced Bash Scripting Guide.
Postscript 5-Feb-2008:
We live and learn! Hat tip to buford for alerting me to the seq utility, which simplifies the iteration over a range, as in:
for a in `seq 1 10`
do
echo "Looping with a=$a"
done
You still need to determine the start and end values of the range, which is the whole point of the variable expansions approach posted here.
read more and comment..
Generating a temp filename in Bash
Here's a function that simplifies the process of generating temporary filenames in shell scripts (I use bash). This function will generate a temporary filename given optional path and filename prefix parameters. If the file happens to already exist (a small chance), it recurses to try a new filename.
It doesn't cleanup temp files or anything fancy like that, but it does have the behaviour that if you never write to the temp file, it is not created. If you don't like that idea, touch the file before returning the name.
This procedure demonstrates the use of variable expansion modifiers to parse the parameters, and the $RANDOM builtin variable.
By default (with no parameters specified), this function will return a random filename in the /tmp directory:function gettmpfile()
{
local tmppath=${1:-/tmp}
local tmpfile=$2${2:+-}
tmpfile=$tmppath/$tmpfile$RANDOM$RANDOM.tmp
if [ -e $tmpfile ]
then
# if file already exists, recurse and try again
tmpfile=$(gettmpfile $1 $2)
fi
echo $tmpfile
}
[prompt]$ echo $(gettmpfile)
/tmp/324003570.tmp
If you specify a path and filename prefix, these are used to generate the name:
[prompt]$ echo $(gettmpfile /my_tmp_path app-tmpfile)
/my_tmp_path/app-tmpfile-276051579.tmp
read more and comment..
Why we love Tom
I just picked up my copy of Effective Oracle by Design to check some facts. It just took a few moments for it to remind me how much I enjoy and learn from Tom Kyte's work.
Why do we love Tom? I have a theory on this! It comes down to two factors:
- Substance. In an industry overwhelmed by candyfloss powerpoints, its refreshing to read someone who lives in the details, yet manages to retain sparkling clarity. It's apple pie for the technically oriented: database administrators, developers, and perhaps even a few architects(!).
- Uncompromising rigour. Never one to let an assumption go unchallenged or untested. If there was an IT version of MythBusters, he would be your Jamie to Dvorak's Adam (or vice versa if you like). Highly opinionated, his opinions are (annoyingly) based on hard facts. Sometimes you just want to jump on the keyboard and hack away to try and prove him wrong ... But that's good! He's got you thinking.
read more and comment..