/**
* 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 org.apache.curator.utils;
import org.apache.curator.
CuratorZookeeperClient;
import org.apache.curator.
RetryLoop;
import org.apache.zookeeper.
ZooKeeper;
import java.util.concurrent.
Callable;
import java.util.concurrent.atomic.
AtomicReference;
/**
* <p>
* Utility to ensure that a particular path is created.
* </p>
* <p>
* The first time it is used, a synchronized call to {@link ZKPaths#mkdirs(ZooKeeper, String)} is made to
* ensure that the entire path has been created (with an empty byte array if needed). Subsequent
* calls with the instance are un-synchronized NOPs.
* </p>
* <p>
* Usage:<br>
* </p>
* <pre>
* EnsurePath ensurePath = new EnsurePath(aFullPathToEnsure);
* ...
* String nodePath = aFullPathToEnsure + "/foo";
* ensurePath.ensure(zk); // first time syncs and creates if needed
* zk.create(nodePath, ...);
* ...
* ensurePath.ensure(zk); // subsequent times are NOPs
* zk.create(nodePath, ...);
* </pre>
*
* @deprecated Since 2.9.0 - Prefer CuratorFramework.create().creatingParentContainersIfNeeded() or CuratorFramework.exists().creatingParentContainersIfNeeded()
*/
@
Deprecated
public class
EnsurePath
{
private final
String path;
private final boolean
makeLastNode;
private final
InternalACLProvider aclProvider;
private final
AtomicReference<
Helper>
helper;
private static final
Helper doNothingHelper = new
Helper()
{
@
Override
public void
ensure(
CuratorZookeeperClient client,
String path, final boolean
makeLastNode) throws
Exception
{
// NOP
}
};
interface
Helper
{
public void
ensure(
CuratorZookeeperClient client,
String path, final boolean
makeLastNode) throws
Exception;
}
/**
* @param path the full path to ensure
*/
public
EnsurePath(
String path)
{
this(
path, null, true, null);
}
/**
* @param path the full path to ensure
* @param aclProvider if not null, the ACL provider to use when creating parent nodes
*/
public
EnsurePath(
String path,
InternalACLProvider aclProvider)
{
this(
path, null, true,
aclProvider);
}
/**
* First time, synchronizes and makes sure all nodes in the path are created. Subsequent calls
* with this instance are NOPs.
*
* @param client ZK client
* @throws Exception ZK errors
*/
public void
ensure(
CuratorZookeeperClient client) throws
Exception
{
Helper localHelper =
helper.
get();
localHelper.
ensure(
client,
path,
makeLastNode);
}
/**
* Returns a view of this EnsurePath instance that does not make the last node.
* i.e. if the path is "/a/b/c" only "/a/b" will be ensured
*
* @return view
*/
public
EnsurePath excludingLast()
{
return new
EnsurePath(
path,
helper, false,
aclProvider);
}
protected
EnsurePath(
String path,
AtomicReference<
Helper>
helper, boolean
makeLastNode,
InternalACLProvider aclProvider)
{
this.
path =
path;
this.
makeLastNode =
makeLastNode;
this.
aclProvider =
aclProvider;
this.
helper = (
helper != null) ?
helper : new
AtomicReference<
Helper>(new
InitialHelper());
}
/**
* Returns the path being Ensured
*
* @return the path being ensured
*/
public
String getPath()
{
return this.
path;
}
protected boolean
asContainers()
{
return false;
}
private class
InitialHelper implements
Helper
{
private boolean
isSet = false; // guarded by synchronization
@
Override
public synchronized void
ensure(final
CuratorZookeeperClient client, final
String path, final boolean
makeLastNode) throws
Exception
{
if ( !
isSet )
{
RetryLoop.
callWithRetry
(
client,
new
Callable<
Object>()
{
@
Override
public
Object call() throws
Exception
{
ZKPaths.
mkdirs(
client.
getZooKeeper(),
path,
makeLastNode,
aclProvider,
asContainers());
helper.
set(
doNothingHelper);
isSet = true;
return null;
}
}
);
}
}
}
}