blob: 78a85b0546abfb31db6462abf124d5731a93995c [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.hadoop.hdfs.inotify;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.fs.XAttr;
import org.apache.hadoop.fs.permission.AclEntry;
import org.apache.hadoop.fs.permission.FsPermission;
import java.util.List;
/**
* Events sent by the inotify system. Note that no events are necessarily sent
* when a file is opened for read (although a MetadataUpdateEvent will be sent
* if the atime is updated).
*/
@InterfaceAudience.Public
@InterfaceStability.Unstable
public abstract class Event {
public enum EventType {
CREATE, CLOSE, APPEND, RENAME, METADATA, UNLINK, TRUNCATE
}
private EventType eventType;
public EventType getEventType() {
return eventType;
}
public Event(EventType eventType) {
this.eventType = eventType;
}
/**
* Sent when a file is closed after append or create.
*/
@InterfaceAudience.Public
public static class CloseEvent extends Event {
private String path;
private long fileSize;
private long timestamp;
public CloseEvent(String path, long fileSize, long timestamp) {
super(EventType.CLOSE);
this.path = path;
this.fileSize = fileSize;
this.timestamp = timestamp;
}
public String getPath() {
return path;
}
/**
* The size of the closed file in bytes. May be -1 if the size is not
* available (e.g. in the case of a close generated by a concat operation).
*/
public long getFileSize() {
return fileSize;
}
/**
* The time when this event occurred, in milliseconds since the epoch.
*/
public long getTimestamp() {
return timestamp;
}
@Override
@InterfaceStability.Unstable
public String toString() {
return "CloseEvent [path=" + path + ", fileSize=" + fileSize
+ ", timestamp=" + timestamp + "]";
}
}
/**
* Sent when a new file is created (including overwrite).
*/
@InterfaceAudience.Public
public static class CreateEvent extends Event {
public enum INodeType {
FILE, DIRECTORY, SYMLINK
}
private INodeType iNodeType;
private String path;
private long ctime;
private int replication;
private String ownerName;
private String groupName;
private FsPermission perms;
private String symlinkTarget;
private boolean overwrite;
private long defaultBlockSize;
public static class Builder {
private INodeType iNodeType;
private String path;
private long ctime;
private int replication;
private String ownerName;
private String groupName;
private FsPermission perms;
private String symlinkTarget;
private boolean overwrite;
private long defaultBlockSize = 0;
public Builder iNodeType(INodeType type) {
this.iNodeType = type;
return this;
}
public Builder path(String path) {
this.path = path;
return this;
}
public Builder ctime(long ctime) {
this.ctime = ctime;
return this;
}
public Builder replication(int replication) {
this.replication = replication;
return this;
}
public Builder ownerName(String ownerName) {
this.ownerName = ownerName;
return this;
}
public Builder groupName(String groupName) {
this.groupName = groupName;
return this;
}
public Builder perms(FsPermission perms) {
this.perms = perms;
return this;
}
public Builder symlinkTarget(String symlinkTarget) {
this.symlinkTarget = symlinkTarget;
return this;
}
public Builder overwrite(boolean overwrite) {
this.overwrite = overwrite;
return this;
}
public Builder defaultBlockSize(long defaultBlockSize) {
this.defaultBlockSize = defaultBlockSize;
return this;
}
public CreateEvent build() {
return new CreateEvent(this);
}
}
private CreateEvent(Builder b) {
super(EventType.CREATE);
this.iNodeType = b.iNodeType;
this.path = b.path;
this.ctime = b.ctime;
this.replication = b.replication;
this.ownerName = b.ownerName;
this.groupName = b.groupName;
this.perms = b.perms;
this.symlinkTarget = b.symlinkTarget;
this.overwrite = b.overwrite;
this.defaultBlockSize = b.defaultBlockSize;
}
public INodeType getiNodeType() {
return iNodeType;
}
public String getPath() {
return path;
}
/**
* Creation time of the file, directory, or symlink.
*/
public long getCtime() {
return ctime;
}
/**
* Replication is zero if the CreateEvent iNodeType is directory or symlink.
*/
public int getReplication() {
return replication;
}
public String getOwnerName() {
return ownerName;
}
public String getGroupName() {
return groupName;
}
public FsPermission getPerms() {
return perms;
}
/**
* Symlink target is null if the CreateEvent iNodeType is not symlink.
*/
public String getSymlinkTarget() {
return symlinkTarget;
}
public boolean getOverwrite() {
return overwrite;
}
public long getDefaultBlockSize() {
return defaultBlockSize;
}
@Override
@InterfaceStability.Unstable
public String toString() {
StringBuilder content = new StringBuilder();
content.append("CreateEvent [INodeType=").append(iNodeType)
.append(", path=").append(path)
.append(", ctime=").append(ctime)
.append(", replication=").append(replication)
.append(", ownerName=").append(ownerName)
.append(", groupName=").append(groupName)
.append(", perms=").append(perms).append(", ");
if (symlinkTarget != null) {
content.append("symlinkTarget=").append(symlinkTarget).append(", ");
}
content.append("overwrite=").append(overwrite)
.append(", defaultBlockSize=").append(defaultBlockSize)
.append("]");
return content.toString();
}
}
/**
* Sent when there is an update to directory or file (none of the metadata
* tracked here applies to symlinks) that is not associated with another
* inotify event. The tracked metadata includes atime/mtime, replication,
* owner/group, permissions, ACLs, and XAttributes. Fields not relevant to the
* metadataType of the MetadataUpdateEvent will be null or will have their default
* values.
*/
@InterfaceAudience.Public
public static class MetadataUpdateEvent extends Event {
public enum MetadataType {
TIMES, REPLICATION, OWNER, PERMS, ACLS, XATTRS
}
private String path;
private MetadataType metadataType;
private long mtime;
private long atime;
private int replication;
private String ownerName;
private String groupName;
private FsPermission perms;
private List<AclEntry> acls;
private List<XAttr> xAttrs;
private boolean xAttrsRemoved;
public static class Builder {
private String path;
private MetadataType metadataType;
private long mtime;
private long atime;
private int replication;
private String ownerName;
private String groupName;
private FsPermission perms;
private List<AclEntry> acls;
private List<XAttr> xAttrs;
private boolean xAttrsRemoved;
public Builder path(String path) {
this.path = path;
return this;
}
public Builder metadataType(MetadataType type) {
this.metadataType = type;
return this;
}
public Builder mtime(long mtime) {
this.mtime = mtime;
return this;
}
public Builder atime(long atime) {
this.atime = atime;
return this;
}
public Builder replication(int replication) {
this.replication = replication;
return this;
}
public Builder ownerName(String ownerName) {
this.ownerName = ownerName;
return this;
}
public Builder groupName(String groupName) {
this.groupName = groupName;
return this;
}
public Builder perms(FsPermission perms) {
this.perms = perms;
return this;
}
public Builder acls(List<AclEntry> acls) {
this.acls = acls;
return this;
}
public Builder xAttrs(List<XAttr> xAttrs) {
this.xAttrs = xAttrs;
return this;
}
public Builder xAttrsRemoved(boolean xAttrsRemoved) {
this.xAttrsRemoved = xAttrsRemoved;
return this;
}
public MetadataUpdateEvent build() {
return new MetadataUpdateEvent(this);
}
}
private MetadataUpdateEvent(Builder b) {
super(EventType.METADATA);
this.path = b.path;
this.metadataType = b.metadataType;
this.mtime = b.mtime;
this.atime = b.atime;
this.replication = b.replication;
this.ownerName = b.ownerName;
this.groupName = b.groupName;
this.perms = b.perms;
this.acls = b.acls;
this.xAttrs = b.xAttrs;
this.xAttrsRemoved = b.xAttrsRemoved;
}
public String getPath() {
return path;
}
public MetadataType getMetadataType() {
return metadataType;
}
public long getMtime() {
return mtime;
}
public long getAtime() {
return atime;
}
public int getReplication() {
return replication;
}
public String getOwnerName() {
return ownerName;
}
public String getGroupName() {
return groupName;
}
public FsPermission getPerms() {
return perms;
}
/**
* The full set of ACLs currently associated with this file or directory.
* May be null if all ACLs were removed.
*/
public List<AclEntry> getAcls() {
return acls;
}
public List<XAttr> getxAttrs() {
return xAttrs;
}
/**
* Whether the xAttrs returned by getxAttrs() were removed (as opposed to
* added).
*/
public boolean isxAttrsRemoved() {
return xAttrsRemoved;
}
@Override
@InterfaceStability.Unstable
public String toString() {
StringBuilder content = new StringBuilder();
content.append("MetadataUpdateEvent [path=").append(path)
.append(", metadataType=").append(metadataType);
switch (metadataType) {
case TIMES:
content.append(", mtime=").append(mtime)
.append(", atime=").append(atime);
break;
case REPLICATION:
content.append(", replication=").append(replication);
break;
case OWNER:
content.append(", ownerName=").append(ownerName)
.append(", groupName=").append(groupName);
break;
case PERMS:
content.append(", perms=").append(perms);
break;
case ACLS:
content.append(", acls=").append(acls);
break;
case XATTRS:
content.append(", xAttrs=").append(xAttrs)
.append(", xAttrsRemoved=").append(xAttrsRemoved);
break;
default:
break;
}
content.append(']');
return content.toString();
}
}
/**
* Sent when a file, directory, or symlink is renamed.
*/
@InterfaceAudience.Public
public static class RenameEvent extends Event {
private String srcPath;
private String dstPath;
private long timestamp;
public static class Builder {
private String srcPath;
private String dstPath;
private long timestamp;
public Builder srcPath(String srcPath) {
this.srcPath = srcPath;
return this;
}
public Builder dstPath(String dstPath) {
this.dstPath = dstPath;
return this;
}
public Builder timestamp(long timestamp) {
this.timestamp = timestamp;
return this;
}
public RenameEvent build() {
return new RenameEvent(this);
}
}
private RenameEvent(Builder builder) {
super(EventType.RENAME);
this.srcPath = builder.srcPath;
this.dstPath = builder.dstPath;
this.timestamp = builder.timestamp;
}
public String getSrcPath() {
return srcPath;
}
public String getDstPath() {
return dstPath;
}
/**
* The time when this event occurred, in milliseconds since the epoch.
*/
public long getTimestamp() {
return timestamp;
}
@Override
@InterfaceStability.Unstable
public String toString() {
return "RenameEvent [srcPath=" + srcPath + ", dstPath=" + dstPath
+ ", timestamp=" + timestamp + "]";
}
}
/**
* Sent when an existing file is opened for append.
*/
@InterfaceAudience.Public
public static class AppendEvent extends Event {
private String path;
private boolean newBlock;
public static class Builder {
private String path;
private boolean newBlock;
public Builder path(String path) {
this.path = path;
return this;
}
public Builder newBlock(boolean newBlock) {
this.newBlock = newBlock;
return this;
}
public AppendEvent build() {
return new AppendEvent(this);
}
}
private AppendEvent(Builder b) {
super(EventType.APPEND);
this.path = b.path;
this.newBlock = b.newBlock;
}
public String getPath() {
return path;
}
public boolean toNewBlock() {
return newBlock;
}
@Override
@InterfaceStability.Unstable
public String toString() {
return "AppendEvent [path=" + path + ", newBlock=" + newBlock + "]";
}
}
/**
* Sent when a file, directory, or symlink is deleted.
*/
@InterfaceAudience.Public
public static class UnlinkEvent extends Event {
private String path;
private long timestamp;
public static class Builder {
private String path;
private long timestamp;
public Builder path(String path) {
this.path = path;
return this;
}
public Builder timestamp(long timestamp) {
this.timestamp = timestamp;
return this;
}
public UnlinkEvent build() {
return new UnlinkEvent(this);
}
}
private UnlinkEvent(Builder builder) {
super(EventType.UNLINK);
this.path = builder.path;
this.timestamp = builder.timestamp;
}
public String getPath() {
return path;
}
/**
* The time when this event occurred, in milliseconds since the epoch.
*/
public long getTimestamp() {
return timestamp;
}
@Override
@InterfaceStability.Unstable
public String toString() {
return "UnlinkEvent [path=" + path + ", timestamp=" + timestamp + "]";
}
}
/**
* Sent when a file is truncated.
*/
@InterfaceAudience.Public
public static class TruncateEvent extends Event {
private String path;
private long fileSize;
private long timestamp;
public TruncateEvent(String path, long fileSize, long timestamp) {
super(EventType.TRUNCATE);
this.path = path;
this.fileSize = fileSize;
this.timestamp = timestamp;
}
public String getPath() {
return path;
}
/**
* The size of the truncated file in bytes.
*/
public long getFileSize() {
return fileSize;
}
/**
* The time when this event occurred, in milliseconds since the epoch.
*/
public long getTimestamp() {
return timestamp;
}
@Override
@InterfaceStability.Unstable
public String toString() {
return "TruncateEvent [path=" + path + ", fileSize=" + fileSize
+ ", timestamp=" + timestamp + "]";
}
}
}