blob: 33d6a8ce12260d553645a1c064768581fa8b8747 [file] [log] [blame]
/*
* 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.ignite.internal.processors.igfs;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.igfs.IgfsMode;
import org.apache.ignite.igfs.IgfsPath;
import org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashMap;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
/**
*
*/
public class IgfsModeResolver implements Externalizable {
/** */
private static final long serialVersionUID = 0L;
/** Maximum size of map with cached path modes. */
private static final int MAX_PATH_CACHE = 1000;
/** Default mode. */
private IgfsMode dfltMode;
/** Modes for particular paths. Ordered from longest to shortest. */
private List<T2<IgfsPath, IgfsMode>> modes;
/** Cached modes per path. */
private Map<IgfsPath, IgfsMode> modesCache;
/** Set to store parent dual paths that have primary children. */
private Set<IgfsPath> dualParentsWithPrimaryChildren;
/**
* Empty constructor required by {@link Externalizable}.
*/
public IgfsModeResolver() {
// No-op.
}
/**
* Constructor
*
* @param dfltMode Default IGFS mode.
* @param modes List of configured modes. The order is significant as modes are added in order of occurrence.
* @throws IgniteCheckedException On error.
*/
public IgfsModeResolver(IgfsMode dfltMode, @Nullable ArrayList<T2<IgfsPath, IgfsMode>> modes)
throws IgniteCheckedException {
assert dfltMode != null;
this.dfltMode = dfltMode;
dualParentsWithPrimaryChildren = new HashSet<>();
this.modes = IgfsUtils.preparePathModes(dfltMode, modes, dualParentsWithPrimaryChildren);
if (modes != null)
modesCache = new GridBoundedConcurrentLinkedHashMap<>(MAX_PATH_CACHE);
}
/**
* Resolves IGFS mode for the given path.
*
* @param path IGFS path.
* @return IGFS mode.
*/
public IgfsMode resolveMode(IgfsPath path) {
assert path != null;
if (modes == null)
return dfltMode;
else {
IgfsMode mode = modesCache.get(path);
if (mode == null) {
for (T2<IgfsPath, IgfsMode> entry : modes) {
if (F.eq(path, entry.getKey()) || path.isSubDirectoryOf(entry.getKey())) {
// As modes ordered from most specific to least specific first mode found is ours.
mode = entry.getValue();
break;
}
}
if (mode == null)
mode = dfltMode;
modesCache.put(path, mode);
}
return mode;
}
}
/**
* Answers if the given path has an immediate child of PRIMARY mode.
*
* @param path The path to query.
* @return If the given path has an immediate child of PRIMARY mode.
*/
public boolean hasPrimaryChild(IgfsPath path) {
return dualParentsWithPrimaryChildren.contains(path);
}
/** {@inheritDoc} */
@Override public void writeExternal(ObjectOutput out) throws IOException {
U.writeEnum(out, dfltMode);
if (modes != null) {
out.writeBoolean(true);
out.writeInt(modes.size());
for (T2<IgfsPath, IgfsMode> pathMode : modes) {
assert pathMode.getKey() != null;
pathMode.getKey().writeExternal(out);
U.writeEnum(out, pathMode.getValue());
}
}
else
out.writeBoolean(false);
if (!F.isEmpty(dualParentsWithPrimaryChildren)) {
out.writeBoolean(true);
out.writeInt(dualParentsWithPrimaryChildren.size());
for (IgfsPath p : dualParentsWithPrimaryChildren)
p.writeExternal(out);
}
else
out.writeBoolean(false);
}
/** {@inheritDoc} */
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
dfltMode = IgfsMode.fromOrdinal(in.readByte());
if (in.readBoolean()) {
int size = in.readInt();
modes = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
IgfsPath path = IgfsUtils.readPath(in);
modes.add(new T2<>(path, IgfsMode.fromOrdinal(in.readByte())));
}
modesCache = new GridBoundedConcurrentLinkedHashMap<>(MAX_PATH_CACHE);
}
dualParentsWithPrimaryChildren = new HashSet<>();
if (in.readBoolean()) {
int size = in.readInt();
for (int i = 0; i < size; i++)
dualParentsWithPrimaryChildren.add(IgfsUtils.readPath(in));
}
}
}