StoreStatus ServerContext::Store(std::string& resultPublicId, DicomInstanceToStore& dicom) { try { StorageAccessor accessor(area_); DicomInstanceHasher hasher(dicom.GetSummary()); resultPublicId = hasher.HashInstance(); Json::Value simplifiedTags; Toolbox::SimplifyTags(simplifiedTags, dicom.GetJson(), DicomToJsonFormat_Human); // Test if the instance must be filtered out bool accepted = true; { boost::recursive_mutex::scoped_lock lock(listenersMutex_); for (ServerListeners::iterator it = listeners_.begin(); it != listeners_.end(); ++it) { try { if (!it->GetListener().FilterIncomingInstance(dicom, simplifiedTags)) { accepted = false; break; } } catch (OrthancException& e) { LOG(ERROR) << "Error in the " << it->GetDescription() << " callback while receiving an instance: " << e.What(); throw; } } } if (!accepted) { LOG(INFO) << "An incoming instance has been discarded by the filter"; return StoreStatus_FilteredOut; } // TODO Should we use "gzip" instead? CompressionType compression = (compressionEnabled_ ? CompressionType_ZlibWithSize : CompressionType_None); FileInfo dicomInfo = accessor.Write(dicom.GetBufferData(), dicom.GetBufferSize(), FileContentType_Dicom, compression, storeMD5_); FileInfo jsonInfo = accessor.Write(dicom.GetJson().toStyledString(), FileContentType_DicomAsJson, compression, storeMD5_); ServerIndex::Attachments attachments; attachments.push_back(dicomInfo); attachments.push_back(jsonInfo); typedef std::map<MetadataType, std::string> InstanceMetadata; InstanceMetadata instanceMetadata; StoreStatus status = index_.Store(instanceMetadata, dicom, attachments); // Only keep the metadata for the "instance" level dicom.GetMetadata().clear(); for (InstanceMetadata::const_iterator it = instanceMetadata.begin(); it != instanceMetadata.end(); ++it) { dicom.GetMetadata().insert(std::make_pair(std::make_pair(ResourceType_Instance, it->first), it->second)); } if (status != StoreStatus_Success) { accessor.Remove(dicomInfo); accessor.Remove(jsonInfo); } switch (status) { case StoreStatus_Success: LOG(INFO) << "New instance stored"; break; case StoreStatus_AlreadyStored: LOG(INFO) << "Already stored"; break; case StoreStatus_Failure: LOG(ERROR) << "Store failure"; break; default: // This should never happen break; } if (status == StoreStatus_Success || status == StoreStatus_AlreadyStored) { boost::recursive_mutex::scoped_lock lock(listenersMutex_); for (ServerListeners::iterator it = listeners_.begin(); it != listeners_.end(); ++it) { try { it->GetListener().SignalStoredInstance(resultPublicId, dicom, simplifiedTags); } catch (OrthancException& e) { LOG(ERROR) << "Error in the " << it->GetDescription() << " callback while receiving an instance: " << e.What(); } } } return status; } catch (OrthancException& e) { if (e.GetErrorCode() == ErrorCode_InexistentTag) { Toolbox::LogMissingRequiredTag(dicom.GetSummary()); } throw; } }
StoreStatus ServerContext::Store(const char* dicomInstance, size_t dicomSize, const DicomMap& dicomSummary, const Json::Value& dicomJson, const std::string& remoteAet) { // Test if the instance must be filtered out if (lua_.IsExistingFunction(RECEIVED_INSTANCE_FILTER)) { Json::Value simplified; SimplifyTags(simplified, dicomJson); LuaFunctionCall call(lua_, RECEIVED_INSTANCE_FILTER); call.PushJSON(simplified); call.PushString(remoteAet); if (!call.ExecutePredicate()) { LOG(INFO) << "An incoming instance has been discarded by the filter"; return StoreStatus_FilteredOut; } } if (compressionEnabled_) { accessor_.SetCompressionForNextOperations(CompressionType_Zlib); } else { accessor_.SetCompressionForNextOperations(CompressionType_None); } FileInfo dicomInfo = accessor_.Write(dicomInstance, dicomSize, FileContentType_Dicom); FileInfo jsonInfo = accessor_.Write(dicomJson.toStyledString(), FileContentType_Json); ServerIndex::Attachments attachments; attachments.push_back(dicomInfo); attachments.push_back(jsonInfo); StoreStatus status = index_.Store(dicomSummary, attachments, remoteAet); if (status != StoreStatus_Success) { storage_.Remove(dicomInfo.GetUuid()); storage_.Remove(jsonInfo.GetUuid()); } switch (status) { case StoreStatus_Success: LOG(INFO) << "New instance stored"; break; case StoreStatus_AlreadyStored: LOG(INFO) << "Already stored"; break; case StoreStatus_Failure: LOG(ERROR) << "Store failure"; break; default: // This should never happen break; } return status; }