001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hdfs.inotify; 020 021import org.apache.hadoop.classification.InterfaceAudience; 022import org.apache.hadoop.classification.InterfaceStability; 023import org.apache.hadoop.fs.XAttr; 024import org.apache.hadoop.fs.permission.AclEntry; 025import org.apache.hadoop.fs.permission.FsPermission; 026 027import java.util.List; 028 029/** 030 * Events sent by the inotify system. Note that no events are necessarily sent 031 * when a file is opened for read (although a MetadataUpdateEvent will be sent 032 * if the atime is updated). 033 */ 034@InterfaceAudience.Public 035@InterfaceStability.Unstable 036public abstract class Event { 037 public static enum EventType { 038 CREATE, CLOSE, APPEND, RENAME, METADATA, UNLINK 039 } 040 041 private EventType eventType; 042 043 public EventType getEventType() { 044 return eventType; 045 } 046 047 public Event(EventType eventType) { 048 this.eventType = eventType; 049 } 050 051 /** 052 * Sent when a file is closed after append or create. 053 */ 054 public static class CloseEvent extends Event { 055 private String path; 056 private long fileSize; 057 private long timestamp; 058 059 public CloseEvent(String path, long fileSize, long timestamp) { 060 super(EventType.CLOSE); 061 this.path = path; 062 this.fileSize = fileSize; 063 this.timestamp = timestamp; 064 } 065 066 public String getPath() { 067 return path; 068 } 069 070 /** 071 * The size of the closed file in bytes. May be -1 if the size is not 072 * available (e.g. in the case of a close generated by a concat operation). 073 */ 074 public long getFileSize() { 075 return fileSize; 076 } 077 078 /** 079 * The time when this event occurred, in milliseconds since the epoch. 080 */ 081 public long getTimestamp() { 082 return timestamp; 083 } 084 } 085 086 /** 087 * Sent when a new file is created (including overwrite). 088 */ 089 public static class CreateEvent extends Event { 090 091 public static enum INodeType { 092 FILE, DIRECTORY, SYMLINK; 093 } 094 095 private INodeType iNodeType; 096 private String path; 097 private long ctime; 098 private int replication; 099 private String ownerName; 100 private String groupName; 101 private FsPermission perms; 102 private String symlinkTarget; 103 private boolean overwrite; 104 private long defaultBlockSize; 105 106 public static class Builder { 107 private INodeType iNodeType; 108 private String path; 109 private long ctime; 110 private int replication; 111 private String ownerName; 112 private String groupName; 113 private FsPermission perms; 114 private String symlinkTarget; 115 private boolean overwrite; 116 private long defaultBlockSize = 0; 117 118 public Builder iNodeType(INodeType type) { 119 this.iNodeType = type; 120 return this; 121 } 122 123 public Builder path(String path) { 124 this.path = path; 125 return this; 126 } 127 128 public Builder ctime(long ctime) { 129 this.ctime = ctime; 130 return this; 131 } 132 133 public Builder replication(int replication) { 134 this.replication = replication; 135 return this; 136 } 137 138 public Builder ownerName(String ownerName) { 139 this.ownerName = ownerName; 140 return this; 141 } 142 143 public Builder groupName(String groupName) { 144 this.groupName = groupName; 145 return this; 146 } 147 148 public Builder perms(FsPermission perms) { 149 this.perms = perms; 150 return this; 151 } 152 153 public Builder symlinkTarget(String symlinkTarget) { 154 this.symlinkTarget = symlinkTarget; 155 return this; 156 } 157 158 public Builder overwrite(boolean overwrite) { 159 this.overwrite = overwrite; 160 return this; 161 } 162 163 public Builder defaultBlockSize(long defaultBlockSize) { 164 this.defaultBlockSize = defaultBlockSize; 165 return this; 166 } 167 168 public CreateEvent build() { 169 return new CreateEvent(this); 170 } 171 } 172 173 private CreateEvent(Builder b) { 174 super(EventType.CREATE); 175 this.iNodeType = b.iNodeType; 176 this.path = b.path; 177 this.ctime = b.ctime; 178 this.replication = b.replication; 179 this.ownerName = b.ownerName; 180 this.groupName = b.groupName; 181 this.perms = b.perms; 182 this.symlinkTarget = b.symlinkTarget; 183 this.overwrite = b.overwrite; 184 this.defaultBlockSize = b.defaultBlockSize; 185 } 186 187 public INodeType getiNodeType() { 188 return iNodeType; 189 } 190 191 public String getPath() { 192 return path; 193 } 194 195 /** 196 * Creation time of the file, directory, or symlink. 197 */ 198 public long getCtime() { 199 return ctime; 200 } 201 202 /** 203 * Replication is zero if the CreateEvent iNodeType is directory or symlink. 204 */ 205 public int getReplication() { 206 return replication; 207 } 208 209 public String getOwnerName() { 210 return ownerName; 211 } 212 213 public String getGroupName() { 214 return groupName; 215 } 216 217 public FsPermission getPerms() { 218 return perms; 219 } 220 221 /** 222 * Symlink target is null if the CreateEvent iNodeType is not symlink. 223 */ 224 public String getSymlinkTarget() { 225 return symlinkTarget; 226 } 227 228 public boolean getOverwrite() { 229 return overwrite; 230 } 231 232 public long getDefaultBlockSize() { 233 return defaultBlockSize; 234 } 235 } 236 237 /** 238 * Sent when there is an update to directory or file (none of the metadata 239 * tracked here applies to symlinks) that is not associated with another 240 * inotify event. The tracked metadata includes atime/mtime, replication, 241 * owner/group, permissions, ACLs, and XAttributes. Fields not relevant to the 242 * metadataType of the MetadataUpdateEvent will be null or will have their default 243 * values. 244 */ 245 public static class MetadataUpdateEvent extends Event { 246 247 public static enum MetadataType { 248 TIMES, REPLICATION, OWNER, PERMS, ACLS, XATTRS; 249 } 250 251 private String path; 252 private MetadataType metadataType; 253 private long mtime; 254 private long atime; 255 private int replication; 256 private String ownerName; 257 private String groupName; 258 private FsPermission perms; 259 private List<AclEntry> acls; 260 private List<XAttr> xAttrs; 261 private boolean xAttrsRemoved; 262 263 public static class Builder { 264 private String path; 265 private MetadataType metadataType; 266 private long mtime; 267 private long atime; 268 private int replication; 269 private String ownerName; 270 private String groupName; 271 private FsPermission perms; 272 private List<AclEntry> acls; 273 private List<XAttr> xAttrs; 274 private boolean xAttrsRemoved; 275 276 public Builder path(String path) { 277 this.path = path; 278 return this; 279 } 280 281 public Builder metadataType(MetadataType type) { 282 this.metadataType = type; 283 return this; 284 } 285 286 public Builder mtime(long mtime) { 287 this.mtime = mtime; 288 return this; 289 } 290 291 public Builder atime(long atime) { 292 this.atime = atime; 293 return this; 294 } 295 296 public Builder replication(int replication) { 297 this.replication = replication; 298 return this; 299 } 300 301 public Builder ownerName(String ownerName) { 302 this.ownerName = ownerName; 303 return this; 304 } 305 306 public Builder groupName(String groupName) { 307 this.groupName = groupName; 308 return this; 309 } 310 311 public Builder perms(FsPermission perms) { 312 this.perms = perms; 313 return this; 314 } 315 316 public Builder acls(List<AclEntry> acls) { 317 this.acls = acls; 318 return this; 319 } 320 321 public Builder xAttrs(List<XAttr> xAttrs) { 322 this.xAttrs = xAttrs; 323 return this; 324 } 325 326 public Builder xAttrsRemoved(boolean xAttrsRemoved) { 327 this.xAttrsRemoved = xAttrsRemoved; 328 return this; 329 } 330 331 public MetadataUpdateEvent build() { 332 return new MetadataUpdateEvent(this); 333 } 334 } 335 336 private MetadataUpdateEvent(Builder b) { 337 super(EventType.METADATA); 338 this.path = b.path; 339 this.metadataType = b.metadataType; 340 this.mtime = b.mtime; 341 this.atime = b.atime; 342 this.replication = b.replication; 343 this.ownerName = b.ownerName; 344 this.groupName = b.groupName; 345 this.perms = b.perms; 346 this.acls = b.acls; 347 this.xAttrs = b.xAttrs; 348 this.xAttrsRemoved = b.xAttrsRemoved; 349 } 350 351 public String getPath() { 352 return path; 353 } 354 355 public MetadataType getMetadataType() { 356 return metadataType; 357 } 358 359 public long getMtime() { 360 return mtime; 361 } 362 363 public long getAtime() { 364 return atime; 365 } 366 367 public int getReplication() { 368 return replication; 369 } 370 371 public String getOwnerName() { 372 return ownerName; 373 } 374 375 public String getGroupName() { 376 return groupName; 377 } 378 379 public FsPermission getPerms() { 380 return perms; 381 } 382 383 /** 384 * The full set of ACLs currently associated with this file or directory. 385 * May be null if all ACLs were removed. 386 */ 387 public List<AclEntry> getAcls() { 388 return acls; 389 } 390 391 public List<XAttr> getxAttrs() { 392 return xAttrs; 393 } 394 395 /** 396 * Whether the xAttrs returned by getxAttrs() were removed (as opposed to 397 * added). 398 */ 399 public boolean isxAttrsRemoved() { 400 return xAttrsRemoved; 401 } 402 403 } 404 405 /** 406 * Sent when a file, directory, or symlink is renamed. 407 */ 408 public static class RenameEvent extends Event { 409 private String srcPath; 410 private String dstPath; 411 private long timestamp; 412 413 public static class Builder { 414 private String srcPath; 415 private String dstPath; 416 private long timestamp; 417 418 public Builder srcPath(String srcPath) { 419 this.srcPath = srcPath; 420 return this; 421 } 422 423 public Builder dstPath(String dstPath) { 424 this.dstPath = dstPath; 425 return this; 426 } 427 428 public Builder timestamp(long timestamp) { 429 this.timestamp = timestamp; 430 return this; 431 } 432 433 public RenameEvent build() { 434 return new RenameEvent(this); 435 } 436 } 437 438 private RenameEvent(Builder builder) { 439 super(EventType.RENAME); 440 this.srcPath = builder.srcPath; 441 this.dstPath = builder.dstPath; 442 this.timestamp = builder.timestamp; 443 } 444 445 public String getSrcPath() { 446 return srcPath; 447 } 448 449 public String getDstPath() { 450 return dstPath; 451 } 452 453 /** 454 * The time when this event occurred, in milliseconds since the epoch. 455 */ 456 public long getTimestamp() { 457 return timestamp; 458 } 459 } 460 461 /** 462 * Sent when an existing file is opened for append. 463 */ 464 public static class AppendEvent extends Event { 465 private String path; 466 private boolean newBlock; 467 468 public static class Builder { 469 private String path; 470 private boolean newBlock; 471 472 public Builder path(String path) { 473 this.path = path; 474 return this; 475 } 476 477 public Builder newBlock(boolean newBlock) { 478 this.newBlock = newBlock; 479 return this; 480 } 481 482 public AppendEvent build() { 483 return new AppendEvent(this); 484 } 485 } 486 487 private AppendEvent(Builder b) { 488 super(EventType.APPEND); 489 this.path = b.path; 490 this.newBlock = b.newBlock; 491 } 492 493 public String getPath() { 494 return path; 495 } 496 497 public boolean toNewBlock() { 498 return newBlock; 499 } 500 } 501 502 /** 503 * Sent when a file, directory, or symlink is deleted. 504 */ 505 public static class UnlinkEvent extends Event { 506 private String path; 507 private long timestamp; 508 509 public static class Builder { 510 private String path; 511 private long timestamp; 512 513 public Builder path(String path) { 514 this.path = path; 515 return this; 516 } 517 518 public Builder timestamp(long timestamp) { 519 this.timestamp = timestamp; 520 return this; 521 } 522 523 public UnlinkEvent build() { 524 return new UnlinkEvent(this); 525 } 526 } 527 528 private UnlinkEvent(Builder builder) { 529 super(EventType.UNLINK); 530 this.path = builder.path; 531 this.timestamp = builder.timestamp; 532 } 533 534 public String getPath() { 535 return path; 536 } 537 538 /** 539 * The time when this event occurred, in milliseconds since the epoch. 540 */ 541 public long getTimestamp() { 542 return timestamp; 543 } 544 } 545}