Bug #2535 » WtSessionDisconnect.patch
| src/Wt/Dbo/Session | ||
|---|---|---|
|
*/
|
||
|
void rereadAll(const char *tableName = 0);
|
||
|
/*! \brief Disconnects all objects from session management.
|
||
|
*
|
||
|
* This disconnects all objects from the session management.
|
||
|
* Disconnected objects are not synchronized with the database.
|
||
|
*/
|
||
|
virtual void disconnectAll();
|
||
|
/*! \brief Discards all unflushed changes.
|
||
|
*
|
||
|
* This method is useful when the flushMode() is set to Manual. It discards
|
||
| ... | ... | |
|
virtual void dropTable(Session& session,
|
||
|
std::set<std::string>& tablesDropped);
|
||
|
virtual void rereadAll();
|
||
|
virtual void disconnectAll();
|
||
|
std::string primaryKeys() const;
|
||
|
};
|
||
| ... | ... | |
|
virtual void dropTable(Session& session,
|
||
|
std::set<std::string>& tablesDropped);
|
||
|
virtual void rereadAll();
|
||
|
virtual void disconnectAll();
|
||
|
};
|
||
|
|
||
|
typedef const std::type_info * const_typeinfo_ptr;
|
||
| src/Wt/Dbo/Session.C | ||
|---|---|---|
|
throw Exception("Not to be done.");
|
||
|
}
|
||
|
void Session::MappingInfo::disconnectAll()
|
||
|
{
|
||
|
throw Exception("Not to be done.");
|
||
|
}
|
||
|
std::string Session::MappingInfo::primaryKeys() const
|
||
|
{
|
||
|
if (surrogateIdFieldName)
|
||
| ... | ... | |
|
i->second->rereadAll();
|
||
|
}
|
||
|
void Session::disconnectAll()
|
||
|
{
|
||
|
if (!dirtyObjects_.empty())
|
||
|
std::cerr << "Warning: Wt::Dbo::Session disconnecting with "
|
||
|
<< dirtyObjects_.size() << " dirty objects" << std::endl;
|
||
|
for (MetaDboBaseSet::iterator i = dirtyObjects_.begin();
|
||
|
i != dirtyObjects_.end(); ++i)
|
||
|
(*i)->decRef();
|
||
|
dirtyObjects_.clear();
|
||
|
for (ClassRegistry::iterator i = classRegistry_.begin();
|
||
|
i != classRegistry_.end(); ++i)
|
||
|
i->second->disconnectAll();
|
||
|
}
|
||
|
void Session::discardUnflushed()
|
||
|
{
|
||
|
objectsToAdd_.clear();
|
||
| src/Wt/Dbo/Session_impl.h | ||
|---|---|---|
|
}
|
||
|
template <class C>
|
||
|
void Session::Mapping<C>::disconnectAll()
|
||
|
{
|
||
|
for (typename Registry::iterator i = registry_.begin();
|
||
|
i != registry_.end(); ++i) {
|
||
|
i->second->setSession(0);
|
||
|
i->second->setState(MetaDboBase::Disconnected);
|
||
|
}
|
||
|
registry_.clear();
|
||
|
}
|
||
|
template <class C>
|
||
|
void Session::Mapping<C>::init(Session& session)
|
||
|
{
|
||
|
if (!initialized_) {
|
||
| src/Wt/Dbo/ptr | ||
|---|---|---|
|
New = 0x000,
|
||
|
Persisted = 0x001,
|
||
|
Orphaned = 0x002,
|
||
|
Disconnected = 0x004,
|
||
|
// flags
|
||
|
NeedsDelete = 0x010,
|
||
| ... | ... | |
|
bool isPersisted() const
|
||
|
{ return 0 != (state_ & (Persisted | SavedInTransaction)); }
|
||
|
bool isOrphaned() const { return 0 != (state_ & Orphaned); }
|
||
|
bool isDisconnected() const { return 0 != (state_ & Disconnected); }
|
||
|
bool isDeleted() const
|
||
|
{ return 0 != (state_ & (NeedsDelete | DeletedInTransaction)); }
|
||
| ... | ... | |
|
int refCount_;
|
||
|
void checkNotOrphaned();
|
||
|
void checkNotDisconnected();
|
||
|
};
|
||
|
/*! \class dbo_default_traits Wt/Dbo/Dbo Wt/Dbo/Dbo
|
||
| src/Wt/Dbo/ptr.C | ||
|---|---|---|
|
}
|
||
|
}
|
||
|
void MetaDboBase::checkNotDisconnected()
|
||
|
{
|
||
|
if (isDisconnected()) {
|
||
|
throw Exception("modifying disconnected dbo ptr");
|
||
|
}
|
||
|
}
|
||
|
ptr_base::~ptr_base()
|
||
|
{ }
|
||
| src/Wt/Dbo/ptr_impl.h | ||
|---|---|---|
|
if (refCount_)
|
||
|
throw std::logic_error("Dbo: refCount > 0");
|
||
|
if ((!isOrphaned()) && session())
|
||
|
if ((!isOrphaned()) && (!isDisconnected()) && session())
|
||
|
session()->prune(this);
|
||
|
delete obj_;
|
||
| ... | ... | |
|
void MetaDbo<C>::flush()
|
||
|
{
|
||
|
checkNotOrphaned();
|
||
|
checkNotDisconnected();
|
||
|
if (state_ & NeedsDelete) {
|
||
|
state_ &= ~NeedsDelete;
|
||
| test/dbo/DboDisconnectTest.C | ||
|---|---|---|
|
/*
|
||
|
* Copyright (C) 2009 Emweb bvba, Kessel-Lo, Belgium.
|
||
|
*
|
||
|
* See the LICENSE file for terms of use.
|
||
|
*/
|
||
|
#include <boost/test/unit_test.hpp>
|
||
|
#include <Wt/Dbo/Dbo>
|
||
|
#include <Wt/Dbo/backend/Postgres>
|
||
|
#include <Wt/Dbo/backend/MySQL>
|
||
|
#include <Wt/Dbo/backend/Sqlite3>
|
||
|
#include <Wt/Dbo/backend/Firebird>
|
||
|
#include <Wt/WDate>
|
||
|
#include <Wt/WDateTime>
|
||
|
#include <Wt/WTime>
|
||
|
#include <Wt/Dbo/WtSqlTraits>
|
||
|
#include <Wt/Dbo/ptr_tuple>
|
||
|
#include <string>
|
||
|
namespace dbo = Wt::Dbo;
|
||
|
class TestDbo;
|
||
|
typedef dbo::collection< dbo::ptr<TestDbo> > TestDboCollection;
|
||
|
class TestDbo : public Wt::Dbo::Dbo<TestDbo>
|
||
|
{
|
||
|
public:
|
||
|
int intC;
|
||
|
double doubleC;
|
||
|
template<class Action>
|
||
|
void persist(Action &a)
|
||
|
{
|
||
|
Wt::Dbo::field(a, intC, "intC");
|
||
|
Wt::Dbo::field(a, doubleC, "doubleC");
|
||
|
}
|
||
|
static const char *TableName()
|
||
|
{
|
||
|
return "func";
|
||
|
}
|
||
|
};
|
||
|
struct Dbo3Fixture
|
||
|
{
|
||
|
typedef std::map<long long, Wt::Dbo::ptr<TestDbo>> TestMapType;
|
||
|
TestMapType TestMap;
|
||
|
dbo::SqlConnection *connection_;
|
||
|
dbo::Session *session_;
|
||
|
Dbo3Fixture()
|
||
|
{
|
||
|
connection_ = new dbo::backend::Sqlite3(":memory:");
|
||
|
connection_->setProperty("show-queries", "true");
|
||
|
session_ = new dbo::Session();
|
||
|
session_->setConnection(*connection_);
|
||
|
session_->mapClass<TestDbo>(TestDbo::TableName());
|
||
|
session_->createTables();
|
||
|
{
|
||
|
dbo::Transaction tr(*session_);
|
||
|
dbo::ptr<TestDbo> New1 = session_->add(new TestDbo());
|
||
|
New1.modify()->intC = 1;
|
||
|
New1.modify()->doubleC = 1.1;
|
||
|
dbo::ptr<TestDbo> New2 = session_->add(new TestDbo());
|
||
|
New2.modify()->intC = 2;
|
||
|
New2.modify()->doubleC = 2.2;
|
||
|
}
|
||
|
{
|
||
|
//Check initial values
|
||
|
FetchAll();
|
||
|
dbo::ptr<TestDbo> DisconnectedTestPtr = TestMap[1]; //id: 1
|
||
|
std::cout << "Before modified: intC: " << DisconnectedTestPtr->intC << ", expected: 1" << std::endl;
|
||
|
//Modify from outside session_'s knowledge
|
||
|
dbo::Transaction tr(*session_);
|
||
|
session_->execute(std::string("UPDATE ") + TestDbo::TableName() + " SET intC = 99 WHERE id = 1;");
|
||
|
tr.commit();
|
||
|
//Check again
|
||
|
FetchAll();
|
||
|
//should remain unchanged because in FetchAll() none of the ptr<C>s are deleted or modified but swapped with a local TestMap object
|
||
|
std::cout << "After re-fetched: intC: " << DisconnectedTestPtr->intC << ", expected: 1" << std::endl;
|
||
|
//should be a new value because FetchAll uses a collection to map all ptr<C> with newer values from the database
|
||
|
dbo::ptr<TestDbo> NormalTestPtr = TestMap[1]; //id: 1
|
||
|
std::cout << "After re-assignment: intC: " << NormalTestPtr->intC << ", expected: 99" << std::endl;
|
||
|
BOOST_REQUIRE(DisconnectedTestPtr->intC == 1);
|
||
|
BOOST_REQUIRE(NormalTestPtr->intC == 99);
|
||
|
dbo::Transaction tr2(*session_);
|
||
|
NormalTestPtr.modify()->intC = 10;
|
||
|
tr2.commit();
|
||
|
try
|
||
|
{
|
||
|
dbo::Transaction tr3(*session_);
|
||
|
DisconnectedTestPtr.modify()->intC = 5;
|
||
|
tr3.commit();
|
||
|
}
|
||
|
catch(std::exception &e)
|
||
|
{
|
||
|
std::cout << "Exception caught: " << e.what();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
void FetchAll()
|
||
|
{
|
||
|
//Strong exception safety(make TestMap empty by swapping with an empty map, swap back if exception is caught)
|
||
|
TestMapType testmap;
|
||
|
TestMap.swap(testmap);
|
||
|
session_->disconnectAll();
|
||
|
try
|
||
|
{
|
||
|
dbo::Transaction tr(*session_);
|
||
|
TestDboCollection collection = session_->find<TestDbo>();
|
||
|
for(TestDboCollection::const_iterator itr = collection.begin();
|
||
|
itr != collection.end();
|
||
|
++itr)
|
||
|
{
|
||
|
TestMap[itr->id()] = *itr;
|
||
|
}
|
||
|
tr.commit();
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
testmap.swap(TestMap);
|
||
|
}
|
||
|
}
|
||
|
~Dbo3Fixture()
|
||
|
{
|
||
|
session_->dropTables();
|
||
|
delete session_;
|
||
|
delete connection_;
|
||
|
}
|
||
|
};
|
||
|
BOOST_AUTO_TEST_CASE( dbo3_reload_test )
|
||
|
{
|
||
|
Dbo3Fixture f;
|
||
|
}
|
||
- « Previous
- 1
- 2
- Next »