/* * Copyright 2016 The Simple File Server Authors * * 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. */ package org.sfs.vo; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.net.HostAndPort; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import static com.google.common.base.Optional.fromNullable; import static com.google.common.collect.FluentIterable.from; import static com.google.common.collect.Iterables.addAll; import static java.util.Calendar.getInstance; import static java.util.Collections.unmodifiableList; import static org.sfs.util.DateFormatter.fromDateTimeString; import static org.sfs.util.DateFormatter.toDateTimeString; public abstract class ServiceDef<T extends ServiceDef> { private String id; private XFileSystem<? extends XFileSystem> fileSystem; private Calendar lastUpdate; private Boolean master; private Boolean dataNode; private Long documentCount; private Integer availableProcessors; private Long freeMemory; private Long totalMemory; private Long maxMemory; private List<HostAndPort> publishAddresses = new ArrayList<>(); private List<XVolume<? extends XVolume>> volumes = new ArrayList<>(); public ServiceDef(String id) { this.id = id; } public ServiceDef() { } public String getId() { return id; } public Calendar getLastUpdate() { if (lastUpdate == null) { lastUpdate = getInstance(); } return lastUpdate; } public T setLastUpdate(Calendar lastUpdate) { this.lastUpdate = lastUpdate; return (T) this; } public Optional<Boolean> getMaster() { return fromNullable(master); } public T setMaster(Boolean master) { this.master = master; return (T) this; } public Optional<Boolean> getDataNode() { return fromNullable(dataNode); } public T setDataNode(Boolean dataNode) { this.dataNode = dataNode; return (T) this; } public T setDocumentCount(Long documentCount) { this.documentCount = documentCount; return (T) this; } public Optional<Long> getDocumentCount() { return fromNullable(documentCount); } public List<HostAndPort> getPublishAddresses() { return unmodifiableList(publishAddresses); } public T setPublishAddresses(Iterable<HostAndPort> publishAddresses) { this.publishAddresses.clear(); addAll(this.publishAddresses, publishAddresses); return (T) this; } public List<XVolume<? extends XVolume>> getVolumes() { return volumes; } public T setVolumes(Iterable<? extends XVolume<? extends XVolume>> volumes) { this.volumes.clear(); addAll(this.volumes, volumes); return (T) this; } public Optional<Integer> getAvailableProcessors() { return fromNullable(availableProcessors); } public T setAvailableProcessors(Integer availableProcessors) { this.availableProcessors = availableProcessors; return (T) this; } public Optional<Long> getFreeMemory() { return fromNullable(freeMemory); } public T setFreeMemory(Long freeMemory) { this.freeMemory = freeMemory; return (T) this; } public Optional<Long> getMaxMemory() { return fromNullable(maxMemory); } public T setMaxMemory(Long maxMemory) { this.maxMemory = maxMemory; return (T) this; } public Optional<Long> getTotalMemory() { return fromNullable(totalMemory); } public T setTotalMemory(Long totalMemory) { this.totalMemory = totalMemory; return (T) this; } public Optional<XFileSystem<? extends XFileSystem>> getFileSystem() { return fromNullable(fileSystem); } public T setFileSystem(XFileSystem<? extends XFileSystem> fileSystem) { this.fileSystem = fileSystem; return (T) this; } public abstract T copy(); protected T copyInternal(ServiceDef t) { setDataNode(t.dataNode); setDocumentCount(t.documentCount); if (t.lastUpdate != null) { Calendar cal = getInstance(); cal.setTimeInMillis(t.lastUpdate.getTimeInMillis()); setLastUpdate(cal); } setMaster(t.master); setDataNode(t.dataNode); setAvailableProcessors(t.availableProcessors); setFreeMemory(t.freeMemory); setMaxMemory(t.maxMemory); setTotalMemory(t.totalMemory); setFileSystem(t.fileSystem != null ? t.fileSystem.copy() : null); if (t.volumes != null) { setVolumes( from(t.volumes) .transform(new Function<XVolume<? extends XVolume>, XVolume<? extends XVolume>>() { @Override public XVolume<? extends XVolume> apply(XVolume<? extends XVolume> input) { return input.copy(); } })); } if (t.publishAddresses != null) { setPublishAddresses(t.publishAddresses); } return (T) this; } public T merge(ServiceDef<? extends ServiceDef> other) { this.id = other.id; this.lastUpdate = other.lastUpdate != null ? (Calendar) other.lastUpdate.clone() : null; this.master = other.master; this.dataNode = other.dataNode; this.documentCount = other.documentCount; this.availableProcessors = other.availableProcessors; this.freeMemory = other.freeMemory; this.maxMemory = other.maxMemory; this.totalMemory = other.totalMemory; this.fileSystem = other.fileSystem; this.publishAddresses.clear(); addAll(this.publishAddresses, other.publishAddresses); this.volumes.clear(); addAll(this.volumes, other.volumes); return (T) this; } public T merge(JsonObject jsonObject) { this.id = jsonObject.getString("id"); this.lastUpdate = fromDateTimeString(jsonObject.getString("update_ts")); this.master = jsonObject.getBoolean("master_node"); this.dataNode = jsonObject.getBoolean("data_node"); this.documentCount = jsonObject.getLong("document_count"); this.availableProcessors = jsonObject.getInteger("available_processors"); this.freeMemory = jsonObject.getLong("free_memory"); this.maxMemory = jsonObject.getLong("max_memory"); this.totalMemory = jsonObject.getLong("total_memory"); JsonObject jsonFileSystem = jsonObject.getJsonObject("file_system"); if (jsonFileSystem != null) { this.fileSystem = new TransientXFileSystem() .merge(jsonFileSystem); } else { this.fileSystem = null; } JsonArray jsonListeners = jsonObject.getJsonArray("publish_addresses"); this.publishAddresses.clear(); if (jsonListeners != null) { for (Object o : jsonListeners) { String jsonListener = (String) o; this.publishAddresses.add(HostAndPort.fromString(jsonListener)); } } JsonArray jsonVolumes = jsonObject.getJsonArray("volumes"); this.volumes.clear(); if (jsonVolumes != null) { for (Object o : jsonVolumes) { JsonObject jsonVolume = (JsonObject) o; TransientXVolume transientXVolume = new TransientXVolume() .merge(jsonVolume); this.volumes.add(transientXVolume); } } return (T) this; } public JsonObject toJsonObject() { JsonObject jsonObject = new JsonObject() .put("id", id) .put("update_ts", toDateTimeString(getLastUpdate())) .put("master_node", master) .put("data_node", dataNode) .put("document_count", documentCount) .put("available_processors", availableProcessors) .put("free_memory", freeMemory) .put("max_memory", maxMemory) .put("total_memory", totalMemory); if (fileSystem != null) { JsonObject jsonFileSystem = fileSystem.toJsonObject(); jsonObject = jsonObject.put("file_system", jsonFileSystem); } JsonArray jsonListeners = new JsonArray(); for (HostAndPort publishAddress : publishAddresses) { jsonListeners.add(publishAddress.toString()); } jsonObject.put("publish_addresses", jsonListeners); JsonArray jsonVolumes = new JsonArray(); for (XVolume<? extends XVolume> xVolume : volumes) { jsonVolumes.add(xVolume.toJsonObject()); } jsonObject.put("volumes", jsonVolumes); return jsonObject; } }