You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by ha...@apache.org on 2017/01/11 01:25:08 UTC

sentry git commit: SENTRY-1538: Create schema for storing HMS path change and Sentry permission change. (Hao Hao, Reviewed by: Alexander Kolbasov, Kalyan Kalvagadda and Vamsee Yarlagadda)

Repository: sentry
Updated Branches:
  refs/heads/sentry-ha-redesign 1458d1a3b -> 6df0a66d7


SENTRY-1538: Create schema for storing HMS path change and Sentry permission change. (Hao Hao, Reviewed by: Alexander Kolbasov, Kalyan Kalvagadda and Vamsee Yarlagadda)

Change-Id: I63e9fe7dc4795a98fd82dfc66276ab88fe484c84


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/6df0a66d
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/6df0a66d
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/6df0a66d

Branch: refs/heads/sentry-ha-redesign
Commit: 6df0a66d7d914df2bbafb0b9d6a328dd6966bc41
Parents: 1458d1a
Author: hahao <ha...@cloudera.com>
Authored: Tue Jan 10 17:10:24 2017 -0800
Committer: hahao <ha...@cloudera.com>
Committed: Tue Jan 10 17:12:31 2017 -0800

----------------------------------------------------------------------
 .../org/apache/sentry/hdfs/PathsUpdate.java     |  11 ++
 .../apache/sentry/hdfs/PermissionsUpdate.java   |  11 ++
 .../apache/sentry/hdfs/ThriftSerializer.java    |  17 +++
 .../java/org/apache/sentry/hdfs/Updateable.java |  18 +++
 .../org/apache/sentry/hdfs/TestPathsUpdate.java |  15 ++
 .../sentry/hdfs/TestPermissionUpdate.java       |  41 ++++++
 .../org/apache/sentry/hdfs/UpdateForwarder.java |   2 +-
 .../apache/sentry/hdfs/TestUpdateForwarder.java |  11 ++
 .../db/service/model/MSentryPathChange.java     | 139 +++++++++++++++++++
 .../db/service/model/MSentryPermChange.java     | 137 ++++++++++++++++++
 .../provider/db/service/model/package.jdo       |  24 ++++
 11 files changed, 425 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PathsUpdate.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PathsUpdate.java b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PathsUpdate.java
index 7cfb3bf..9ecd9e4 100644
--- a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PathsUpdate.java
+++ b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PathsUpdate.java
@@ -33,6 +33,7 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.conf.Configuration;
 
 import com.google.common.collect.Lists;
+import org.apache.thrift.TException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -162,4 +163,14 @@ public class PathsUpdate implements Updateable.Update {
     ThriftSerializer.deserialize(tPathsUpdate, data);
   }
 
+  @Override
+  public void JSONDeserialize(String update) throws TException {
+    ThriftSerializer.deserializeFromJSON(tPathsUpdate, update);
+  }
+
+  @Override
+  public String JSONSerialize() throws TException {
+    return ThriftSerializer.serializeToJSON(tPathsUpdate);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PermissionsUpdate.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PermissionsUpdate.java b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PermissionsUpdate.java
index 9834923..a346587 100644
--- a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PermissionsUpdate.java
+++ b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/PermissionsUpdate.java
@@ -25,6 +25,7 @@ import java.util.LinkedList;
 import org.apache.sentry.hdfs.service.thrift.TPermissionsUpdate;
 import org.apache.sentry.hdfs.service.thrift.TPrivilegeChanges;
 import org.apache.sentry.hdfs.service.thrift.TRoleChanges;
+import org.apache.thrift.TException;
 
 public class PermissionsUpdate implements Updateable.Update {
 
@@ -106,4 +107,14 @@ public class PermissionsUpdate implements Updateable.Update {
   public void deserialize(byte[] data) throws IOException {
     ThriftSerializer.deserialize(tPermUpdate, data);
   }
+
+  @Override
+  public void JSONDeserialize(String update) throws TException {
+    ThriftSerializer.deserializeFromJSON(tPermUpdate, update);
+  }
+
+  @Override
+  public String JSONSerialize() throws TException {
+    return ThriftSerializer.serializeToJSON(tPermUpdate);
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ThriftSerializer.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ThriftSerializer.java b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ThriftSerializer.java
index b66f70b..69aa098 100644
--- a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ThriftSerializer.java
+++ b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/ThriftSerializer.java
@@ -25,9 +25,13 @@ import org.apache.thrift.TDeserializer;
 import org.apache.thrift.TException;
 import org.apache.thrift.TSerializer;
 import org.apache.thrift.protocol.TCompactProtocol;
+import org.apache.thrift.protocol.TSimpleJSONProtocol;
 
 public class ThriftSerializer {
 
+  final static private TSimpleJSONProtocol.Factory tSimpleJSONProtocol =
+          new TSimpleJSONProtocol.Factory();
+
   // Use default max thrift message size here.
   // TODO: Figure out a way to make maxMessageSize configurable, eg. create a serializer singleton at startup by
   // passing a max_size parameter
@@ -60,4 +64,17 @@ public class ThriftSerializer {
   private ThriftSerializer() {
     // Make constructor private to avoid instantiation
   }
+
+  public static String serializeToJSON(TBase base) throws TException  {
+    // Initiate a new TSerializer each time for thread safety.
+    TSerializer tSerializer = new TSerializer(tSimpleJSONProtocol);
+    return tSerializer.toString(base);
+  }
+
+  public static void deserializeFromJSON(TBase base, String dataInJson) throws TException {
+    // Initiate a new TDeserializer each time for thread safety.
+    TDeserializer tDeserializer = new TDeserializer(tSimpleJSONProtocol);
+    tDeserializer.fromString(base, dataInJson);
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/Updateable.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/Updateable.java b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/Updateable.java
index 8391b85..12baaa4 100644
--- a/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/Updateable.java
+++ b/sentry-hdfs/sentry-hdfs-common/src/main/java/org/apache/sentry/hdfs/Updateable.java
@@ -17,6 +17,8 @@
  */
 package org.apache.sentry.hdfs;
 
+import org.apache.thrift.TException;
+
 import java.io.IOException;
 import java.util.concurrent.locks.ReadWriteLock;
 
@@ -39,6 +41,22 @@ public interface Updateable<K extends Updateable.Update> {
     byte[] serialize() throws IOException;
 
     void deserialize(byte data[]) throws IOException;
+
+    /**
+     *  Deserialize the update from a JSON format representation to an object.
+     *
+     * @param update the given JSON string representation
+     * @throws TException
+     */
+    void JSONDeserialize(String update) throws TException;
+
+    /**
+     * Serialize the update from the object to a JSON format representation.
+     *
+     * @return the JSON string representation
+     * @throws TException
+     */
+    String JSONSerialize() throws TException;
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPathsUpdate.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPathsUpdate.java b/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPathsUpdate.java
index 53243b4..b5cbea9 100644
--- a/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPathsUpdate.java
+++ b/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPathsUpdate.java
@@ -19,6 +19,9 @@ package org.apache.sentry.hdfs;
 
 import java.util.List;
 
+import org.apache.sentry.hdfs.service.thrift.TPathChanges;
+import org.apache.sentry.hdfs.service.thrift.TPathsUpdate;
+import org.apache.thrift.TException;
 import org.junit.Test;
 import org.junit.Assert;
 
@@ -59,4 +62,16 @@ public class TestPathsUpdate {
     System.out.println(results);
     Assert.assertNull("Parse path without throwing exception",results);
   }
+
+  @Test
+  public void testSerializeDeserializeInJSON() throws SentryMalformedPathException, TException{
+    PathsUpdate update = new PathsUpdate(1, true);
+    TPathChanges pathChange = update.newPathChange("db1.tbl12");
+    pathChange.addToAddPaths(PathsUpdate.parsePath("hdfs:///db1/tbl12/part121"));
+
+    // Serialize and deserialize the PermssionUpdate object should equals to the original one.
+    TPathsUpdate before = update.toThrift();
+    update.JSONDeserialize(update.JSONSerialize());
+    junit.framework.Assert.assertEquals(before, update.toThrift());
+  }
 }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPermissionUpdate.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPermissionUpdate.java b/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPermissionUpdate.java
new file mode 100644
index 0000000..11d3a2a
--- /dev/null
+++ b/sentry-hdfs/sentry-hdfs-common/src/test/java/org/apache/sentry/hdfs/TestPermissionUpdate.java
@@ -0,0 +1,41 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.sentry.hdfs;
+
+
+import junit.framework.Assert;
+import org.apache.sentry.hdfs.service.thrift.TPermissionsUpdate;
+import org.apache.sentry.hdfs.service.thrift.TPrivilegeChanges;
+import org.apache.thrift.TException;
+import org.junit.Test;
+
+public class TestPermissionUpdate {
+
+  @Test
+  public void testSerializeDeserializeInJSON() throws TException {
+    PermissionsUpdate update = new PermissionsUpdate(0, false);
+    TPrivilegeChanges privUpdate = update.addPrivilegeUpdate(PermissionsUpdate.RENAME_PRIVS);
+    privUpdate.putToAddPrivileges("newAuthz", "newAuthz");
+    privUpdate.putToDelPrivileges("oldAuthz", "oldAuthz");
+
+    // Serialize and deserialize the PermssionUpdate object should equals to the original one.
+    TPermissionsUpdate before = update.toThrift();
+    update.JSONDeserialize(update.JSONSerialize());
+    Assert.assertEquals(before, update.toThrift());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java b/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java
index 8131350..6d5c607 100644
--- a/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java
+++ b/sentry-hdfs/sentry-hdfs-service/src/main/java/org/apache/sentry/hdfs/UpdateForwarder.java
@@ -78,7 +78,7 @@ public class UpdateForwarder<K extends Updateable.Update> implements
 
   protected UpdateForwarder(Configuration conf, Updateable<K> updateable, //NOPMD
       ExternalImageRetriever<K> imageRetreiver, int maxUpdateLogSize,
-      int initUpdateRetryDelay) { 
+      int initUpdateRetryDelay) {
     this.maxUpdateLogSize = maxUpdateLogSize;
     this.imageRetreiver = imageRetreiver;
     if (imageRetreiver != null) {

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestUpdateForwarder.java
----------------------------------------------------------------------
diff --git a/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestUpdateForwarder.java b/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestUpdateForwarder.java
index 315d4b3..0f0d0a7 100644
--- a/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestUpdateForwarder.java
+++ b/sentry-hdfs/sentry-hdfs-service/src/test/java/org/apache/sentry/hdfs/TestUpdateForwarder.java
@@ -23,6 +23,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.locks.ReadWriteLock;
 
+import org.apache.thrift.TException;
 import org.junit.Assert;
 
 import org.apache.hadoop.conf.Configuration;
@@ -77,6 +78,16 @@ public class TestUpdateForwarder {
     public void deserialize(byte[] data) throws IOException {
       state = new String(data);
     }
+
+    @Override
+    public String JSONSerialize() throws TException {
+      return state;
+    }
+
+    @Override
+    public void JSONDeserialize(String update) throws TException {
+      state = new String(update);
+    }
   }
 
   static class DummyUpdatable implements Updateable<DummyUpdate> {

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java
new file mode 100644
index 0000000..b88e7d1
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPathChange.java
@@ -0,0 +1,139 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.PrimaryKey;
+
+/**
+ * Database backend store for HMS path delta change. Each record contains
+ * change ID, JSON format of a single &lt Hive Obj, HDFS Path &gt change, and
+ * timestamp.
+ * <p>
+ * e.g. for add paths change in JSON format.
+ * <pre>
+ * {@code
+ * {
+ *  "hasFullImage":1,
+ *  "seqNum":1,
+ *  "pathChanges":[
+ *    {
+ *      "authzObj":"db1.tbl12",
+ *      "addPaths":[
+ *        [
+ *          "db1",
+ *          "tbl12",
+ *          "part121"
+ *        ]
+ *      ],
+ *      "delPaths":[]
+ *    }
+ *  ]
+ * }
+ * }
+ * </pre>
+ * <p>
+ * Any changes to this objects require re-running the maven build so DN
+ * can re-enhance.
+ */
+
+@PersistenceCapable
+public class MSentryPathChange {
+
+  @PrimaryKey
+  private long changeID;
+
+  // Path change in JSON format.
+  private String pathChange;
+  private long createTimeMs;
+
+  public MSentryPathChange(long changeID, String pathChange, long createTime) {
+    this.changeID = changeID;
+    this.pathChange = pathChange;
+    this.createTimeMs = createTime;
+  }
+
+  public void setCreateTimeMs(long createTimeMs) {
+    this.createTimeMs = createTimeMs;
+  }
+
+  public long getCreateTimeMs() {
+    return createTimeMs;
+  }
+
+  public void setPathChange(String pathChange) {
+    this.pathChange = pathChange;
+  }
+
+  public String getPathChange() {
+    return pathChange;
+  }
+
+  public long getChangeID() {
+    return changeID;
+  }
+
+  public void setChangeID(long changeID) {
+    this.changeID = changeID;
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryChange [changeID=" + changeID + " , pathChange= " + pathChange + ", createTime=" + createTimeMs +  "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + Long.valueOf(changeID).hashCode();
+    result = prime * result + ((pathChange == null) ? 0 : pathChange.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MSentryPathChange other = (MSentryPathChange) obj;
+    if (changeID != other.changeID) {
+      return false;
+    }
+
+    if (!pathChange.equals(other.pathChange)) {
+      return false;
+    }
+
+    if (createTimeMs != other.createTimeMs) {
+      return false;
+    }
+
+    return true;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java
new file mode 100644
index 0000000..2ccace0
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPermChange.java
@@ -0,0 +1,137 @@
+/**
+ * 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.sentry.provider.db.service.model;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.PrimaryKey;
+
+
+/**
+ * Database backend store for Sentry permission delta change. Each record
+ * contains change ID, JSON format of a single Sentry permission change,
+ * and timestamp.
+ * <p>
+ * e.g. for rename privileges change in JSON format.
+ * <pre>
+ * {@code
+ * {
+ *   "hasfullImage":0,
+ *   "seqNum":0,
+ *   "privilegeChanges":{
+ *     "__RENAME_PRIV__":{
+ *       "authzObj":"__RENAME_PRIV__",
+ *       "addPrivileges":{
+ *         "newAuthz":"newAuthz"
+ *       },
+ *       "delPrivileges":{
+ *         "oldAuthz":"oldAuthz"
+ *       }
+ *     }
+ *   },
+ *   "roleChanges":{}
+ * }
+ * </pre>
+ * <p>
+ * Any changes to this objects require re-running the maven build so DN
+ * can re-enhance.
+ */
+@PersistenceCapable
+public class MSentryPermChange {
+
+  @PrimaryKey
+  private long changeID;
+
+  // Permission change in JSON format.
+  private String permChange;
+  private long createTimeMs;
+
+  public MSentryPermChange(long changeID, String permChange, long createTimeMs) {
+    this.changeID = changeID;
+    this.permChange = permChange;
+    this.createTimeMs = createTimeMs;
+  }
+
+  public void setCreateTimeMs(long createTimeMs) {
+    this.createTimeMs = createTimeMs;
+  }
+
+  public long getCreateTimeMs() {
+    return createTimeMs;
+  }
+
+  public void setPermChange(String permChange) {
+    this.permChange = permChange;
+  }
+
+  public String getPermChange() {
+    return permChange;
+  }
+
+  public long getChangeID() {
+    return changeID;
+  }
+
+  public void setChangeID(long changeID) {
+    this.changeID = changeID;
+  }
+
+  @Override
+  public String toString() {
+    return "MSentryPermChange [changeID=" + changeID + ", permChange= " + permChange + ", createTimeMs=" + createTimeMs +  "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + Long.valueOf(changeID).hashCode();
+    result = prime * result + ((permChange == null) ? 0 : permChange.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MSentryPermChange other = (MSentryPermChange) obj;
+    if (changeID != other.changeID) {
+      return false;
+    }
+
+    if (createTimeMs != other.createTimeMs) {
+      return false;
+    }
+
+    if (!permChange.equals(other.permChange)) {
+      return false;
+    }
+
+    return true;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/sentry/blob/6df0a66d/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
index fb5470f..dc8fdbf 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
@@ -262,6 +262,30 @@
        </field>
      </class>
 
+     <class name="MSentryPermChange" table="SENTRY_PERM_CHANGE" identity-type="application" detachable="true">
+       <field name="changeID" primary-key="true">
+         <column name="CHANGE_ID" jdbc-type="BIGINT" allows-null="false"/>
+       </field>
+       <field name ="permChange">
+         <column name="PERM_CHANGE" length="4000" jdbc-type="VARCHAR" allows-null="false"/>
+       </field>
+       <field name="createTimeMs">
+         <column name="CREATE_TIME_MS" jdbc-type="BIGINT"/>
+       </field>
+     </class>
+
+     <class name="MSentryPathChange" table="SENTRY_PATH_CHANGE" identity-type="application" detachable="true">
+       <field name="changeID" primary-key="true">
+         <column name="CHANGE_ID" jdbc-type="BIGINT" allows-null="false"/>
+       </field>
+       <field name ="pathChange">
+         <column name="PATH_CHANGE" length="4000" jdbc-type="VARCHAR" allows-null="false"/>
+       </field>
+       <field name="createTimeMs">
+         <column name="CREATE_TIME_MS" jdbc-type="BIGINT"/>
+       </field>
+     </class>
+
   </package>
 </jdo>