blob: e4612c3b39d3a5319525d1f4562b7b466dfff808 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.core.locking;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.tycho.locking.facade.FileLocker;
import org.eclipse.tycho.locking.facade.LockTimeoutException;
public class FileLockerImpl implements FileLocker {
private static final String LOCKFILE_SUFFIX = ".tycholock";
private final Location lockFileLocation;
final File lockMarkerFile;
public FileLockerImpl(File file, Location anyLocation) {
try {
if (file.isDirectory()) {
this.lockMarkerFile = new File(file, LOCKFILE_SUFFIX).getCanonicalFile();
} else {
this.lockMarkerFile = new File(file.getParentFile(), file.getName() + LOCKFILE_SUFFIX)
.getCanonicalFile();
}
if (lockMarkerFile.isDirectory()) {
throw new RuntimeException("Lock marker file " + lockMarkerFile + " already exists and is a directory");
}
File parentDir = lockMarkerFile.getParentFile();
if (!parentDir.isDirectory() && !parentDir.mkdirs()) {
throw new RuntimeException("Could not create parent directory " + parentDir + " of lock marker file");
}
this.lockFileLocation = anyLocation.createLocation(null, null, false);
this.lockFileLocation.set(lockMarkerFile.toURL(), false, lockMarkerFile.getAbsolutePath());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void lock() {
lock(10000L);
}
@Override
public void lock(long timeout) {
if (timeout < 0) {
throw new IllegalArgumentException("timeout must not be negative");
}
boolean success = false;
final long waitInterval = 50L;
long maxTries = (timeout / waitInterval) + 1;
IOException ioException = null;
for (long i = 0; i < maxTries; i++) {
ioException = null;
try {
success = lockFileLocation.lock();
} catch (IOException ioe) {
// keep trying (and re-throw eventually)
ioException = ioe;
}
if (success) {
return;
}
try {
Thread.sleep(waitInterval);
} catch (InterruptedException e) {
// ignore
}
}
String message = "lock timeout: Could not acquire lock on file " + lockFileLocation.getURL() + " for "
+ timeout + " msec";
if (ioException != null) {
throw new LockTimeoutException(message, ioException);
} else {
throw new LockTimeoutException(message);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.tycho.p2.repository.IFileLocker#release()
*/
@Override
public void release() {
lockFileLocation.release();
if (lockMarkerFile.isFile() && !lockMarkerFile.delete()) {
// this can happen if another process already holds the lock again
lockMarkerFile.deleteOnExit();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.tycho.p2.repository.IFileLocker#isLocked()
*/
@Override
public boolean isLocked() {
try {
return lockFileLocation.isLocked();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}