summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Transform/Data.cpp186
-rw-r--r--cpp/src/Transform/Data.h12
-rw-r--r--cpp/src/Transform/TransformDB.cpp15
-rw-r--r--cpp/src/Transform/Transformer.cpp85
4 files changed, 225 insertions, 73 deletions
diff --git a/cpp/src/Transform/Data.cpp b/cpp/src/Transform/Data.cpp
index 55e282190a2..a149d5c531d 100644
--- a/cpp/src/Transform/Data.cpp
+++ b/cpp/src/Transform/Data.cpp
@@ -222,14 +222,9 @@ Transform::DataPtr
Transform::DataFactory::create(const Slice::TypePtr& type, bool readOnly)
{
DataPtr data = createImpl(type, readOnly);
- if(_initializersEnabled && !readOnly)
+ if(!readOnly)
{
- string name = typeName(type);
- InitMap::iterator p = _initializers.find(name);
- if(p != _initializers.end())
- {
- p->second->initialize(this, data, _communicator);
- }
+ initialize(data);
}
return data;
}
@@ -237,31 +232,94 @@ Transform::DataFactory::create(const Slice::TypePtr& type, bool readOnly)
Transform::DataPtr
Transform::DataFactory::createBoolean(bool b, bool readOnly)
{
- return new BooleanData(getBuiltin(Slice::Builtin::KindBool), _errorReporter, readOnly, b);
+ DataPtr data = new BooleanData(getBuiltin(Slice::Builtin::KindBool), _errorReporter, readOnly, b);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createInteger(Ice::Long i, bool readOnly)
{
- return new IntegerData(getBuiltin(Slice::Builtin::KindLong), _errorReporter, readOnly, i);
+ DataPtr data = new IntegerData(getBuiltin(Slice::Builtin::KindLong), _errorReporter, readOnly, i);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createDouble(double d, bool readOnly)
{
- return new DoubleData(getBuiltin(Slice::Builtin::KindDouble), _errorReporter, readOnly, d);
+ DataPtr data = new DoubleData(getBuiltin(Slice::Builtin::KindDouble), _errorReporter, readOnly, d);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createString(const string& s, bool readOnly)
{
- return new StringData(this, getBuiltin(Slice::Builtin::KindString), _errorReporter, readOnly, s);
+ DataPtr data = new StringData(this, getBuiltin(Slice::Builtin::KindString), _errorReporter, readOnly, s);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createNil(bool readOnly)
{
- return new ObjectRef(this, getBuiltin(Slice::Builtin::KindObject), readOnly);
+ DataPtr data = new ObjectRef(this, getBuiltin(Slice::Builtin::KindObject), readOnly);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+Transform::DataPtr
+Transform::DataFactory::createObject(const Slice::TypePtr& type, bool readOnly)
+{
+ ObjectRefPtr obj;
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ Slice::ClassDefPtr def = cl->definition();
+ if(!def)
+ {
+ _errorReporter->error("class " + cl->scoped() + " declared but not defined");
+ }
+ obj = new ObjectRef(this, cl, readOnly);
+ }
+ else
+ {
+ Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type);
+ if(b && b->kind() == Slice::Builtin::KindObject)
+ {
+ obj = new ObjectRef(this, b, readOnly);
+ }
+ }
+
+ if(!obj)
+ {
+ _errorReporter->error("type `" + typeName(type) + "' is not a class");
+ }
+
+ obj->instantiate();
+
+ if(!readOnly)
+ {
+ initialize(obj);
+ }
+
+ return obj;
}
Slice::BuiltinPtr
@@ -374,6 +432,20 @@ Transform::DataFactory::createImpl(const Slice::TypePtr& type, bool readOnly)
return 0;
}
+void
+Transform::DataFactory::initialize(const DataPtr& data)
+{
+ if(_initializersEnabled)
+ {
+ string name = typeName(data->getType());
+ InitMap::iterator p = _initializers.find(name);
+ if(p != _initializers.end())
+ {
+ p->second->initialize(this, data, _communicator);
+ }
+ }
+}
+
//
// Data
//
@@ -1587,12 +1659,6 @@ Transform::DataPtr
Transform::ProxyData::getMember(const string& member) const
{
// TODO: Support members (id, facet, etc.)?
-#if 0
- if(member == "length")
- {
- return new IntegerData(_value.length());
- }
-#endif
return 0;
}
@@ -2296,12 +2362,28 @@ Transform::SequenceData::transformI(const DataPtr& data, DataInterceptor& interc
for(DataList::const_iterator p = s->_elements.begin(); p != s->_elements.end(); ++p)
{
DataPtr element = _factory->create(_type->type(), _readOnly);
- //
- // We add the element regardless of whether transform() succeeds in order to
- // preserve the original sequence size and order.
- //
- element->transform((*p), interceptor);
- elements.push_back(element);
+ Destroyer<DataPtr> elementDestroyer(element);
+ try
+ {
+ element->transform((*p), interceptor);
+ elements.push_back(element);
+ elementDestroyer.release();
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the sequence element fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the sequence) or raise the exception again.
+ //
+ if(!interceptor.purgeObjects())
+ {
+ throw;
+ }
+ _errorReporter->warning("purging element of sequence " + typeName(_type) +
+ " due to missing class type " + ex.id);
+ }
}
_elements = elements;
_length = _factory->createInteger(static_cast<Ice::Long>(_elements.size()), true);
@@ -2631,8 +2713,6 @@ Transform::DictionaryData::getMember(const string& member) const
Transform::DataPtr
Transform::DictionaryData::getElement(const DataPtr& element) const
{
- // TODO: Validate element's type
-
DataMap::const_iterator p = _map.find(element);
if(p != _map.end())
{
@@ -2824,9 +2904,33 @@ Transform::DictionaryData::transformI(const DataPtr& data, DataInterceptor& inte
for(DataMap::const_iterator p = d->_map.begin(); p != d->_map.end(); ++p)
{
DataPtr key = _factory->create(_type->keyType(), _readOnly);
+ Destroyer<DataPtr> keyDestroyer(key);
DataPtr value = _factory->create(_type->valueType(), _readOnly);
+ Destroyer<DataPtr> valueDestroyer(value);
+
key->transform(p->first, interceptor);
- value->transform(p->second, interceptor);
+
+ try
+ {
+ value->transform(p->second, interceptor);
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the dictionary value fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the dictionary) or raise the exception again.
+ //
+ if(!interceptor.purgeObjects())
+ {
+ throw;
+ }
+ _errorReporter->warning("purging element of dictionary " + typeName(_type) +
+ " due to missing class type " + ex.id);
+ continue;
+ }
+
DataMap::const_iterator q = m.find(key);
if(q != m.end())
{
@@ -2839,6 +2943,8 @@ Transform::DictionaryData::transformI(const DataPtr& data, DataInterceptor& inte
else
{
m.insert(DataMap::value_type(key, value));
+ keyDestroyer.release();
+ valueDestroyer.release();
}
}
_map = m;
@@ -3018,6 +3124,7 @@ Transform::ObjectData::transform(const DataPtr& data, DataInterceptor& intercept
}
catch(...)
{
+ objectMap.erase(p);
objectMap.insert(ObjectDataMap::value_type(o.get(), 0));
throw;
}
@@ -3208,11 +3315,6 @@ Transform::ObjectRef::operator!=(const Data& rhs) const
_errorReporter->typeMismatchError(_type, rhs.getType(), true);
}
- if(!_value || !r->_value)
- {
- return !_value && r->_value;
- }
-
//
// Reference comparison.
//
@@ -3429,8 +3531,7 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept
Slice::TypeList l = _type->unit()->lookupType(name, false);
if(l.empty())
{
- // TODO: Slice object? Or missing type exception?
- _errorReporter->warning("type `" + name + "' not found");
+ throw ClassNotFoundException(name);
}
else
{
@@ -3443,9 +3544,24 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept
_errorReporter->error("no definition for " + name);
}
}
+ //
+ // Create a new object and increment its reference count. We do this
+ // because it's possible for its reference count to be manipulated
+ // during transformation, and we don't want it to be destroyed.
+ //
ObjectDataPtr data = new ObjectData(_factory, l.front(), _readOnly);
- data->transform(o->_value, interceptor);
+ data->incRef();
+ try
+ {
+ data->transform(o->_value, interceptor);
+ }
+ catch(...)
+ {
+ data->decRef();
+ throw;
+ }
setValue(data);
+ data->decRef();
}
}
}
diff --git a/cpp/src/Transform/Data.h b/cpp/src/Transform/Data.h
index 1b023c446a6..fef7aea4f66 100644
--- a/cpp/src/Transform/Data.h
+++ b/cpp/src/Transform/Data.h
@@ -50,6 +50,7 @@ public:
virtual bool preTransform(const DataPtr&, const DataPtr&) = 0;
virtual void postTransform(const DataPtr&, const DataPtr&) = 0;
virtual ObjectDataMap& getObjectMap() = 0;
+ virtual bool purgeObjects() const = 0;
};
class DataInitializer : virtual public IceUtil::SimpleShared
@@ -74,6 +75,7 @@ public:
DataPtr createDouble(double, bool);
DataPtr createString(const std::string&, bool);
DataPtr createNil(bool);
+ DataPtr createObject(const Slice::TypePtr&, bool);
Slice::BuiltinPtr getBuiltin(Slice::Builtin::Kind) const;
@@ -85,6 +87,7 @@ public:
private:
DataPtr createImpl(const Slice::TypePtr&, bool);
+ void initialize(const DataPtr&);
Ice::CommunicatorPtr _communicator;
Slice::UnitPtr _unit; // Only used for creating builtin types.
@@ -654,6 +657,15 @@ private:
Slice::UnitPtr _unit;
};
+class ClassNotFoundException
+{
+public:
+
+ ClassNotFoundException(const std::string& s) : id(s) {}
+
+ std::string id;
+};
+
} // End of namespace Transform
#endif
diff --git a/cpp/src/Transform/TransformDB.cpp b/cpp/src/Transform/TransformDB.cpp
index 5fd6e75fa77..3bf321b57c8 100644
--- a/cpp/src/Transform/TransformDB.cpp
+++ b/cpp/src/Transform/TransformDB.cpp
@@ -45,6 +45,7 @@ usage(const char* n)
"-o FILE Output transformation descriptors into the file FILE.\n"
" Database transformation is not performed.\n"
"-i Ignore incompatible type changes.\n"
+ "-p Purge objects whose types no longer exist.\n"
"-f FILE Execute the transformation descriptors in the file FILE.\n"
" Database transformation is not performed.\n"
"--old SLICE Load old Slice definitions from the file SLICE.\n"
@@ -107,6 +108,7 @@ run(int argc, char** argv, const Ice::CommunicatorPtr& communicator)
bool caseSensitive = false;
string outputFile;
bool ignoreTypeChanges = false;
+ bool purgeObjects = false;
string inputFile;
vector<string> oldSlice;
vector<string> newSlice;
@@ -209,6 +211,15 @@ run(int argc, char** argv, const Ice::CommunicatorPtr& communicator)
}
--argc;
}
+ else if(strcmp(argv[idx], "-p") == 0)
+ {
+ purgeObjects = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
else if(strcmp(argv[idx], "-f") == 0)
{
if(idx + 1 >= argc || argv[idx + 1][0] == '-')
@@ -351,7 +362,7 @@ run(int argc, char** argv, const Ice::CommunicatorPtr& communicator)
//
// Create the Transformer.
//
- Transform::Transformer transformer(communicator, oldUnit, newUnit, ignoreTypeChanges);
+ Transform::Transformer transformer(communicator, oldUnit, newUnit, ignoreTypeChanges, purgeObjects);
//
// If no input file was provided, then we need to analyze the Slice types.
@@ -492,7 +503,7 @@ run(int argc, char** argv, const Ice::CommunicatorPtr& communicator)
db = new Db(&dbEnv, 0);
db->open(0, dbName.c_str(), 0, DB_BTREE, DB_RDONLY, TRANSFORM_DB_MODE);
dbNew = new Db(&dbEnv, 0);
- dbNew->open(0, dbNameNew.c_str(), 0, DB_BTREE, DB_CREATE | DB_TRUNCATE, TRANSFORM_DB_MODE);
+ dbNew->open(0, dbNameNew.c_str(), 0, DB_BTREE, DB_CREATE | DB_EXCL, TRANSFORM_DB_MODE);
istringstream istr(descriptors);
transformer.transform(istr, db, dbNew, cerr);
diff --git a/cpp/src/Transform/Transformer.cpp b/cpp/src/Transform/Transformer.cpp
index 13733049b55..02945be4552 100644
--- a/cpp/src/Transform/Transformer.cpp
+++ b/cpp/src/Transform/Transformer.cpp
@@ -296,7 +296,6 @@ private:
};
typedef IceUtil::Handle<InitDescriptor> InitDescriptorPtr;
-// TODO: Is this class necessary?
class RecordDescriptor : public ExecutableContainerDescriptor
{
public:
@@ -316,7 +315,7 @@ public:
virtual void execute(TransformSymbolTable&, DataInterceptor&);
bool transform(IceInternal::BasicStream&, IceInternal::BasicStream&, IceInternal::BasicStream&,
- IceInternal::BasicStream&, const TransformMap&);
+ IceInternal::BasicStream&, const TransformMap&, bool);
private:
@@ -344,7 +343,7 @@ public:
virtual Slice::UnitPtr newUnit() const;
virtual ErrorReporterPtr errorReporter() const;
- void transform(const Ice::CommunicatorPtr&, Db*, Db*);
+ void transform(const Ice::CommunicatorPtr&, Db*, Db*, bool);
private:
@@ -386,11 +385,12 @@ class TransformInterceptor : public DataInterceptor
public:
TransformInterceptor(const DataFactoryPtr&, const ErrorReporterPtr&, const Slice::UnitPtr&,
- const Slice::UnitPtr&, const TransformMap&);
+ const Slice::UnitPtr&, const TransformMap&, bool);
virtual bool preTransform(const DataPtr&, const DataPtr&);
virtual void postTransform(const DataPtr&, const DataPtr&);
virtual ObjectDataMap& getObjectMap();
+ virtual bool purgeObjects() const;
private:
@@ -400,6 +400,7 @@ private:
Slice::UnitPtr _new;
const TransformMap& _transformMap;
ObjectDataMap _objectMap;
+ bool _purgeObjects;
};
} // End of namespace Transform
@@ -794,14 +795,8 @@ Transform::SetDescriptor::execute(TransformSymbolTable& sym, DataInterceptor& in
{
errorReporter()->error("type `" + _type + "' not found");
}
- value = factory()->create(l.front(), false);
+ value = factory()->createObject(l.front(), false);
valueDestroyer.set(value);
- ObjectRefPtr ref = ObjectRefPtr::dynamicCast(value);
- if(!ref)
- {
- errorReporter()->error("type `" + _type + "' is not a class");
- }
- ref->instantiate();
}
DataPtr length;
@@ -937,14 +932,8 @@ Transform::AddDescriptor::execute(TransformSymbolTable& sym, DataInterceptor& in
{
errorReporter()->error("type `" + _type + "' not found");
}
- value = factory()->create(l.front(), false);
+ value = factory()->createObject(l.front(), false);
valueDestroyer.set(value);
- ObjectRefPtr ref = ObjectRefPtr::dynamicCast(value);
- if(!ref)
- {
- errorReporter()->error("type `" + _type + "' is not a class");
- }
- ref->instantiate();
}
if(value)
@@ -1392,15 +1381,19 @@ void
Transform::InitDescriptor::initialize(const DataFactoryPtr& factory, const DataPtr& data,
const Ice::CommunicatorPtr& communicator)
{
- DescriptorErrorContext ctx(errorReporter(), "init", _line);
-
-#if 0 // TODO
- // Is interceptor really necessary?
- TransformSymbolTable sym(factory, _old, _new);
+ //
+ // Create a new symbol table for the initializer and add the value to be initialized
+ // as the symbol "value".
+ //
+ TransformSymbolTable sym(factory, oldUnit(), newUnit(), errorReporter());
sym.add("value", data);
- eh->raise(true);
+ errorReporter()->raise(true);
+ //
+ // Also need an interceptor in order to call execute.
+ //
+ TransformMap transforms;
+ TransformInterceptor interceptor(factory, errorReporter(), oldUnit(), newUnit(), transforms, false);
execute(sym, interceptor);
-#endif
}
string
@@ -1507,11 +1500,11 @@ Transform::DatabaseDescriptor::execute(TransformSymbolTable&, DataInterceptor&)
bool
Transform::DatabaseDescriptor::transform(IceInternal::BasicStream& inKey, IceInternal::BasicStream& inValue,
IceInternal::BasicStream& outKey, IceInternal::BasicStream& outValue,
- const TransformMap& transforms)
+ const TransformMap& transforms, bool purgeObjects)
{
errorReporter()->raise(false);
- TransformInterceptor interceptor(factory(), errorReporter(), oldUnit(), newUnit(), transforms);
+ TransformInterceptor interceptor(factory(), errorReporter(), oldUnit(), newUnit(), transforms, purgeObjects);
//
// Create data representations of the old key and value types.
@@ -1672,10 +1665,9 @@ Transform::TransformerDescriptor::errorReporter() const
}
void
-Transform::TransformerDescriptor::transform(const Ice::CommunicatorPtr& communicator, Db* db, Db* dbNew)
+Transform::TransformerDescriptor::transform(const Ice::CommunicatorPtr& communicator, Db* db, Db* dbNew,
+ bool purgeObjects)
{
- DescriptorErrorContext ctx(errorReporter(), "transformer", _line);
-
Dbc* dbc = 0;
IceInternal::InstancePtr instance = IceInternal::getInstance(communicator);
@@ -1704,7 +1696,7 @@ Transform::TransformerDescriptor::transform(const Ice::CommunicatorPtr& communic
outValue.startWriteEncaps();
try
{
- if(_database->transform(inKey, inValue, outKey, outValue, _transforms))
+ if(_database->transform(inKey, inValue, outKey, outValue, _transforms, purgeObjects))
{
outValue.endWriteEncaps();
Dbt dbNewKey(&outKey.b[0], outKey.b.size()), dbNewValue(&outValue.b[0], outValue.b.size());
@@ -1718,6 +1710,18 @@ Transform::TransformerDescriptor::transform(const Ice::CommunicatorPtr& communic
{
// The record is deleted simply by not adding it to the new database.
}
+ catch(const ClassNotFoundException& ex)
+ {
+ if(!purgeObjects)
+ {
+ errorReporter()->error("class " + ex.id + " not found in new Slice definitions");
+ }
+ else
+ {
+ // The record is deleted simply by not adding it to the new database.
+ errorReporter()->warning("purging database record due to missing class type " + ex.id);
+ }
+ }
}
}
catch(...)
@@ -2127,8 +2131,10 @@ Transform::TransformInterceptor::TransformInterceptor(const DataFactoryPtr& fact
const ErrorReporterPtr& errorReporter,
const Slice::UnitPtr& oldUnit,
const Slice::UnitPtr& newUnit,
- const TransformMap& transformMap) :
- _factory(factory), _errorReporter(errorReporter), _old(oldUnit), _new(newUnit), _transformMap(transformMap)
+ const TransformMap& transformMap,
+ bool purgeObjects) :
+ _factory(factory), _errorReporter(errorReporter), _old(oldUnit), _new(newUnit), _transformMap(transformMap),
+ _purgeObjects(purgeObjects)
{
}
@@ -2182,12 +2188,19 @@ Transform::TransformInterceptor::getObjectMap()
return _objectMap;
}
+bool
+Transform::TransformInterceptor::purgeObjects() const
+{
+ return _purgeObjects;
+}
+
//
// Transformer
//
Transform::Transformer::Transformer(const Ice::CommunicatorPtr& communicator, const Slice::UnitPtr& oldUnit,
- const Slice::UnitPtr& newUnit, bool ignoreTypeChanges) :
- _communicator(communicator), _old(oldUnit), _new(newUnit), _ignoreTypeChanges(ignoreTypeChanges)
+ const Slice::UnitPtr& newUnit, bool ignoreTypeChanges, bool purgeObjects) :
+ _communicator(communicator), _old(oldUnit), _new(newUnit), _ignoreTypeChanges(ignoreTypeChanges),
+ _purgeObjects(purgeObjects)
{
}
@@ -2239,7 +2252,7 @@ Transform::Transformer::transform(istream& is, Db* db, Db* dbNew, ostream& error
TransformerDescriptorPtr descriptor = dh.descriptor();
descriptor->validate();
- descriptor->transform(_communicator, db, dbNew);
+ descriptor->transform(_communicator, db, dbNew, _purgeObjects);
}
catch(const IceXML::ParserException& ex)
{