diff --git a/ChaosDataService/QueryDataConsumer.cpp b/ChaosDataService/QueryDataConsumer.cpp index 386ae1b286c46bf0b36e8928ea9e51437bcccc8f..8f6b26314063452a510eff495d1fa250d2d057ee 100644 --- a/ChaosDataService/QueryDataConsumer.cpp +++ b/ChaosDataService/QueryDataConsumer.cpp @@ -312,12 +312,76 @@ int QueryDataConsumer::consumeNewSnapshotEvent(opcode_headers::DirectIOSystemAPI // Manage the delete operation on an existing snapshot int QueryDataConsumer::consumeDeleteSnapshotEvent(opcode_headers::DirectIOSystemAPIChannelOpcodeNDGSnapshotHeader *header, DirectIOSystemAPISnapshotResult *api_result) { - + int err = 0; + if(settings->cache_only) { + //data service is in cache only mode throw the error + api_result->error = -1; + std::strncpy(api_result->error_message, "Chaos Data Service is in cache only", 255); + //delete header + if(header) free(header); + return 0; + } + if((err = db_driver->snapshotDeleteWithName(header->field.snap_name))) { + api_result->error = err; + std::strcpy(api_result->error_message, "Error deleteing the snapshot"); + QDCERR_ << api_result->error_message << "->" << header->field.snap_name; + } else { + api_result->error = 0; + std::strcpy(api_result->error_message, "Snapshot deleted"); + } + return err; } // Return the dataset for a producerkey ona specific snapshot int QueryDataConsumer::consumeGetDatasetSnapshotEvent(opcode_headers::DirectIOSystemAPIChannelOpcodeNDGSnapshotHeader *header, const std::string& producer_id, - DirectIOSystemAPIGetDatasetSnapshotResult *api_result) { + void **channel_found_data, + uint32_t& channel_found_data_length, + DirectIOSystemAPISnapshotResult *api_result) { + int err = 0; + std::string channel_type; + if(settings->cache_only) { + //data service is in cache only mode throw the error + api_result->error = -1; + std::strncpy(api_result->error_message, "Chaos Data Service is in cache only", 255); + //delete header + if(header) free(header); + return -1; + } + //trduce int to postfix channel type + switch(header->field.channel_type) { + case 0: + channel_type = DataPackPrefixID::OUTPUT_DATASE_PREFIX; + break; + case 1: + channel_type = DataPackPrefixID::INPUT_DATASE_PREFIX; + break; + case 2: + channel_type = DataPackPrefixID::CUSTOM_DATASE_PREFIX; + break; + case 3: + channel_type = DataPackPrefixID::SYSTEM_DATASE_PREFIX; + break; + } + + if((err = db_driver->snapshotGetDatasetForProducerKey(header->field.snap_name, + producer_id, + channel_type, + channel_found_data, + channel_found_data_length))) { + api_result->error = err; + std::strcpy(api_result->error_message, "Error retriving the snapshoted dataaset for producer key"); + QDCERR_ << api_result->error_message << "[" << header->field.snap_name << "/" << producer_id<<"]"; + } else { + if(*channel_found_data) { + api_result->error = 0; + std::strcpy(api_result->error_message, "Snapshot found"); + } else { + api_result->error = -2; + std::strcpy(api_result->error_message, "Channel data not found in snapshot"); + + } + } + return err; } diff --git a/ChaosDataService/QueryDataConsumer.h b/ChaosDataService/QueryDataConsumer.h index 945f57d858e8f7a54dfff86861f1695ab2379d23..e6cea9a2221f18d57a44c0fb45fb50aca48ea46d 100644 --- a/ChaosDataService/QueryDataConsumer.h +++ b/ChaosDataService/QueryDataConsumer.h @@ -107,7 +107,9 @@ namespace chaos{ // Return the dataset for a producerkey ona specific snapshot int consumeGetDatasetSnapshotEvent(opcode_headers::DirectIOSystemAPIChannelOpcodeNDGSnapshotHeader *header, const std::string& producer_id, - DirectIOSystemAPIGetDatasetSnapshotResult *api_result); + void **channel_found_data, + uint32_t& channel_found_data_length, + DirectIOSystemAPISnapshotResult *api_result); //async central timer hook void timeout(); public: diff --git a/ChaosDataService/db_system/DBDriver.h b/ChaosDataService/db_system/DBDriver.h index 26e4cf0a2c78e2570e9f3bbb4db99756d18a40e6..001a2d31584331c2c536bf3cdfc6f73700620e28 100644 --- a/ChaosDataService/db_system/DBDriver.h +++ b/ChaosDataService/db_system/DBDriver.h @@ -227,7 +227,7 @@ namespace chaos { \param working_job_unique_id the identification of the job \param snapshot_name the name of the snapshot where put the element \param producer_unique_key the unique key of the producer - \param dataset_type the type of the dataset, refer to @DataPackCommonKey::DPCK_DATASET_TYPE field of the dataset + \param dataset_type the type of the dataset, refer to @DataPackPrefixID field of the dataset \param data the serialized data of the dataset \param data_len the length of the serialized data */ @@ -255,7 +255,7 @@ namespace chaos { snapshot \param snapshot_name the name of the snapshot to delete \param producer_unique_key the unique key of the producer - \param dataset_type the type of the dataset, refer to @DataPackCommonKey::DPCK_DATASET_TYPE field of the dataset + \param dataset_type the type of the dataset, refer to @DataPackPrefixID field of the dataset \param channel_data the data of the channel; \param channel_data_size the size of the channel data */ diff --git a/ChaosDataService/db_system/MongoDBDriver.cpp b/ChaosDataService/db_system/MongoDBDriver.cpp index a12df3f5d6c160fcc014cd42dfc4367f1f1a290b..f503648f1d85ce39b6077dcfec9d581cbad607da 100644 --- a/ChaosDataService/db_system/MongoDBDriver.cpp +++ b/ChaosDataService/db_system/MongoDBDriver.cpp @@ -939,7 +939,40 @@ int MongoDBDriver::snapshotGetDatasetForProducerKey(const std::string& snapshot_ const std::string& dataset_type, void **channel_data, uint32_t& channel_data_size) { - + int err = 0; + mongo::BSONObj result; + mongo::BSONObjBuilder search_snapshot; + try{ + //search for snapshot name and producer unique key + search_snapshot << MONGO_DB_FIELD_SNAPSHOT_DATA_SNAPSHOT_NAME << snapshot_name + << MONGO_DB_FIELD_SNAPSHOT_DATA_PRODUCER_ID << producer_unique_key; + + mongo::BSONObj q = search_snapshot.obj(); + DEBUG_CODE(MDBID_LDBG_ << "snapshotGetDatasetForProducerKey findOne ---------------------------------------------";) + DEBUG_CODE(MDBID_LDBG_ << "condition" << q;) + DEBUG_CODE(MDBID_LDBG_ << "snapshotGetDatasetForProducerKey findOne ---------------------------------------------";) + + //update and waith until the data is on the server + if((err = ha_connection_pool->findOne(result, MONGO_DB_COLLECTION_NAME(db_name, MONGO_DB_COLLECTION_SNAPSHOT_DATA), q))) { + MDBID_LERR_ << "Errore finding the snapshot "<< snapshot_name << " for the unique key "<< producer_unique_key <<"with error "<<err; + } else { + std::string channel_unique_key = producer_unique_key+dataset_type; + if(result.hasField(channel_unique_key)) { + //! get data + mongo::BSONObj channel_data_obj = result.getObjectField(channel_unique_key); + if((channel_data_size = channel_data_obj.objsize())) { + *channel_data = malloc(channel_data_size); + if(*channel_data) { + std::memcpy(*channel_data, (void*)channel_data_obj.objdata(), channel_data_size); + } + } + } + } + } catch( const mongo::DBException &e ) { + MDBID_LERR_ << e.what(); + err = -1; + } + return 0; } //! Delete a snapshot where no job is working @@ -950,10 +983,9 @@ int MongoDBDriver::snapshotDeleteWithName(const std::string& snapshot_name) { try{ //search for snapshot name and producer unique key search_snapshot << MONGO_DB_FIELD_SNAPSHOT_DATA_SNAPSHOT_NAME << snapshot_name; - + mongo::BSONObj q = search_snapshot.obj(); DEBUG_CODE(MDBID_LDBG_ << "snapshotDeleteWithName count ---------------------------------------------";) - DEBUG_CODE(MDBID_LDBG_ << "condition" << q;) DEBUG_CODE(MDBID_LDBG_ << "snapshotDeleteWithName count ---------------------------------------------";) diff --git a/ChaosSnapshotUtility/main.cpp b/ChaosSnapshotUtility/main.cpp index 237c3962c8d5a507bb784e9ed92ae28accb2c9da..19cd6ffdd3f9d4d611a24adc1c876639ffa7bf42 100644 --- a/ChaosSnapshotUtility/main.cpp +++ b/ChaosSnapshotUtility/main.cpp @@ -25,13 +25,14 @@ #include <chaos/ui_toolkit/LowLevelApi/LLRpcApi.h> #include <chaos/ui_toolkit/HighLevelApi/HLDataApi.h> -#define OPT_CU_ID "device-id" -#define OPT_CDS_ADDRESS "cds-address" -#define OPT_SNAP_NAME "snapshot-name" -#define OPT_SNAPSHOT_OP "op" - +#define OPT_CU_ID "device-id" +#define OPT_CDS_ADDRESS "cds-address" +#define OPT_SNAP_NAME "snapshot-name" +#define OPT_SNAPSHOT_OP "op" +#define OPT_SNAPSHOT_DS_TYPE "dataset_type" using namespace chaos; using namespace chaos::ui; +using namespace chaos::common::data; int main(int argc, char * argv[]) { int64_t err = 0; @@ -39,12 +40,14 @@ int main(int argc, char * argv[]) { std::vector<std::string> device_id_list; std::string snap_name; std::string cds_addr; + uint32_t ds_type; unsigned int operation; try{ ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->addOption<std::string>(OPT_CDS_ADDRESS, "CDS address", &cds_addr); ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->addOption< std::vector<std::string> >(OPT_CU_ID, "The identification string of the device to snapshuot", &device_id_list); ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->addOption<std::string>(OPT_SNAP_NAME, "The name of the snapshot", &snap_name); - ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->addOption<unsigned int>(OPT_SNAPSHOT_OP, "Operation on snapshot [create(0), delete(1)]", 0, &operation); + ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->addOption<unsigned int>(OPT_SNAPSHOT_OP, "Operation on snapshot [create(0), delete(1), get(2)]", 0, &operation); + ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->addOption<unsigned int>(OPT_SNAPSHOT_DS_TYPE, "Dataset type [output(0), input(1), custom(2), system(3)]", 0, &ds_type); ChaosUIToolkit::getInstance()->init(argc, argv); //! [UIToolkit Init] @@ -55,27 +58,78 @@ int main(int argc, char * argv[]) { if(!ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->hasOption(OPT_SNAP_NAME)){ throw CException(-2, "Invalid snapshot name set", "check param"); } - - if(!snap_name.size()) throw CException(-3, "Snapshot name can't zero-length", "check param"); + if(!ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->hasOption(OPT_SNAPSHOT_OP)){ + throw CException(-3, "Invalid operation set", "check param"); + } + if(!snap_name.size()) throw CException(-4, "Snapshot name can't zero-length", "check param"); SystemApiChannel *system_api_channel = LLRpcApi::getInstance()->getSystemApiClientChannel(cds_addr); + if(!system_api_channel) throw CException(-5, "Invalid system api channel instance", "getSystemApiClientChannel"); chaos::common::direct_io::channel::opcode_headers::DirectIOSystemAPISnapshotResultPtr system_api_result = NULL; - - //!make snap on device - if(!(err = system_api_channel->system_api_channel->makeNewDatasetSnapshot(snap_name, - device_id_list, - &system_api_result))){ - if(system_api_result) { - std::cout << "Snapshot creation report: " << std::endl; - std::cout << "Error code:" << system_api_result->error << std::endl; - std::cout << "Error message:" << system_api_result->error_message << std::endl; - free(system_api_result); - } else { - std::cout << "no result received" << std::endl; + switch(operation) { + case 0:{//new + //!make snap on device + if(!(err = system_api_channel->system_api_channel->makeNewDatasetSnapshot(snap_name, + device_id_list, + &system_api_result))){ + if(system_api_result) { + std::cout << "Snapshot creation report: " << std::endl; + std::cout << "Error code:" << system_api_result->error << std::endl; + std::cout << "Error message:" << system_api_result->error_message << std::endl; + free(system_api_result); + } else { + std::cout << "no result received" << std::endl; + } + } else { + std::cout << "Error executing directio call" << std::endl; + } + break; + } + case 1:{//delete + if(!(err = system_api_channel->system_api_channel->deleteDatasetSnapshot(snap_name, + &system_api_result))){ + if(system_api_result) { + std::cout << "Snapshot delete report: " << std::endl; + std::cout << "Error code:" << system_api_result->error << std::endl; + std::cout << "Error message:" << system_api_result->error_message << std::endl; + free(system_api_result); + } else { + std::cout << "no result received" << std::endl; + } + } else { + std::cout << "Error executing directio call" << std::endl; + } + break; + } + case 2:{//get + if(device_id_list.size()!=1) throw CException(-6, "For get oepration only a single producer key is required", "Get snapshot dataset operation"); + if(!ChaosUIToolkit::getInstance()->getGlobalConfigurationInstance()->hasOption(OPT_SNAPSHOT_DS_TYPE)){ + throw CException(-7, "The type of dataset is mandatory in get operation", "Get dataset from snapshot"); + } + chaos::common::direct_io::channel::opcode_headers::DirectIOSystemAPIGetDatasetSnapshotResultPtr get_system_api_result = NULL; + if(!(err = system_api_channel->system_api_channel->getDatasetSnapshotForProducerKey(snap_name, + device_id_list[0], + ds_type, + &get_system_api_result))){ + if(get_system_api_result) { + std::cout << "Snapshot delete report: " << std::endl; + std::cout << "Error code:" << get_system_api_result->api_result.error << std::endl; + std::cout << "Error message:" << get_system_api_result->api_result.error_message << std::endl; + if(get_system_api_result->channel_data) { + auto_ptr<CDataWrapper> data(new CDataWrapper(((char*)get_system_api_result+sizeof(chaos::common::direct_io::channel::opcode_headers::DirectIOSystemAPISnapshotResult) + 4))); + std::cout << "Data found-------------------------"<< std::endl; + std::cout << data->getJSONString() << std::endl; + } + free(get_system_api_result); + } else { + std::cout << "no result received" << std::endl; + } + } else { + std::cout << "Error executing directio call" << std::endl; + } + break; } - } else { - std::cout << "Error executing directio call" << std::endl; } if(system_api_channel) { diff --git a/chaos/common/direct_io/channel/DirectIODeviceChannelGlobal.h b/chaos/common/direct_io/channel/DirectIODeviceChannelGlobal.h index 661191acf8622574a0a7be89794d7713ecbfc106..3f5bed71a9dad83a63912921832cd63c78b9d130 100644 --- a/chaos/common/direct_io/channel/DirectIODeviceChannelGlobal.h +++ b/chaos/common/direct_io/channel/DirectIODeviceChannelGlobal.h @@ -223,7 +223,7 @@ namespace chaos { //-----------------------------------SYSTEM CHANNEL-------------------------------- #pragma mark System Channel -#define SYSTEM_API_CHANNEL_NEW_Snapshot 256+4 +#define SYSTEM_API_CHANNEL_NEW_Snapshot 256+4+4 //! Header for the snapshot system api managment for new, delete and get managment /*! @@ -240,6 +240,10 @@ namespace chaos { struct header { //!is the snapshot name char snap_name[256]; + + //! the type of channel + uint32_t channel_type; + //! is the lenght of comma separated list of the //! producer to include on the snapshot, if it is //! empty all the producer are snapped. The list is @@ -262,13 +266,10 @@ namespace chaos { DirectIOSystemAPISnapshotResult api_result; //channels lenght - uint32_t output_channel_len; - uint32_t input_channel_len; - uint32_t custom_channel_len; - uint32_t system_channel_len; + uint32_t channel_len; //!concatenated channels data in order [o,i,c,s] - void* channels_data; + void* channel_data; }DirectIOSystemAPIGetDatasetSnapshotResult, *DirectIOSystemAPIGetDatasetSnapshotResultPtr; } diff --git a/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.cpp b/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.cpp index b1eed03c2674aa61a77a99a9c0e52e3212648a6e..1cb78b8b676da744beb5f06947e0d6966af9e9e6 100644 --- a/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.cpp +++ b/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.cpp @@ -148,6 +148,7 @@ int64_t DirectIOSystemAPIClientChannel::deleteDatasetSnapshot(const std::string& //! get the snapshot for one or more producer key int64_t DirectIOSystemAPIClientChannel::getDatasetSnapshotForProducerKey(const std::string& snapshot_name, const std::string& producer_key, + uint32_t channel_type, DirectIOSystemAPIGetDatasetSnapshotResult **api_result_handle) { int64_t err = 0; DirectIOSynchronousAnswer *answer = NULL; @@ -167,6 +168,7 @@ int64_t DirectIOSystemAPIClientChannel::getDatasetSnapshotForProducerKey(const s //copy the snapshot name to the header std::memcpy(get_snapshot_opcode_header->field.snap_name, snapshot_name.c_str(), snapshot_name.size()); + get_snapshot_opcode_header->field.channel_type = channel_type; //set header DIRECT_IO_SET_CHANNEL_HEADER(data_pack, get_snapshot_opcode_header, sizeof(DirectIOSystemAPIChannelOpcodeNDGSnapshotHeader)) @@ -187,7 +189,7 @@ int64_t DirectIOSystemAPIClientChannel::getDatasetSnapshotForProducerKey(const s if(answer && answer->answer_data) free(answer->answer_data); } else { //we got answer - if(answer && answer->answer_size == sizeof(DirectIOSystemAPISnapshotResult)) { + if(answer) { *api_result_handle = static_cast<DirectIOSystemAPIGetDatasetSnapshotResult*>(answer->answer_data); (*api_result_handle)->api_result.error = FROM_LITTLE_ENDNS_NUM(int32_t, (*api_result_handle)->api_result.error); } else { diff --git a/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.h b/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.h index 87bc2ac4ee4f0ecdaad0397fedc5989ecaf171f5..780cf7529e2fdb9653f6121011e669b36a1c9c7c 100644 --- a/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.h +++ b/chaos/common/direct_io/channel/DirectIOSystemAPIClientChannel.h @@ -78,10 +78,12 @@ namespace chaos { Retrieve the dataset form the snapshot for one or more producer key. Is possible to decide the type of the snapshot to get \param snapshot_name the name of the snapshot to delete + \param channel_type the type of the channel [0-output, 1-input, 2-custom, 3-system]] \param producer_key the key of the producer for wich return the datasets */ int64_t getDatasetSnapshotForProducerKey(const std::string& snapshot_name, const std::string& producer_key, + uint32_t channel_type, DirectIOSystemAPIGetDatasetSnapshotResult **api_result_handle); }; } diff --git a/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.cpp b/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.cpp index 5bea5ea045684665283844d23bcce558de602671..f8c3757139efebdd7597e628483ac42f155d1eee 100644 --- a/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.cpp +++ b/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.cpp @@ -87,27 +87,38 @@ int DirectIOSystemAPIServerChannel::consumeDataPack(DirectIODataPack *dataPack, case opcode::SystemAPIChannelOpcodeGetSnapshotDatasetForAKey: { std::string producer_key; - //set the answer pointer - synchronous_answer->answer_data = std::calloc(sizeof(DirectIOSystemAPIGetDatasetSnapshotResult), 1); - synchronous_answer->answer_size = sizeof(DirectIOSystemAPIGetDatasetSnapshotResult); + void *channel_found_data = NULL; + uint32_t channel_found_data_length = 0; //get the header + DirectIOSystemAPIGetDatasetSnapshotResult *result_data = (DirectIOSystemAPIGetDatasetSnapshotResult*)std::calloc(sizeof(DirectIOSystemAPIGetDatasetSnapshotResult), 1); opcode_headers::DirectIOSystemAPIChannelOpcodeNDGSnapshotHeaderPtr header = reinterpret_cast< opcode_headers::DirectIOSystemAPIChannelOpcodeNDGSnapshotHeaderPtr >(dataPack->channel_header_data); header->field.producer_key_set_len = FROM_LITTLE_ENDNS_NUM(uint32_t, header->field.producer_key_set_len); //chec if a producere key has been forwarded - if(!dataPack->header.channel_data_size) { + if(dataPack->header.channel_data_size) { //set error producer_key.assign((const char*)dataPack->channel_data, dataPack->header.channel_data_size); //delete the memory where is located producer key free(dataPack->channel_data); } - //call the handler handler->consumeGetDatasetSnapshotEvent(header, producer_key, - (DirectIOSystemAPIGetDatasetSnapshotResult*)synchronous_answer->answer_data); + &channel_found_data, + channel_found_data_length, + &result_data->api_result); + //set the answer pointer + if(channel_found_data) { + //whe have data to return + result_data = (DirectIOSystemAPIGetDatasetSnapshotResult*)std::realloc(result_data, (synchronous_answer->answer_size = (channel_found_data_length+sizeof(DirectIOSystemAPIGetDatasetSnapshotResult)))); + synchronous_answer->answer_data = result_data; + + std::memcpy(((char*)result_data+sizeof(DirectIOSystemAPISnapshotResult)+4), channel_found_data, channel_found_data_length); + ((DirectIOSystemAPIGetDatasetSnapshotResult*)synchronous_answer->answer_data)->channel_len = channel_found_data_length; + free(channel_found_data); + } //fix endianes into api result ((DirectIOSystemAPIGetDatasetSnapshotResult*)synchronous_answer->answer_data)->api_result.error = TO_LITTE_ENDNS_NUM(int32_t, ((DirectIOSystemAPIGetDatasetSnapshotResult*)synchronous_answer->answer_data)->api_result.error); diff --git a/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.h b/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.h index 2f1d3101a0a413a3a561987f39f219560fc6c29c..1bad177a8390b1c9ed20e0650f0bf6e6da29fd8d 100644 --- a/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.h +++ b/chaos/common/direct_io/channel/DirectIOSystemAPIServerChannel.h @@ -80,7 +80,9 @@ namespace chaos { */ virtual int consumeGetDatasetSnapshotEvent(opcode_headers::DirectIOSystemAPIChannelOpcodeNDGSnapshotHeader *header, const std::string& producer_id, - DirectIOSystemAPIGetDatasetSnapshotResult *api_result) + void **channel_found_data, + uint32_t& channel_found_data_length, + DirectIOSystemAPISnapshotResult *api_result) {DELETE_HEADER(header) return 0;}; } DirectIOSystemAPIServerChannelHandler;