package com.openseedbox.models;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.openseedbox.backend.*;
import com.openseedbox.backend.node.NodeBackend;
import com.openseedbox.code.MessageException;
import com.openseedbox.code.Util;
import play.data.validation.Required;
import play.jobs.Job;
import play.libs.WS;
import play.libs.WS.HttpResponse;
import play.libs.WS.WSRequest;
import siena.Column;
import siena.Table;
import siena.embed.Embedded;
@Table("node")
public class Node extends ModelBase {
@Required private String name;
@Required @Column("ip_address") private String ipAddress;
@Required private String scheme;
@Column("download_ip_address") private String downloadIpAddress;
@Column("download_scheme") private String downloadScheme;
@Required @Column("api_key") private String apiKey;
private boolean down;
private boolean active;
@Embedded private NodeStatus status;
public static Node getBestForNewTorrent(User u) {
//TODO: work this out properly. For now, just use the first one
if (u.hasDedicatedNode()) {
return u.getDedicatedNode();
}
return Node.all().limit(1).get();
}
public static List<Node> getActiveNodes() {
return Node.all().filter("active", true).fetch();
}
/**
* Returns the total space available from all the nodes in the system
* @return The space, in bytes
*/
public static long getTotalSpaceBytes() {
long space = 0;
List<Node> nodes = getActiveNodes();
for (Node n : nodes) {
INodeStatus s = n.getNodeStatus(true);
if (s != null) {
space += s.getTotalSpaceBytes();
}
}
return space;
}
/**
* Returns the total space used on all the nodes in the system
* @return The space, in bytes
*/
public static long getUsedSpaceBytes() {
long space = 0;
List<Node> nodes = getActiveNodes();
for (Node n : nodes) {
INodeStatus s = n.getNodeStatus(true);
if (s != null) {
space += s.getUsedSpaceBytes();
}
}
return space;
}
public INodeStatus getNodeStatus() {
return getNodeStatus(false);
}
public INodeStatus getNodeStatus(boolean fromDb) {
if (fromDb) {
return status;
}
HttpResponse res = getWebService("/status").get();
if (res.success()) {
JsonObject fullResponse = handleWebServiceResponse(res).getAsJsonObject();
status = Util.getGson().fromJson(fullResponse, NodeStatus.class);
new Job() {
@Override
public void doJob() throws Exception {
update();
}
}.now();
return status;
} else {
throw new MessageException("Node returned status: " + res.getStatus() + ". Probably java isnt running.");
}
}
public JsonElement handleWebServiceResponse(HttpResponse res) {
try {
if (res.success()) {
JsonObject fullResponse = res.getJson().getAsJsonObject();
if (!fullResponse.get("success").getAsBoolean()) {
String error = fullResponse.get("error").getAsString();
throw new MessageException(error);
}
return fullResponse.get("data");
}
throw new MessageException("Unsuccessful webservice call, status: " + res.getStatusText());
} catch (Exception ex) {
if (ex.getMessage().contains("Connection refused")) {
throw new MessageException("Connection refused");
} else if (ex.getMessage().contains("No route to host")) {
throw new MessageException("Unable to contact node at all! No route to host.");
}
throw new MessageException(ex.getMessage());
}
}
public ITorrentBackend getNodeBackend() {
return new NodeBackend(this);
}
public WSRequest getWebService(String action) {
if (!action.startsWith("/")) {
action = "/" + action;
}
String url = getNodeUrl() + action;
return WS.url(url)
.setParameter("ext", "json")
.setParameter("api_key", this.apiKey);
}
public WSRequest getWebService(String action, String hash) {
WSRequest req = getWebService(action);
req.setParameter("hash", hash);
return req;
}
public WSRequest getWebService(String action, List<String> hashes) {
WSRequest req = getWebService(action);
req.setParameter("hashes", hashes);
return req;
}
public String getNodeUrl() {
return String.format("%s://%s", getScheme(), getIpAddress());
}
public String getNodeDownloadUrl() {
return String.format("%s://%s", getDownloadScheme(), getDownloadIpAddress());
}
/* Getters and Setters */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public boolean isDown() {
return down;
}
public void setDown(boolean down) {
this.down = down;
}
public String getScheme() {
if (StringUtils.isEmpty(scheme)) {
return "http";
}
return scheme;
}
public void setScheme(String scheme) {
this.scheme = scheme;
}
public void setNodeStatus(NodeStatus status) {
this.status = status;
}
public String getDownloadIpAddress() {
return StringUtils.isBlank(downloadIpAddress) ? ipAddress : downloadIpAddress;
}
public void setDownloadIpAddress(String downloadIpAddress) {
this.downloadIpAddress = downloadIpAddress;
}
public String getDownloadScheme() {
return StringUtils.isBlank(downloadScheme) ? scheme : downloadScheme;
}
public void setDownloadScheme(String downloadScheme) {
this.downloadScheme = downloadScheme;
}
/* End Getters and Setters */
}