/*************************GO-LICENSE-START*********************************
* Copyright 2014 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*************************GO-LICENSE-END***********************************/
package com.thoughtworks.go.server.service;
import com.thoughtworks.go.server.messaging.SendEmailMessage;
import com.thoughtworks.go.server.service.result.OperationResult;
import com.thoughtworks.go.serverhealth.HealthStateType;
import com.thoughtworks.go.util.GoConstants;
import com.thoughtworks.go.util.SystemEnvironment;
import java.io.File;
import java.io.IOException;
/**
* @understands when disk space is too low to be safe on server
*/
public abstract class DiskSpaceChecker implements SchedulingChecker {
protected final SystemEnvironment systemEnvironment;
private final EmailSender sender;
protected GoConfigService goConfigService;
private final HealthStateType healthStateType;
private boolean error = false;
private File targetFolder;
private String targetFolderCanicalPath;
private final SystemDiskSpaceChecker diskSpaceChecker;
private boolean targetExists;
private long availableSpace;
private volatile long lastCheckedTime;
// TODO: will separate SchedulingChecker responsibility out
public DiskSpaceChecker(EmailSender sender, SystemEnvironment systemEnvironment, File targetFolder,
GoConfigService goConfigService, HealthStateType healthStateType, final SystemDiskSpaceChecker diskSpaceChecker) {
this.sender = sender;
this.systemEnvironment = systemEnvironment;
this.goConfigService = goConfigService;
this.healthStateType = healthStateType;
this.targetFolder = targetFolder;
this.diskSpaceChecker = diskSpaceChecker;
}
protected synchronized String targetFolderCanonicalPath() {
if (this.targetFolderCanicalPath == null) {
targetFolderCanicalPath = getCanicalPath(this.targetFolder);
}
return targetFolderCanicalPath;
}
public void check(OperationResult result) {
if (timeSinceLastChecked() > systemEnvironment.getDiskSpaceCacheRefresherInterval()) {
synchronized (this) {
if (timeSinceLastChecked() > systemEnvironment.getDiskSpaceCacheRefresherInterval()) {
targetExists = targetFolder.exists();
availableSpace = availableSpace();
lastCheckedTime = System.currentTimeMillis();
}
}
}
long size = limitInMb();
if (!targetExists) {
result.success(healthStateType);
return;
}
long limit = size * GoConstants.MEGA_BYTE;
boolean notEnoughSpace = availableSpace < limit;
if (notEnoughSpace) {
if (!isInErrorState()) {
inErrorState();
if (sender != null) {
sender.sendEmail(createEmail());
}
}
createFailure(result, size, availableSpace);
}
else {
clearErrorState();
result.success(healthStateType);
}
}
protected long availableSpace() {
return diskSpaceChecker.getUsableSpace(targetFolder);
}
private long timeSinceLastChecked() {
return System.currentTimeMillis() - lastCheckedTime;
}
private String getCanicalPath(File file) {
try {
return file.getCanonicalPath();
} catch (IOException e) {
return file.getAbsolutePath();
}
}
protected abstract long limitInMb();
protected abstract void createFailure(OperationResult result, long size, long availableSpace);
protected abstract SendEmailMessage createEmail();
private boolean isInErrorState() {
return error;
}
private void inErrorState() {
error = true;
}
private void clearErrorState() {
error = false;
}
protected String getAdminMail() {
return goConfigService.adminEmail();
}
public OperationResult resultFor(OperationResult result) {
return result;
}
}