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 <[email protected]> Authored: Tue Jan 10 17:10:24 2017 -0800 Committer: hahao <[email protected]> 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 < Hive Obj, HDFS Path > 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>
