@@ -112,26 +112,37 @@ private File increaseFileReference(
112112
113113 segmentLock .lock (hardlinkOrCopiedFile );
114114 try {
115- resultFile =
116- isTsFile
117- ? FileUtils .createHardLink (source , hardlinkOrCopiedFile )
118- : FileUtils .copyFile (source , hardlinkOrCopiedFile );
119-
120- // If the file is not a hardlink or copied file, and there is no related hardlink or copied
121- // file in pipe dir, create a hardlink or copy it to pipe dir, maintain a reference count for
122- // the hardlink or copied file, and return the hardlink or copied file.
123- if (Objects .nonNull (pipeName )) {
124- hardlinkOrCopiedFileToPipeTsFileResourceMap
125- .computeIfAbsent (pipeName , k -> new ConcurrentHashMap <>())
126- .put (resultFile .getPath (), new PipeTsFileResource (resultFile ));
115+ final PipeTsFileResource existingResource =
116+ getResourceMap (pipeName ).get (hardlinkOrCopiedFile .getPath ());
117+ if (existingResource != null ) {
118+ existingResource .increaseReferenceCount ();
119+ resultFile = existingResource .getFile ();
127120 } else {
128- hardlinkOrCopiedFileToTsFilePublicResourceMap .put (
129- resultFile .getPath (), new PipeTsFilePublicResource (resultFile ));
121+ resultFile =
122+ isTsFile
123+ ? FileUtils .createHardLink (source , hardlinkOrCopiedFile )
124+ : FileUtils .copyFile (source , hardlinkOrCopiedFile );
125+
126+ // Create the hardlink or copy and its reference-counted resource only when none exists.
127+ if (Objects .nonNull (pipeName )) {
128+ hardlinkOrCopiedFileToPipeTsFileResourceMap
129+ .computeIfAbsent (pipeName , k -> new ConcurrentHashMap <>())
130+ .put (resultFile .getPath (), new PipeTsFileResource (resultFile ));
131+ } else {
132+ hardlinkOrCopiedFileToTsFilePublicResourceMap .put (
133+ resultFile .getPath (), new PipeTsFilePublicResource (resultFile ));
134+ }
130135 }
131136 } finally {
132137 segmentLock .unlock (hardlinkOrCopiedFile );
133138 }
134- increasePublicReference (resultFile , pipeName , isTsFile );
139+ try {
140+ increasePublicReference (resultFile , pipeName , isTsFile );
141+ } catch (final IOException e ) {
142+ // The private reference must not outlive a failed public reference increase.
143+ decreaseFileReference (resultFile , pipeName , false );
144+ throw e ;
145+ }
135146 return resultFile ;
136147 }
137148
@@ -216,6 +227,13 @@ private static String getRelativeFilePath(File file) {
216227 */
217228 public void decreaseFileReference (
218229 final File hardlinkOrCopiedFile , final @ Nullable String pipeName ) {
230+ decreaseFileReference (hardlinkOrCopiedFile , pipeName , true );
231+ }
232+
233+ private void decreaseFileReference (
234+ final File hardlinkOrCopiedFile ,
235+ final @ Nullable String pipeName ,
236+ final boolean decreasePublicReference ) {
219237 segmentLock .lock (hardlinkOrCopiedFile );
220238 try {
221239 final String filePath = hardlinkOrCopiedFile .getPath ();
@@ -229,7 +247,9 @@ public void decreaseFileReference(
229247
230248 // Decrease the assigner's file to clear hard-link and memory cache
231249 // Note that it does not exist for historical files
232- decreasePublicReferenceIfExists (hardlinkOrCopiedFile , pipeName );
250+ if (decreasePublicReference ) {
251+ decreasePublicReferenceIfExists (hardlinkOrCopiedFile , pipeName );
252+ }
233253 }
234254
235255 private void decreasePublicReferenceIfExists (final File file , final @ Nullable String pipeName ) {
@@ -340,6 +360,7 @@ public Map<String, TSDataType> getMeasurementDataTypeMapFromCache(
340360 }
341361 }
342362
363+ /** Returns the shared public resource map when {@code pipeName} is null. */
343364 public Map <String , ? extends PipeTsFileResource > getResourceMap (final @ Nullable String pipeName ) {
344365 return Objects .nonNull (pipeName )
345366 ? hardlinkOrCopiedFileToPipeTsFileResourceMap .computeIfAbsent (
0 commit comments