Connection pool corrupt in Oracle provider

G

Guest

We have come across what appears to be a problem with connection pooling in
the Oracle Provider for .NET, v1.1. I am using the latest 9i client and
hitting against various 9i servers running on Win2K.

When using connection pooling, if database connectivity is lost temporarily
(for example, restarting the service), any pool connections that error
during the interruption will never recover - Subsequent calls on the
connection result in the error, "ORA-03114: not connected to ORACLE". This
problem does not occur is pooling is disabled. Additionally, the problem
"eventually" corrects itself if a "Connection Lifetime" is specified for the
connection.

The issue was originally discovered in a service-based application that
would poll the database periodically. When the database was shutdown for
maintenance, the service would still attempt to connect. We found that if
pooling was enable, the service would not reconnect after the database was
brought back online. The following short block of code, executed in a
single process (the scope of the connection pool), will reproduce the issue.
Execute the block and everything works properly. Stop the Oracle service
and it will fail, as expected (the execute fails, not the open). However,
if the Oracle service is restarted, executing the block again will also
fail - and continue to fail. If connection lifetimes are specified, the
pool will eventually correct itself as the underlying connections are
terminated and replaced. My best guess is that, when a connection is
returned to the pool, the "error state" is being maintained by either the
underlying .NET classes or the OCI.

We are currently using the connection lifetime as a work around, but feel
that there is an issue with the connection pool that needs to be addressed.

try
{
using(OracleConnection connection = new OracleConnection("Data
Source=DBA9i;Pooling=true;Enlist=false;User Id=myid;Password=mypwd;Min Pool
Size=1;Max Pool Size=1"))
{
connection.Open();
try
{
using(OracleCommand command = connection.CreateCommand())
{
command.CommandText = "select * from mytable";
using (IDataReader reader = command.ExecuteReader())
{
// omitted
}
}
}
finally
{
connection.Close();
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
 
K

Kevin Yu [MSFT]

Hi,

I'm currently working on this issue, and will update you as soon as I get
any progress.

If anything is unclear, please feel free to reply to the post.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

--------------------
| From: <[email protected]>
| Subject: Connection pool corrupt in Oracle provider
| Date: Thu, 16 Oct 2003 15:53:43 -0400
| Lines: 60
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.framework.adonet
| NNTP-Posting-Host: ext-nat-lou.mercer.com 168.168.67.112
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.adonet:63800
| X-Tomcat-NG: microsoft.public.dotnet.framework.adonet
|
| We have come across what appears to be a problem with connection pooling
in
| the Oracle Provider for .NET, v1.1. I am using the latest 9i client and
| hitting against various 9i servers running on Win2K.
|
| When using connection pooling, if database connectivity is lost
temporarily
| (for example, restarting the service), any pool connections that error
| during the interruption will never recover - Subsequent calls on the
| connection result in the error, "ORA-03114: not connected to ORACLE".
This
| problem does not occur is pooling is disabled. Additionally, the problem
| "eventually" corrects itself if a "Connection Lifetime" is specified for
the
| connection.
|
| The issue was originally discovered in a service-based application that
| would poll the database periodically. When the database was shutdown for
| maintenance, the service would still attempt to connect. We found that if
| pooling was enable, the service would not reconnect after the database was
| brought back online. The following short block of code, executed in a
| single process (the scope of the connection pool), will reproduce the
issue.
| Execute the block and everything works properly. Stop the Oracle service
| and it will fail, as expected (the execute fails, not the open). However,
| if the Oracle service is restarted, executing the block again will also
| fail - and continue to fail. If connection lifetimes are specified, the
| pool will eventually correct itself as the underlying connections are
| terminated and replaced. My best guess is that, when a connection is
| returned to the pool, the "error state" is being maintained by either the
| underlying .NET classes or the OCI.
|
| We are currently using the connection lifetime as a work around, but feel
| that there is an issue with the connection pool that needs to be
addressed.
|
| try
| {
| using(OracleConnection connection = new OracleConnection("Data
| Source=DBA9i;Pooling=true;Enlist=false;User Id=myid;Password=mypwd;Min
Pool
| Size=1;Max Pool Size=1"))
| {
| connection.Open();
| try
| {
| using(OracleCommand command = connection.CreateCommand())
| {
| command.CommandText = "select * from mytable";
| using (IDataReader reader = command.ExecuteReader())
| {
| // omitted
| }
| }
| }
| finally
| {
| connection.Close();
| }
| }
| }
| catch(Exception ex)
| {
| MessageBox.Show(ex.Message);
| }
|
|
|
 
W

William \(Bill\) Vaughn

We're seeing this in the SqlClient as well. With the current round of .NET
Data providers, there's no built-in mechanism to "test" or poll existing
(dormant) connections. If they are made invalid by a server restart, these
dormant connections are all unusable. When the pooling mechanism tries to
reactivate one of the dormant connections, it (incorrectly IMO) simply
reports an exception back to the client. I think it should toss the bad
connection and build another and carry on.

hth

--
____________________________________
Bill Vaughn
MVP, hRD
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
 
A

Angel Saenz-Badillos[MS]

We have just signed off on the fix for this problem, you should be able to
contact PSS to get a fix for this in the next couple of days.

To be clear, the problem we have fixed is that we where not checking for all
possible Oracle exceptions that indicate that a connection is no longer
valid. When we received an error that was not in our expected list but that
still killed the connection we would fail to recognize it and the pool would
get corrupt. We are now checking for the following set of oracle exceptions,
if you are aware of any other exception that may kill the connection please
contact me asap. Thank you.

oracle exceptions checked
case 18: // max sessions exceeded
case 19: // max session licenses exceeded
case 24: // server is in single process mode
case 28: // session has been killed
case 436: // oracle isn't licensed
case 1012 //not logged on error
case 1033: // startup/shutdown in progress
case 1034: // oracle not available
case 1075: // currently logged on
case 3113: // end-of-file on communication channel
case 3114: // not connected to ORACLE
case 12154: // can't resolve service name
case 12xxx //any error starting with 12 thousand


--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.
 
A

Angel Saenz-Badillos[MS]

Bill,
I responded on the other threat, unfortunatelly the bug with the Oracle
provider was worse than this.

As far as this problem, we are still looking at the best way to handle it. I
believe that reopening a new connection and continue is not the best
solution, what about the state of the previous connection, existing
transactions that have been rolled back etc.
The best we can probably do is throw an exception and clean the pool, so
that the next time you open a connection we start with an empty pool and you
will succeed or fail depending on the actual server status.

Would this be a good solution? Any other suggestions?
Thanks
 
W

William \(Bill\) Vaughn

Well, there are two situations that I think are of concern.
1) Where the connection is "active" and the server goes down. In this
case, when a client tries to use the active connection, you should throw an
exception because the client (server-side) state is clearly not the same.
2) Where the connection is "dormant" and the server goes down. In this
case the pooler was going to reset the connection state anyway (in most
cases) and getting a "virgin" connection should not matter--so open a new
connection and continue as if nothing had happened. If the reset connection
flag was turned off, the client is pooched anyway so throw an exception.
That should teach them to try to manage server-side state on their own! ;)

hth


--
____________________________________
Bill Vaughn
MVP, hRD
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________

Angel Saenz-Badillos said:
Bill,
I responded on the other threat, unfortunatelly the bug with the Oracle
provider was worse than this.

As far as this problem, we are still looking at the best way to handle it. I
believe that reopening a new connection and continue is not the best
solution, what about the state of the previous connection, existing
transactions that have been rolled back etc.
The best we can probably do is throw an exception and clean the pool, so
that the next time you open a connection we start with an empty pool and you
will succeed or fail depending on the actual server status.

Would this be a good solution? Any other suggestions?
Thanks

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

William (Bill) Vaughn said:
We're seeing this in the SqlClient as well. With the current round of ..NET
Data providers, there's no built-in mechanism to "test" or poll existing
(dormant) connections. If they are made invalid by a server restart, these
dormant connections are all unusable. When the pooling mechanism tries to
reactivate one of the dormant connections, it (incorrectly IMO) simply
reports an exception back to the client. I think it should toss the bad
connection and build another and carry on.

hth

--
____________________________________
Bill Vaughn
MVP, hRD
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________

pooling
in for
the
that
 
H

Harry

How do I contact PSS to get this fix?


Angel Saenz-Badillos said:
We have just signed off on the fix for this problem, you should be able to
contact PSS to get a fix for this in the next couple of days.

To be clear, the problem we have fixed is that we where not checking for all
possible Oracle exceptions that indicate that a connection is no longer
valid. When we received an error that was not in our expected list but that
still killed the connection we would fail to recognize it and the pool would
get corrupt. We are now checking for the following set of oracle exceptions,
if you are aware of any other exception that may kill the connection please
contact me asap. Thank you.

oracle exceptions checked
case 18: // max sessions exceeded
case 19: // max session licenses exceeded
case 24: // server is in single process mode
case 28: // session has been killed
case 436: // oracle isn't licensed
case 1012 //not logged on error
case 1033: // startup/shutdown in progress
case 1034: // oracle not available
case 1075: // currently logged on
case 3113: // end-of-file on communication channel
case 3114: // not connected to ORACLE
case 12154: // can't resolve service name
case 12xxx //any error starting with 12 thousand


--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

Kevin Yu said:
Hi,

I'm currently working on this issue, and will update you as soon as I get
any progress.

If anything is unclear, please feel free to reply to the post.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

--------------------
| From: <[email protected]>
| Subject: Connection pool corrupt in Oracle provider
| Date: Thu, 16 Oct 2003 15:53:43 -0400
| Lines: 60
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.framework.adonet
| NNTP-Posting-Host: ext-nat-lou.mercer.com 168.168.67.112
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.adonet:63800
| X-Tomcat-NG: microsoft.public.dotnet.framework.adonet
|
| We have come across what appears to be a problem with connection pooling in
| the Oracle Provider for .NET, v1.1. I am using the latest 9i client and
| hitting against various 9i servers running on Win2K.
|
| When using connection pooling, if database connectivity is lost temporarily
| (for example, restarting the service), any pool connections that error
| during the interruption will never recover - Subsequent calls on the
| connection result in the error, "ORA-03114: not connected to ORACLE". This
| problem does not occur is pooling is disabled. Additionally, the problem
| "eventually" corrects itself if a "Connection Lifetime" is specified for the
| connection.
|
| The issue was originally discovered in a service-based application that
| would poll the database periodically. When the database was shutdown for
| maintenance, the service would still attempt to connect. We found that if
| pooling was enable, the service would not reconnect after the database was
| brought back online. The following short block of code, executed in a
| single process (the scope of the connection pool), will reproduce the issue.
| Execute the block and everything works properly. Stop the Oracle service
| and it will fail, as expected (the execute fails, not the open). However,
| if the Oracle service is restarted, executing the block again will also
| fail - and continue to fail. If connection lifetimes are specified, the
| pool will eventually correct itself as the underlying connections are
| terminated and replaced. My best guess is that, when a connection is
| returned to the pool, the "error state" is being maintained by either the
| underlying .NET classes or the OCI.
|
| We are currently using the connection lifetime as a work around, but feel
| that there is an issue with the connection pool that needs to be addressed.
|
| try
| {
| using(OracleConnection connection = new OracleConnection("Data
| Source=DBA9i;Pooling=true;Enlist=false;User Id=myid;Password=mypwd;Min Pool
| Size=1;Max Pool Size=1"))
| {
| connection.Open();
| try
| {
| using(OracleCommand command = connection.CreateCommand())
| {
| command.CommandText = "select * from mytable";
| using (IDataReader reader = command.ExecuteReader())
| {
| // omitted
| }
| }
| }
| finally
| {
| connection.Close();
| }
| }
| }
| catch(Exception ex)
| {
| MessageBox.Show(ex.Message);
| }
|
|
|
 
A

Angel Saenz-Badillos[MS]

Harry, I have to admit that I am not completelly sure of how it works. You
can start with the following link:
http://support.microsoft.com/common/international.aspx?rdpath=fh;en-us;cntactms

You should be able to find a PSS contact number, support calls for known
issues (QFE's) like the one we are discussing here are free. I believe the
KB for this issue is 829195.
Hope this helped

--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

Harry said:
How do I contact PSS to get this fix?


"Angel Saenz-Badillos[MS]" <[email protected]> wrote in message
We have just signed off on the fix for this problem, you should be able to
contact PSS to get a fix for this in the next couple of days.

To be clear, the problem we have fixed is that we where not checking for all
possible Oracle exceptions that indicate that a connection is no longer
valid. When we received an error that was not in our expected list but that
still killed the connection we would fail to recognize it and the pool would
get corrupt. We are now checking for the following set of oracle exceptions,
if you are aware of any other exception that may kill the connection please
contact me asap. Thank you.

oracle exceptions checked
case 18: // max sessions exceeded
case 19: // max session licenses exceeded
case 24: // server is in single process mode
case 28: // session has been killed
case 436: // oracle isn't licensed
case 1012 //not logged on error
case 1033: // startup/shutdown in progress
case 1034: // oracle not available
case 1075: // currently logged on
case 3113: // end-of-file on communication channel
case 3114: // not connected to ORACLE
case 12154: // can't resolve service name
case 12xxx //any error starting with 12 thousand


--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

Kevin Yu said:
Hi,

I'm currently working on this issue, and will update you as soon as I get
any progress.

If anything is unclear, please feel free to reply to the post.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

--------------------
| From: <[email protected]>
| Subject: Connection pool corrupt in Oracle provider
| Date: Thu, 16 Oct 2003 15:53:43 -0400
| Lines: 60
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.framework.adonet
| NNTP-Posting-Host: ext-nat-lou.mercer.com 168.168.67.112
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.adonet:63800
| X-Tomcat-NG: microsoft.public.dotnet.framework.adonet
|
| We have come across what appears to be a problem with connection
pooling
in
| the Oracle Provider for .NET, v1.1. I am using the latest 9i client and
| hitting against various 9i servers running on Win2K.
|
| When using connection pooling, if database connectivity is lost temporarily
| (for example, restarting the service), any pool connections that error
| during the interruption will never recover - Subsequent calls on the
| connection result in the error, "ORA-03114: not connected to
ORACLE".
This
| problem does not occur is pooling is disabled. Additionally, the problem
| "eventually" corrects itself if a "Connection Lifetime" is specified
for
the
| connection.
|
| The issue was originally discovered in a service-based application that
| would poll the database periodically. When the database was
shutdown
for
| maintenance, the service would still attempt to connect. We found
that
if
| pooling was enable, the service would not reconnect after the
database
was
| brought back online. The following short block of code, executed in a
| single process (the scope of the connection pool), will reproduce
the
issue.
| Execute the block and everything works properly. Stop the Oracle service
| and it will fail, as expected (the execute fails, not the open). However,
| if the Oracle service is restarted, executing the block again will also
| fail - and continue to fail. If connection lifetimes are specified, the
| pool will eventually correct itself as the underlying connections are
| terminated and replaced. My best guess is that, when a connection is
| returned to the pool, the "error state" is being maintained by
either
the
| underlying .NET classes or the OCI.
|
| We are currently using the connection lifetime as a work around, but feel
| that there is an issue with the connection pool that needs to be addressed.
|
| try
| {
| using(OracleConnection connection = new OracleConnection("Data
| Source=DBA9i;Pooling=true;Enlist=false;User
Id=myid;Password=mypwd;Min
Pool
| Size=1;Max Pool Size=1"))
| {
| connection.Open();
| try
| {
| using(OracleCommand command = connection.CreateCommand())
| {
| command.CommandText = "select * from mytable";
| using (IDataReader reader = command.ExecuteReader())
| {
| // omitted
| }
| }
| }
| finally
| {
| connection.Close();
| }
| }
| }
| catch(Exception ex)
| {
| MessageBox.Show(ex.Message);
| }
|
|
|
 
F

Frans Bouma

Harry, I have to admit that I am not completelly sure of how it works.
You can start with the following link:
http://support.microsoft.com/common/international.aspx?rdpath=fh;en-us;cn
tactms

You should be able to find a PSS contact number, support calls for known
issues (QFE's) like the one we are discussing here are free. I believe
the KB for this issue is 829195.
Hope this helped

Can you answer a question for me, please?
Why is it that this important fix (I find pool corruption a serious
problem) is not distributed publicly, but only available when you call PSS?
Or do we have to wait till Whidbey ships before we get this fix?

Thanks.

FB
 
A

Angel Saenz-Badillos[MS]

The answer of course is that we are trying to do the right thing.
If you have any specific concerns regarding calling PSS for a fix versus
downloading them from a web site I would be happy to pass them on.

As far as when these fixes will be widely distributed, every QFE that we
ship is considered for the next available service pack. Some QFEs can't be
included in a service pack, they may contain breaking changes that only make
sense for the customer that originally requested the QFE for example.
 
S

Scott Sosna

The original problem was reported with .NET 1.1. I am seeing the same
problem with the Oracle Data Provider 1.0 (the 10/18/2002 version with
various bug fixes), will the fix include this one?

Angel Saenz-Badillos said:
The answer of course is that we are trying to do the right thing.
If you have any specific concerns regarding calling PSS for a fix versus
downloading them from a web site I would be happy to pass them on.

As far as when these fixes will be widely distributed, every QFE that we
ship is considered for the next available service pack. Some QFEs can't be
included in a service pack, they may contain breaking changes that only make
sense for the customer that originally requested the QFE for example.
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

Frans Bouma said:
Can you answer a question for me, please?
Why is it that this important fix (I find pool corruption a serious
problem) is not distributed publicly, but only available when you call PSS?
Or do we have to wait till Whidbey ships before we get this fix?

Thanks.

FB
 
A

Angel Saenz-Badillos

Scott,
There is currently not going to be a patch for the 1.0 version of this
provider, unless a customer requests it as a QFE via PSS.

There are a number of important fixes in the 1.1 provider and added
functionality that we believe make for a very compelling upgrade
story, are there any particular reasons why you would like to continue
using the 1.0 provider?

Thanks
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.
Please do not send email directly to this alias. This alias is for
newsgroup
purposes only.

The original problem was reported with .NET 1.1. I am seeing the same
problem with the Oracle Data Provider 1.0 (the 10/18/2002 version with
various bug fixes), will the fix include this one?

Angel Saenz-Badillos said:
The answer of course is that we are trying to do the right thing.
If you have any specific concerns regarding calling PSS for a fix versus
downloading them from a web site I would be happy to pass them on.

As far as when these fixes will be widely distributed, every QFE that we
ship is considered for the next available service pack. Some QFEs can't be
included in a service pack, they may contain breaking changes that only make
sense for the customer that originally requested the QFE for example.
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.

Frans Bouma said:
Harry, I have to admit that I am not completelly sure of how it works.
You can start with the following link:
http://support.microsoft.com/common/international.aspx?rdpath=fh;en-us;cn
tactms

You should be able to find a PSS contact number, support calls for known
issues (QFE's) like the one we are discussing here are free. I believe
the KB for this issue is 829195.
Hope this helped

Can you answer a question for me, please?
Why is it that this important fix (I find pool corruption a serious
problem) is not distributed publicly, but only available when you call PSS?
Or do we have to wait till Whidbey ships before we get this fix?

Thanks.

FB
 
S

Scott Sosna

The reason we want to keep using the 1.0 provider is that we have not
moved to .NET 1.1 yet and there are no immediate plans to do so.
Thanks for your response.
-scs

Scott,
There is currently not going to be a patch for the 1.0 version of this
provider, unless a customer requests it as a QFE via PSS.

There are a number of important fixes in the 1.1 provider and added
functionality that we believe make for a very compelling upgrade
story, are there any particular reasons why you would like to continue
using the 1.0 provider?

Thanks
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no
rights.
Please do not send email directly to this alias. This alias is for
newsgroup
purposes only.

The original problem was reported with .NET 1.1. I am seeing the same
problem with the Oracle Data Provider 1.0 (the 10/18/2002 version with
various bug fixes), will the fix include this one?

Angel Saenz-Badillos said:
The answer of course is that we are trying to do the right thing.
If you have any specific concerns regarding calling PSS for a fix versus
downloading them from a web site I would be happy to pass them on.

As far as when these fixes will be widely distributed, every QFE that we
ship is considered for the next available service pack. Some QFEs can't be
included in a service pack, they may contain breaking changes that only make
sense for the customer that originally requested the QFE for example.
--
Angel Saenz-Badillos [MS] Managed Providers
This posting is provided "AS IS", with no warranties, and confers no rights.
Please do not send email directly to this alias. This alias is for newsgroup
purposes only.


Harry, I have to admit that I am not completelly sure of how it works.
You can start with the following link:
http://support.microsoft.com/common/international.aspx?rdpath=fh;en-us;cn
tactms

You should be able to find a PSS contact number, support calls for known
issues (QFE's) like the one we are discussing here are free. I believe
the KB for this issue is 829195.
Hope this helped

Can you answer a question for me, please?
Why is it that this important fix (I find pool corruption a serious
problem) is not distributed publicly, but only available when you call PSS?
Or do we have to wait till Whidbey ships before we get this fix?

Thanks.

FB
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top