You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2016/04/21 22:33:51 UTC

incubator-ranger git commit: RANGER-901: fields that track policies/tags in a service are moved from x_service to x_service_version_info table

Repository: incubator-ranger
Updated Branches:
  refs/heads/master 0699c3401 -> cb58449b6


RANGER-901: fields that track policies/tags in a service are moved from x_service to x_service_version_info table

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ranger/commit/cb58449b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ranger/tree/cb58449b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ranger/diff/cb58449b

Branch: refs/heads/master
Commit: cb58449b6b61d65b722f03da6bf9b65a1f5c6fbc
Parents: 0699c34
Author: Abhay Kulkarni <ak...@hortonworks.com>
Authored: Thu Apr 7 12:17:04 2016 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Thu Apr 21 12:44:29 2016 -0700

----------------------------------------------------------------------
 .../contextenricher/RangerTagEnricher.java      |   2 +-
 .../mysql/patches/022-split-service-table.sql   |  29 +++
 .../oracle/patches/022-split-service-table.sql  |  36 ++++
 .../patches/022-split-service-table.sql         |  32 +++
 .../patches/022-split-service-table.sql         |  31 +++
 .../patches/022-split-service-table.sql         |  55 ++++++
 .../org/apache/ranger/biz/ServiceDBStore.java   | 123 +++++++++---
 .../java/org/apache/ranger/biz/TagDBStore.java  |  23 ++-
 .../org/apache/ranger/common/AppConstants.java  |  10 +-
 .../apache/ranger/db/RangerDaoManagerBase.java  |  11 +-
 .../java/org/apache/ranger/db/XXServiceDao.java |  65 ------
 .../ranger/db/XXServiceVersionInfoDao.java      | 131 ++++++++++++
 .../ranger/entity/XXServiceVersionInfo.java     | 197 +++++++++++++++++++
 .../PatchForServiceVersionInfo_J10004.java      | 122 ++++++++++++
 .../service/RangerServiceResourceService.java   |   2 +-
 .../ranger/service/RangerServiceService.java    |  35 +++-
 .../service/RangerServiceServiceBase.java       |  24 ++-
 .../ranger/service/RangerTagDefService.java     |   2 +-
 .../service/RangerTagResourceMapService.java    |   6 +-
 .../apache/ranger/service/RangerTagService.java |   2 +-
 .../resources/META-INF/jpa_named_queries.xml    |  30 ++-
 .../apache/ranger/biz/TestServiceDBStore.java   |  43 ++++
 .../service/TestRangerServiceService.java       |  41 ++++
 .../service/TestRangerServiceServiceBase.java   |  15 ++
 24 files changed, 941 insertions(+), 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
----------------------------------------------------------------------
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index 9d3d201..206385c 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -339,8 +339,8 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 
 				if (serviceTags != null) {
 					tagEnricher.setServiceTags(serviceTags);
+					lastKnownVersion = serviceTags.getTagVersion() == null ? -1L : serviceTags.getTagVersion();
 					LOG.info("RangerTagRefresher.populateTags() - Updated tags-cache to new version of tags, lastKnownVersion=" + lastKnownVersion + "; newVersion=" + serviceTags.getTagVersion());
-					lastKnownVersion = serviceTags.getTagVersion();
 					hasProvidedTagsToReceiver = true;
 				} else {
 					if (LOG.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/db/mysql/patches/022-split-service-table.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/mysql/patches/022-split-service-table.sql b/security-admin/db/mysql/patches/022-split-service-table.sql
new file mode 100644
index 0000000..962e715
--- /dev/null
+++ b/security-admin/db/mysql/patches/022-split-service-table.sql
@@ -0,0 +1,29 @@
+-- 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.
+
+DROP TABLE IF EXISTS `x_service_version_info`;
+
+CREATE TABLE `x_service_version_info` (
+`id` bigint(20) NOT NULL AUTO_INCREMENT,
+`service_id` bigint(20) NOT NULL,
+`policy_version` bigint(20) NOT NULL DEFAULT 0,
+`policy_update_time` datetime DEFAULT NULL,
+`tag_version` bigint(20) NOT NULL DEFAULT 0,
+`tag_update_time` datetime DEFAULT NULL,
+primary key (`id`),
+CONSTRAINT `x_service_version_info_service_id` FOREIGN KEY (`service_id`) REFERENCES `x_service` (`id`) 
+);
+CREATE INDEX x_service_version_info_IDX_service_id ON x_service_version_info(service_id);
+

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/db/oracle/patches/022-split-service-table.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/oracle/patches/022-split-service-table.sql b/security-admin/db/oracle/patches/022-split-service-table.sql
new file mode 100644
index 0000000..7059be2
--- /dev/null
+++ b/security-admin/db/oracle/patches/022-split-service-table.sql
@@ -0,0 +1,36 @@
+-- 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.
+
+/
+DROP SEQUENCE IF EXISTS x_service_version_info_seq;
+
+CREATE SEQUENCE x_service_version_info_seq START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
+
+DROP TABLE IF EXISTS `x_service_version_info`;
+
+CREATE TABLE `x_service_version_info` (
+id NUMBER(20) NOT NULL,
+service_id NUMBER(20) NOT NULL,
+policy_version NUMBER(20) NOT NULL DEFAULT 0,
+policy_update_time DATE DEFAULT NULL NULL,
+tag_version NUMBER(20) NOT NULL DEFAULT 0,
+tag_update_time DATE DEFAULT NULL NULL,
+primary key (id),
+CONSTRAINT x_service_version_info_service_id FOREIGN KEY (service_id) REFERENCES x_service(id) 
+);
+CREATE INDEX x_service_version_info_IDX_service_id ON x_service_version_info(service_id);
+
+commit;
+

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/db/postgres/patches/022-split-service-table.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/postgres/patches/022-split-service-table.sql b/security-admin/db/postgres/patches/022-split-service-table.sql
new file mode 100644
index 0000000..5fe1ef2
--- /dev/null
+++ b/security-admin/db/postgres/patches/022-split-service-table.sql
@@ -0,0 +1,32 @@
+-- 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.
+
+DROP TABLE IF EXISTS x_service_version_info;
+DROP SEQUENCE IF EXISTS x_service_version_info_seq;
+
+CREATE SEQUENCE x_service_version_info_seq;
+
+CREATE TABLE x_service_version_info (
+ id BIGINT DEFAULT nextval('x_service_version_info_seq'::regclass),
+service_id bigint NOT NULL,
+policy_version bigint NOT NULL DEFAULT '0',
+policy_update_time TIMESTAMP DEFAULT NULL,
+tag_version bigint NOT NULL DEFAULT '0',
+tag_update_time TIMESTAMP DEFAULT NULL,
+primary key (id),
+CONSTRAINT x_service_version_info_service_id FOREIGN KEY (service_id) REFERENCES x_service (id) 
+);
+CREATE INDEX x_service_version_info_IDX_service_id ON x_service_version_info(service_id);
+

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/db/sqlanywhere/patches/022-split-service-table.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/sqlanywhere/patches/022-split-service-table.sql b/security-admin/db/sqlanywhere/patches/022-split-service-table.sql
new file mode 100644
index 0000000..d32966d
--- /dev/null
+++ b/security-admin/db/sqlanywhere/patches/022-split-service-table.sql
@@ -0,0 +1,31 @@
+-- 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.
+
+CREATE TABLE dbo.x_service_version_info(
+	id bigint IDENTITY NOT NULL,
+	service_id bigint NOT NULL,
+	policy_version bigint NOT NULL DEFAULT 0,
+	policy_update_time datetime DEFAULT NULL NULL,
+	tag_version bigint NOT NULL DEFAULT 0,
+	tag_update_time datetime DEFAULT NULL NULL,
+	CONSTRAINT x_service_version_info_PK_id PRIMARY KEY CLUSTERED(id)
+)
+GO
+ALTER TABLE dbo.x_service_version_info ADD CONSTRAINT x_service_version_info_service_id FOREIGN KEY(service_id) REFERENCES dbo.x_service (id)
+GO
+CREATE NONCLUSTERED INDEX x_service_version_info_IDX_service_id ON dbo.x_service_version_info(service_id ASC)
+GO
+
+exit

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/db/sqlserver/patches/022-split-service-table.sql
----------------------------------------------------------------------
diff --git a/security-admin/db/sqlserver/patches/022-split-service-table.sql b/security-admin/db/sqlserver/patches/022-split-service-table.sql
new file mode 100644
index 0000000..3be0416
--- /dev/null
+++ b/security-admin/db/sqlserver/patches/022-split-service-table.sql
@@ -0,0 +1,55 @@
+-- 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.
+
+GO
+IF (OBJECT_ID('x_service_version_info_service_id') IS NOT NULL)
+BEGIN
+    ALTER TABLE [dbo].[x_service_version_info] DROP CONSTRAINT x_service_version_info_service_id
+END
+GO
+IF (OBJECT_ID('x_service_version_info') IS NOT NULL)
+BEGIN
+    DROP TABLE [dbo].[x_service_version_info]
+END
+GO
+SET ANSI_NULLS ON
+GO
+SET QUOTED_IDENTIFIER ON
+GO
+SET ANSI_PADDING ON
+GO
+CREATE TABLE [dbo].[x_service_version_info](
+	[id] [bigint] IDENTITY(1,1) NOT NULL,
+	[service_id] [bigint] NOT NULL,
+	[policy_version] [bigint] NOT NULL DEFAULT 0,
+	[policy_update_time] [datetime2] DEFAULT NULL NULL,
+	[tag_version] [bigint] NOT NULL DEFAULT 0,
+	[tag_update_time] [datetime2] DEFAULT NULL NULL,
+	PRIMARY KEY CLUSTERED 
+(
+	[id] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+GO
+ALTER TABLE [dbo].[x_service_version_info] WITH CHECK ADD CONSTRAINT [x_service_version_info_service_id] FOREIGN KEY([service_id]) REFERENCES [dbo].[x_service] ([id])
+GO
+CREATE NONCLUSTERED INDEX [x_service_version_info_IDX_service_id] ON [x_service_version_info]
+(
+   [service_id] ASC
+)
+WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]
+GO
+
+exit

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 7ef950a..53b33b2 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -1404,10 +1404,6 @@ public class ServiceDBStore extends AbstractServiceStore {
 			service.setCreateTime(existing.getCreateTime());
 			service.setGuid(existing.getGuid());
 			service.setVersion(existing.getVersion());
-			service.setPolicyUpdateTime(existing.getPolicyUpdateTime());
-			service.setPolicyVersion(existing.getPolicyVersion());
-			service.setTagVersion(existing.getTagVersion());
-			service.setTagUpdateTime(existing.getTagUpdateTime());
 
 			service = svcService.update(service);
 
@@ -2052,7 +2048,13 @@ public class ServiceDBStore extends AbstractServiceStore {
 			throw new Exception("service does not exist. name=" + serviceName);
 		}
 
-		if (lastKnownVersion == null || serviceDbObj.getPolicyVersion() == null || !lastKnownVersion.equals(serviceDbObj.getPolicyVersion())) {
+		XXServiceVersionInfo serviceVersionInfoDbObj = daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName);
+
+		if (serviceVersionInfoDbObj == null) {
+			LOG.warn("serviceVersionInfo does not exist. name=" + serviceName);
+		}
+
+		if (lastKnownVersion == null || serviceVersionInfoDbObj == null || serviceVersionInfoDbObj.getPolicyVersion() == null || !lastKnownVersion.equals(serviceVersionInfoDbObj.getPolicyVersion())) {
 			ret = RangerServicePoliciesCache.getInstance().getServicePolicies(serviceName, this);
 		}
 
@@ -2075,9 +2077,9 @@ public class ServiceDBStore extends AbstractServiceStore {
 	@Override
 	public Long getServicePolicyVersion(String serviceName) {
 
-		XXService serviceDbObj = daoMgr.getXXService().findByName(serviceName);
+		XXServiceVersionInfo serviceVersionInfoDbObj = daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName);
 
-		return serviceDbObj != null ? serviceDbObj.getPolicyVersion() : null;
+		return serviceVersionInfoDbObj != null ? serviceVersionInfoDbObj.getPolicyVersion() : null;
 	}
 
 	@Override
@@ -2094,6 +2096,12 @@ public class ServiceDBStore extends AbstractServiceStore {
 			throw new Exception("service does not exist. name=" + serviceName);
 		}
 
+		XXServiceVersionInfo serviceVersionInfoDbObj = daoMgr.getXXServiceVersionInfo().findByServiceName(serviceName);
+
+		if (serviceVersionInfoDbObj == null) {
+			LOG.warn("serviceVersionInfo does not exist. name=" + serviceName);
+		}
+
 		RangerServiceDef serviceDef = getServiceDef(serviceDbObj.getType());
 
 		if (serviceDef == null) {
@@ -2113,12 +2121,17 @@ public class ServiceDBStore extends AbstractServiceStore {
 						throw new Exception("service-def does not exist. id=" + tagServiceDbObj.getType());
 					}
 
+					XXServiceVersionInfo tagServiceVersionInfoDbObj = daoMgr.getXXServiceVersionInfo().findByServiceId(serviceDbObj.getTagService());
+
+					if (tagServiceVersionInfoDbObj == null) {
+						LOG.warn("serviceVersionInfo does not exist. name=" + tagServiceDbObj.getName());
+					}
 					tagPolicies = new ServicePolicies.TagPolicies();
 
 					tagPolicies.setServiceId(tagServiceDbObj.getId());
 					tagPolicies.setServiceName(tagServiceDbObj.getName());
-					tagPolicies.setPolicyVersion(tagServiceDbObj.getPolicyVersion());
-					tagPolicies.setPolicyUpdateTime(tagServiceDbObj.getPolicyUpdateTime());
+					tagPolicies.setPolicyVersion(tagServiceVersionInfoDbObj == null ? null : tagServiceVersionInfoDbObj.getPolicyVersion());
+					tagPolicies.setPolicyUpdateTime(tagServiceVersionInfoDbObj == null ? null : tagServiceVersionInfoDbObj.getPolicyUpdateTime());
 					tagPolicies.setPolicies(getServicePoliciesFromDb(tagServiceDbObj));
 					tagPolicies.setServiceDef(tagServiceDef);
 				}
@@ -2134,8 +2147,8 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 		ret.setServiceId(serviceDbObj.getId());
 		ret.setServiceName(serviceDbObj.getName());
-		ret.setPolicyVersion(serviceDbObj.getPolicyVersion());
-		ret.setPolicyUpdateTime(serviceDbObj.getPolicyUpdateTime());
+		ret.setPolicyVersion(serviceVersionInfoDbObj == null ? null : serviceVersionInfoDbObj.getPolicyVersion());
+		ret.setPolicyUpdateTime(serviceVersionInfoDbObj == null ? null : serviceVersionInfoDbObj.getPolicyUpdateTime());
 		ret.setPolicies(policies);
 		ret.setServiceDef(serviceDef);
 		ret.setTagPolicies(tagPolicies);
@@ -2404,20 +2417,34 @@ public class ServiceDBStore extends AbstractServiceStore {
 		XXServiceDao serviceDao = daoMgr.getXXService();
 
 		XXService serviceDbObj = serviceDao.getById(service.getId());
-
 		if(serviceDbObj == null) {
 			LOG.warn("updatePolicyVersion(serviceId=" + service.getId() + "): service not found");
 
 			return;
 		}
 
-		service.setPolicyVersion(getNextVersion(service.getPolicyVersion()));
-		service.setPolicyUpdateTime(new Date());
+		XXServiceVersionInfoDao serviceVersionInfoDao = daoMgr.getXXServiceVersionInfo();
+
+		XXServiceVersionInfo serviceVersionInfoDbObj = serviceVersionInfoDao.findByServiceId(service.getId());
+
+		if(serviceVersionInfoDbObj != null) {
+			serviceVersionInfoDbObj.setPolicyVersion(getNextVersion(serviceVersionInfoDbObj.getPolicyVersion()));
+			serviceVersionInfoDbObj.setPolicyUpdateTime(new Date());
 
-		serviceDbObj.setPolicyVersion(service.getPolicyVersion());
-		serviceDbObj.setPolicyUpdateTime(service.getPolicyUpdateTime());
+			serviceVersionInfoDao.update(serviceVersionInfoDbObj);
 
-		serviceDao.update(serviceDbObj);
+		} else {
+			LOG.warn("updatePolicyVersion(service=" + serviceDbObj.getName() + "): serviceVersionInfo not found, creating it..");
+
+			serviceVersionInfoDbObj = new XXServiceVersionInfo();
+			serviceVersionInfoDbObj.setServiceId(serviceDbObj.getId());
+			serviceVersionInfoDbObj.setPolicyVersion(getNextVersion(serviceDbObj.getPolicyVersion()));
+			serviceVersionInfoDbObj.setTagVersion(serviceDbObj.getTagVersion());
+			serviceVersionInfoDbObj.setPolicyUpdateTime(new Date());
+			serviceVersionInfoDbObj.setTagUpdateTime(serviceDbObj.getTagUpdateTime());
+
+			serviceVersionInfoDao.create(serviceVersionInfoDbObj);
+		}
 
 		// if this is a tag service, update all services that refer to this tag service
 		// so that next policy-download from plugins will get updated tag policies
@@ -2427,10 +2454,25 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 			if(CollectionUtils.isNotEmpty(referringServices)) {
 				for(XXService referringService : referringServices) {
-					referringService.setPolicyVersion(getNextVersion(referringService.getPolicyVersion()));
-					referringService.setPolicyUpdateTime(service.getPolicyUpdateTime());
 
-					serviceDao.update(referringService);
+					serviceVersionInfoDbObj = serviceVersionInfoDao.findByServiceId(referringService.getId());
+					if (serviceVersionInfoDbObj != null) {
+
+						serviceVersionInfoDbObj.setPolicyVersion(getNextVersion(serviceVersionInfoDbObj.getPolicyVersion()));
+						serviceVersionInfoDbObj.setPolicyUpdateTime(service.getPolicyUpdateTime());
+
+						serviceVersionInfoDao.update(serviceVersionInfoDbObj);
+					} else {
+						LOG.warn("updatePolicyVersion(service=" + referringService.getName() + "): serviceVersionInfo not found, creating it..");
+						serviceVersionInfoDbObj = new XXServiceVersionInfo();
+						serviceVersionInfoDbObj.setServiceId(referringService.getId());
+						serviceVersionInfoDbObj.setPolicyVersion(getNextVersion(referringService.getPolicyVersion()));
+						serviceVersionInfoDbObj.setTagVersion(referringService.getTagVersion());
+						serviceVersionInfoDbObj.setPolicyUpdateTime(new Date());
+						serviceVersionInfoDbObj.setTagUpdateTime(referringService.getTagUpdateTime());
+
+						serviceVersionInfoDao.create(serviceVersionInfoDbObj);
+					}
 				}
 			}
 		}
@@ -2766,25 +2808,52 @@ public class ServiceDBStore extends AbstractServiceStore {
 		boolean isTagServiceDef = StringUtils.equals(serviceDef.getName(), EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME);
 
 		XXServiceDao serviceDao = daoMgr.getXXService();
+		XXServiceVersionInfoDao serviceVersionInfoDao = daoMgr.getXXServiceVersionInfo();
 
 		List<XXService> services = serviceDao.findByServiceDefId(serviceDef.getId());
 
 		if(CollectionUtils.isNotEmpty(services)) {
 			for(XXService service : services) {
-				service.setPolicyVersion(getNextVersion(service.getPolicyVersion()));
-				service.setPolicyUpdateTime(serviceDef.getUpdateTime());
+				XXServiceVersionInfo serviceVersionInfo = serviceVersionInfoDao.findByServiceId(service.getId());
+				if (serviceVersionInfo != null) {
+					serviceVersionInfo.setPolicyVersion(getNextVersion(serviceVersionInfo.getPolicyVersion()));
+					serviceVersionInfo.setPolicyUpdateTime(serviceDef.getUpdateTime());
 
-				serviceDao.update(service);
+					serviceVersionInfoDao.update(serviceVersionInfo);
+				} else {
+					LOG.warn("updateServicesForServiceDefUpdate(service=" + service.getName() + "): serviceVersionInfo not found, creating it..");
+					serviceVersionInfo = new XXServiceVersionInfo();
+					serviceVersionInfo.setServiceId(service.getId());
+					serviceVersionInfo.setPolicyVersion(getNextVersion(service.getPolicyVersion()));
+					serviceVersionInfo.setTagVersion(service.getTagVersion());
+					serviceVersionInfo.setPolicyUpdateTime(new Date());
+					serviceVersionInfo.setTagUpdateTime(service.getTagUpdateTime());
+
+					serviceVersionInfoDao.create(serviceVersionInfo);
+				}
 
 				if(isTagServiceDef) {
 					List<XXService> referrringServices = serviceDao.findByTagServiceId(service.getId());
 
 					if(CollectionUtils.isNotEmpty(referrringServices)) {
 						for(XXService referringService : referrringServices) {
-							referringService.setPolicyVersion(getNextVersion(referringService.getPolicyVersion()));
-							referringService.setPolicyUpdateTime(serviceDef.getUpdateTime());
-
-							serviceDao.update(referringService);
+							serviceVersionInfo = serviceVersionInfoDao.findByServiceId(referringService.getId());
+							if (serviceVersionInfo != null) {
+								serviceVersionInfo.setPolicyVersion(getNextVersion(serviceVersionInfo.getPolicyVersion()));
+								serviceVersionInfo.setPolicyUpdateTime(serviceDef.getUpdateTime());
+
+								serviceVersionInfoDao.update(serviceVersionInfo);
+							} else {
+								LOG.warn("updateServicesForServiceDefUpdate(service=" + referringService.getName() + "): serviceVersionInfo not found, creating it..");
+								serviceVersionInfo = new XXServiceVersionInfo();
+								serviceVersionInfo.setServiceId(referringService.getId());
+								serviceVersionInfo.setPolicyVersion(getNextVersion(referringService.getPolicyVersion()));
+								serviceVersionInfo.setTagVersion(referringService.getTagVersion());
+								serviceVersionInfo.setPolicyUpdateTime(new Date());
+								serviceVersionInfo.setTagUpdateTime(referringService.getTagUpdateTime());
+
+								serviceVersionInfoDao.create(serviceVersionInfo);
+							}
 						}
 					}
 				}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
index e11dad6..5f298d9 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
@@ -39,6 +39,7 @@ import org.apache.ranger.entity.XXResourceDef;
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceDef;
 import org.apache.ranger.entity.XXServiceResource;
+import org.apache.ranger.entity.XXServiceVersionInfo;
 import org.apache.ranger.entity.XXTag;
 import org.apache.ranger.entity.XXTagAttribute;
 import org.apache.ranger.entity.XXTagAttributeDef;
@@ -909,7 +910,13 @@ public class TagDBStore extends AbstractTagStore {
 			throw new Exception("service does not exist. name=" + serviceName);
 		}
 
-		if (lastKnownVersion == null || xxService.getTagVersion() == null || !lastKnownVersion.equals(xxService.getTagVersion())) {
+		XXServiceVersionInfo serviceVersionInfoDbObj = daoManager.getXXServiceVersionInfo().findByServiceName(serviceName);
+
+		if (serviceVersionInfoDbObj == null) {
+			LOG.warn("serviceVersionInfo does not exist. name=" + serviceName);
+		}
+
+		if (lastKnownVersion == null || serviceVersionInfoDbObj == null || serviceVersionInfoDbObj.getTagVersion() == null || !lastKnownVersion.equals(serviceVersionInfoDbObj.getTagVersion())) {
 			ret = RangerServiceTagsCache.getInstance().getServiceTags(serviceName, this);
 		}
 
@@ -932,9 +939,9 @@ public class TagDBStore extends AbstractTagStore {
 	@Override
 	public Long getTagVersion(String serviceName) {
 
-		XXService serviceDbObj = daoManager.getXXService().findByName(serviceName);
+		XXServiceVersionInfo serviceVersionInfoDbObj = daoManager.getXXServiceVersionInfo().findByServiceName(serviceName);
 
-		return serviceDbObj != null ? serviceDbObj.getTagVersion() : null;
+		return serviceVersionInfoDbObj != null ? serviceVersionInfoDbObj.getTagVersion() : null;
 	}
 
 	@Override
@@ -952,6 +959,12 @@ public class TagDBStore extends AbstractTagStore {
 			throw new Exception("service does not exist. name=" + serviceName);
 		}
 
+		XXServiceVersionInfo serviceVersionInfoDbObj = daoManager.getXXServiceVersionInfo().findByServiceName(serviceName);
+
+		if (serviceVersionInfoDbObj == null) {
+			LOG.warn("serviceVersionInfo does not exist for service [" + serviceName + "]");
+		}
+
 		RangerServiceDef serviceDef = svcStore.getServiceDef(xxService.getType());
 
 		if (serviceDef == null) {
@@ -992,8 +1005,8 @@ public class TagDBStore extends AbstractTagStore {
 		ret = new ServiceTags();
 
 		ret.setServiceName(xxService.getName());
-		ret.setTagVersion(xxService.getTagVersion());
-		ret.setTagUpdateTime(xxService.getTagUpdateTime());
+		ret.setTagVersion(serviceVersionInfoDbObj == null ? null : serviceVersionInfoDbObj.getTagVersion());
+		ret.setTagUpdateTime(serviceVersionInfoDbObj == null ? null : serviceVersionInfoDbObj.getTagUpdateTime());
 		ret.setTagDefinitions(tagDefMap);
 		ret.setTags(tagMap);
 		ret.setServiceResources(resources);

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java b/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java
index 3851069..e9c7ac0 100644
--- a/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java
+++ b/security-admin/src/main/java/org/apache/ranger/common/AppConstants.java
@@ -589,9 +589,14 @@ public class AppConstants extends RangerCommonEnums {
 	public static final int CLASS_TYPE_RANGER_POLICY_ITEM_ROWFILTER_INFO = 1051;
 
 	/**
+	 * CLASS_TYPE_XA_SERVICE_VERSION_INFO is an element of enum ClassTypes. Its value is "CLASS_TYPE_XA_SERVICE_VERSION_INFO".
+	 */
+	public static final int CLASS_TYPE_XA_SERVICE_VERSION_INFO = 1052;
+
+	/**
 	 * Max value for enum ClassTypes_MAX
 	 */
-	public static final int ClassTypes_MAX = 1051;
+	public static final int ClassTypes_MAX = 1052;
 	
 	/***************************************************************
 	 * Enum values for Default SortOrder
@@ -953,6 +958,9 @@ public class AppConstants extends RangerCommonEnums {
 		if( elementValue == 1033 ) {
 			return "XA Service Def"; //CLASS_TYPE_XA_SERVICE_DEF
 		}
+		if( elementValue == 1052 ) {
+			return "XA Service Version Info"; //CLASS_TYPE_XA_SERVICE_VERSION_INFO
+		}
 		return null;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java b/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
index 6559850..21efcf9 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/RangerDaoManagerBase.java
@@ -195,7 +195,9 @@ public abstract class RangerDaoManagerBase {
 		if (classType== AppConstants.CLASS_TYPE_RANGER_POLICY_ITEM_ROWFILTER_INFO) {
 			return getXXPolicyItemRowFilterInfo();
 		}
-
+		if (classType== AppConstants.CLASS_TYPE_XA_SERVICE_VERSION_INFO) {
+			return getXXServiceVersionInfo();
+		}
 		logger.error("No DaoManager found for classType=" + classType, new Throwable());
 		return null;
 	}
@@ -358,7 +360,9 @@ public abstract class RangerDaoManagerBase {
 		if (className.equals("XXPolicyItemRowFilterInfo")) {
 			return getXXPolicyItemRowFilterInfo();
 		}
-
+		if (className.equals("XXServiceVersionInfo")) {
+			return getXXServiceVersionInfo();
+		}
 		logger.error("No DaoManager found for className=" + className, new Throwable());
 		return null;
 	}
@@ -576,5 +580,8 @@ public abstract class RangerDaoManagerBase {
 		return new XXPolicyItemRowFilterInfoDao(this);
 	}
 
+	public XXServiceVersionInfoDao getXXServiceVersionInfo() {
+		return new XXServiceVersionInfoDao(this);
+	}
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/db/XXServiceDao.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXServiceDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXServiceDao.java
index 54c48dc..240345f 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXServiceDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXServiceDao.java
@@ -18,12 +18,10 @@
 package org.apache.ranger.db;
 
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 
 import javax.persistence.NoResultException;
 
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXService;
 
@@ -83,48 +81,6 @@ public class XXServiceDao extends BaseDao<XXService> {
 		}
 	}
 
-	public void updateServiceForServiceResourceUpdate(Long resourceId, Date updateTime) {
-		if (resourceId == null) {
-			return;
-		}
-
-		try {
-			List<XXService> services = getEntityManager().createNamedQuery("XXService.findByServiceResourceId", tClass).setParameter("resourceId", resourceId).getResultList();
-
-			updateTagVersionAndTagUpdateTime(services, updateTime);
-		} catch (NoResultException e) {
-			return;
-		}
-	}
-
-	public void updateServiceForTagUpdate(Long tagId, Date updateTime) {
-		if (tagId == null) {
-			return;
-		}
-
-		try {
-			List<XXService> services = getEntityManager().createNamedQuery("XXService.findByTagId", tClass).setParameter("tagId", tagId).getResultList();
-
-			updateTagVersionAndTagUpdateTime(services, updateTime);
-		} catch (NoResultException e) {
-			return;
-		}
-	}
-
-	public void updateServiceForTagDefUpdate(Long tagDefId, Date updateTime) {
-		if (tagDefId == null) {
-			return;
-		}
-
-		try {
-			List<XXService> services = getEntityManager().createNamedQuery("XXService.findByTagDefId", tClass).setParameter("tagDefId", tagDefId).getResultList();
-
-			updateTagVersionAndTagUpdateTime(services, updateTime);
-		} catch (NoResultException e) {
-			return;
-		}
-	}
-
 	public void updateSequence() {
 		Long maxId = getMaxIdOfXXService();
 
@@ -134,25 +90,4 @@ public class XXServiceDao extends BaseDao<XXService> {
 
 		updateSequence("X_SERVICE_SEQ", maxId + 1);
 	}
-
-	private void updateTagVersionAndTagUpdateTime(List<XXService> services, Date updateTime) {
-		if(CollectionUtils.isEmpty(services)) {
-			return;
-		}
-
-		if(updateTime == null) {
-			updateTime = new Date();
-		}
-
-		for(XXService service : services) {
-			Long currentTagVersion = service.getTagVersion();
-
-			if(currentTagVersion == null) {
-				currentTagVersion = Long.valueOf(0);
-			}
-
-			service.setTagVersion(currentTagVersion + 1);
-			service.setTagUpdateTime(updateTime);
-		}
-	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/db/XXServiceVersionInfoDao.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXServiceVersionInfoDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXServiceVersionInfoDao.java
new file mode 100644
index 0000000..5291045
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXServiceVersionInfoDao.java
@@ -0,0 +1,131 @@
+/*
+ * 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.ranger.db;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.NoResultException;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.ranger.common.db.BaseDao;
+import org.apache.ranger.entity.XXServiceVersionInfo;
+
+/**
+ */
+
+public class XXServiceVersionInfoDao extends BaseDao<XXServiceVersionInfo> {
+	/**
+	 * Default Constructor
+	 */
+	public XXServiceVersionInfoDao(RangerDaoManagerBase daoManager) {
+		super(daoManager);
+	}
+
+	public XXServiceVersionInfo findByServiceName(String serviceName) {
+		if (serviceName == null) {
+			return null;
+		}
+		try {
+			return getEntityManager()
+					.createNamedQuery("XXServiceVersionInfo.findByServiceName", tClass)
+					.setParameter("serviceName", serviceName).getSingleResult();
+		} catch (NoResultException e) {
+			return null;
+		}
+	}
+
+	public XXServiceVersionInfo findByServiceId(Long serviceId) {
+		if (serviceId == null) {
+			return null;
+		}
+		try {
+			return getEntityManager().createNamedQuery("XXServiceVersionInfo.findByServiceId", tClass)
+					.setParameter("serviceId", serviceId).getSingleResult();
+		} catch (NoResultException e) {
+			return null;
+		}
+	}
+
+	public void updateServiceVersionInfoForServiceResourceUpdate(Long resourceId, Date updateTime) {
+		if (resourceId == null) {
+			return;
+		}
+
+		try {
+			List<XXServiceVersionInfo> serviceVersionInfos = getEntityManager().createNamedQuery("XXServiceVersionInfo.findByServiceResourceId", tClass).setParameter("resourceId", resourceId).getResultList();
+
+			updateTagVersionAndTagUpdateTime(serviceVersionInfos, updateTime);
+		} catch (NoResultException e) {
+			return;
+		}
+	}
+
+	public void updateServiceVersionInfoForTagUpdate(Long tagId, Date updateTime) {
+		if (tagId == null) {
+			return;
+		}
+
+		try {
+			List<XXServiceVersionInfo> serviceVersionInfos = getEntityManager().createNamedQuery("XXServiceVersionInfo.findByTagId", tClass).setParameter("tagId", tagId).getResultList();
+
+			updateTagVersionAndTagUpdateTime(serviceVersionInfos, updateTime);
+		} catch (NoResultException e) {
+			return;
+		}
+	}
+
+	public void updateServiceVersionInfoForTagDefUpdate(Long tagDefId, Date updateTime) {
+		if (tagDefId == null) {
+			return;
+		}
+
+		try {
+			List<XXServiceVersionInfo> serviceVersionInfos = getEntityManager().createNamedQuery("XXServiceVersionInfo.findByTagDefId", tClass).setParameter("tagDefId", tagDefId).getResultList();
+
+			updateTagVersionAndTagUpdateTime(serviceVersionInfos, updateTime);
+		} catch (NoResultException e) {
+			return;
+		}
+	}
+
+	private void updateTagVersionAndTagUpdateTime(List<XXServiceVersionInfo> serviceVersionInfos, Date updateTime) {
+		if(CollectionUtils.isEmpty(serviceVersionInfos)) {
+			return;
+		}
+
+		if(updateTime == null) {
+			updateTime = new Date();
+		}
+
+		for(XXServiceVersionInfo serviceVersionInfo : serviceVersionInfos) {
+			Long currentTagVersion = serviceVersionInfo.getTagVersion();
+
+			if(currentTagVersion == null) {
+				currentTagVersion = Long.valueOf(0);
+			}
+
+			if (updateTime == null) {
+				updateTime = new Date();
+			}
+
+			serviceVersionInfo.setTagVersion(currentTagVersion + 1);
+			serviceVersionInfo.setTagUpdateTime(updateTime);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java b/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java
new file mode 100644
index 0000000..921e72f
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/entity/XXServiceVersionInfo.java
@@ -0,0 +1,197 @@
+/*
+ * 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.ranger.entity;
+
+import java.util.Date;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.ranger.common.AppConstants;
+import org.apache.ranger.common.DateUtil;
+
+@EntityListeners( org.apache.ranger.common.db.JPABeanCallbacks.class)
+@Entity
+@Cacheable
+@XmlRootElement
+@Table(name = "x_service_version_info")
+public class XXServiceVersionInfo extends Object implements java.io.Serializable {
+	private static final long serialVersionUID = 1L;
+
+	@Id
+	@SequenceGenerator(name = "X_SERVICE_VERSION_INFO_SEQ", sequenceName = "X_SERVICE_VERSION_INFO_SEQ", allocationSize = 1)
+	@GeneratedValue(strategy = GenerationType.AUTO, generator = "X_SERVICE_VERSION_INFO_SEQ")
+	@Column(name = "id")
+	protected Long id;
+
+	@Column(name = "service_id")
+	protected Long serviceId;
+
+	@Column(name = "policy_version")
+	protected Long policyVersion;
+
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name="policy_update_time"   )
+	protected Date policyUpdateTime = DateUtil.getUTCDate();
+
+	@Column(name = "tag_version")
+	protected Long tagVersion;
+
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name="tag_update_time"   )
+	protected Date tagUpdateTime = DateUtil.getUTCDate();
+
+	/**
+	 * Default constructor. This will set all the attributes to default value.
+	 */
+	public XXServiceVersionInfo ( ) {
+	}
+
+	public int getMyClassType( ) {
+	    return AppConstants.CLASS_TYPE_NONE;
+	}
+
+	public String getMyDisplayValue() {
+		return null;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getId() {
+		return this.id;
+	}
+
+	public void setServiceId(Long serviceId) {
+		this.serviceId = serviceId;
+	}
+
+	public Long getServiceId() {
+		return this.serviceId;
+	}
+
+	public void setPolicyVersion(Long policyVersion) {
+		this.policyVersion = policyVersion;
+	}
+
+	public Long getPolicyVersion() {
+		return this.policyVersion;
+	}
+
+	public void setPolicyUpdateTime( Date updateTime ) {
+		this.policyUpdateTime = updateTime;
+	}
+
+	public Date getPolicyUpdateTime( ) {
+		return this.policyUpdateTime;
+	}
+
+	public void setTagVersion(Long tagVersion) {
+		this.tagVersion = tagVersion;
+	}
+
+	public Long getTagVersion() {
+		return this.tagVersion;
+	}
+
+	public void setTagUpdateTime( Date updateTime ) {
+		this.tagUpdateTime = updateTime;
+	}
+
+	public Date getTagUpdateTime( ) {
+		return this.tagUpdateTime;
+	}
+
+
+	/**
+	 * This return the bean content in string format
+	 * @return formatedStr
+	*/
+	@Override
+	public String toString( ) {
+		String str = "XXServiceVersionInfo={";
+		str += "id={" + id + "} ";
+		str += "serviceId={" + serviceId + "} ";
+		str += "policyVersion={" + policyVersion + "} ";
+		str += "policyUpdateTime={" + policyUpdateTime + "} ";
+		str += "tagVersion={" + tagVersion + "} ";
+		str += "tagUpdateTime={" + tagUpdateTime + "} ";
+		str += "}";
+		return str;
+	}
+
+	/**
+	 * Checks for all attributes except referenced db objects
+	 * @return true if all attributes match
+	*/
+	@Override
+	public boolean equals( Object obj) {
+		if (obj == null)
+			return false;
+		if (this == obj)
+			return true;
+		if (!super.equals(obj))
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		XXServiceVersionInfo other = (XXServiceVersionInfo) obj;
+		if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
+			return false;
+		}
+		if ((this.serviceId == null && other.serviceId != null) || (this.serviceId != null && !this.serviceId.equals(other.serviceId))) {
+			return false;
+		}
+		if ((this.policyVersion == null && other.policyVersion != null) || (this.policyVersion != null && !this.policyVersion.equals(other.policyVersion))) {
+			return false;
+		}
+		if ((this.policyUpdateTime == null && other.policyUpdateTime != null) || (this.policyUpdateTime != null && !this.policyUpdateTime.equals(other.policyUpdateTime))) {
+			return false;
+		}
+		if ((this.tagVersion == null && other.tagVersion != null) || (this.tagVersion != null && !this.tagVersion.equals(other.tagVersion))) {
+			return false;
+		}
+		if ((this.tagUpdateTime == null && other.tagUpdateTime != null) || (this.tagUpdateTime != null && !this.tagUpdateTime.equals(other.tagUpdateTime))) {
+			return false;
+		}
+		return true;
+	}
+
+	public static boolean equals(Object object1, Object object2) {
+		if (object1 == object2) {
+			return true;
+		}
+		if ((object1 == null) || (object2 == null)) {
+			return false;
+		}
+		return object1.equals(object2);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/patch/PatchForServiceVersionInfo_J10004.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/patch/PatchForServiceVersionInfo_J10004.java b/security-admin/src/main/java/org/apache/ranger/patch/PatchForServiceVersionInfo_J10004.java
new file mode 100644
index 0000000..380cca0
--- /dev/null
+++ b/security-admin/src/main/java/org/apache/ranger/patch/PatchForServiceVersionInfo_J10004.java
@@ -0,0 +1,122 @@
+/*
+ * 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.ranger.patch;
+
+import java.util.Date;
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.entity.XXServiceVersionInfo;
+
+import org.apache.ranger.util.CLIUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PatchForServiceVersionInfo_J10004 extends BaseLoader {
+	private static Logger logger = Logger
+			.getLogger(PatchForServiceVersionInfo_J10004.class);
+
+	@Autowired
+	RangerDaoManager daoManager;
+
+	public static void main(String[] args) {
+		logger.info("main()");
+		try {
+			PatchForServiceVersionInfo_J10004 loader = (PatchForServiceVersionInfo_J10004) CLIUtil
+					.getBean(PatchForServiceVersionInfo_J10004.class);
+
+			loader.init();
+			while (loader.isMoreToProcess()) {
+				loader.load();
+			}
+			logger.info("Load complete. Exiting!!!");
+			System.exit(0);
+		} catch (Exception e) {
+			logger.error("Error loading", e);
+			System.exit(1);
+		}
+	}
+
+	@Override
+	public void init() throws Exception {
+		// Do Nothing
+	}
+
+	@Override
+	public void execLoad() {
+		logger.info("==> ServiceVersionInfoPatch.execLoad()");
+		copyVersionsFromServiceToServiceVersionInfo();
+		logger.info("<== ServiceVersionInfoPatch.execLoad()");
+	}
+
+	public void copyVersionsFromServiceToServiceVersionInfo() {
+		List<XXService> allServices = daoManager.getXXService().getAll();
+		Date now = new Date();
+
+		for (XXService xService : allServices) {
+
+			boolean needToCreateServiceVersionInfo = false;
+			XXServiceVersionInfo serviceVersionInfoDbObj = daoManager.getXXServiceVersionInfo().findByServiceId(xService.getId());
+
+			if (serviceVersionInfoDbObj == null) {
+				needToCreateServiceVersionInfo = true;
+				serviceVersionInfoDbObj = new XXServiceVersionInfo();
+				serviceVersionInfoDbObj.setServiceId(xService.getId());
+			}
+			serviceVersionInfoDbObj.setPolicyVersion(xService.getPolicyVersion() == null ? 1L : xService.getPolicyVersion());
+			serviceVersionInfoDbObj.setTagVersion(xService.getTagVersion());
+			serviceVersionInfoDbObj.setPolicyUpdateTime(xService.getPolicyUpdateTime());
+			serviceVersionInfoDbObj.setTagUpdateTime(xService.getTagUpdateTime());
+
+			if (needToCreateServiceVersionInfo) {
+				daoManager.getXXServiceVersionInfo().create(serviceVersionInfoDbObj);
+				logger.info("Created serviceVesionInfo for serviceName [" + xService.getName() + "]");
+			} else {
+				daoManager.getXXServiceVersionInfo().update(serviceVersionInfoDbObj);
+				logger.info("Updated serviceVesionInfo for serviceName [" + xService.getName() + "]");
+			}
+
+			// Consider this scenario:
+			// 1. ranger-admin is upgraded to use versions from x_service_version_info table;
+			// 2. there are updates to policies and/or tags;
+			// 3. no plug-ins download service-policies;
+			// 4. upgrade is rolled back, for ranger-admin to use versions from x_service table;
+			// 5. Now plug-in downloads service-policies.
+			// In this scenario, plug-ins will miss the policy/tag updates down in step 2. To ensure that
+			// plug-ins get updated policies/tags, we increment versions in x_service table when x_service_version_info
+			// table is updated in this patch. This may cause one potentially unnecessary download to plugin in case
+			// step 2 above did not take place, but it is safer.
+
+			xService.setPolicyVersion(xService.getPolicyVersion() == null ? 2L : xService.getPolicyVersion() + 1);
+			xService.setTagVersion(xService.getTagVersion() + 1);
+
+			xService.setPolicyUpdateTime(now);
+			xService.setTagUpdateTime(now);
+
+			daoManager.getXXService().update(xService);
+			logger.info("Incremented policy and tag versions for serviceName [" + xService.getName() + "]");
+		}
+	}
+
+	@Override
+	public void printStats() {
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceService.java
index 807ad61..0621e75 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceResourceService.java
@@ -63,7 +63,7 @@ public class RangerServiceResourceService extends RangerServiceResourceServiceBa
 		RangerServiceResource ret = super.postUpdate(resource);
 
 		if (serviceUpdateNeeded) {
-			daoMgr.getXXService().updateServiceForServiceResourceUpdate(resource.getId(), resource.getUpdateTime());
+			daoMgr.getXXServiceVersionInfo().updateServiceVersionInfoForServiceResourceUpdate(resource.getId(), resource.getUpdateTime());
 		}
 
 		return ret;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
index a8f54f6..8c2e568 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceService.java
@@ -20,6 +20,7 @@ package org.apache.ranger.service;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -32,10 +33,12 @@ import org.apache.ranger.common.JSONUtil;
 import org.apache.ranger.common.PasswordUtils;
 import org.apache.ranger.common.PropertiesUtil;
 import org.apache.ranger.common.view.VTrxLogAttr;
+import org.apache.ranger.db.XXServiceVersionInfoDao;
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceBase;
 import org.apache.ranger.entity.XXServiceConfigMap;
 import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.entity.XXServiceVersionInfo;
 import org.apache.ranger.entity.XXTrxLog;
 import org.apache.ranger.plugin.model.RangerService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -107,7 +110,6 @@ public class RangerServiceService extends RangerServiceServiceBase<XXService, Ra
 			configs.put(svcConfMap.getConfigkey(), configValue);
 		}
 		vService.setConfigs(configs);
-		
 		return vService;
 	}
 	
@@ -291,4 +293,35 @@ public class RangerServiceService extends RangerServiceServiceBase<XXService, Ra
 		return configs;
 	}
 
+	public RangerService postCreate(XXService xObj) {
+		XXServiceVersionInfo serviceVersionInfo = new XXServiceVersionInfo();
+
+		serviceVersionInfo.setServiceId(xObj.getId());
+		serviceVersionInfo.setPolicyVersion(1L);
+		serviceVersionInfo.setTagVersion(1L);
+		Date now = new Date();
+		serviceVersionInfo.setPolicyUpdateTime(now);
+		serviceVersionInfo.setTagUpdateTime(now);
+
+		XXServiceVersionInfoDao serviceVersionInfoDao = daoMgr.getXXServiceVersionInfo();
+
+		XXServiceVersionInfo createdServiceVersionInfo = serviceVersionInfoDao.create(serviceVersionInfo);
+
+		return createdServiceVersionInfo != null ? super.postCreate(xObj) : null;
+	}
+
+	protected XXService preDelete(Long id) {
+		XXService ret = super.preDelete(id);
+
+		if (ret != null) {
+			XXServiceVersionInfoDao serviceVersionInfoDao = daoMgr.getXXServiceVersionInfo();
+
+			XXServiceVersionInfo serviceVersionInfo = serviceVersionInfoDao.findByServiceId(id);
+
+			if (serviceVersionInfo != null) {
+				serviceVersionInfoDao.remove(serviceVersionInfo.getId());
+			}
+		}
+		return ret;
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceServiceBase.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceServiceBase.java b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceServiceBase.java
index 594d091..33c7d71 100755
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerServiceServiceBase.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerServiceServiceBase.java
@@ -31,6 +31,7 @@ import org.apache.ranger.common.SortField.SORT_ORDER;
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceBase;
 import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.entity.XXServiceVersionInfo;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.view.RangerServiceList;
@@ -92,10 +93,9 @@ public abstract class RangerServiceServiceBase<T extends XXServiceBase, V extend
 		xObj.setType(xServiceDef.getId());
 		xObj.setName(vObj.getName());
 		xObj.setTagService(tagServiceId);
-		xObj.setPolicyVersion(vObj.getPolicyVersion());
-		xObj.setTagVersion(vObj.getTagVersion());
-		xObj.setPolicyUpdateTime(vObj.getPolicyUpdateTime());
-		xObj.setTagUpdateTime(vObj.getTagUpdateTime());
+		if (OPERATION_CONTEXT == OPERATION_CREATE_CONTEXT) {
+			xObj.setTagVersion(vObj.getTagVersion());
+		}
 		xObj.setDescription(vObj.getDescription());
 		xObj.setIsEnabled(vObj.getIsEnabled());
 		return xObj;
@@ -112,10 +112,18 @@ public abstract class RangerServiceServiceBase<T extends XXServiceBase, V extend
 		vObj.setName(xObj.getName());
 		vObj.setDescription(xObj.getDescription());
 		vObj.setTagService(xTagService != null ? xTagService.getName() : null);
-		vObj.setPolicyVersion(xObj.getPolicyVersion());
-		vObj.setTagVersion(xObj.getTagVersion());
-		vObj.setPolicyUpdateTime(xObj.getPolicyUpdateTime());
-		vObj.setTagUpdateTime(xObj.getTagUpdateTime());
+		XXServiceVersionInfo versionInfoObj = daoMgr.getXXServiceVersionInfo().findByServiceId(xObj.getId());
+		if (versionInfoObj != null) {
+			vObj.setPolicyVersion(versionInfoObj.getPolicyVersion());
+			vObj.setTagVersion(versionInfoObj.getTagVersion());
+			vObj.setPolicyUpdateTime(versionInfoObj.getPolicyUpdateTime());
+			vObj.setTagUpdateTime(versionInfoObj.getTagUpdateTime());
+		} else {
+			vObj.setPolicyVersion(xObj.getPolicyVersion());
+			vObj.setTagVersion(xObj.getTagVersion());
+			vObj.setPolicyUpdateTime(xObj.getPolicyUpdateTime());
+			vObj.setTagUpdateTime(xObj.getTagUpdateTime());
+		}
 		vObj.setIsEnabled(xObj.getIsenabled());
 		return vObj;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/service/RangerTagDefService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerTagDefService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerTagDefService.java
index beb6295..8a3d14d 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerTagDefService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerTagDefService.java
@@ -54,7 +54,7 @@ public class RangerTagDefService extends RangerTagDefServiceBase<XXTagDef, Range
 	public RangerTagDef postUpdate(XXTagDef tagDef) {
 		RangerTagDef ret = super.postUpdate(tagDef);
 
-		daoMgr.getXXService().updateServiceForTagDefUpdate(tagDef.getId(), tagDef.getUpdateTime());
+		daoMgr.getXXServiceVersionInfo().updateServiceVersionInfoForTagDefUpdate(tagDef.getId(), tagDef.getUpdateTime());
 
 		return ret;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
index 257821d..391774e 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
@@ -54,7 +54,7 @@ public class RangerTagResourceMapService extends RangerTagResourceMapServiceBase
 	public RangerTagResourceMap postCreate(XXTagResourceMap tagResMap) {
 		RangerTagResourceMap ret = super.postCreate(tagResMap);
 
-		daoMgr.getXXService().updateServiceForTagUpdate(tagResMap.getTagId(), tagResMap.getUpdateTime());
+		daoMgr.getXXServiceVersionInfo().updateServiceVersionInfoForServiceResourceUpdate(tagResMap.getResourceId(), tagResMap.getUpdateTime());
 
 		return ret;
 	}
@@ -63,7 +63,7 @@ public class RangerTagResourceMapService extends RangerTagResourceMapServiceBase
 	public RangerTagResourceMap postUpdate(XXTagResourceMap tagResMap) {
 		RangerTagResourceMap ret = super.postUpdate(tagResMap);
 
-		daoMgr.getXXService().updateServiceForTagUpdate(tagResMap.getTagId(), tagResMap.getUpdateTime());
+		daoMgr.getXXServiceVersionInfo().updateServiceVersionInfoForServiceResourceUpdate(tagResMap.getResourceId(), tagResMap.getUpdateTime());
 
 		return ret;
 	}
@@ -73,7 +73,7 @@ public class RangerTagResourceMapService extends RangerTagResourceMapServiceBase
 		XXTagResourceMap tagResMap = super.preDelete(id);
 
 		if (tagResMap != null) {
-			daoMgr.getXXService().updateServiceForServiceResourceUpdate(tagResMap.getResourceId(), null);
+			daoMgr.getXXServiceVersionInfo().updateServiceVersionInfoForServiceResourceUpdate(tagResMap.getResourceId(), null);
 		}
 
 		return tagResMap;

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
index 34ed0ad..28b9115 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
@@ -55,7 +55,7 @@ public class RangerTagService extends RangerTagServiceBase<XXTag, RangerTag> {
 	public RangerTag postUpdate(XXTag tag) {
 		RangerTag ret = super.postUpdate(tag);
 
-		daoMgr.getXXService().updateServiceForTagUpdate(tag.getId(), tag.getUpdateTime());
+		daoMgr.getXXServiceVersionInfo().updateServiceVersionInfoForTagUpdate(tag.getId(), tag.getUpdateTime());
 
 		return ret;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
----------------------------------------------------------------------
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index 0f65243..39c8ec3 100644
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -402,25 +402,35 @@
 		<query>select obj from XXService obj where obj.tagService = :tagServiceId</query>
 	</named-query>
 
-	<named-query name="XXService.findByServiceResourceId">
+	<!-- XXServiceVersionInfo -->
+	<named-query name="XXServiceVersionInfo.findByServiceName">
 		<query>
-			select obj from XXService obj where obj.id in
-			  (select res.serviceId from XXServiceResource res, XXTagResourceMap tagRes
-			    where res.id = :resourceId and res.id = tagRes.resourceId)
+			select obj from XXServiceVersionInfo obj, XXService service where obj.serviceId = service.id and service.name = :serviceName
 		</query>
 	</named-query>
 
-	<named-query name="XXService.findByTagId">
+	<named-query name="XXServiceVersionInfo.findByServiceId">
+		<query>select obj from XXServiceVersionInfo obj where obj.serviceId = :serviceId</query>
+	</named-query>
+
+	<named-query name="XXServiceVersionInfo.findByServiceResourceId">
+		<query>
+			select obj from XXServiceVersionInfo obj where obj.serviceId in
+			(select res.serviceId from XXServiceResource res where res.id = :resourceId)
+		</query>
+	</named-query>
+
+	<named-query name="XXServiceVersionInfo.findByTagId">
 		<query>
-			select obj from XXService obj where obj.id in
-			  (select res.serviceId from XXServiceResource res, XXTagResourceMap tagRes, XXTag tag
-			    where res.id = tagRes.resourceId and tagRes.tagId = tag.id and tag.id = :tagId)
+			select obj from XXServiceVersionInfo obj where obj.serviceId in
+			(select res.serviceId from XXServiceResource res, XXTagResourceMap tagRes
+			where res.id = tagRes.resourceId and tagRes.tagId = :tagId)
 		</query>
 	</named-query>
 
-	<named-query name="XXService.findByTagDefId">
+	<named-query name="XXServiceVersionInfo.findByTagDefId">
 		<query>
-			select obj from XXService obj where obj.id in
+			select obj from XXServiceVersionInfo obj where obj.serviceId in
 			(select res.serviceId from XXServiceResource res, XXTagResourceMap tagRes, XXTag tag
 			where res.id = tagRes.resourceId and tagRes.tagId = tag.id and tag.type = :tagDefId)
 		</query>

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
index 61e13da..7af5c45 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestServiceDBStore.java
@@ -1200,6 +1200,8 @@ public class TestServiceDBStore {
 	public void test20updateService() throws Exception {
 		XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
 		XXService xService = Mockito.mock(XXService.class);
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+		XXServiceVersionInfo xServiceVersionInfo = Mockito.mock(XXServiceVersionInfo.class);
 		XXServiceConfigMapDao xServiceConfigMapDao = Mockito
 				.mock(XXServiceConfigMapDao.class);
 		XXServiceConfigDefDao xServiceConfigDefDao = Mockito
@@ -1288,6 +1290,10 @@ public class TestServiceDBStore {
 		Mockito.when(svcService.getPopulatedViewObject(xService)).thenReturn(
 				rangerService);
 
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(Id)).thenReturn(xServiceVersionInfo);
+		Mockito.when(xServiceVersionInfoDao.update(xServiceVersionInfo)).thenReturn(xServiceVersionInfo);
+
 		RangerService dbRangerService = serviceDBStore
 				.updateService(rangerService);
 		Assert.assertNotNull(dbRangerService);
@@ -1309,6 +1315,8 @@ public class TestServiceDBStore {
 		XXPolicyDao xPolicyDao = Mockito.mock(XXPolicyDao.class);
 		XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
 		XXService xService = Mockito.mock(XXService.class);
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+		XXServiceVersionInfo xServiceVersionInfo = Mockito.mock(XXServiceVersionInfo.class);
 		XXPolicyItemDao xPolicyItemDao = Mockito.mock(XXPolicyItemDao.class);
 		XXPolicyItemDataMaskInfoDao xxPolicyItemDataMaskInfoDao = Mockito.mock(XXPolicyItemDataMaskInfoDao.class);
 		XXPolicyItemRowFilterInfoDao xxPolicyItemRowFilterInfoDao = Mockito.mock(XXPolicyItemRowFilterInfoDao.class);
@@ -1479,6 +1487,10 @@ public class TestServiceDBStore {
 		Mockito.when(svcService.getPopulatedViewObject(xService)).thenReturn(
 				rangerService);
 
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(Id)).thenReturn(xServiceVersionInfo);
+		Mockito.when(xServiceVersionInfoDao.update(xServiceVersionInfo)).thenReturn(xServiceVersionInfo);
+
 		Mockito.when(daoManager.getXXPolicyItem()).thenReturn(xPolicyItemDao);
 		Mockito.when(xPolicyItemDao.findByPolicyId(policyItem.getId()))
 				.thenReturn(policyItemList);
@@ -1683,7 +1695,9 @@ public class TestServiceDBStore {
 		XXPolicy xPolicy = Mockito.mock(XXPolicy.class);
 		XXPolicyDao xPolicyDao = Mockito.mock(XXPolicyDao.class);
 		XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
 		XXService xService = Mockito.mock(XXService.class);
+		XXServiceVersionInfo xServiceVersionInfo = Mockito.mock(XXServiceVersionInfo.class);
 		XXPolicyItemDao xPolicyItemDao = Mockito.mock(XXPolicyItemDao.class);
 		XXServiceConfigDefDao xServiceConfigDefDao = Mockito
 				.mock(XXServiceConfigDefDao.class);
@@ -1844,6 +1858,10 @@ public class TestServiceDBStore {
 
 		Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
 		Mockito.when(xServiceDao.findByName(name)).thenReturn(xService);
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(Id)).thenReturn(xServiceVersionInfo);
+		Mockito.when(xServiceVersionInfoDao.update(xServiceVersionInfo)).thenReturn(xServiceVersionInfo);
+
 		Mockito.when(svcService.getPopulatedViewObject(xService)).thenReturn(
 				rangerService);
 
@@ -1992,8 +2010,10 @@ public class TestServiceDBStore {
 		XXPolicy xPolicy = Mockito.mock(XXPolicy.class);
 		XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
 		XXService xService = Mockito.mock(XXService.class);
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
 		XXServiceDefDao xServiceDefDao = Mockito.mock(XXServiceDefDao.class);
 		XXServiceDef xServiceDef = Mockito.mock(XXServiceDef.class);
+		XXServiceVersionInfo xServiceVersionInfo = Mockito.mock(XXServiceVersionInfo.class);
 		XXPolicyResourceDao xPolicyResourceDao = Mockito
 				.mock(XXPolicyResourceDao.class);
 		XXPolicyResourceMapDao xPolicyResourceMapDao = Mockito
@@ -2064,6 +2084,10 @@ public class TestServiceDBStore {
 		Mockito.when(svcService.getPopulatedViewObject(xService)).thenReturn(
 				rangerService);
 
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(Id)).thenReturn(xServiceVersionInfo);
+		Mockito.when(xServiceVersionInfoDao.update(xServiceVersionInfo)).thenReturn(xServiceVersionInfo);
+
 		Mockito.when(daoManager.getXXServiceDef()).thenReturn(xServiceDefDao);
 		Mockito.when(xServiceDefDao.findByName(rangerService.getType()))
 				.thenReturn(xServiceDef);
@@ -2152,6 +2176,9 @@ public class TestServiceDBStore {
 		setup();
 		XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
 		XXService xService = Mockito.mock(XXService.class);
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+		XXServiceVersionInfo xServiceVersionInfo = Mockito.mock(XXServiceVersionInfo.class);
+
 		XXPolicyItemDao xPolicyItemDao = Mockito.mock(XXPolicyItemDao.class);
 		XXPolicyItemDataMaskInfoDao xPolicyItemDataMaskInfoDao = Mockito.mock(XXPolicyItemDataMaskInfoDao.class);
 		XXPolicyItemRowFilterInfoDao xPolicyItemRowFilterInfoDao = Mockito.mock(XXPolicyItemRowFilterInfoDao.class);
@@ -2338,6 +2365,10 @@ public class TestServiceDBStore {
 		Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
 		Mockito.when(xServiceDao.getById(Id)).thenReturn(xService);
 
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(Id)).thenReturn(xServiceVersionInfo);
+		Mockito.when(xServiceVersionInfoDao.update(xServiceVersionInfo)).thenReturn(xServiceVersionInfo);
+
 		Mockito.when(daoManager.getXXServiceConfigDef()).thenReturn(
 				xServiceConfigDefDao);
 		Mockito.when(
@@ -2435,6 +2466,7 @@ public class TestServiceDBStore {
 	@Test
 	public void test33getServicePoliciesIfUpdated() throws Exception {
 		XXServiceDao xServiceDao = Mockito.mock(XXServiceDao.class);
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
 
 		XXServiceDefDao xServiceDefDao = Mockito.mock(XXServiceDefDao.class);
 		XXServiceDef xServiceDef = Mockito.mock(XXServiceDef.class);
@@ -2456,10 +2488,21 @@ public class TestServiceDBStore {
 		xService.setUpdatedByUserId(Id);
 		xService.setUpdateTime(new Date());
 
+		XXServiceVersionInfo xServiceVersionInfo = new XXServiceVersionInfo();
+
+		xServiceVersionInfo.setServiceId(Id);
+		xServiceVersionInfo.setPolicyVersion(1L);
+		xServiceVersionInfo.setPolicyUpdateTime(new Date());
+		xServiceVersionInfo.setTagVersion(1L);
+		xServiceVersionInfo.setTagUpdateTime(new Date());
+
 		String serviceName = "HDFS_1";
 		Long lastKnownVersion = 1l;
 		Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
 		Mockito.when(xServiceDao.findByName(serviceName)).thenReturn(xService);
+		Mockito.when(xServiceVersionInfoDao.findByServiceName(serviceName)).thenReturn(xServiceVersionInfo);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(Id)).thenReturn(xServiceVersionInfo);
 		Mockito.when(svcService.getPopulatedViewObject(xService)).thenReturn(
 				rangerService);
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceService.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceService.java b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceService.java
index 215506e..c8cb716 100644
--- a/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceService.java
+++ b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceService.java
@@ -32,10 +32,12 @@ import org.apache.ranger.db.XXServiceConfigMapDao;
 import org.apache.ranger.db.XXServiceDao;
 import org.apache.ranger.db.XXServiceDefDao;
 
+import org.apache.ranger.db.XXServiceVersionInfoDao;
 import org.apache.ranger.entity.XXPortalUser;
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceConfigMap;
 import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.entity.XXServiceVersionInfo;
 import org.apache.ranger.entity.XXTrxLog;
 import org.apache.ranger.plugin.model.RangerService;
 
@@ -197,6 +199,19 @@ public class TestRangerServiceService {
 		xServiceDef.setGuid("1427365526516_835_0");
 		xServiceDef.setId(userId);
 
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+
+		XXServiceVersionInfo serviceVersionInfo = new XXServiceVersionInfo();
+		serviceVersionInfo.setServiceId(xService.getId());
+		serviceVersionInfo.setPolicyVersion(xService.getPolicyVersion());
+		serviceVersionInfo.setPolicyUpdateTime(xService.getPolicyUpdateTime());
+		serviceVersionInfo.setTagVersion(xService.getTagVersion());
+		serviceVersionInfo.setTagUpdateTime(xService.getTagUpdateTime());
+
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(xService.getId())).thenReturn(
+				serviceVersionInfo);
+
 		Mockito.when(daoManager.getXXPortalUser()).thenReturn(xPortalUserDao);
 		Mockito.when(xPortalUserDao.getById(userId)).thenReturn(tUser);
 
@@ -264,6 +279,19 @@ public class TestRangerServiceService {
 		xServiceDef.setGuid("1427365526516_835_0");
 		xServiceDef.setId(userId);
 
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+
+		XXServiceVersionInfo serviceVersionInfo = new XXServiceVersionInfo();
+		serviceVersionInfo.setServiceId(xService.getId());
+		serviceVersionInfo.setPolicyVersion(xService.getPolicyVersion());
+		serviceVersionInfo.setPolicyUpdateTime(xService.getPolicyUpdateTime());
+		serviceVersionInfo.setTagVersion(xService.getTagVersion());
+		serviceVersionInfo.setTagUpdateTime(xService.getTagUpdateTime());
+
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(xService.getId())).thenReturn(
+				serviceVersionInfo);
+
 		Mockito.when(daoManager.getXXPortalUser()).thenReturn(xPortalUserDao);
 		Mockito.when(xPortalUserDao.getById(userId)).thenReturn(tUser);
 
@@ -337,6 +365,19 @@ public class TestRangerServiceService {
 		xServiceDef.setGuid("1427365526516_835_0");
 		xServiceDef.setId(userId);
 
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+
+		XXServiceVersionInfo serviceVersionInfo = new XXServiceVersionInfo();
+		serviceVersionInfo.setServiceId(xService.getId());
+		serviceVersionInfo.setPolicyVersion(xService.getPolicyVersion());
+		serviceVersionInfo.setPolicyUpdateTime(xService.getPolicyUpdateTime());
+		serviceVersionInfo.setTagVersion(xService.getTagVersion());
+		serviceVersionInfo.setTagUpdateTime(xService.getTagUpdateTime());
+
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(xService.getId())).thenReturn(
+				serviceVersionInfo);
+
 		Mockito.when(daoManager.getXXService()).thenReturn(xServiceDao);
 		Mockito.when(xServiceDao.getAll()).thenReturn(xServiceList);
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/cb58449b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceServiceBase.java
----------------------------------------------------------------------
diff --git a/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceServiceBase.java b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceServiceBase.java
index 5dff936..216c338 100644
--- a/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceServiceBase.java
+++ b/security-admin/src/test/java/org/apache/ranger/service/TestRangerServiceServiceBase.java
@@ -32,8 +32,10 @@ import org.apache.ranger.common.UserSessionBase;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.db.RangerDaoManager;
 import org.apache.ranger.db.XXServiceDefDao;
+import org.apache.ranger.db.XXServiceVersionInfoDao;
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.entity.XXServiceVersionInfo;
 import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.security.context.RangerContextHolder;
@@ -169,6 +171,19 @@ public class TestRangerServiceServiceBase {
 		RangerService rangerService = rangerService();
 		XXService service = service();
 
+		XXServiceVersionInfoDao xServiceVersionInfoDao = Mockito.mock(XXServiceVersionInfoDao.class);
+
+		XXServiceVersionInfo serviceVersionInfo = new XXServiceVersionInfo();
+		serviceVersionInfo.setServiceId(service.getId());
+		serviceVersionInfo.setPolicyVersion(service.getPolicyVersion());
+		serviceVersionInfo.setPolicyUpdateTime(service.getPolicyUpdateTime());
+		serviceVersionInfo.setTagVersion(service.getTagVersion());
+		serviceVersionInfo.setPolicyUpdateTime(service.getTagUpdateTime());
+
+		Mockito.when(daoManager.getXXServiceVersionInfo()).thenReturn(xServiceVersionInfoDao);
+		Mockito.when(xServiceVersionInfoDao.findByServiceId(service.getId())).thenReturn(
+				serviceVersionInfo);
+
 		Mockito.when(daoManager.getXXServiceDef()).thenReturn(xServiceDefDao);
 		Mockito.when(xServiceDefDao.getById(service.getType())).thenReturn(
 				xServiceDef);