Rephrasing my original post after some research in dcm4che3 and dicom protocol.
I am using dcm4che3 toolkit to build an application that is essentially going to be a simple Image Archive able to forward studies on demand to other modalities.The tool also implements a s-store scu service to query itself but also other modalities.
A requirement is to able and "delete" periodically studies from this local archive.
I am also new to the dicom protocol and dcm4che, so i am trying to understand the logic of the underlying dicomdir (used by dcm4che-tool-dcmqrscp) as also any available services or methods for deleting studies.
So my questions are the following:
In the context of dicom protocol is it valid the term: "Delete a study"?
As i can see the "dcm4che-tool-dcmdir" when deleting a study (using the tool), what happens actually is to "delete records referring DICOM files specified by file.. or directory.. arguments from existing directory file by setting its Record In-use Flag = 0" so the files remain on the filesystem.
Even more if i try and delete a study in this way (-d option in tool-dicomdir) when i query the archive with my c-find scu, i can find the study. So even if the record in dicomdir is marked as Inactive if i perform a c-find query to the archive i can still fetch it.
If i try and delete study files manually from the filesystem i guess that the dicomdir becomes corrupted.
Are there any other ways (or part of protocol) for deleting in consistent way a study (permanently from dicomdir records but also from filesystem if possibly) from the dicomdir?
The code i use to delete the study (using similar approach with -d option in dicomdir) is:
public void deleteDicomDir(String studyDir) throws IOException {
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
LOG.info("$$$ Trying to delete dicomdir: " + studyDir);
main.open(new File("C:\\dicomrouter_dev\\dcmrouter_root\\dicomdir"));
main.removeReferenceTo(new File(studyDir));
main.close();
long end = System.currentTimeMillis();
System.out.println();
System.out.println(MessageFormat.format(
rb.getString("deleted"),
num, main.getFile(), (end - start)));
}
And what actually does the "removeReferenceTo()" method is calling at the end DicomDirWritter method:
public synchronized boolean deleteRecord(Attributes rec)
throws IOException {
if (rec.getInt(Tag.RecordInUseFlag, 0) == INACTIVE)
return false; // already disabled
for (Attributes lowerRec = readLowerDirectoryRecord(rec);
lowerRec != null;
lowerRec = readNextDirectoryRecord(lowerRec))
deleteRecord(lowerRec);
rec.setInt(Tag.RecordInUseFlag, VR.US, INACTIVE);
markAsDirty(rec);
return true;
}
Thanks for your time and i am looking forward for any info that will declare this
Actually after some research on dicom protocol as also dcm4che toolkit i am able to delete a study and synchonize my DICOMDIR and remove studies(or files) with Record In-use Flag = 0 in 3 steps:
//delete records referring DICOM files specified by <directory:studyDir> arguments from existing directory file <dicomdir> by setting its Record In-use Flag = 0
public void deleteDicomDir(String studyDir) {
String dicomdir = "C:\\dicomrouter_dev\\dcmrouter_root\\DICOMDIR";
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
try {
LOG.info("$$$ Trying to delete dicomdir: " + studyDir);
main.open(new File(dicomdir));
int num = 0;
main.removeReferenceTo(new File(studyDir));
main.close();
long end = System.currentTimeMillis();
System.out.println();
System.out.println(MessageFormat.format(
rb.getString("deleted"),
num, main.getFile(), (end - start)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(DcmDir1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
main.close();
}
}
//purge records without file references from directory file <dicomdir> by setting its Record In-use Flag = 0
public void purgeDicomDir() {
String dicomdir = "C:\\dicomrouter_dev\\dcmrouter_root\\DICOMDIR";
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
try {
main.open(new File(dicomdir));
int num = main.purge();
main.close();
long end = System.currentTimeMillis();
System.out.println(MessageFormat.format(
rb.getString("purged"),
num, main.getFile(), (end - start)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(DcmDir1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
main.close();
}
}
//compact existing directory file <dicomdir> by removing records with Record In-use Flag != 0
public void compactDicomDir() {
String fpath = "C:\\dicomrouter_dev\\dcmrouter_root\\DICOMDIR";
File f = new File(fpath);
File bak = new File(fpath + "~");
DcmDir1 main = new DcmDir1();
long start = System.currentTimeMillis();
try {
LOG.info("$$$ Trying to compact dicomdir: " + fpath);
main.compact(f, bak);
long end = System.currentTimeMillis();
System.out.println(MessageFormat.format(
rb.getString("compacted"),
f, bak.length(), f.length(), (end - start)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(DcmDir1.class.getName()).log(Level.SEVERE, null, ex);
} finally {
main.close();
}
}
Then i can also safely delete the files from the disk.