All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.tfeng.playmods.avro.d2.AvroD2Server Maven / Gradle / Ivy

There is a newer version: 0.11.0
Show newest version
/**
 * 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