/*
* Copyright (C) 2014 Indeed Inc.
*
* 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 com.indeed.imhotep.service;
import com.google.common.base.Charsets;
import com.indeed.util.zookeeper.ZooKeeperConnection;
import org.apache.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import java.io.Closeable;
import java.io.IOException;
import java.util.UUID;
/**
* @author jsgroth
*/
public class ServiceZooKeeperWrapper implements Closeable {
private static final Logger log = Logger.getLogger(ServiceZooKeeperWrapper.class);
private static final int TIMEOUT = 60000;
private final ZooKeeperConnection zkConnection;
private final String rootPath, nodeName;
private final byte[] data;
private volatile boolean closed;
public ServiceZooKeeperWrapper(final String zkNodes, final String hostname, final int port,
final String rootPath) {
zkConnection = new ZooKeeperConnection(zkNodes, TIMEOUT);
this.rootPath = rootPath;
nodeName = UUID.randomUUID().toString();
data = (hostname+":"+port).getBytes(Charsets.UTF_8);
closed = false;
createNode();
zkConnection.register(new MyWatcher());
}
@Override
public void close() throws IOException {
closed = true;
try {
zkConnection.close();
} catch (InterruptedException e) {
log.error(e);
}
}
public boolean isAlive() {
return zkConnection.getState().isAlive();
}
private void createNode() {
boolean created = false;
while (!created) {
try {
try {
zkConnection.connect();
ZooKeeperConnection.createFullPath(zkConnection, rootPath, new byte[0], CreateMode.PERSISTENT, true);
zkConnection.create(rootPath + "/"+nodeName, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
created = true;
} catch (IOException e) {
log.error(e);
Thread.sleep(TIMEOUT);
} catch (KeeperException e) {
log.error(e);
zkConnection.close();
Thread.sleep(TIMEOUT);
}
} catch (InterruptedException e) {
log.error(e);
}
}
}
private class MyWatcher implements Watcher {
@Override
public void process(WatchedEvent watchedEvent) {
if (!closed) {
if (watchedEvent.getType() == Event.EventType.None && watchedEvent.getState() != Event.KeeperState.SyncConnected) {
try {
zkConnection.close();
} catch (InterruptedException e) {
log.error(e);
}
createNode();
}
zkConnection.register(this);
}
}
}
}