11/*
2- * Copyright (c) 2012, 2019 , 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
@@ -59,17 +59,16 @@ public class PortFile {
5959 // Followed by a 4 byte int, with the port nr.
6060 // Followed by a 8 byte long, with cookie nr.
6161
62- private String filename ;
63- private File file ;
64- private File stopFile ;
62+ private final String filename ;
63+ private final File file ;
64+ private final File stopFile ;
6565 private RandomAccessFile rwfile ;
66- private FileChannel channel ;
6766
6867 // FileLock used to solve inter JVM synchronization, lockSem used to avoid
6968 // JVM internal OverlappingFileLockExceptions.
7069 // Class invariant: lock.isValid() <-> lockSem.availablePermits() == 0
7170 private FileLock lock ;
72- private Semaphore lockSem = new Semaphore (1 );
71+ private final Semaphore lockSem = new Semaphore (1 );
7372
7473 private boolean containsPortInfo ;
7574 private int serverPort ;
@@ -98,17 +97,18 @@ private void initializeChannel() throws PortFileInaccessibleException {
9897 }
9998 // The rwfile should only be readable by the owner of the process
10099 // and no other! How do we do that on a RandomAccessFile?
101- channel = rwfile .getChannel ();
102100 }
103101
104102 /**
105103 * Lock the port file.
106104 */
107105 public void lock () throws IOException , InterruptedException {
108- if (channel == null ) {
109- initializeChannel ();
110- }
111106 lockSem .acquire ();
107+ if (rwfile != null ) {
108+ throw new IllegalStateException ("rwfile not null" );
109+ }
110+ initializeChannel ();
111+ FileChannel channel = rwfile .getChannel ();
112112 lock = channel .lock ();
113113 }
114114
@@ -119,8 +119,7 @@ public void lock() throws IOException, InterruptedException {
119119 public void getValues () {
120120 containsPortInfo = false ;
121121 if (lock == null ) {
122- // Not locked, remain ignorant about port file contents.
123- return ;
122+ throw new IllegalStateException ("Must lock before calling getValues" );
124123 }
125124 try {
126125 if (rwfile .length ()>0 ) {
@@ -167,6 +166,9 @@ public long getCookie() {
167166 * Store the values into the locked port file.
168167 */
169168 public void setValues (int port , long cookie ) throws IOException {
169+ if (lock == null ) {
170+ throw new IllegalStateException ("Must lock before calling setValues" );
171+ }
170172 Assert .check (lock != null );
171173 rwfile .seek (0 );
172174 // Write the magic nr that identifies a port file.
@@ -181,19 +183,19 @@ public void setValues(int port, long cookie) throws IOException {
181183 * Delete the port file.
182184 */
183185 public void delete () throws IOException , InterruptedException {
184- // Access to file must be closed before deleting.
185- rwfile .close ();
186-
187- file .delete ();
188-
189- // Wait until file has been deleted (deletes are asynchronous on Windows!) otherwise we
186+ if (!file .exists ()) { // file deleted already
187+ return ;
188+ }
189+ // Keep trying until file has been deleted, otherwise we
190190 // might shutdown the server and prevent another one from starting.
191- for (int i = 0 ; i < 10 && file .exists (); i ++) {
191+ for (int i = 0 ; i < 10 && file .exists () && ! file . delete () ; i ++) {
192192 Thread .sleep (1000 );
193193 }
194194 if (file .exists ()) {
195195 throw new IOException ("Failed to delete file." );
196196 }
197+ // allow some time for late clients to connect
198+ Thread .sleep (1000 );
197199 }
198200
199201 /**
@@ -222,10 +224,12 @@ public boolean markedForStop() throws IOException {
222224 */
223225 public void unlock () throws IOException {
224226 if (lock == null ) {
225- return ;
227+ throw new IllegalStateException ( "Not locked" ) ;
226228 }
227229 lock .release ();
228230 lock = null ;
231+ rwfile .close ();
232+ rwfile = null ;
229233 lockSem .release ();
230234 }
231235
0 commit comments