Quantcast
Channel: Visual C forum
Viewing all articles
Browse latest Browse all 15302

ATL OLEDB Cosumer Templates - caching of CDataSource and CSession

$
0
0

Hi,

I have a native service on Azure and I'm using ATL for the DB connection.

I have created a connection manager which basically creates and caches a DB connection for each thread (every connection is kept for a specific amount of time before it is recycled).

I was wondering whether this is a good approach or if I should be caching CSession objects instead.

Here is part of my code, any comments welcome:

struct ThreadSessionInfo
{
	CDataSource _data_source;
	chrono::system_clock::time_point _creation_time;
	std::thread::id _thread_id;
	AutoCOMInit<COINIT_APARTMENTTHREADED> _com_init_token;
};

///
/// \brief Returns a DB session for the current execution thread
///
CSession ConnectionManager::GetDBSession()
{
	CDataSource ds;

	{
		unique_lock<mutex> lock(_connections_map_mtx);
		// Use the existing datasource for this thread if the refresh threshold hasn't been breached
		auto match = _connections_map.find(this_thread::get_id());
		if (match != end(_connections_map))
		{
			auto elapsed_period = chrono::system_clock::now() - match->second._creation_time;
			auto mins = chrono::duration_cast<chrono::minutes>(elapsed_period);

			if (mins.count() <= REFRESH_THRESHOLD_MINS)
			{
				ds = match->second._data_source;
			}
			else
			{
				// Remove the old ThreadSessionInfo obj so that CoUninitialize is called before
				// CoInitializeEx is called by the new ThreadSessionInfo obj
				_connections_map.erase(this_thread::get_id());
			}
		}
	}

	// Otherwise initialize a new datasource in for the thread
	// COM is initialized for the thread as well
	if (!ds.m_spInit)
	{
		// CoInitializeEx is called here
		ThreadSessionInfo tsi;

		HRESULT hr = E_FAIL;

		for (int i = 0; i < DB_CONN_RETRY_ITERATIONS, !SUCCEEDED(hr); ++i)
		{
			// Try SQL Native Client 11 (Azure Server) first
			hr = tsi._data_source.OpenFromInitializationString(GetConnectionString(L"SQLNCLI11.1").c_str());

			// Fall back to SQL Native Client 10 - Azure Server if required
			if (hr == REGDB_E_CLASSNOTREG)
				hr = tsi._data_source.OpenFromInitializationString(GetConnectionString(L"SQLNCLI10.1").c_str());

			if (FAILED(hr))
				this_thread::sleep_for(chrono::milliseconds(50));
		}

		ATLENSURE_SUCCEEDED(hr);

		tsi._creation_time = chrono::system_clock::now();
		tsi._thread_id = this_thread::get_id();

		{
			unique_lock<mutex> lock(_connections_map_mtx);
			_connections_map[tsi._thread_id] = tsi;
		}

		ds = tsi._data_source;
	}

	CSession ret;
	ATLENSURE_SUCCEEDED(ret.Open(ds));
	return ret;

}

Thanks in advance,

Yiannis


Viewing all articles
Browse latest Browse all 15302

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>