//============================================================================ // FUNCTION: SPELLutils::dumpFrameInfo() //============================================================================ void SPELLutils::dumpFrameInfo( const std::string& id, PyFrameObject* frame, int iStateId, int TStateId, int FrameId ) { LOG_INFO("Dump information for frame " + ISTR(iStateId) + "." + ISTR(TStateId) + "." + ISTR(FrameId)); std::string dataDir = getSPELL_DATA() + PATH_SEPARATOR + "Runtime" + PATH_SEPARATOR; std::string filename = dataDir + id + "_frame_state_" + ISTR(iStateId) + "." + ISTR(TStateId) + "." + ISTR(FrameId) + ".dump"; std::ofstream dumpFile; dumpFile.open( filename.c_str() , std::ios::out ); dumpFile << "FRAME STATE " << TStateId << " DATA" << std::endl; dumpFile << "--------------------------------------" << std::endl; dumpFile << "Address : " << PSTR(frame) << std::endl; dumpFile << "Next address : " << PSTR(frame->f_back) << std::endl; dumpFile << "Thread state address : " << PSTR(frame->f_tstate) << std::endl; dumpFile << "Last instruction : " << frame->f_lasti << std::endl; dumpFile << "Last line : " << frame->f_lineno << std::endl; dumpFile << "Try blocks count : " << frame->f_iblock << std::endl; dumpFile << "Try blocks : " << PSTR(frame->f_blockstack) << std::endl; dumpFile << "Value stack : " << PSTR(frame->f_valuestack) << std::endl; dumpFile << "Stack top : " << PSTR(frame->f_stacktop) << std::endl; dumpFile << "Stack count : " << (frame->f_stacktop - frame->f_valuestack) << std::endl; dumpFile << "Fast locals : " << (frame->f_code->co_nlocals-1) << std::endl; dumpFile << "Exception type : " << PYREPR(frame->f_exc_type) << std::endl; dumpFile << "Exception value : " << PYREPR(frame->f_exc_value) << std::endl; dumpFile << "Exception traceback : " << PYREPR(frame->f_exc_traceback) << std::endl; dumpFile << "Trace function : " << PYREPR(frame->f_trace) << std::endl; dumpFile << "Builtins : " << PYSIZE(frame->f_builtins) << std::endl; dumpFile << "Globals : " << PYSIZE(frame->f_globals) << std::endl; dumpFile << "Locals : " << PYSIZE(frame->f_locals) << std::endl; dumpFile << "Code : " << PYCREPR(frame->f_code) << std::endl; // Close the frame state dump, no more to add dumpFile.flush(); dumpFile.close(); }
//============================================================================= // METHOD : SPELLwsClassDataHandler::read() //============================================================================= void SPELLwsClassDataHandler::read() { // Store the class name SPELLwsObjectDataHandler nameHandler( NULL ); nameHandler.setStorage(getStorage()); SPELLwsDictDataHandler dictHandler( NULL ); dictHandler.setStorage(getStorage()); // Read the data DEBUG("[CDH] Reading name"); nameHandler.read(); DEBUG("[CDH] Name read: " + PYREPR(nameHandler.getObject())); PyObject* classObject = NULL; if ( PYSTR(nameHandler.getObject()) == "__FAILED_WS_CLASS__" ) { classObject = PyClass_New( NULL, PyDict_New(), nameHandler.getObject() ); std::string msg = "Detected failed WS class, assuming error during marshal process"; LOG_ERROR(msg); std::cerr << msg << std::endl; } else { DEBUG("[CDH] Reading dictionary"); dictHandler.read(); DEBUG("[CDH] Dictionary read: " + PYREPR(dictHandler.getObject())); // Create the class object classObject = PyClass_New( NULL, dictHandler.getObject(), nameHandler.getObject() ); } // Set it as associated object setObject( classObject ); }
//============================================================================= // METHOD: SPELLvariableMonitor::retrieveNames() //============================================================================= std::vector<std::string> SPELLvariableMonitor::retrieveNames() { std::vector<std::string> varNames; PyObject* varList = m_frame->f_code->co_names; DEBUG("[VM] CO_NAMES : " + PYREPR(varList)); unsigned int numVars = PyTuple_Size(varList); /* * co_varnames contains the names of the local variables * (starting with the argument names) */ varList = m_frame->f_code->co_varnames; DEBUG("[VM] CO_VARNAMES: " + PYREPR(varList)); numVars = PyTuple_Size(varList); for( unsigned int index = 0; index<numVars; index++) { PyObject* varName = PyTuple_GetItem( varList, index ); varNames.push_back( PYSSTR( varName ) ); } varList = m_frame->f_code->co_freevars; DEBUG("[VM] CO_FREEVARS : " + PYREPR(varList)); varList = m_frame->f_code->co_cellvars; DEBUG("[VM] CO_CELLVARS : " + PYREPR(varList)); return varNames; }
//============================================================================= // METHOD: SPELLvariableMonitor::changeVariable() //============================================================================= void SPELLvariableMonitor::changeVariable( SPELLvarInfo& var ) { SPELLsafePythonOperations ops("SPELLvariableMonitor::changeVariable()"); DEBUG("[VM] Request changing variable " + var.varName); // Evaluate the value for the variable PyObject* value = NULL; // If varValue is '<empty>' or empty string, do not try to evaluate it, // directly assign Python empty string if ((var.varValue == EMPTY_STRING)||(var.varValue == "")) { value = STRPY(""); } else { // Build assignment expression. We need to check first, if there // are double quotes, convert them to single quotes SPELLutils::replace(var.varValue, "\"", "'"); DEBUG("[VM] Evaluating value expression: " + var.varValue ); // Check value correctness and evaluate it value = SPELLpythonHelper::instance().eval(var.varValue, false); } if ((m_frame->f_globals)&&(var.isGlobal)) { DEBUG("[VM] Setting " + var.varName + " to " + PYREPR(value) + " in globals"); PyDict_SetItemString( m_frame->f_globals, var.varName.c_str(), value ); } else if ((m_frame->f_locals)&&(!var.isGlobal)) { DEBUG("[VM] Setting " + var.varName + " to " + PYREPR(value) + " in locals"); // Update locals from fast locals first PyFrame_FastToLocals(m_frame); PyDict_SetItemString( m_frame->f_locals, var.varName.c_str(), value ); PyFrame_LocalsToFast(m_frame,0); } var.varValue = PYSSTR(value); if (var.varValue == "") var.varValue = EMPTY_STRING; // Update the variable if it is registered, and notify to listeners VarMap::iterator it = m_variables.find(var.varName); if (it != m_variables.end()) { std::vector<SPELLvarInfo> changed; it->second.varValue = var.varValue; DEBUG("[VM] Variable changed by user: "******", current value: " + var.varValue ); changed.push_back(it->second); m_listener->variableChanged( changed ); } }
//============================================================================ // FUNCTION: SPELLutils::dumpThreadStateInfo() //============================================================================ void SPELLutils::dumpThreadStateInfo( const std::string& id, PyThreadState* ts, int iStateId, int TStateId ) { LOG_INFO("Dump information for thread state " + ISTR(iStateId) + "." + ISTR(TStateId)); std::string dataDir = getSPELL_DATA() + PATH_SEPARATOR + "Runtime" + PATH_SEPARATOR; std::string filename = dataDir + id + "_thread_state_" + ISTR(iStateId) + "." + ISTR(TStateId) + ".dump"; std::ofstream dumpFile; dumpFile.open( filename.c_str() , std::ios::out ); dumpFile << "THREAD STATE " << TStateId << " DATA" << std::endl; dumpFile << "--------------------------------------" << std::endl; dumpFile << "Address : " << PSTR(ts) << std::endl; dumpFile << "Next address : " << PSTR(ts->next) << std::endl; dumpFile << "IState address : " << PSTR(ts->interp) << std::endl; dumpFile << "Recursion depth : " << ts->recursion_depth << std::endl; dumpFile << "Tracing flag : " << ts->tracing << std::endl; dumpFile << "Use tracing flg : " << ts->use_tracing << std::endl; dumpFile << "Profile function : " << ts->c_profilefunc << std::endl; dumpFile << "Trace function : " << ts->c_tracefunc << std::endl; dumpFile << "Profile object : " << PYREPR(ts->c_profileobj) << std::endl; dumpFile << "Trace object : " << PYREPR(ts->c_traceobj) << std::endl; dumpFile << "Current exc. type : " << PYREPR(ts->curexc_type) << std::endl; dumpFile << "Current exc. value: " << PYREPR(ts->curexc_value) << std::endl; dumpFile << "Current exc. tback: " << PYREPR(ts->curexc_traceback) << std::endl; dumpFile << "Exception type : " << PYREPR(ts->exc_type) << std::endl; dumpFile << "Exception value : " << PYREPR(ts->exc_value) << std::endl; dumpFile << "Exception tback : " << PYREPR(ts->exc_traceback) << std::endl; dumpFile << "Main dict : " << PYSIZE(ts->dict) << " items." << std::endl; dumpFile << "Tick counter : " << ts->tick_counter << std::endl; dumpFile << "GIL state counter : " << ts->gilstate_counter << std::endl; dumpFile << "Async. exception : " << PYREPR(ts->async_exc) << std::endl; dumpFile << "Thread id : " << ts->thread_id << std::endl; // Count frames int numFR = 0; PyFrameObject* currFR = ts->frame; while( currFR != NULL ) { dumpFrameInfo( id, currFR, iStateId, TStateId, numFR ); numFR++; currFR = currFR->f_back; } dumpFile << "Number of frames : " << numFR << std::endl; // Close the thread state dump, no more to add dumpFile.flush(); dumpFile.close(); }
//============================================================================= // METHOD : SPELLwsClassDataHandler::write() //============================================================================= void SPELLwsClassDataHandler::write() { assert( PyClass_Check(getObject()) ); PyClassObject* classObject = reinterpret_cast<PyClassObject*>(getObject()); DEBUG("[CDH] Storing name: " + PYREPR(classObject->cl_name) ); SPELLwsObjectDataHandler nameHandler( classObject->cl_name ); nameHandler.setStorage(getStorage()); DEBUG("[CDH] Storing dictionary: " + PYREPR(classObject->cl_dict)); SPELLwsDictDataHandler dictHandler( classObject->cl_dict ); dictHandler.setStorage(getStorage()); // Store the class name, We dont need a data code, we know what is there nameHandler.write(); // Store the class dictionary dictHandler.write(); DEBUG("[CDH] Storing class done" ); }
//============================================================================= // METHOD: SPELLvariableMonitor::retrieveLocalVariables() //============================================================================= void SPELLvariableMonitor::retrieveLocalVariables(std::vector<SPELLvarInfo>& vars) { DEBUG("[VM] Retrieve Locals"); /* * Bottom stack frame is discarded, * as globals and locals are the same dictionary */ if (m_frame->f_back == NULL) return; /* * Get the names defined in the current code, including arguments */ std::vector<std::string> varNames = retrieveNames(); /* * Iterate over the locals dictionary, retrieving the names contained in * varNames */ PyFrame_FastToLocals(m_frame); PyObject* dict = m_frame->f_locals; DEBUG("[VM] Frame: " + PYCREPR(m_frame)); for( unsigned int index = 0; index< varNames.size(); index++) { std::string varName = varNames[index]; PyObject* pyVarName = SSTRPY(varName); if (PyDict_Contains( dict, pyVarName )) { PyObject* object = PyDict_GetItem( dict, pyVarName ); if (!SPELLpythonHelper::instance().isInstance(object, "Database", "spell.lib.adapter.databases.database")) { if (PyCallable_Check(object)) continue; if (PyClass_Check(object)) continue; if (PyModule_Check(object)) continue; if (PyInstance_Check(object)) continue; } DEBUG("[VM] Processing " + varName); std::string type = PYSSTR( PyObject_Type(object) ); DEBUG("[VM] Type : " + type); std::string value = PYREPR( object ); DEBUG("[VM] Value : " + value); DEBUG("[VM] Global : " + BSTR(false)); DEBUG("[VM] Registered: " + BSTR(isRegistered(varName))); // Mark empty values (empty strings) as "<empty>" if (value == "") value = EMPTY_STRING; vars.push_back( SPELLvarInfo(varName, type, value, false, isRegistered(varName)) ); } } PyFrame_LocalsToFast(m_frame,0); }
//============================================================================= // STATIC : SPELLwsWarmStartImpl::shouldFilter() //============================================================================= bool SPELLwsWarmStartImpl::shouldFilter( PyObject* key, PyObject* item ) { bool doFilter = false; // Do not consider modules if (PyModule_Check(item)) { doFilter = true; } // Do not consider callables else if (PyCallable_Check(item)) { doFilter = true; } // Do not consider functions else if (PyFunction_Check(item)) { doFilter = true; } else if ( PYREPR(key) == DatabaseConstants::SCDB ) { doFilter = true; } else if ( PYREPR(key) == DatabaseConstants::GDB ) { doFilter = true; } else if ( PYREPR(key) == DatabaseConstants::PROC ) { doFilter = true; } if ((!doFilter) && (s_filterKeys != NULL)) { // If the set contains the key, must filter it int contains = PySet_Contains( s_filterKeys, key ); doFilter = (contains!=0); } return doFilter; }
//============================================================================= // METHOD : SPELLwsStorage::storeObject //============================================================================= void SPELLwsStorage::storeObject( PyObject* object ) { if (!m_file.is_open()) return; if (object == NULL) { THROW_EXCEPTION("Unable to store object", "Null reference given", SPELL_ERROR_WSTART); } if (m_mode == MODE_READ) { THROW_EXCEPTION("Unable to store object", "Initialized in read mode", SPELL_ERROR_WSTART); } std::string ptype = PYREPR(PyObject_Type(object)); DEBUG("Encoding object " + PYREPR(object) + " of type " + ptype); // Marshal the object to the persistent storage file PyObject* marshal = PyMarshal_WriteObjectToString( object, LATEST_MARSHAL_VERSION ); // Ensure there is no internal Python error SPELLpythonHelper::instance().checkError(); int marshal_len = PyObject_Length(marshal); DEBUG("Marshal length: " + ISTR(marshal_len)); char* encoded = PyString_AsString(marshal); // FORMAT IN FILE: // COUNT \1 PTYPE \1 MARSHAL LENGTH // MARSHAL // If the marshal was OK, continue and store in file: OP,TYPE,MARSHALLED m_opCounter++; m_file << m_opCounter << "\1" << ptype << "\1" << marshal_len << std::endl; m_file.write(encoded,marshal_len); m_file << std::endl; std::flush(m_file); m_trace << "[" << m_opCounter << "] STORE (" << m_filename << ") " + PYREPR(object) << " [ Type=" + ptype << ", Marhsal length=" + ISTR(marshal_len) + " ]" << std::endl; std::flush(m_trace); }
//============================================================================= // METHOD : SPELLwsStorage::loadObject //============================================================================= PyObject* SPELLwsStorage::loadObject() { if (!m_file.is_open()) return NULL; if (m_mode == MODE_WRITE) { THROW_EXCEPTION("Unable to load object", "Initialized in write mode", SPELL_ERROR_WSTART); } // FORMAT IN FILE: // COUNT \1 PTYPE \1 MARSHAL LENGTH // MARSHAL std::string line = ""; // Get first the line with the info while(!m_file.eof() && (line == "")) { std::getline(m_file,line); DEBUG("Obtained line [" + line + "]"); } DEBUG("Load object from line [" + line + "]"); std::vector<std::string> elements = SPELLutils::tokenize(line,"\1"); PyObject* obj = NULL; std::string ptype = elements[1]; int marshal_len = STRI(elements[2]); DEBUG("Decoding object of type " + elements[1] + ", marshal length " + elements[2]); // Get the line with the marshal char buffer[4512]; m_file.read(buffer,marshal_len); obj = (PyObject*) PyMarshal_ReadObjectFromString( buffer, marshal_len ); DEBUG("Decoded: " + PYCREPR(obj)); // Check that the unmarshal was ok SPELLpythonHelper::instance().checkError(); m_opCounter++; m_trace << "[" << m_opCounter << "] LOAD (" << m_filename << ") " << PYREPR(obj) << " [ Type=" << PYREPR(PyObject_Type(obj)) << ", Marshal length=" + ISTR(marshal_len) + " ]" << std::endl; std::flush(m_trace); if (obj != NULL) Py_INCREF(obj); return obj; }
//============================================================================= // STATIC : SPELLwsDataHandlerFactory::createDataHandler() //============================================================================= SPELLwsDataHandler* SPELLwsDataHandlerFactory::createDataHandler( PyObject* object ) { assert(object != NULL); SPELLwsDataHandler* handler = NULL; DEBUG("[DHF] Creating handler for object of type " + PYREPR( PyObject_Type(object) )); if (PyDict_Check(object)) { DEBUG("[DHF] Object is a dictionary"); handler = new SPELLwsDictDataHandler(object); } else if (PyList_Check(object)) { DEBUG("[DHF] Object is a list"); handler = new SPELLwsListDataHandler(object); } else if ( Py_None == object ) { DEBUG("[DHF] Object is None"); handler = new SPELLwsNoneDataHandler(); } else if (SPELLpythonHelper::instance().isDatabase(object)) { DEBUG("[DHF] Object is database"); handler = new SPELLwsDbDataHandler(object); } else if (SPELLpythonHelper::instance().isTime(object)) { DEBUG("[DHF] Object is TIME"); handler = new SPELLwsTimeDataHandler(object); } else if (PyClass_Check(object)) { DEBUG("[DHF] Object is a class: " + PYCREPR(object)); handler = new SPELLwsClassDataHandler(object); } else if (PyInstance_Check(object)) { DEBUG("[DHF] Object is a instance: " + PYCREPR(object)); handler = new SPELLwsInstanceDataHandler(object); } else if (SPELLpythonHelper::instance().isSubclassInstance(object, "TmItemClass", "spell.lib.adapter.tm_item")) { DEBUG("[DHF] Object is a TM item: " + PYCREPR(object)); handler = new SPELLwsTmItemDataHandler(object); } // Look discussion at mail.python.org/pipermail/python-dev/2004-July/046074.html else if ((object->ob_type->tp_flags & Py_TPFLAGS_HEAPTYPE)>0) { DEBUG("[DHF] Object is a custom type: " + PYCREPR(object)); handler = new SPELLwsCustomTypeDataHandler(object); } else { DEBUG("[DHF] Default to object handler: " + PYCREPR(object)); handler = new SPELLwsObjectDataHandler(object); } return handler; }
//============================================================================ // METHOD: SPELLpyValue::set //============================================================================ void SPELLpyValue::set( PyObject* pyValue ) { m_type = NONE; m_intValue = 0; m_boolValue = false; m_floatValue = 0.0; m_timeValue.set(0,0); m_stringValue = ""; if (pyValue == NULL) return; DEBUG("[PYVAL] Set value from " + PYREPR(pyValue)); if (pyValue != Py_None) { if (PyBool_Check(pyValue)) { m_type = BOOLEAN; m_boolValue = pyValue == Py_True; } else if (PyLong_Check(pyValue)) { DEBUG("[PYVAL] Long check"); m_type = LONG; m_intValue = PyLong_AsLongLong(pyValue); } else if (PyInt_Check(pyValue)) { DEBUG("[PYVAL] Int check"); m_type = LONG; m_intValue = PyInt_AsLong(pyValue); } else if (PyFloat_Check(pyValue)) { m_type = DOUBLE; m_floatValue = PyFloat_AsDouble(pyValue); } else if (SPELLpythonHelper::instance().isTime(pyValue)) { m_timeValue = SPELLpythonHelper::instance().evalTime(PYSSTR(pyValue)); if (m_timeValue.isDelta()) { m_type = RELTIME; } else { m_type = ABSTIME; } } else if (PyString_Check(pyValue)) { m_type = STRING; m_stringValue = PYSTR(pyValue); } else if (PyList_Check(pyValue)) { m_type = LIST; m_listValue.clear(); unsigned int numItems = PyList_Size(pyValue); for(unsigned int idx = 0; idx < numItems; idx++) { m_listValue.push_back( SPELLpyValue( PyList_GetItem( pyValue, idx) )); } } else if (PyDict_Check(pyValue)) { m_type = DICT; m_dictValue.clear(); PyObject* keys = PyDict_Keys(pyValue); unsigned int numItems = PyList_Size(keys); for(unsigned int idx = 0; idx < numItems; idx++) { PyObject* key = PyList_GetItem(keys,idx); PyObject* value = PyDict_GetItem( pyValue, key ); m_dictValue.insert( std::make_pair( PYSSTR(key), SPELLpyValue(value) ) ); } } else { THROW_EXCEPTION("Cannot create variable value", "Cannot infer type from value (" + PYREPR(pyValue) + ")", SPELL_ERROR_LANGUAGE); } SPELLpythonHelper::instance().checkError(); } }
//============================================================================= // METHOD: SPELLvariableMonitor::retrieveGlobalVariables() //============================================================================= void SPELLvariableMonitor::retrieveGlobalVariables(std::vector<SPELLvarInfo>& vars, std::set<std::string> locals) { DEBUG("[VM] Retrieve Globals"); /* * Once we get the bottom stack frame, we have to iterate over all the keys * in the globals dictionary, and filter them agains the m_initialVariables */ PyObject* dict = m_frame->f_globals; PyObject* itemList = PyDict_Keys(dict); unsigned int numItems = PyList_Size(itemList); for( unsigned int index = 0; index<numItems; index++) { PyObject* key = PyList_GetItem( itemList, index ); std::string varName = PYSSTR(key); // Do the following check just when the considered variables are not internal databases if ( (varName != DatabaseConstants::SCDB) && (varName != DatabaseConstants::GDB) && (varName != DatabaseConstants::PROC) && (varName != DatabaseConstants::ARGS) && (varName != DatabaseConstants::IVARS)) { /* If they key is contained in the initial variables set, then ignore it */ if (m_initialVariables.find(varName) != m_initialVariables.end()) { continue; } } /* If a variable with the same name has been retrieved in the local scope * then it must be ignored */ if (locals.find(varName) != locals.end()) { continue; } // Ignore internal flags if (varName == "__USERLIB__") continue; PyObject* object = PyDict_GetItem( dict, key ); if (!SPELLpythonHelper::instance().isInstance(object, "Database", "spell.lib.adapter.databases.database")) { if (PyCallable_Check(object)) continue; if (PyClass_Check(object)) continue; if (PyModule_Check(object)) continue; if (PyInstance_Check(object)) continue; } DEBUG("[VM] Processing " + varName); std::string type = PYSSTR( PyObject_Type(object) ); std::string value = PYREPR( object ); DEBUG("[VM] Type : " + type); DEBUG("[VM] Value : " + value); DEBUG("[VM] Global : " + BSTR(true)); DEBUG("[VM] Registered: " + BSTR(isRegistered(PYSSTR(key)))); // Mark empty values (empty strings) as "<empty>" if (value == "") value = EMPTY_STRING; vars.push_back( SPELLvarInfo(varName, type, value, true, isRegistered(PYSSTR(key))) ); } }
//============================================================================= // METHOD : SPELLwsDictDataHandler::write() //============================================================================= void SPELLwsDictDataHandler::write() { if (getObject() == NULL) { getStorage()->storeLong( -1 ); return; } assert( PyDict_Check(getObject())); SPELLpyHandle keys = PyDict_Keys( getObject() ); unsigned int numItems = PyList_Size( keys.get() ); DEBUG("[DDH] Storing dictionary items (total " + ISTR(numItems) + ") address " + PSTR(getObject())); PyObject* key = NULL; PyObject* item = NULL; long toStore = 0; // Calculate the number of items to store // Store each list item DEBUG("[DDH] Keys of the dictionary:"); for( unsigned int index = 0; index < numItems; index++) { key = PyList_GetItem( keys.get(), index ); item = PyDict_GetItem( getObject(), key ); if (SPELLwsWarmStartImpl::shouldFilter(key,item)) { continue; } else { DEBUG(" - " + PYSSTR(key)); } toStore++; } DEBUG("[DDH] Will store " + ISTR(toStore) + " keys"); // Store the number of items getStorage()->storeLong( (long) toStore ); DEBUG("[DDH] Start checking items"); if (toStore>0) { // Store each list item for( unsigned int index = 0; index < numItems; index++) { key = PyList_GetItem( keys.get(), index ); item = PyDict_GetItem( getObject(), key ); DEBUG("[DDH] Checking item " + PYCREPR(key)); // Do not consider filtered values if (SPELLwsWarmStartImpl::shouldFilter(key,item)) continue; SPELLpythonHelper::instance().checkError(); DEBUG(" [DDH] Key index " + ISTR(index)); DEBUG(" [DDH] Key to use" + PYREPR(key)); DEBUG(" [DDH] Item type:" + PYREPR(PyObject_Type(item))); // Handler for the key SPELLwsObjectDataHandler keyHandler(key); keyHandler.setStorage(getStorage()); DEBUG(" [DDH] Creating handler"); // Create a handler for the item SPELLwsDataHandler* handler = SPELLwsDataHandlerFactory::createDataHandler(item); handler->setStorage(getStorage()); // Store the key DEBUG(" [DDH] Storing key: " + PYREPR(key)); keyHandler.write(); // Store the item data code in order to recognise it later DEBUG(" [DDH] Storing data code: " + SPELLwsData::codeStr(handler->getCode())); handler->storeDataCode(); // IMPORTANT in the case of lists and dictionaries, we want to be able to continue // the storage even if there is a problem in the handler processing at this point. // If that is the case, a fake empty object will be replaced by the object being // processed by the handler, and the dumping of this collection will continue. try { if (handler->getCode() == SPELLwsData::DATA_CUSTOM_TYPE ) { std::string msg = "WARNING! warm start not supported for custom Python types (" + PYREPR(key) + "=" + PYREPR(item) + ")"; LOG_WARN(msg); SPELLexecutor::instance().getCIF().warning(msg); storeFakeObject( SPELLwsData::DATA_NONE ); } else { // Store the value DEBUG(" [DDH] Storing value: " + PYREPR(item)); handler->write(); DEBUG(" [DDH] Storing value done"); } } catch(SPELLcoreException& ex) { std::string msg = "WARNING! WS storage of element " + ISTR(index) + " failed: " + ex.what(); LOG_WARN(msg); SPELLexecutor::instance().getCIF().warning(msg); storeFakeObject( handler->getCode() ); } delete handler; } } DEBUG("[DDH] Storing dictionary done"); }
//============================================================================= // METHOD : SPELLwsDictDataHandler::read() //============================================================================= void SPELLwsDictDataHandler::read() { DEBUG("[DDH] Loading dictionary items"); // Load the number of items int numItems = getStorage()->loadLong(); DEBUG("[DDH] Number of items " + ISTR(numItems)); if (numItems == -1) { setObject(NULL); return; } // Create a dictionary PyObject* dictObject = PyDict_New(); for( unsigned int index = 0; index < (unsigned) numItems; index++) { // We know that first an Object comes, as the key. So make the handler directly. SPELLwsObjectDataHandler keyHandler(NULL); keyHandler.setStorage(getStorage()); DEBUG(" [DDH] Loading key"); keyHandler.read(); PyObject* key = keyHandler.getObject(); DEBUG(" [DDH] Loaded key " + PYREPR(key)); // Load the item code DEBUG(" [DDH] Loading data code"); SPELLwsData::Code code = loadDataCode(); DEBUG(" [DDH] Loaded data code " + SPELLwsData::codeStr(code)); if (code == SPELLwsData::DATA_CUSTOM_TYPE ) { std::string msg = "WARNING! warm start not supported for custom Python types (" + PYREPR(key) + ")"; LOG_WARN(msg); SPELLexecutor::instance().getCIF().warning(msg); getStorage()->loadObject(); // Load none PyDict_SetItem(dictObject, key, Py_None); } else { // Create an appropriate handler SPELLwsDataHandler* handler = SPELLwsDataHandlerFactory::createDataHandler(code); handler->setStorage(getStorage()); try { // Read the data DEBUG(" [DDH] Loading value"); handler->read(); DEBUG(" [DDH] Value loaded " + PYREPR(handler->getObject())); // Add the item to the dictionary PyDict_SetItem(dictObject, key, handler->getObject()); } catch(SPELLcoreException& ex) { std::string msg = "Failed to recover dictionary item " + PYREPR(key) + ": " + ex.what(); LOG_WARN(msg); SPELLexecutor::instance().getCIF().warning(msg); PyDict_SetItem(dictObject, key, Py_None); } delete handler; DEBUG(" [DDH] "); } } DEBUG("[DDH] Dictionary loaded"); // Set it as associated object setObject( dictObject ); }