From: <gun...@us...> - 2010-02-18 13:21:03
|
Revision: 12785 http://dcm4che.svn.sourceforge.net/dcm4che/?rev=12785&view=rev Author: gunterze Date: 2010-02-18 13:20:56 +0000 (Thu, 18 Feb 2010) Log Message: ----------- [#DCMEE-1340] System crash may cause truncated files on disk of just received objects Modified Paths: -------------- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-storescp-xmbean.xml dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScp.java dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScpService.java Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-storescp-xmbean.xml =================================================================== --- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-storescp-xmbean.xml 2010-02-18 13:19:22 UTC (rev 12784) +++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-storescp-xmbean.xml 2010-02-18 13:20:56 UTC (rev 12785) @@ -409,6 +409,39 @@ </descriptors> </attribute> <attribute access="read-write" + getMethod="isSyncFileBeforeCStoreRSP" + setMethod="setSyncFileBeforeCStoreRSP"> + <description><![CDATA[Flush file system buffers after storage of received + objects <b>before</b> sending successful C-STORE RSP. <b>Excludes</b> + possibility of truncated files on disk, caused by a system crash just + after storage of a received object because the OS disk cache may not + yet have written to the storage device, at the expense of storage + performance.]]> + </description> + <name>SyncFileBeforeCStoreRSP</name> + <type>boolean</type> + <descriptors> + <value value="true"/> + </descriptors> + </attribute> + <attribute access="read-write" + getMethod="isSyncFileAfterCStoreRSP" + setMethod="setSyncFileAfterCStoreRSP"> + <description><![CDATA[Flush file system buffers after storage of received + objects <b>after</b> sending successful C-STORE RSP. <b>Minimize</b> + likilihood of truncated files on disk, caused by a system crash just + after storage of a received object because the OS disk cache may not + yet have written to the storage device, <b>without</b> significant + decrease of storage performance. Only effective, if + <b>SyncFileBeforeCStoreRSP</b> is <code>false</code>.]]> + </description> + <name>SyncFileAfterCStoreRSP</name> + <type>boolean</type> + <descriptors> + <value value="false"/> + </descriptors> + </attribute> + <attribute access="read-write" getMethod="isStoreDuplicateIfDiffMD5" setMethod="setStoreDuplicateIfDiffMD5"> <description><![CDATA[Store a duplicate object if the MD5 sum of the Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScp.java =================================================================== --- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScp.java 2010-02-18 13:19:22 UTC (rev 12784) +++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScp.java 2010-02-18 13:20:56 UTC (rev 12785) @@ -58,6 +58,10 @@ import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import javax.ejb.CreateException; import javax.ejb.FinderException; @@ -197,6 +201,8 @@ private PerfMonDelegate perfMon; + private volatile Executor syncFileExecutor; + public StoreScp(StoreScpService service) { this.service = service; this.log = service.getLog(); @@ -1046,7 +1052,7 @@ .hashCode()); } - private byte[] storeToFile(DcmParser parser, Dataset ds, File file, + private byte[] storeToFile(DcmParser parser, Dataset ds, final File file, CompressCmd compressCmd, byte[] buffer) throws Exception { log.info("M-WRITE file:" + file); MessageDigest md = null; @@ -1093,18 +1099,48 @@ parser.parseDataset(decParam, -1); ds.subSet(Tags.PixelData, -1).writeDataset(bos, encParam); } - // ensure data is written on storage device - // before returning successful C-STORE RSP bos.flush(); - fos.getFD().sync(); + if (service.isSyncFileBeforeCStoreRSP()) { + fos.getFD().sync(); + } else if (service.isSyncFileAfterCStoreRSP()) { + final FileOutputStream fos2 = fos; + syncFileExecutor().execute(new Runnable() { + public void run() { + try { + fos2.getFD().sync(); + } catch (Exception e) { + log.error("sync of " + file + " failed:", e); + } finally { + try { + fos2.close(); + } catch (Exception ignore) {} + } + }}); + fos = null; + } } finally { - try { - fos.close(); - } catch (Exception ignore) {} + if (fos != null) + try { + fos.close(); + } catch (Exception ignore) {} } return md != null ? md.digest() : null; } + private Executor syncFileExecutor() { + Executor result = syncFileExecutor; + if (result == null) { + synchronized (this) { + result = syncFileExecutor; + if (result == null) { + syncFileExecutor = result + = Executors.newSingleThreadExecutor(); + } + } + } + return result; + } + private static void skipFully(InputStream in, int n) throws IOException { int remaining = n; int skipped = 0; Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScpService.java =================================================================== --- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScpService.java 2010-02-18 13:19:22 UTC (rev 12784) +++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/dcm/storescp/StoreScpService.java 2010-02-18 13:20:56 UTC (rev 12785) @@ -208,6 +208,10 @@ private boolean md5sum = true; + private boolean syncFileBeforeCStoreRSP = true; + + private boolean syncFileAfterCStoreRSP = false; + private StoreScp scp = null; public StoreScpService() { @@ -272,6 +276,22 @@ this.md5sum = md5sum; } + public final void setSyncFileBeforeCStoreRSP(boolean syncFileBeforeCStoreRSP) { + this.syncFileBeforeCStoreRSP = syncFileBeforeCStoreRSP; + } + + public final boolean isSyncFileBeforeCStoreRSP() { + return syncFileBeforeCStoreRSP; + } + + public final void setSyncFileAfterCStoreRSP(boolean syncFileAfterCStoreRSP) { + this.syncFileAfterCStoreRSP = syncFileAfterCStoreRSP; + } + + public final boolean isSyncFileAfterCStoreRSP() { + return syncFileAfterCStoreRSP; + } + public int getMaxValueLength() { return maxValueLength; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |