
me.tfeng.playmods.avro.d2.AvroD2Server Maven / Gradle / Ivy
/**
* Copyright 2016 Thomas Feng
*
* 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 me.tfeng.playmods.avro.d2;
import java.net.URL;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.avro.Protocol;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooKeeper.States;
import play.Logger;
import play.Logger.ALogger;
/**
* @author Thomas Feng ([email protected])
*/
public class AvroD2Server implements Watcher {
private static final ALogger LOG = Logger.of(AvroD2Server.class);
protected volatile String nodePath;
private final Protocol protocol;
private final ScheduledExecutorService scheduler;
private final long serverRegisterRetryDelay;
private final URL url;
private final ZooKeeper zk;
public AvroD2Server(Protocol protocol, URL url, ZooKeeper zk, ScheduledExecutorService scheduler,
long serverRegisterRetryDelay) {
this.protocol = protocol;
this.url = url;
this.zk = zk;
this.scheduler = scheduler;
this.serverRegisterRetryDelay = serverRegisterRetryDelay;
}
public synchronized void close() throws InterruptedException, KeeperException {
String path = nodePath;
if (path != null) {
LOG.info("Closing server for " + protocol.getName() + " at " + url);
try {
zk.delete(path, -1);
} catch (NoNodeException e) {
// Ignore.
}
nodePath = null;
}
}
public Protocol getProtocol() {
return protocol;
}
public URL getUrl() {
return url;
}
@Override
public void process(WatchedEvent event) {
if (event.getType() == EventType.NodeDeleted && event.getPath().equals(nodePath)
|| event.getType() == EventType.None && event.getState() == KeeperState.SyncConnected) {
// If the node is unexpectedly deleted or if ZooKeeper connection is restored, register the
// server again.
register();
}
}
public synchronized void register() {
try {
close();
if (zk == null) {
// ZooKeeper is not initialized yet.
scheduleRegister();
} if (zk.getState() == States.CLOSED) {
LOG.warn("ZooKeeper connection is closed; canceling registration for " + protocol.getName());
} else {
AvroD2Helper.createVersionNode(zk, protocol);
nodePath = AvroD2Helper.createServerNode(zk, protocol, url);
zk.getData(nodePath, this, null);
LOG.info("Registered server for " + protocol.getName() + " at " + url);
}
} catch (Exception e) {
if (e instanceof KeeperException) {
LOG.warn("Unable to register server for " + protocol.getName() + " (code = " + ((KeeperException) e).code()
+ "); retry later");
} else {
LOG.warn("Unable to register server for " + protocol.getName() + "; retry later", e);
}
scheduleRegister();
}
}
private void scheduleRegister() {
scheduler.schedule(this::register, serverRegisterRetryDelay, TimeUnit.MILLISECONDS);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy