Mercurial > hg > orthanc
comparison OrthancServer/Sources/ServerIndex.cpp @ 4565:3495a3d97ab6 db-changes
start of read-write transactions
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 08 Mar 2021 12:34:17 +0100 |
parents | 5a0adc1c19a9 |
children | f52d0bc19e07 |
comparison
equal
deleted
inserted
replaced
4564:5a0adc1c19a9 | 4565:3495a3d97ab6 |
---|---|
430 } | 430 } |
431 } | 431 } |
432 }; | 432 }; |
433 | 433 |
434 | 434 |
435 bool ServerIndex::DeleteResource(Json::Value& target, | |
436 const std::string& uuid, | |
437 ResourceType expectedType) | |
438 { | |
439 boost::mutex::scoped_lock lock(mutex_); | |
440 | |
441 Transaction t(*this); | |
442 | |
443 int64_t id; | |
444 ResourceType type; | |
445 if (!db_.LookupResource(id, type, uuid) || | |
446 expectedType != type) | |
447 { | |
448 return false; | |
449 } | |
450 | |
451 db_.DeleteResource(id); | |
452 | |
453 if (listener_->HasRemainingLevel()) | |
454 { | |
455 ResourceType remainingType = listener_->GetRemainingType(); | |
456 const std::string& remainingUuid = listener_->GetRemainingPublicId(); | |
457 | |
458 target["RemainingAncestor"] = Json::Value(Json::objectValue); | |
459 target["RemainingAncestor"]["Path"] = GetBasePath(remainingType, remainingUuid); | |
460 target["RemainingAncestor"]["Type"] = EnumerationToString(remainingType); | |
461 target["RemainingAncestor"]["ID"] = remainingUuid; | |
462 } | |
463 else | |
464 { | |
465 target["RemainingAncestor"] = Json::nullValue; | |
466 } | |
467 | |
468 t.Commit(0); | |
469 | |
470 return true; | |
471 } | |
472 | |
473 | |
474 void ServerIndex::FlushThread(ServerIndex* that, | 435 void ServerIndex::FlushThread(ServerIndex* that, |
475 unsigned int threadSleep) | 436 unsigned int threadSleep) |
476 { | 437 { |
477 // By default, wait for 10 seconds before flushing | 438 // By default, wait for 10 seconds before flushing |
478 unsigned int sleep = 10; | 439 unsigned int sleep = 10; |
1158 | 1119 |
1159 target["Last"] = static_cast<int>(last); | 1120 target["Last"] = static_cast<int>(last); |
1160 } | 1121 } |
1161 | 1122 |
1162 | 1123 |
1163 void ServerIndex::LogExportedResource(const std::string& publicId, | |
1164 const std::string& remoteModality) | |
1165 { | |
1166 boost::mutex::scoped_lock lock(mutex_); | |
1167 Transaction transaction(*this); | |
1168 | |
1169 int64_t id; | |
1170 ResourceType type; | |
1171 if (!db_.LookupResource(id, type, publicId)) | |
1172 { | |
1173 throw OrthancException(ErrorCode_InexistentItem); | |
1174 } | |
1175 | |
1176 std::string patientId; | |
1177 std::string studyInstanceUid; | |
1178 std::string seriesInstanceUid; | |
1179 std::string sopInstanceUid; | |
1180 | |
1181 int64_t currentId = id; | |
1182 ResourceType currentType = type; | |
1183 | |
1184 // Iteratively go up inside the patient/study/series/instance hierarchy | |
1185 bool done = false; | |
1186 while (!done) | |
1187 { | |
1188 DicomMap map; | |
1189 db_.GetMainDicomTags(map, currentId); | |
1190 | |
1191 switch (currentType) | |
1192 { | |
1193 case ResourceType_Patient: | |
1194 if (map.HasTag(DICOM_TAG_PATIENT_ID)) | |
1195 { | |
1196 patientId = map.GetValue(DICOM_TAG_PATIENT_ID).GetContent(); | |
1197 } | |
1198 done = true; | |
1199 break; | |
1200 | |
1201 case ResourceType_Study: | |
1202 if (map.HasTag(DICOM_TAG_STUDY_INSTANCE_UID)) | |
1203 { | |
1204 studyInstanceUid = map.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).GetContent(); | |
1205 } | |
1206 currentType = ResourceType_Patient; | |
1207 break; | |
1208 | |
1209 case ResourceType_Series: | |
1210 if (map.HasTag(DICOM_TAG_SERIES_INSTANCE_UID)) | |
1211 { | |
1212 seriesInstanceUid = map.GetValue(DICOM_TAG_SERIES_INSTANCE_UID).GetContent(); | |
1213 } | |
1214 currentType = ResourceType_Study; | |
1215 break; | |
1216 | |
1217 case ResourceType_Instance: | |
1218 if (map.HasTag(DICOM_TAG_SOP_INSTANCE_UID)) | |
1219 { | |
1220 sopInstanceUid = map.GetValue(DICOM_TAG_SOP_INSTANCE_UID).GetContent(); | |
1221 } | |
1222 currentType = ResourceType_Series; | |
1223 break; | |
1224 | |
1225 default: | |
1226 throw OrthancException(ErrorCode_InternalError); | |
1227 } | |
1228 | |
1229 // If we have not reached the Patient level, find the parent of | |
1230 // the current resource | |
1231 if (!done) | |
1232 { | |
1233 bool ok = db_.LookupParent(currentId, currentId); | |
1234 (void) ok; // Remove warning about unused variable in release builds | |
1235 assert(ok); | |
1236 } | |
1237 } | |
1238 | |
1239 ExportedResource resource(-1, | |
1240 type, | |
1241 publicId, | |
1242 remoteModality, | |
1243 SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */), | |
1244 patientId, | |
1245 studyInstanceUid, | |
1246 seriesInstanceUid, | |
1247 sopInstanceUid); | |
1248 | |
1249 db_.LogExportedResource(resource); | |
1250 transaction.Commit(0); | |
1251 } | |
1252 | |
1253 | |
1254 bool ServerIndex::IsRecyclingNeeded(uint64_t instanceSize) | 1124 bool ServerIndex::IsRecyclingNeeded(uint64_t instanceSize) |
1255 { | 1125 { |
1256 if (maximumStorageSize_ != 0) | 1126 if (maximumStorageSize_ != 0) |
1257 { | 1127 { |
1258 assert(maximumStorageSize_ >= instanceSize); | 1128 assert(maximumStorageSize_ >= instanceSize); |
1991 } | 1861 } |
1992 else | 1862 else |
1993 { | 1863 { |
1994 assert(writeOperations != NULL); | 1864 assert(writeOperations != NULL); |
1995 ReadWriteTransaction t(db_); | 1865 ReadWriteTransaction t(db_); |
1996 writeOperations->Apply(t); | 1866 writeOperations->Apply(t, *listener_); |
1997 } | 1867 } |
1998 | 1868 |
1999 transaction.Commit(0); | 1869 transaction.Commit(0); |
2000 | 1870 |
2001 return; // Success | 1871 return; // Success |
3246 if (instancesId != NULL) | 3116 if (instancesId != NULL) |
3247 { | 3117 { |
3248 CopyListToVector(*instancesId, operations.GetInstancesList()); | 3118 CopyListToVector(*instancesId, operations.GetInstancesList()); |
3249 } | 3119 } |
3250 } | 3120 } |
3121 | |
3122 | |
3123 bool ServerIndex::DeleteResource(Json::Value& target, | |
3124 const std::string& uuid, | |
3125 ResourceType expectedType) | |
3126 { | |
3127 class Operations : public IReadWriteOperations | |
3128 { | |
3129 private: | |
3130 bool found_; | |
3131 Json::Value& target_; | |
3132 const std::string& uuid_; | |
3133 ResourceType expectedType_; | |
3134 | |
3135 public: | |
3136 Operations(Json::Value& target, | |
3137 const std::string& uuid, | |
3138 ResourceType expectedType) : | |
3139 found_(false), | |
3140 target_(target), | |
3141 uuid_(uuid), | |
3142 expectedType_(expectedType) | |
3143 { | |
3144 } | |
3145 | |
3146 bool IsFound() const | |
3147 { | |
3148 return found_; | |
3149 } | |
3150 | |
3151 virtual void Apply(ReadWriteTransaction& transaction, | |
3152 Listener& listener) ORTHANC_OVERRIDE | |
3153 { | |
3154 int64_t id; | |
3155 ResourceType type; | |
3156 if (!transaction.LookupResource(id, type, uuid_) || | |
3157 expectedType_ != type) | |
3158 { | |
3159 found_ = false; | |
3160 } | |
3161 else | |
3162 { | |
3163 found_ = true; | |
3164 transaction.DeleteResource(id); | |
3165 | |
3166 if (listener.HasRemainingLevel()) | |
3167 { | |
3168 ResourceType remainingType = listener.GetRemainingType(); | |
3169 const std::string& remainingUuid = listener.GetRemainingPublicId(); | |
3170 | |
3171 target_["RemainingAncestor"] = Json::Value(Json::objectValue); | |
3172 target_["RemainingAncestor"]["Path"] = GetBasePath(remainingType, remainingUuid); | |
3173 target_["RemainingAncestor"]["Type"] = EnumerationToString(remainingType); | |
3174 target_["RemainingAncestor"]["ID"] = remainingUuid; | |
3175 } | |
3176 else | |
3177 { | |
3178 target_["RemainingAncestor"] = Json::nullValue; | |
3179 } | |
3180 } | |
3181 } | |
3182 }; | |
3183 | |
3184 Operations operations(target, uuid, expectedType); | |
3185 Apply(operations); | |
3186 return operations.IsFound(); | |
3187 } | |
3188 | |
3189 | |
3190 void ServerIndex::LogExportedResource(const std::string& publicId, | |
3191 const std::string& remoteModality) | |
3192 { | |
3193 class Operations : public IReadWriteOperations | |
3194 { | |
3195 private: | |
3196 const std::string& publicId_; | |
3197 const std::string& remoteModality_; | |
3198 | |
3199 public: | |
3200 Operations(const std::string& publicId, | |
3201 const std::string& remoteModality) : | |
3202 publicId_(publicId), | |
3203 remoteModality_(remoteModality) | |
3204 { | |
3205 } | |
3206 | |
3207 virtual void Apply(ReadWriteTransaction& transaction, | |
3208 Listener& listener) ORTHANC_OVERRIDE | |
3209 { | |
3210 int64_t id; | |
3211 ResourceType type; | |
3212 if (!transaction.LookupResource(id, type, publicId_)) | |
3213 { | |
3214 throw OrthancException(ErrorCode_InexistentItem); | |
3215 } | |
3216 | |
3217 std::string patientId; | |
3218 std::string studyInstanceUid; | |
3219 std::string seriesInstanceUid; | |
3220 std::string sopInstanceUid; | |
3221 | |
3222 int64_t currentId = id; | |
3223 ResourceType currentType = type; | |
3224 | |
3225 // Iteratively go up inside the patient/study/series/instance hierarchy | |
3226 bool done = false; | |
3227 while (!done) | |
3228 { | |
3229 DicomMap map; | |
3230 transaction.GetMainDicomTags(map, currentId); | |
3231 | |
3232 switch (currentType) | |
3233 { | |
3234 case ResourceType_Patient: | |
3235 if (map.HasTag(DICOM_TAG_PATIENT_ID)) | |
3236 { | |
3237 patientId = map.GetValue(DICOM_TAG_PATIENT_ID).GetContent(); | |
3238 } | |
3239 done = true; | |
3240 break; | |
3241 | |
3242 case ResourceType_Study: | |
3243 if (map.HasTag(DICOM_TAG_STUDY_INSTANCE_UID)) | |
3244 { | |
3245 studyInstanceUid = map.GetValue(DICOM_TAG_STUDY_INSTANCE_UID).GetContent(); | |
3246 } | |
3247 currentType = ResourceType_Patient; | |
3248 break; | |
3249 | |
3250 case ResourceType_Series: | |
3251 if (map.HasTag(DICOM_TAG_SERIES_INSTANCE_UID)) | |
3252 { | |
3253 seriesInstanceUid = map.GetValue(DICOM_TAG_SERIES_INSTANCE_UID).GetContent(); | |
3254 } | |
3255 currentType = ResourceType_Study; | |
3256 break; | |
3257 | |
3258 case ResourceType_Instance: | |
3259 if (map.HasTag(DICOM_TAG_SOP_INSTANCE_UID)) | |
3260 { | |
3261 sopInstanceUid = map.GetValue(DICOM_TAG_SOP_INSTANCE_UID).GetContent(); | |
3262 } | |
3263 currentType = ResourceType_Series; | |
3264 break; | |
3265 | |
3266 default: | |
3267 throw OrthancException(ErrorCode_InternalError); | |
3268 } | |
3269 | |
3270 // If we have not reached the Patient level, find the parent of | |
3271 // the current resource | |
3272 if (!done) | |
3273 { | |
3274 bool ok = transaction.LookupParent(currentId, currentId); | |
3275 (void) ok; // Remove warning about unused variable in release builds | |
3276 assert(ok); | |
3277 } | |
3278 } | |
3279 | |
3280 ExportedResource resource(-1, | |
3281 type, | |
3282 publicId_, | |
3283 remoteModality_, | |
3284 SystemToolbox::GetNowIsoString(true /* use UTC time (not local time) */), | |
3285 patientId, | |
3286 studyInstanceUid, | |
3287 seriesInstanceUid, | |
3288 sopInstanceUid); | |
3289 | |
3290 transaction.LogExportedResource(resource); | |
3291 } | |
3292 }; | |
3293 | |
3294 Operations operations(publicId, remoteModality); | |
3295 Apply(operations); | |
3296 } | |
3251 } | 3297 } |