//------------------------------------------------------- void OdbcPersistor::Remove(const Safir::Dob::Typesystem::EntityId& entityId) { m_debug << "Deleting " << entityId <<std::endl; int retries = 0; bool errorReported = false; bool paramSet = false; bool done = false; while (!done) { try { ConnectIfNeeded(m_odbcConnection, m_isOdbcConnected, retries); if (!m_deleteIsValid) { m_helper.AllocStatement(&m_deleteStatement, m_odbcConnection); m_helper.Prepare(m_deleteStatement, "DELETE FROM PersistentEntity WHERE typeId=? AND instance=?"); m_helper.BindParamInt64(m_deleteStatement, 1, &m_type); m_helper.BindParamInt64(m_deleteStatement, 2, &m_instance); SetStmtTimeout(m_deleteStatement); m_deleteIsValid = true; paramSet = false; } if (!paramSet) { m_type = entityId.GetTypeId(); m_instance = entityId.GetInstanceId().GetRawValue(); paramSet = true; } m_helper.Execute(m_deleteStatement); done = true; if (errorReported) { Safir::Logging::SendSystemLog(Safir::Logging::Informational, L"Successfully connected to the database"); errorReported = false; retries = 0; } } catch(const OdbcException& e) { const std::wstring err = Safir::Dob::Typesystem::Utilities::ToWstring(e.what()); m_debug << "Caught a ReconnectException in Delete:\n" << err << std::endl; if (retries > REPORT_AFTER_RECONNECTS && !errorReported) { Safir::Logging::SendSystemLog(Safir::Logging::Error, L"Remove: Failed to connect to the database, will keep trying. Exception info: " + err); errorReported = true; } DisconnectOdbcConnection(); boost::this_thread::sleep_for(RECONNECT_EXCEPTION_DELAY); } } }
//------------------------------------------------------- void OdbcPersistor::Insert(const Safir::Dob::Typesystem::EntityId& entityId) { int retries = 0; bool errorReported = false; m_debug << "Inserting " << entityId <<std::endl; bool paramSet = false; bool done = false; while (!done) { try { ConnectIfNeeded(m_odbcConnection, m_isOdbcConnected, retries); if (!m_insertIsValid) { m_helper.AllocStatement(&m_rowExistsStatement, m_odbcConnection); m_helper.AllocStatement(&m_insertStatement, m_odbcConnection); m_insertIsValid = true; m_helper.Prepare (m_rowExistsStatement, "SELECT count(*) as antal from PersistentEntity where typeId=? AND instance=? "); m_helper.Prepare (m_insertStatement, "INSERT INTO PersistentEntity (typeid, instance, typename) " "values (?, ?, ?); "); m_helper.BindParamInt64(m_rowExistsStatement, 1, &m_type); m_helper.BindParamInt64(m_rowExistsStatement, 2, &m_instance); m_helper.BindColumnInt64(m_rowExistsStatement,1, &m_rowCount); m_helper.BindParamInt64(m_insertStatement, 1, &m_type); m_helper.BindParamInt64(m_insertStatement, 2, &m_instance); if (Safir::Dob::PersistenceParameters::TextColumnsAreUtf8()) { m_helper.BindParamString(m_insertStatement, 3, Safir::Dob::PersistenceParameters::TypeNameColumnSize(), m_typename.get(), &m_currentTypenameSize); } else { m_helper.BindParamStringW(m_insertStatement, 3, Safir::Dob::PersistenceParameters::TypeNameColumnSize() / sizeof(wchar_t), m_typenameW.get(), &m_currentTypenameSize); } SetStmtTimeout(m_insertStatement); SetStmtTimeout(m_rowExistsStatement); paramSet = false; } if (!paramSet) { m_type = entityId.GetTypeId(); m_instance = entityId.GetInstanceId().GetRawValue(); const std::wstring typeName = Safir::Dob::Typesystem::Operations::GetName(m_type); if (Safir::Dob::PersistenceParameters::TextColumnsAreUtf8()) { const std::string typeNameUtf8 = Safir::Dob::Typesystem::Utilities::ToUtf8(typeName); const size_t size = (typeNameUtf8.size() + 1)* sizeof (char); if (size > static_cast<size_t>(Safir::Dob::PersistenceParameters::TypeNameColumnSize())) { throw Safir::Dob::Typesystem::SoftwareViolationException (L"The size in bytes of '" + typeName + L"' exceeds Safir.Dob.PersistenceParameters.TypeNameColumnSize", __WFILE__, __LINE__); } memcpy(m_typename.get(), typeNameUtf8.c_str(), size); } else { const size_t size = (typeName.size() + 1)* sizeof (wchar_t); if (size > static_cast<size_t>(Safir::Dob::PersistenceParameters::TypeNameColumnSize())) { throw Safir::Dob::Typesystem::SoftwareViolationException (L"The size in bytes of '" + typeName + L"' exceeds Safir.Dob.PersistenceParameters.TypeNameColumnSize", __WFILE__, __LINE__); } memcpy(m_typenameW.get(), typeName.c_str(), size); } m_currentTypenameSize = SQL_NTS; paramSet = true; } m_helper.Execute(m_rowExistsStatement); bool bExecuteInsert = false; if (m_helper.Fetch(m_rowExistsStatement)) { // Insert if no row exist if (m_rowCount <= 0) { bExecuteInsert = true; } } CloseCursor(m_rowExistsStatement); if (bExecuteInsert) { m_helper.Execute(m_insertStatement); } done = true; if (errorReported) { Safir::Logging::SendSystemLog(Safir::Logging::Informational, L"Successfully connected to the database"); errorReported = false; retries = 0; } } catch(const OdbcException& e) { const std::wstring err = Safir::Dob::Typesystem::Utilities::ToWstring(e.what()); m_debug << "Caught a ReconnectException in Insert:\n" << err << std::endl; if (retries > REPORT_AFTER_RECONNECTS && !errorReported) { Safir::Logging::SendSystemLog(Safir::Logging::Error, L"Insert: Failed to connect to the database, will keep trying. Exception info: " + err); errorReported = true; } DisconnectOdbcConnection(); boost::this_thread::sleep_for(RECONNECT_EXCEPTION_DELAY); } } }
//------------------------------------------------------- void OdbcPersistor::Store(const Safir::Dob::Typesystem::EntityId& entityId, const Safir::Dob::Typesystem::HandlerId& handlerId, Safir::Dob::Typesystem::BinarySerialization& bin, const bool update) { const bool small = static_cast<int>(bin.size()) < Safir::Dob::PersistenceParameters::BinarySmallDataColumnSize(); int retries = 0; bool errorReported = false; bool paramSet = false; bool done = false; while (!done) { try { ConnectIfNeeded(m_odbcConnection, m_isOdbcConnected, retries); if (!m_storeIsValid) { m_helper.AllocStatement(&m_storeStatement, m_odbcConnection); m_storeIsValid = true; m_helper.Prepare(m_storeStatement, "UPDATE PersistentEntity " "SET xmlData=NULL, binarySmallData=?, binaryData=?, handlerid=? " "WHERE typeId=? AND instance=?"); BindParamBinary(m_storeStatement, 1, Safir::Dob::PersistenceParameters::BinarySmallDataColumnSize(), m_storeBinarySmallData.get(), &m_currentSmallDataSize); BindParamBinary(m_storeStatement, 2, Safir::Dob::PersistenceParameters::BinaryDataColumnSize(), m_storeBinaryLargeData.get(), &m_currentLargeDataSize); m_helper.BindParamInt64(m_storeStatement, 3, &m_handler); m_helper.BindParamInt64(m_storeStatement, 4, &m_type); m_helper.BindParamInt64(m_storeStatement, 5, &m_instance); SetStmtTimeout(m_storeStatement); paramSet = false; } if (!paramSet) { if (small) { memcpy(m_storeBinarySmallData.get(),&bin[0], bin.size()); m_currentSmallDataSize = bin.size(); m_currentLargeDataSize = SQL_NULL_DATA; } else { memcpy(m_storeBinaryLargeData.get(),&bin[0], bin.size()); m_currentLargeDataSize = bin.size(); m_currentSmallDataSize = SQL_NULL_DATA; } m_type = entityId.GetTypeId(); m_instance = entityId.GetInstanceId().GetRawValue(); m_handler = handlerId.GetRawValue(); paramSet = true; } if (!update) { // After global instanceid's we can no longer assume that all instanceid's are written to the // the database at startup. So try to insert them here if the entity already exist Insert(entityId); } m_helper.Execute(m_storeStatement); m_debug << "Successfully stored binary entity in database. Size = "<<bin.size() << std::endl; done = true; if (errorReported) { Safir::Logging::SendSystemLog(Safir::Logging::Informational, L"Successfully connected to the database"); errorReported = false; retries = 0; } } catch(const OdbcException& e) { const std::wstring err = Safir::Dob::Typesystem::Utilities::ToWstring(e.what()); m_debug << "Caught a ReconnectException in Store:\n" << err << std::endl; if (retries > REPORT_AFTER_RECONNECTS && !errorReported) { Safir::Logging::SendSystemLog(Safir::Logging::Error, L"Store: Failed to connect to the database, will keep trying. Exception info: " + err); errorReported = true; } DisconnectOdbcConnection(); boost::this_thread::sleep_for(RECONNECT_EXCEPTION_DELAY); } } }
void ConvertDb() { Safir::Databases::Odbc::Connection readConnection; Safir::Databases::Odbc::Connection updateConnection; Safir::Databases::Odbc::Environment environment; environment.Alloc(); readConnection.Alloc(environment); updateConnection.Alloc(environment); Safir::Databases::Odbc::Statement getAllStatement; Safir::Databases::Odbc::Int64Column typeIdColumn; Safir::Databases::Odbc::Int64Column instanceColumn; Safir::Databases::Odbc::Int64Column handlerColumn; Safir::Databases::Odbc::WideStringColumn xmlDataColumn(Safir::Dob::PersistenceParameters::XmlDataColumnSize()); Safir::Databases::Odbc::BinaryColumn binaryDataColumn(Safir::Dob::PersistenceParameters::BinaryDataColumnSize()); Safir::Databases::Odbc::BinaryColumn binarySmallDataColumn(Safir::Dob::PersistenceParameters::BinarySmallDataColumnSize()); Safir::Databases::Odbc::Statement updateStatement; Safir::Databases::Odbc::Int64Parameter updateTypeIdParam; Safir::Databases::Odbc::Int64Parameter updateInstanceParam; Safir::Databases::Odbc::LongWideStringParameter updateXmlDataParam(Safir::Dob::PersistenceParameters::XmlDataColumnSize()); readConnection.Connect(Safir::Dob::PersistenceParameters::OdbcStorageConnectString()); updateConnection.Connect(Safir::Dob::PersistenceParameters::OdbcStorageConnectString()); updateStatement.Alloc(updateConnection); updateStatement.Prepare(L"UPDATE PersistentEntity SET xmlData=?, binarySmallData=NULL, binaryData=NULL WHERE typeId=? AND instance=?"); updateStatement.BindLongParameter( 1, updateXmlDataParam ); updateStatement.BindParameter( 2, updateTypeIdParam ); updateStatement.BindParameter( 3, updateInstanceParam ); getAllStatement.Alloc(readConnection); getAllStatement.Prepare( L"SELECT typeId, instance, binarySmallData, binaryData from PersistentEntity where binaryData is not null or binarySmallData is not null"); getAllStatement.BindColumn( 1, typeIdColumn ); getAllStatement.BindColumn( 2, instanceColumn); getAllStatement.BindColumn( 3, binarySmallDataColumn); getAllStatement.Execute(); for (;;) { if (!getAllStatement.Fetch()) {//we've got all rows! break; } Safir::Dob::Typesystem::EntityId entityId (typeIdColumn.GetValue(), Safir::Dob::Typesystem::InstanceId(instanceColumn.GetValue())); Safir::Dob::Typesystem::ObjectPtr object; if (!binarySmallDataColumn.IsNull()) { const char * const data = reinterpret_cast<const char * const>(binarySmallDataColumn.GetValue()); object = Safir::Dob::Typesystem::ObjectFactory::Instance().CreateObject(data); } else { getAllStatement.GetData(4, binaryDataColumn); if (!binaryDataColumn.IsNull()) { //some binarypersistent data set const char * const data = reinterpret_cast<const char * const>(binaryDataColumn.GetValue()); object = Safir::Dob::Typesystem::ObjectFactory::Instance().CreateObject(data); } } if (object != NULL) { std::wstring xml = Safir::Dob::Typesystem::Serialization::ToXml(object); updateTypeIdParam.SetValue(entityId.GetTypeId()); updateInstanceParam.SetValue(entityId.GetInstanceId().GetRawValue()); updateXmlDataParam.SetValueAtExecution(static_cast<int>(xml.size() * sizeof (wchar_t))); updateStatement.Execute(); unsigned short param = 0; if (!updateStatement.ParamData(param)) { throw Safir::Dob::Typesystem::SoftwareViolationException(L"There should be one call to ParamData!",__WFILE__,__LINE__); } updateXmlDataParam.SetValue(&xml); updateStatement.PutData(updateXmlDataParam); if (updateStatement.ParamData(param)) { throw Safir::Dob::Typesystem::SoftwareViolationException(L"There should only be one call to ParamData!",__WFILE__,__LINE__); } updateConnection.Commit(); } else { // m_debug << "No data set for " << objectId <<std::endl; } } }