/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package tachyon;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import tachyon.conf.CommonConf;
import tachyon.util.CommonUtils;
/**
* <code>Users</code> represents and manages all users contacting to a worker.
*/
public class Users {
public static final int sDATASERVER_USER_ID = -1;
public static final int sCHECKPOINT_USER_ID = -2;
private final Logger LOG = Logger.getLogger(Constants.LOGGER_TYPE);
private final String USER_FOLDER;
private final String USER_UNDERFS_FOLDER;
private final Map<Long, UserInfo> USERS;
public Users(String userfolder, String userUnderfsFolder) {
USER_FOLDER = userfolder;
USER_UNDERFS_FOLDER = userUnderfsFolder;
USERS = new HashMap<Long, UserInfo>();
}
public void addOwnBytes(long userId, long newBytes) {
UserInfo tUser = null;
synchronized (USERS) {
userHeartbeat(userId);
tUser = USERS.get(userId);
}
tUser.addOwnBytes(newBytes);
}
/**
* Check the status of the users pool.
*
* @return the list of timeout users.
*/
public List<Long> checkStatus() {
LOG.debug("Worker is checking all users' status.");
List<Long> ret = new ArrayList<Long>();
synchronized (USERS) {
for (Entry<Long, UserInfo> entry : USERS.entrySet()) {
if (entry.getValue().timeout()) {
ret.add(entry.getKey());
}
}
}
return ret;
}
public String getUserTempFolder(long userId) {
return CommonUtils.concat(USER_FOLDER, userId);
}
public String getUserUnderfsTempFolder(long userId) {
return CommonUtils.concat(USER_UNDERFS_FOLDER, userId);
}
/**
* Get how much space quote does a user own.
*
* @param userId
* The queried user.
* @return Bytes the user owns.
*/
public long ownBytes(long userId) {
synchronized (USERS) {
UserInfo tUser = USERS.get(userId);
return tUser == null ? 0 : tUser.getOwnBytes();
}
}
/**
* Remove <code> userId </code> from user pool.
*
* @param userId
* The user to be removed.
* @return The space quote the removed user occupied in bytes.
*/
public synchronized long removeUser(long userId) {
StringBuilder sb = new StringBuilder("Trying to cleanup user " + userId + " : ");
UserInfo tUser = null;
synchronized (USERS) {
tUser = USERS.get(userId);
USERS.remove(userId);
}
long returnedBytes = 0;
if (tUser == null) {
returnedBytes = 0;
sb.append(" The user does not exist in the worker's current user pool.");
} else {
returnedBytes = tUser.getOwnBytes();
String folder = getUserTempFolder(userId);
sb.append(" The user returns " + returnedBytes + " bytes. Remove the user's folder "
+ folder + " ;");
try {
FileUtils.deleteDirectory(new File(folder));
} catch (IOException e) {
CommonUtils.runtimeException(e);
}
folder = getUserUnderfsTempFolder(userId);
sb.append(" Also remove users underfs folder " + folder);
try {
UnderFileSystem.get(CommonConf.get().UNDERFS_ADDRESS).delete(folder, true);
} catch (IOException e) {
LOG.error(e);
}
}
LOG.info(sb.toString());
return returnedBytes;
}
public void userHeartbeat(long userId) {
synchronized (USERS) {
if (USERS.containsKey(userId)) {
USERS.get(userId).heartbeat();
} else {
USERS.put(userId, new UserInfo(userId));
}
}
}
}