diff options
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/Transform/Data.cpp | 186 | ||||
-rw-r--r-- | cpp/src/Transform/Data.h | 12 | ||||
-rw-r--r-- | cpp/src/Transform/TransformDB.cpp | 15 | ||||
-rw-r--r-- | cpp/src/Transform/Transformer.cpp | 85 |
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) { |