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}