11/*
2- * Copyright (c) 2012, 2022 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2012, 2024 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -50,17 +50,16 @@ public class PortFile {
5050 // Followed by a 4 byte int, with the port nr.
5151 // Followed by a 8 byte long, with cookie nr.
5252
53- private String filename ;
54- private File file ;
55- private File stopFile ;
53+ private final String filename ;
54+ private final File file ;
55+ private final File stopFile ;
5656 private RandomAccessFile rwfile ;
57- private FileChannel channel ;
5857
5958 // FileLock used to solve inter JVM synchronization, lockSem used to avoid
6059 // JVM internal OverlappingFileLockExceptions.
6160 // Class invariant: lock.isValid() <-> lockSem.availablePermits() == 0
6261 private FileLock lock ;
63- private Semaphore lockSem = new Semaphore (1 );
62+ private final Semaphore lockSem = new Semaphore (1 );
6463
6564 private boolean containsPortInfo ;
6665 private int serverPort ;
@@ -89,17 +88,18 @@ private void initializeChannel() throws PortFileInaccessibleException {
8988 }
9089 // The rwfile should only be readable by the owner of the process
9190 // and no other! How do we do that on a RandomAccessFile?
92- channel = rwfile .getChannel ();
9391 }
9492
9593 /**
9694 * Lock the port file.
9795 */
9896 public void lock () throws IOException , InterruptedException {
99- if (channel == null ) {
100- initializeChannel ();
101- }
10297 lockSem .acquire ();
98+ if (rwfile != null ) {
99+ throw new IllegalStateException ("rwfile not null" );
100+ }
101+ initializeChannel ();
102+ FileChannel channel = rwfile .getChannel ();
103103 lock = channel .lock ();
104104 }
105105
@@ -110,8 +110,7 @@ public void lock() throws IOException, InterruptedException {
110110 public void getValues () {
111111 containsPortInfo = false ;
112112 if (lock == null ) {
113- // Not locked, remain ignorant about port file contents.
114- return ;
113+ throw new IllegalStateException ("Must lock before calling getValues" );
115114 }
116115 try {
117116 if (rwfile .length ()>0 ) {
@@ -156,6 +155,9 @@ public long getCookie() {
156155 * Store the values into the locked port file.
157156 */
158157 public void setValues (int port , long cookie ) throws IOException {
158+ if (lock == null ) {
159+ throw new IllegalStateException ("Must lock before calling setValues" );
160+ }
159161 rwfile .seek (0 );
160162 // Write the magic nr that identifies a port file.
161163 rwfile .writeInt (magicNr );
@@ -169,19 +171,19 @@ public void setValues(int port, long cookie) throws IOException {
169171 * Delete the port file.
170172 */
171173 public void delete () throws IOException , InterruptedException {
172- // Access to file must be closed before deleting.
173- rwfile .close ();
174-
175- file .delete ();
176-
177- // Wait until file has been deleted (deletes are asynchronous on Windows!) otherwise we
174+ if (!file .exists ()) { // file deleted already
175+ return ;
176+ }
177+ // Keep trying until file has been deleted, otherwise we
178178 // might shutdown the server and prevent another one from starting.
179- for (int i = 0 ; i < 10 && file .exists (); i ++) {
179+ for (int i = 0 ; i < 10 && file .exists () && ! file . delete () ; i ++) {
180180 Thread .sleep (1000 );
181181 }
182182 if (file .exists ()) {
183183 throw new IOException ("Failed to delete file." );
184184 }
185+ // allow some time for late clients to connect
186+ Thread .sleep (1000 );
185187 }
186188
187189 /**
@@ -210,10 +212,12 @@ public boolean markedForStop() throws IOException {
210212 */
211213 public void unlock () throws IOException {
212214 if (lock == null ) {
213- return ;
215+ throw new IllegalStateException ( "Not locked" ) ;
214216 }
215217 lock .release ();
216218 lock = null ;
219+ rwfile .close ();
220+ rwfile = null ;
217221 lockSem .release ();
218222 }
219223
0 commit comments