package rmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import datastructure.FileUnit;
import datastructure.SynchroMeta;
import server.Machine;
import server.naming.NamingServer;
public class NamingServiceImpl extends UnicastRemoteObject implements NamingService {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(NamingServiceImpl.class);
public NamingServiceImpl() throws RemoteException {
super();
}
@Override
public void updateMachine(Machine machine) throws RemoteException {
logger.entry(machine);
final Map<Machine, Long> storageValids = NamingServer.getInstance().storageValids;
final long now = new Date().getTime();
if ( storageValids.containsKey(machine) ) {
final long date = storageValids.get(machine);
if ( date < now ) storageValids.put(machine, now);
} else {
storageValids.put(machine, now);
NamingServer.getInstance().checkDupFileNumAndIncrease(NamingServer.getInstance().getRoot(), "");
}
}
@Override
public Machine createFile(String fullFilePath) throws RemoteException {
logger.entry(fullFilePath);
NamingServer namingServer = NamingServer.getInstance();
int storeIndex = fullFilePath.hashCode() % namingServer.storageValids.size();
storeIndex = (storeIndex + namingServer.storageValids.size()) % namingServer.storageValids.size();
Machine machine = new ArrayList<>(namingServer.storageValids.keySet()).get(storeIndex);
String[] path = fullFilePath.split("/");
FileUnit nowFileUnit = namingServer.getRoot();
for (int i = 0; i < path.length; i++) {
if (i != path.length-1) {
List<FileUnit> fileUnits = nowFileUnit.list();
boolean isCreatedDir = false;
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
nowFileUnit = fileUnits.get(j);
isCreatedDir = true;
break;
}
}
if (!isCreatedDir) {
return null;
}
} else {
List<FileUnit> fileUnits = nowFileUnit.list();
boolean isCreatedFile = false;
for (int j = 0; j < fileUnits.size(); j++) {
if (!fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
logger.info("isCreatedFile:" + fileUnits.get(j).getName());
isCreatedFile = true;
break;
}
}
if (isCreatedFile) {
return null;
}
return machine;
}
}
return null;
}
@Override
public Machine getFileLocation(String fullFilePath) throws RemoteException {
logger.entry(fullFilePath);
NamingServer namingServer = NamingServer.getInstance();
String[] path = fullFilePath.split("/");
FileUnit nowFileUnit = namingServer.getRoot();
for (int i = 0; i < path.length; i++) {
List<FileUnit> fileUnits = nowFileUnit.list();
for (int j = 0; j < fileUnits.size(); j++) {
if (i != path.length-1) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
nowFileUnit = fileUnits.get(j);
break;
}
} else {
if (!fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
return fileUnits.get(j).getAllMachines().get(0);
}
}
if (j == fileUnits.size()-1) {
return null;
}
}
}
return null;
}
@Override
public Machine createDir(String fullDirPath) throws RemoteException {
logger.entry(fullDirPath);
NamingServer namingServer = NamingServer.getInstance();
int storeIndex = fullDirPath.hashCode() % namingServer.storageValids.size();
storeIndex = (storeIndex + namingServer.storageValids.size()) % namingServer.storageValids.size();
Machine machine = new ArrayList<>(namingServer.storageValids.keySet()).get(storeIndex);
String[] path = fullDirPath.split("/");
FileUnit nowFileUnit = namingServer.getRoot();
for (int i = 0; i < path.length; i++) {
if (i != path.length-1) {
List<FileUnit> fileUnits = nowFileUnit.list();
boolean isCreatedDir = false;
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
nowFileUnit = fileUnits.get(j);
isCreatedDir = true;
break;
}
}
if (!isCreatedDir) {
return null;
}
} else {
List<FileUnit> fileUnits = nowFileUnit.list();
boolean isCreatedDir = false;
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
isCreatedDir = true;
break;
}
}
if (isCreatedDir) {
return null;
}
return machine;
}
}
return null;
}
@Override
public Machine getDirLocation(String fullDirPath) throws RemoteException {
logger.entry(fullDirPath);
NamingServer namingServer = NamingServer.getInstance();
String[] path = fullDirPath.split("/");
FileUnit nowFileUnit = namingServer.getRoot();
for (int i = 0; i < path.length; i++) {
List<FileUnit> fileUnits = nowFileUnit.list();
for (int j = 0; j < fileUnits.size(); j++) {
if (i != path.length-1) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
nowFileUnit = fileUnits.get(j);
break;
}
} else {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
return fileUnits.get(j).getAllMachines().get(0);
}
}
if (j == fileUnits.size()-1) {
return null;
}
}
}
return null;
}
@Override
public List<FileUnit> listDir(String fullDirPath)
throws RemoteException {
logger.entry(fullDirPath);
NamingServer namingServer = NamingServer.getInstance();
String[] path = fullDirPath.split("/");
FileUnit nowFileUnit = namingServer.getRoot();
if (fullDirPath.equals("")) {
return nowFileUnit.list();
}
for (int i = 0; i < path.length; i++) {
List<FileUnit> fileUnits = nowFileUnit.list();
for (int j = 0; j < fileUnits.size(); j++) {
if (i != path.length-1) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
nowFileUnit = fileUnits.get(j);
break;
}
} else {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
return fileUnits.get(j).list();
}
}
if (j == fileUnits.size()-1) {
return null;
}
}
}
return nowFileUnit.list();
}
private List<SynchroMeta> addToDir(Machine machine, FileUnit srcDir, FileUnit targetDir, String lastDirName) {
List<SynchroMeta> synchroMetas = new ArrayList<>();
List<FileUnit> srcLowerFileUnits = srcDir.list();
for (FileUnit toAddFileUnit : srcLowerFileUnits) {
List<FileUnit> targetLowerFileUnits = targetDir.list();
boolean isExist = false;
boolean isTypeEqual = true;
FileUnit targetAddedFileUnit = null;
for (FileUnit existFileUnit : targetLowerFileUnits) {
if (existFileUnit.getName().equals(toAddFileUnit.getName())) {
isExist = true;
if (existFileUnit.isDir() != toAddFileUnit.isDir()) {
isTypeEqual = false;
} else {
List<Machine> machines = existFileUnit.getAllMachines();
boolean isRecordThisMachine = false;
for (Machine recordMachine : machines) {
if (recordMachine.ip.equals(machine.ip) && recordMachine.port == machine.port) {
isRecordThisMachine = true;
break;
}
}
if (!isRecordThisMachine) {
if (!existFileUnit.isDir()) {
Machine targetMachine = existFileUnit.getAllMachines().get(0);
synchroMetas.add(new SynchroMeta(lastDirName+"/"+toAddFileUnit.getName(), SynchroMeta.CONFIRM, new Machine(targetMachine.ip, targetMachine.port)));
}
targetAddedFileUnit = existFileUnit;
existFileUnit.addStorageMachine(machine);
}
}
}
}
if (isExist) {
if (!isTypeEqual) {
synchroMetas.add(new SynchroMeta(lastDirName+"/"+toAddFileUnit.getName(), SynchroMeta.DELETE, null));
continue;
}
} else {
targetAddedFileUnit = new FileUnit(toAddFileUnit.getName(), toAddFileUnit.isDir());
targetAddedFileUnit.addStorageMachine(machine);
targetDir.addLowerFileUnit(targetAddedFileUnit);
}
if (targetAddedFileUnit.isDir()) {
List<SynchroMeta> lowerSynchroMetas = addToDir(machine, toAddFileUnit, targetAddedFileUnit, lastDirName+"/"+targetAddedFileUnit.getName());
synchroMetas.addAll(lowerSynchroMetas);
}
}
return synchroMetas;
}
@Override
public List<SynchroMeta> informOnline(Machine machine, FileUnit localRoot)
throws RemoteException {
logger.entry(machine, localRoot);
FileUnit root = NamingServer.getInstance().getRoot();
List<SynchroMeta> result = addToDir(machine, localRoot, root, "");
return result;
}
private FileUnit findChangedFileUnitFather(String fullFilePath) {
FileUnit nowFileUnit = NamingServer.getInstance().getRoot();
String[] path = fullFilePath.split("/");
for (int i = 0; i < path.length-1; i++) {
List<FileUnit> fileUnits = nowFileUnit.list();
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
nowFileUnit = fileUnits.get(j);
break;
}
}
}
return nowFileUnit;
}
@Override
public List<Machine> notifyCreateFile(String fullFilePath,
boolean isOrigin, Machine operateMachine) throws RemoteException {
logger.entry(fullFilePath, isOrigin, operateMachine);
FileUnit fatheFileUnit = NamingServer.getInstance().getRoot();
String[] path = fullFilePath.split("/");
for (int i = 0; i < path.length-1; i++) {
List<FileUnit> fileUnits = fatheFileUnit.list();
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(path[i])) {
fatheFileUnit = fileUnits.get(j);
fatheFileUnit.addStorageMachine(operateMachine);
break;
}
}
}
String name = path[path.length-1];
List<FileUnit> fileUnits = fatheFileUnit.list();
FileUnit changedFileUnit = null;
for (int j = 0; j < fileUnits.size(); j++) {
if (!fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(name)) {
changedFileUnit = fileUnits.get(j);
break;
}
}
if (changedFileUnit == null) {
changedFileUnit = new FileUnit(name, false);
fatheFileUnit.addLowerFileUnit(changedFileUnit);
}
changedFileUnit.addStorageMachine(operateMachine);
if (isOrigin) {
NamingServer namingServer = NamingServer.getInstance();
int storeIndex = fullFilePath.hashCode() % namingServer.storageValids.size();
storeIndex = (storeIndex + namingServer.storageValids.size()) % namingServer.storageValids.size();
int backNum = 3;
if (namingServer.storageValids.size() < backNum) {
backNum = namingServer.storageValids.size() - 1;
}
List<Machine> result = new ArrayList<>();
while (backNum > 0) {
Machine machine = new ArrayList<>(namingServer.storageValids.keySet()).get(storeIndex);
if (!machine.ip.equals(operateMachine) || machine.port != operateMachine.port) {
result.add(new Machine(machine.ip, machine.port));
backNum--;
}
storeIndex = (storeIndex + 1) % namingServer.storageValids.size();
}
return result;
}
return null;
}
@Override
public List<Machine> notifyDeleteFile(String fullFilePath,
boolean isOrigin, Machine operateMachine) throws RemoteException {
logger.entry(fullFilePath, isOrigin, operateMachine);
FileUnit fatheFileUnit = findChangedFileUnitFather(fullFilePath);
String[] path = fullFilePath.split("/");
String name = path[path.length-1];
List<FileUnit> fileUnits = fatheFileUnit.list();
FileUnit changedFileUnit = null;
for (int j = 0; j < fileUnits.size(); j++) {
if (!fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(name)) {
changedFileUnit = fileUnits.get(j);
break;
}
}
if (changedFileUnit == null) {
return null;
}
changedFileUnit.deleteStorageMachine(operateMachine);
if (changedFileUnit.getAllMachines().size() == 0) {
fatheFileUnit.deleteLowerFileUnit(changedFileUnit);
}
if (isOrigin) {
List<Machine> result = changedFileUnit.getAllMachines();
return result;
}
return null;
}
@Override
public List<Machine> notifyWriteFile(String fullFilePath, boolean isOrigin) throws RemoteException {
logger.entry(fullFilePath, isOrigin);
if (isOrigin) {
FileUnit fatheFileUnit = findChangedFileUnitFather(fullFilePath);
String[] path = fullFilePath.split("/");
String name = path[path.length-1];
List<FileUnit> fileUnits = fatheFileUnit.list();
FileUnit changedFileUnit = null;
for (int j = 0; j < fileUnits.size(); j++) {
if (!fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(name)) {
changedFileUnit = fileUnits.get(j);
break;
}
}
if (changedFileUnit == null) {
return null;
}
return changedFileUnit.getAllMachines();
}
return null;
}
@Override
public List<Machine> notifyCreateDir(String fullDirPath,
boolean isOrigin, Machine operateMachine) throws RemoteException {
logger.entry(fullDirPath, isOrigin, operateMachine);
FileUnit fatheFileUnit = findChangedFileUnitFather(fullDirPath);
String[] path = fullDirPath.split("/");
String name = path[path.length-1];
List<FileUnit> fileUnits = fatheFileUnit.list();
FileUnit changedFileUnit = null;
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(name)) {
changedFileUnit = fileUnits.get(j);
break;
}
}
if (changedFileUnit == null) {
changedFileUnit = new FileUnit(name, true);
fatheFileUnit.addLowerFileUnit(changedFileUnit);
}
changedFileUnit.addStorageMachine(operateMachine);
if (isOrigin) {
NamingServer namingServer = NamingServer.getInstance();
int storeIndex = fullDirPath.hashCode() % namingServer.storageValids.size();
storeIndex = (storeIndex + namingServer.storageValids.size()) % namingServer.storageValids.size();
int backNum = 3;
if (namingServer.storageValids.size() < backNum) {
backNum = namingServer.storageValids.size() - 1;
}
List<Machine> result = new ArrayList<>();
while (backNum > 0) {
Machine machine = new ArrayList<>(namingServer.storageValids.keySet()).get(storeIndex);
if (!machine.ip.equals(operateMachine) || machine.port != operateMachine.port) {
result.add(new Machine(machine.ip, machine.port));
backNum--;
}
storeIndex = (storeIndex + 1) % namingServer.storageValids.size();
}
return result;
}
return null;
}
@Override
public List<Machine> notifyDeleteDir(String fullDirPath,
boolean isOrigin, Machine operateMachine) throws RemoteException {
logger.entry(fullDirPath, isOrigin, operateMachine);
FileUnit fatheFileUnit = findChangedFileUnitFather(fullDirPath);
String[] path = fullDirPath.split("/");
String name = path[path.length-1];
List<FileUnit> fileUnits = fatheFileUnit.list();
FileUnit changedFileUnit = null;
for (int j = 0; j < fileUnits.size(); j++) {
if (fileUnits.get(j).isDir() && fileUnits.get(j).getName().equals(name)) {
changedFileUnit = fileUnits.get(j);
break;
}
}
if (changedFileUnit == null) {
return null;
}
changedFileUnit.deleteStorageMachine(operateMachine);
if (changedFileUnit.getAllMachines().size() == 0) {
fatheFileUnit.deleteLowerFileUnit(changedFileUnit);
}
if (isOrigin) {
List<Machine> result = changedFileUnit.getAllMachines();
return result;
}
return null;
}
}