/* * Copyright (c) 2009-2011 by Bjoern Kolbeck, * Zuse Institute Berlin * * Licensed under the BSD License, see LICENSE file for details. * */ package org.xtreemfs.dir.operations; import java.util.ConcurrentModificationException; import java.util.Map; import org.xtreemfs.babudb.api.database.Database; import org.xtreemfs.babudb.api.exception.BabuDBException; import org.xtreemfs.common.HeartbeatThread; import org.xtreemfs.dir.DIRRequest; import org.xtreemfs.dir.DIRRequestDispatcher; import org.xtreemfs.dir.data.ServiceRecord; import org.xtreemfs.foundation.buffer.ReusableBuffer; import org.xtreemfs.pbrpc.generatedinterfaces.DIR.Service; import org.xtreemfs.pbrpc.generatedinterfaces.DIR.serviceRegisterRequest; import org.xtreemfs.pbrpc.generatedinterfaces.DIR.serviceRegisterResponse; import org.xtreemfs.pbrpc.generatedinterfaces.DIRServiceConstants; import com.google.protobuf.Message; /** * * @author bjko */ public class RegisterServiceOperation extends DIROperation { private final Database database; public RegisterServiceOperation(DIRRequestDispatcher master) throws BabuDBException { super(master); database = master.getDirDatabase(); } @Override public int getProcedureId() { return DIRServiceConstants.PROC_ID_XTREEMFS_SERVICE_REGISTER; } @Override public void startRequest(DIRRequest rq) { final serviceRegisterRequest request = (serviceRegisterRequest) rq.getRequestMessage(); final Service.Builder reg = request.getService().toBuilder(); database.lookup(DIRRequestDispatcher.INDEX_ID_SERVREG, reg.getUuid().getBytes(), rq) .registerListener(new DBRequestListener<byte[], Long>(false) { @Override Long execute(byte[] result, DIRRequest rq) throws Exception { long currentVersion = 0; ServiceRecord sRec = new ServiceRecord(request.getService().toBuilder().build()); // If this request comes from a tool like xtfs_chstatus, this value will be set to // "true" and the last updated time must not be set to the current time. If it does // not exist, it will be set to false. boolean doNotSetLastUpdated = Boolean.parseBoolean(sRec.getData().get( HeartbeatThread.DO_NOT_SET_LAST_UPDATED)); if (result != null) { ReusableBuffer buf = ReusableBuffer.wrap(result); ServiceRecord dbData = new ServiceRecord(buf); currentVersion = dbData.getVersion(); } else { // The registered service wasn't registered before. // Collect data from the request and inform all // listeners about this registration String uuid, name, type, pageUrl, geoCoordinates; long totalRam, usedRam, lastUpdated; int status, load, protoVersion; uuid = sRec.getUuid(); name = sRec.getName(); type = sRec.getType().toString(); pageUrl = sRec.getData().get("status_page_url") == null ? "" : sRec.getData() .get("status_page_url"); geoCoordinates = sRec.getData().get("vivaldi_coordinates") == null ? "" : sRec .getData().get("vivaldi_coordinates"); try { totalRam = Long.parseLong(sRec.getData().get("totalRAM")); } catch (NumberFormatException nfe) { totalRam = -1; } try { usedRam = Long.parseLong(sRec.getData().get("usedRAM")); } catch (NumberFormatException nfe) { usedRam = -1; } lastUpdated = System.currentTimeMillis() / 1000l; try { status = Integer.parseInt(sRec.getData().get(HeartbeatThread.STATUS_ATTR)); } catch (NumberFormatException nfe) { status = -1; } try { load = Integer.parseInt(sRec.getData().get("load")); } catch (NumberFormatException nfe) { load = -1; } try { protoVersion = Integer.parseInt(sRec.getData().get("proto_version")); } catch (NumberFormatException nfe) { protoVersion = -1; } master.notifyServiceRegistred(uuid, name, type, pageUrl, geoCoordinates, totalRam, usedRam, lastUpdated, status, load, protoVersion); } if (reg.getVersion() != currentVersion) { throw new ConcurrentModificationException("The requested version number (" + reg.getVersion() + ") did not match the " + "expected version (" + currentVersion + ")!"); } final long version = ++currentVersion; reg.setVersion(currentVersion); if (!doNotSetLastUpdated) { reg.setLastUpdatedS(System.currentTimeMillis() / 1000l); } ServiceRecord newRec = new ServiceRecord(reg.build()); Map<String, String> newRecData = newRec.getData(); // Remove attributes which must not be stored. newRecData.remove(HeartbeatThread.DO_NOT_SET_LAST_UPDATED); newRec.setData(newRecData); byte[] newData = new byte[newRec.getSize()]; newRec.serialize(ReusableBuffer.wrap(newData)); database.singleInsert(DIRRequestDispatcher.INDEX_ID_SERVREG, newRec.getUuid().getBytes(), newData, rq).registerListener( new DBRequestListener<Object, Long>(true) { @Override Long execute(Object result, DIRRequest rq) throws Exception { return version; } }); return null; } }); } @Override public boolean isAuthRequired() { return false; } @Override protected Message getRequestMessagePrototype() { return serviceRegisterRequest.getDefaultInstance(); } @Override void requestFinished(Object result, DIRRequest rq) { serviceRegisterResponse resp = serviceRegisterResponse.newBuilder().setNewVersion((Long) result) .build(); rq.sendSuccess(resp); } }