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
105    public static class Builder {
106      private INodeType iNodeType;
107      private String path;
108      private long ctime;
109      private int replication;
110      private String ownerName;
111      private String groupName;
112      private FsPermission perms;
113      private String symlinkTarget;
114      private boolean overwrite;
115
116      public Builder iNodeType(INodeType type) {
117        this.iNodeType = type;
118        return this;
119      }
120
121      public Builder path(String path) {
122        this.path = path;
123        return this;
124      }
125
126      public Builder ctime(long ctime) {
127        this.ctime = ctime;
128        return this;
129      }
130
131      public Builder replication(int replication) {
132        this.replication = replication;
133        return this;
134      }
135
136      public Builder ownerName(String ownerName) {
137        this.ownerName = ownerName;
138        return this;
139      }
140
141      public Builder groupName(String groupName) {
142        this.groupName = groupName;
143        return this;
144      }
145
146      public Builder perms(FsPermission perms) {
147        this.perms = perms;
148        return this;
149      }
150
151      public Builder symlinkTarget(String symlinkTarget) {
152        this.symlinkTarget = symlinkTarget;
153        return this;
154      }
155      
156      public Builder overwrite(boolean overwrite) {
157        this.overwrite = overwrite;
158        return this;
159      }
160
161      public CreateEvent build() {
162        return new CreateEvent(this);
163      }
164    }
165
166    private CreateEvent(Builder b) {
167      super(EventType.CREATE);
168      this.iNodeType = b.iNodeType;
169      this.path = b.path;
170      this.ctime = b.ctime;
171      this.replication = b.replication;
172      this.ownerName = b.ownerName;
173      this.groupName = b.groupName;
174      this.perms = b.perms;
175      this.symlinkTarget = b.symlinkTarget;
176      this.overwrite = b.overwrite;
177    }
178
179    public INodeType getiNodeType() {
180      return iNodeType;
181    }
182
183    public String getPath() {
184      return path;
185    }
186
187    /**
188     * Creation time of the file, directory, or symlink.
189     */
190    public long getCtime() {
191      return ctime;
192    }
193
194    /**
195     * Replication is zero if the CreateEvent iNodeType is directory or symlink.
196     */
197    public int getReplication() {
198      return replication;
199    }
200
201    public String getOwnerName() {
202      return ownerName;
203    }
204
205    public String getGroupName() {
206      return groupName;
207    }
208
209    public FsPermission getPerms() {
210      return perms;
211    }
212
213    /**
214     * Symlink target is null if the CreateEvent iNodeType is not symlink.
215     */
216    public String getSymlinkTarget() {
217      return symlinkTarget;
218    }
219    
220    public boolean getOverwrite() {
221      return overwrite;
222    }
223  }
224
225  /**
226   * Sent when there is an update to directory or file (none of the metadata
227   * tracked here applies to symlinks) that is not associated with another
228   * inotify event. The tracked metadata includes atime/mtime, replication,
229   * owner/group, permissions, ACLs, and XAttributes. Fields not relevant to the
230   * metadataType of the MetadataUpdateEvent will be null or will have their default
231   * values.
232   */
233  public static class MetadataUpdateEvent extends Event {
234
235    public static enum MetadataType {
236      TIMES, REPLICATION, OWNER, PERMS, ACLS, XATTRS;
237    }
238
239    private String path;
240    private MetadataType metadataType;
241    private long mtime;
242    private long atime;
243    private int replication;
244    private String ownerName;
245    private String groupName;
246    private FsPermission perms;
247    private List<AclEntry> acls;
248    private List<XAttr> xAttrs;
249    private boolean xAttrsRemoved;
250
251    public static class Builder {
252      private String path;
253      private MetadataType metadataType;
254      private long mtime;
255      private long atime;
256      private int replication;
257      private String ownerName;
258      private String groupName;
259      private FsPermission perms;
260      private List<AclEntry> acls;
261      private List<XAttr> xAttrs;
262      private boolean xAttrsRemoved;
263
264      public Builder path(String path) {
265        this.path = path;
266        return this;
267      }
268
269      public Builder metadataType(MetadataType type) {
270        this.metadataType = type;
271        return this;
272      }
273
274      public Builder mtime(long mtime) {
275        this.mtime = mtime;
276        return this;
277      }
278
279      public Builder atime(long atime) {
280        this.atime = atime;
281        return this;
282      }
283
284      public Builder replication(int replication) {
285        this.replication = replication;
286        return this;
287      }
288
289      public Builder ownerName(String ownerName) {
290        this.ownerName = ownerName;
291        return this;
292      }
293
294      public Builder groupName(String groupName) {
295        this.groupName = groupName;
296        return this;
297      }
298
299      public Builder perms(FsPermission perms) {
300        this.perms = perms;
301        return this;
302      }
303
304      public Builder acls(List<AclEntry> acls) {
305        this.acls = acls;
306        return this;
307      }
308
309      public Builder xAttrs(List<XAttr> xAttrs) {
310        this.xAttrs = xAttrs;
311        return this;
312      }
313
314      public Builder xAttrsRemoved(boolean xAttrsRemoved) {
315        this.xAttrsRemoved = xAttrsRemoved;
316        return this;
317      }
318
319      public MetadataUpdateEvent build() {
320        return new MetadataUpdateEvent(this);
321      }
322    }
323
324    private MetadataUpdateEvent(Builder b) {
325      super(EventType.METADATA);
326      this.path = b.path;
327      this.metadataType = b.metadataType;
328      this.mtime = b.mtime;
329      this.atime = b.atime;
330      this.replication = b.replication;
331      this.ownerName = b.ownerName;
332      this.groupName = b.groupName;
333      this.perms = b.perms;
334      this.acls = b.acls;
335      this.xAttrs = b.xAttrs;
336      this.xAttrsRemoved = b.xAttrsRemoved;
337    }
338
339    public String getPath() {
340      return path;
341    }
342
343    public MetadataType getMetadataType() {
344      return metadataType;
345    }
346
347    public long getMtime() {
348      return mtime;
349    }
350
351    public long getAtime() {
352      return atime;
353    }
354
355    public int getReplication() {
356      return replication;
357    }
358
359    public String getOwnerName() {
360      return ownerName;
361    }
362
363    public String getGroupName() {
364      return groupName;
365    }
366
367    public FsPermission getPerms() {
368      return perms;
369    }
370
371    /**
372     * The full set of ACLs currently associated with this file or directory.
373     * May be null if all ACLs were removed.
374     */
375    public List<AclEntry> getAcls() {
376      return acls;
377    }
378
379    public List<XAttr> getxAttrs() {
380      return xAttrs;
381    }
382
383    /**
384     * Whether the xAttrs returned by getxAttrs() were removed (as opposed to
385     * added).
386     */
387    public boolean isxAttrsRemoved() {
388      return xAttrsRemoved;
389    }
390
391  }
392
393  /**
394   * Sent when a file, directory, or symlink is renamed.
395   */
396  public static class RenameEvent extends Event {
397    private String srcPath;
398    private String dstPath;
399    private long timestamp;
400
401    public RenameEvent(String srcPath, String dstPath, long timestamp) {
402      super(EventType.RENAME);
403      this.srcPath = srcPath;
404      this.dstPath = dstPath;
405      this.timestamp = timestamp;
406    }
407
408    public String getSrcPath() {
409      return srcPath;
410    }
411
412    public String getDstPath() {
413      return dstPath;
414    }
415
416    /**
417     * The time when this event occurred, in milliseconds since the epoch.
418     */
419    public long getTimestamp() {
420      return timestamp;
421    }
422  }
423
424  /**
425   * Sent when an existing file is opened for append.
426   */
427  public static class AppendEvent extends Event {
428    private String path;
429
430    public AppendEvent(String path) {
431      super(EventType.APPEND);
432      this.path = path;
433    }
434
435    public String getPath() {
436      return path;
437    }
438  }
439
440  /**
441   * Sent when a file, directory, or symlink is deleted.
442   */
443  public static class UnlinkEvent extends Event {
444    private String path;
445    private long timestamp;
446
447    public UnlinkEvent(String path, long timestamp) {
448      super(EventType.UNLINK);
449      this.path = path;
450      this.timestamp = timestamp;
451    }
452
453    public String getPath() {
454      return path;
455    }
456
457    /**
458     * The time when this event occurred, in milliseconds since the epoch.
459     */
460    public long getTimestamp() {
461      return timestamp;
462    }
463  }
464}