diff --git a/src/cpp/lib/MultithreadContainer.h b/src/cpp/lib/MultithreadContainer.h index ea4bef5fd..dafc4f9ad 100644 --- a/src/cpp/lib/MultithreadContainer.h +++ b/src/cpp/lib/MultithreadContainer.h @@ -24,6 +24,7 @@ \brief Container Wrapper class for mutex protected container changed to poco mutex for gradido login server + default mutex from poco is recursive so it is some heavy thing \author Dario Rekowski @@ -50,8 +51,8 @@ namespace UniLib { inline const std::string& getLastSucceededLock() { return mLastSucceededLock; } protected: + mutable Poco::Mutex mWorkMutex; private: - Poco::Mutex mWorkMutex; std::string mLastSucceededLock; }; } diff --git a/src/cpp/model/table/EmailOptIn.cpp b/src/cpp/model/table/EmailOptIn.cpp index d8789ee61..256366436 100644 --- a/src/cpp/model/table/EmailOptIn.cpp +++ b/src/cpp/model/table/EmailOptIn.cpp @@ -7,25 +7,25 @@ using namespace Poco::Data::Keywords; namespace model { namespace table { EmailOptIn::EmailOptIn(const Poco::UInt64& code, int user_id, EmailOptInType type/* = EMAIL_OPT_IN_REGISTER*/) - : mUserId(user_id), mEmailVerificationCode(code), mType(type) + : mUserId(user_id), mEmailVerificationCode(code), mType(type), mResendCount(0) { } EmailOptIn::EmailOptIn(const Poco::UInt64& code, EmailOptInType type/* = EMAIL_OPT_IN_REGISTER*/) - : mUserId(0), mEmailVerificationCode(code), mType(type) + : mUserId(0), mEmailVerificationCode(code), mType(type), mResendCount(0) { } EmailOptIn::EmailOptIn() - : mUserId(0), mEmailVerificationCode(0) + : mUserId(0), mEmailVerificationCode(0), mResendCount(0) { } EmailOptIn::EmailOptIn(const EmailOptInTuple& tuple) - : ModelBase(tuple.get<0>()), mUserId(tuple.get<1>()), mEmailVerificationCode(tuple.get<2>()), mType(tuple.get<3>()) + : ModelBase(tuple.get<0>()), mUserId(tuple.get<1>()), mEmailVerificationCode(tuple.get<2>()), mType(tuple.get<3>()), mResendCount(tuple.get<4>()) { } @@ -42,8 +42,8 @@ namespace model { lock(); insert << "INSERT INTO " << getTableName() - << " (user_id, verification_code, email_opt_in_type_id) VALUES(?,?,?)" - , use(mUserId), use(mEmailVerificationCode), bind(mType); + << " (user_id, verification_code, email_opt_in_type_id, resend_count) VALUES(?,?,?,?)" + , use(mUserId), use(mEmailVerificationCode), bind(mType), bind(mResendCount); unlock(); return insert; } @@ -53,9 +53,9 @@ namespace model { { Poco::Data::Statement select(session); - select << "SELECT id, user_id, verification_code, email_opt_in_type_id FROM " << getTableName() + select << "SELECT id, user_id, verification_code, email_opt_in_type_id, resend_count FROM " << getTableName() << " where " << fieldName << " = ?" - , into(mID), into(mUserId), into(mEmailVerificationCode), into(mType); + , into(mID), into(mUserId), into(mEmailVerificationCode), into(mType), into(mResendCount); return select; @@ -76,7 +76,7 @@ namespace model { { Poco::Data::Statement select(session); - select << "SELECT id, user_id, verification_code, email_opt_in_type_id FROM " << getTableName() + select << "SELECT id, user_id, verification_code, email_opt_in_type_id, resend_count FROM " << getTableName() << " where " << fieldName << " = ?"; @@ -90,7 +90,7 @@ namespace model { throw Poco::NullValueException("EmailOptIn::_loadFromDB fieldNames empty or contain only one field"); } - select << "SELECT user_id, verification_code, email_opt_in_type_id FROM " << getTableName() + select << "SELECT user_id, verification_code, email_opt_in_type_id, resend_count FROM " << getTableName() << " where " << fieldNames[0] << " = ? "; if (conditionType == MYSQL_CONDITION_AND) { for (int i = 1; i < fieldNames.size(); i++) { @@ -106,12 +106,19 @@ namespace model { addError(new ParamError("EmailOptIn::_loadFromDB", "condition type not implemented", conditionType)); } //<< " where " << fieldName << " = ?" - select , into(mUserId), into(mEmailVerificationCode), into(mType); + select , into(mUserId), into(mEmailVerificationCode), into(mType), into(mResendCount); return select; } + size_t EmailOptIn::addResendCountAndUpdate() + { + Poco::ScopedLock _lock(mWorkMutex); + mResendCount++; + return updateIntoDB("resend_count", mResendCount); + } + std::string EmailOptIn::toString() { std::stringstream ss; diff --git a/src/cpp/model/table/EmailOptIn.h b/src/cpp/model/table/EmailOptIn.h index 61c558224..d32564710 100644 --- a/src/cpp/model/table/EmailOptIn.h +++ b/src/cpp/model/table/EmailOptIn.h @@ -17,7 +17,7 @@ namespace model { EMAIL_OPT_IN_REGISTER_DIRECT = 3 }; - typedef Poco::Tuple EmailOptInTuple; + typedef Poco::Tuple EmailOptInTuple; class EmailOptIn : public ModelBase { @@ -34,10 +34,13 @@ namespace model { inline Poco::UInt64 getCode() const { return mEmailVerificationCode; } inline int getUserId() const { return mUserId; } + inline int getResendCount() const { Poco::ScopedLock _lock(mWorkMutex); return mResendCount; } inline EmailOptInType getType() const { return static_cast(mType);} inline void setCode(Poco::UInt64 code) { mEmailVerificationCode = code; } inline void setUserId(int user_Id) { mUserId = user_Id; } + size_t addResendCountAndUpdate(); + static const char* typeToString(EmailOptInType type); protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); @@ -50,6 +53,7 @@ namespace model { // data type must be a multiple of 4 Poco::UInt64 mEmailVerificationCode; int mType; + int mResendCount; }; diff --git a/src/cpp/model/table/ModelBase.cpp b/src/cpp/model/table/ModelBase.cpp index daa340353..107b5104c 100644 --- a/src/cpp/model/table/ModelBase.cpp +++ b/src/cpp/model/table/ModelBase.cpp @@ -42,6 +42,7 @@ namespace model { { //printf("ModelBase::insertIntoDB with table: %s\n", getTableName()); auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); Poco::Data::Statement insert = _insertIntoDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); size_t resultCount = 0; @@ -53,11 +54,9 @@ namespace model { try { return select.execute() == 1; } - catch (Poco::Exception& ex) { - lock("ModelBase::insertIntoDB"); + catch (Poco::Exception& ex) { addError(new ParamError(getTableName(), "mysql error by select id", ex.displayText().data())); addError(new ParamError(getTableName(), "data set: ", toString().data())); - unlock(); } } else { @@ -66,10 +65,8 @@ namespace model { } } catch (Poco::Exception& ex) { - lock("ModelBase::insertIntoDB2"); addError(new ParamError(getTableName(), "mysql error by insert", ex.displayText().data())); addError(new ParamError(getTableName(), "data set: ", toString().data())); - unlock(); } //printf("data valid: %s\n", toString().data()); return false; @@ -77,10 +74,9 @@ namespace model { bool ModelBase::deleteFromDB() { + Poco::ScopedLock _lock(mWorkMutex); if (mID == 0) { - lock(); addError(new Error(getTableName(), "id is zero, couldn't delete from db")); - unlock(); return false; } auto cm = ConnectionManager::getInstance(); @@ -102,23 +98,21 @@ namespace model { void ModelBase::duplicate() { - lock(); + Poco::ScopedLock _lock(mWorkMutex); mReferenceCount++; //printf("[ModelBase::duplicate] new value: %d\n", mReferenceCount); - unlock(); } void ModelBase::release() { - lock(); + Poco::ScopedLock _lock(mWorkMutex); mReferenceCount--; //printf("[ModelBase::release] new value: %d\n", mReferenceCount); if (0 == mReferenceCount) { - unlock(); + delete this; return; } - unlock(); } diff --git a/src/cpp/model/table/ModelBase.h b/src/cpp/model/table/ModelBase.h index 95b756882..ac96ebc03 100644 --- a/src/cpp/model/table/ModelBase.h +++ b/src/cpp/model/table/ModelBase.h @@ -13,6 +13,7 @@ #include "Poco/JSON/Object.h" +#include //using namespace Poco::Data::Keywords; namespace model { @@ -68,7 +69,7 @@ namespace model { int mID; // for poco auto ptr - int mReferenceCount; + int mReferenceCount; }; @@ -76,6 +77,7 @@ namespace model { size_t ModelBase::loadFromDB(const std::string& fieldName, const T& fieldValue) { auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); Poco::Data::Statement select = _loadFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldName); select, Poco::Data::Keywords::useRef(fieldValue); @@ -84,10 +86,8 @@ namespace model { resultCount = select.execute(); } catch (Poco::Exception& ex) { - lock(); addError(new ParamError(getTableName(), "mysql error by selecting", ex.displayText().data())); addError(new ParamError(getTableName(), "field name for select: ", fieldName.data())); - unlock(); } return resultCount; } @@ -96,6 +96,7 @@ namespace model { bool ModelBase::isExistInDB(const std::string& fieldName, const T& fieldValue) { auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); Poco::Data::Statement select(session); int id; @@ -122,6 +123,7 @@ namespace model { { //printf("ModelBase::loadFromDB multi\n"); std::vector results; + Poco::ScopedLock _lock(mWorkMutex); //return results; if (expectedResults > 0) { results.reserve(expectedResults); @@ -147,7 +149,7 @@ namespace model { std::vector ModelBase::loadFromDB(const std::vector& fieldNames, const std::vector& fieldValues, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/, int expectedResults/* = 0*/) { std::vector results; - + Poco::ScopedLock _lock(mWorkMutex); if (fieldNames.size() != fieldValues.size() || fieldNames.size() <= 1) { lock(); addError(new Error(getTableName(), "fieldNames and fieldValues size don't match or smaller as 1")); @@ -183,6 +185,7 @@ namespace model { size_t ModelBase::loadFromDB(const std::vector& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) { auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); Poco::Data::Statement select = _loadFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldNames, conditionType); select, Poco::Data::Keywords::useRef(field1Value), Poco::Data::Keywords::useRef(field2Value); @@ -207,6 +210,7 @@ namespace model { size_t ModelBase::updateIntoDB(const std::string& fieldName, const T& fieldValue) { auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); Poco::Data::Statement update(session);