2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.policy.drools.persistence;
23 import java.util.Collection;
24 import java.util.Date;
25 import java.util.LinkedList;
26 import java.util.List;
28 import javax.persistence.EntityManager;
29 import javax.persistence.EntityManagerFactory;
30 import javax.persistence.LockModeType;
31 import javax.persistence.Query;
33 import org.openecomp.policy.drools.core.IntegrityMonitorProperties;
34 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
35 import org.openecomp.policy.common.logging.flexlogger.Logger;
36 import org.openecomp.policy.common.logging.eelf.MessageCodes;
39 public class JpaDroolsPdpsConnector implements DroolsPdpsConnector {
41 // get an instance of logger
42 private static Logger logger = FlexLogger.getLogger(JpaDroolsPdpsConnector.class);
43 private EntityManagerFactory emf;
46 //not sure if we want to use the same entity manager factory for drools session and pass it in here, or create a new one
47 public JpaDroolsPdpsConnector(EntityManagerFactory emf){
51 public Collection<DroolsPdp> getDroolsPdps() {
52 //return a list of all the DroolsPdps in the database
53 EntityManager em = emf.createEntityManager();
55 em.getTransaction().begin();
56 Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p");
57 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.PESSIMISTIC_READ).getResultList();
58 LinkedList<DroolsPdp> droolsPdpsReturnList = new LinkedList<DroolsPdp>();
59 for(Object o : droolsPdpsList){
60 if(o instanceof DroolsPdp){
61 //Make sure it is not a cached version
62 em.refresh((DroolsPdpEntity)o);
63 droolsPdpsReturnList.add((DroolsPdp)o);
64 if (logger.isDebugEnabled()) {
65 DroolsPdp droolsPdp = (DroolsPdp)o;
66 logger.debug("getDroolsPdps: PDP=" + droolsPdp.getPdpId()
67 + ", isDesignated=" + droolsPdp.isDesignated()
68 + ", updatedDate=" + droolsPdp.getUpdatedDate()
69 + ", priority=" + droolsPdp.getPriority());
74 em.getTransaction().commit();
77 (MessageCodes.EXCEPTION_ERROR, e,"Cannot commit getDroolsPdps() transaction");
79 return droolsPdpsReturnList;
81 cleanup(em, "getDroolsPdps");
85 private boolean nullSafeEquals(Object one, Object two){
86 if(one == null && two == null){
89 if(one != null && two != null){
90 return one.equals(two);
96 public void update(DroolsPdp pdp) {
98 if (logger.isDebugEnabled()) {
99 logger.debug("update: Entering, pdpId=" + pdp.getPdpId());
102 //this is to update our own pdp in the database
103 EntityManager em = emf.createEntityManager();
105 em.getTransaction().begin();
106 Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
107 droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId());
108 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.PESSIMISTIC_WRITE).getResultList();
109 //em.getTransaction().begin();
110 DroolsPdpEntity droolsPdpEntity;
111 if(droolsPdpsList.size() == 1 && (droolsPdpsList.get(0) instanceof DroolsPdpEntity)){
112 droolsPdpEntity = (DroolsPdpEntity)droolsPdpsList.get(0);
113 //if(pdp.getSessionId() < 0){
114 //if its less than 0, then we know it is not a real session number so we want to save the one that the database has for us, to avoid information loss
115 //pdp.setSessionId(droolsPdpEntity.getSessionId());
117 Date currentDate = new Date();
118 long difference = currentDate.getTime()-droolsPdpEntity.getUpdatedDate().getTime();
119 //just set some kind of default here
120 long pdpTimeout = 15000;
122 pdpTimeout = Long.parseLong(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_TIMEOUT));
125 (MessageCodes.EXCEPTION_ERROR, e,"Could not get PDP timeout property, using default.");
127 boolean isCurrent = difference<pdpTimeout;
128 if (logger.isDebugEnabled()) {
129 logger.debug("update: PDP=" + pdp.getPdpId() + ", isCurrent="
130 + isCurrent + ", difference=" + difference
131 + ", pdpTimeout=" + pdpTimeout + ", designated="
132 + droolsPdpEntity.isDesignated());
135 if (logger.isDebugEnabled()) {
136 logger.debug("update: For PDP=" + pdp.getPdpId()
137 + ", instantiating new DroolsPdpEntity");
139 droolsPdpEntity = new DroolsPdpEntity();
140 em.persist(droolsPdpEntity);
141 droolsPdpEntity.setPdpId(pdp.getPdpId());
143 if(droolsPdpEntity.getPriority() != pdp.getPriority()){
144 droolsPdpEntity.setPriority(pdp.getPriority());
146 if(!droolsPdpEntity.getUpdatedDate().equals(pdp.getUpdatedDate())){
147 droolsPdpEntity.setUpdatedDate(pdp.getUpdatedDate());
149 if(!droolsPdpEntity.getDesignatedDate().equals(pdp.getDesignatedDate())){
150 droolsPdpEntity.setDesignatedDate(pdp.getDesignatedDate());
152 if(!nullSafeEquals(droolsPdpEntity.getSiteName(),pdp.getSiteName())){
153 droolsPdpEntity.setSiteName(pdp.getSiteName());
155 List<DroolsSessionEntity> sessionsToAdd = new LinkedList<DroolsSessionEntity>();
156 for(DroolsSessionEntity localSession : pdp.getSessions()){
157 boolean found = false;
158 for(DroolsSessionEntity dbSession : droolsPdpEntity.getSessions()){
159 if(localSession.equals(dbSession)){
161 dbSession.setSessionId(localSession.getSessionId());
165 sessionsToAdd.add(localSession);
169 for(DroolsSessionEntity sessionToAdd : sessionsToAdd){
170 em.persist(sessionToAdd);
171 droolsPdpEntity.getSessions().add(sessionToAdd);
175 if(droolsPdpEntity.isDesignated() != pdp.isDesignated()){
176 if (logger.isDebugEnabled()) {
177 logger.debug("update: pdpId=" + pdp.getPdpId()
178 + ", pdp.isDesignated=" + pdp.isDesignated()
179 + ", droolsPdpEntity.pdpId="
180 + droolsPdpEntity.getPdpId()
181 + ", droolsPdpEntity.isDesignated="
182 + droolsPdpEntity.isDesignated());
184 droolsPdpEntity.setDesignated(pdp.isDesignated());
186 em.getTransaction().commit();
188 cleanup(em, "update");
191 if (logger.isDebugEnabled()) {
192 logger.debug("update: Exiting");
198 * Note: A side effect of this boolean method is that if the PDP is designated but not current, the
199 * droolspdpentity.DESIGNATED column will be set to false (the PDP will be un-designated, i.e. marked as
200 * being in standby mode)
203 public boolean isPdpCurrent(DroolsPdp pdp) {
205 boolean isCurrent = isCurrent(pdp);
207 EntityManager em = emf.createEntityManager();
209 if(!isCurrent && pdp.isDesignated()){
210 em.getTransaction().begin();
211 Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
212 droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId());
213 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.PESSIMISTIC_WRITE).getResultList();
214 if(droolsPdpsList.size() == 1 && droolsPdpsList.get(0) instanceof DroolsPdpEntity){
215 if (logger.isDebugEnabled()) {
216 logger.debug("isPdpCurrent: PDP=" + pdp.getPdpId() + " designated but not current; setting designated to false");
218 DroolsPdpEntity droolsPdpEntity = (DroolsPdpEntity)droolsPdpsList.get(0);
219 droolsPdpEntity.setDesignated(false);
220 em.getTransaction().commit();
222 logger.warn("isPdpCurrent: PDP=" + pdp.getPdpId() + " is designated but not current; however it does not have a DB entry, so cannot set DESIGNATED to false!");
225 if (logger.isDebugEnabled()) {
226 logger.debug("isPdpCurrent: For PDP=" + pdp.getPdpId()
228 + pdp.isDesignated() + ", isCurrent=" + isCurrent);
233 (MessageCodes.EXCEPTION_ERROR, e,"Could not update expired record marked as designated in the database");
235 cleanup(em, "isPdpCurrent");
242 public void setDesignated(DroolsPdp pdp, boolean designated) {
244 if (logger.isDebugEnabled()) {
245 logger.debug("setDesignated: Entering, pdpId='" + pdp.getPdpId()
246 + "', designated=" + designated);
249 EntityManager em = null;
251 em = emf.createEntityManager();
252 em.getTransaction().begin();
253 Query droolsPdpsListQuery = em
254 .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
255 droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId());
256 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(
257 LockModeType.PESSIMISTIC_WRITE).getResultList();
258 if (droolsPdpsList.size() == 1
259 && droolsPdpsList.get(0) instanceof DroolsPdpEntity) {
260 DroolsPdpEntity droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList
262 if (logger.isDebugEnabled()) {
263 logger.debug("setDesignated: PDP=" + pdp.getPdpId()
264 + " found, designated="
265 + droolsPdpEntity.isDesignated() + ", setting to "
268 droolsPdpEntity.setDesignated(designated);
269 em.getTransaction().commit();
271 logger.error("setDesignated: PDP=" + pdp.getPdpId()
272 + " not in DB; cannot update designation");
274 } catch (Exception e) {
275 logger.error("setDesignated: Caught Exception, message='"
276 + e.getMessage() + "'");
278 cleanup(em, "setDesignated");
281 if (logger.isDebugEnabled()) {
282 logger.debug("setDesignated: Exiting");
289 public void standDownPdp(String pdpId) {
291 logger.info("standDownPdp: Entering, pdpId='" + pdpId + "'");
293 EntityManager em = null;
298 em = emf.createEntityManager();
299 em.getTransaction().begin();
302 * Get droolspdpentity record for this PDP and mark DESIGNATED as
305 Query droolsPdpsListQuery = em
306 .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
307 droolsPdpsListQuery.setParameter("pdpId", pdpId);
308 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(
309 LockModeType.PESSIMISTIC_WRITE).getResultList();
310 DroolsPdpEntity droolsPdpEntity;
311 if (droolsPdpsList.size() == 1
312 && (droolsPdpsList.get(0) instanceof DroolsPdpEntity)) {
313 droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList.get(0);
314 droolsPdpEntity.setDesignated(false);
315 em.persist(droolsPdpEntity);
316 logger.info("standDownPdp: PDP=" + pdpId + " persisted as non-designated.");
318 logger.error("standDownPdp: Missing record in droolspdpentity for pdpId="
319 + pdpId + "; cannot stand down PDP");
325 em.getTransaction().commit();
326 cleanup(em, "standDownPdp");
329 // Keep the election handler in sync with the DB
330 DroolsPdpsElectionHandler.setMyPdpDesignated(false);
332 } catch (Exception e) {
333 logger.error("standDownPdp: Unexpected Exception attempting to mark DESIGNATED as false for droolspdpentity, pdpId="
335 + ". Cannot stand down PDP; message="
338 cleanup(em, "standDownPdp");
341 logger.info("standDownPdp: Exiting");
346 * Determines whether or not a designated PDP has failed.
348 * Note: The update method, which is run periodically by the
349 * TimerUpdateClass, will un-designate a PDP that is stale.
352 public boolean hasDesignatedPdpFailed(Collection<DroolsPdp> pdps) {
354 if (logger.isDebugEnabled()) {
355 logger.debug("hasDesignatedPdpFailed: Entering, pdps.size()="
359 boolean failed = true;
360 boolean foundDesignatedPdp = false;
362 for (DroolsPdp pdp : pdps) {
365 * Normally, the update method will un-designate any stale PDP, but
366 * we check here to see if the PDP has gone stale since the update
369 * Even if we determine that the designated PDP is current, we keep
370 * going (we don't break), so we can get visibility into the other
371 * PDPs, when in DEBUG mode.
373 if (pdp.isDesignated() && isCurrent(pdp)) {
374 if (logger.isDebugEnabled()) {
375 logger.debug("hasDesignatedPdpFailed: Designated PDP="
376 + pdp.getPdpId() + " is current");
379 foundDesignatedPdp = true;
380 } else if (pdp.isDesignated() && !isCurrent(pdp)) {
381 logger.error("hasDesignatedPdpFailed: Designated PDP="
382 + pdp.getPdpId() + " has failed");
383 foundDesignatedPdp = true;
385 if (logger.isDebugEnabled()) {
386 logger.debug("hasDesignatedPdpFailed: PDP="
387 + pdp.getPdpId() + " is not designated");
392 if (logger.isDebugEnabled()) {
393 logger.debug("hasDesignatedPdpFailed: Exiting and returning, foundDesignatedPdp="
394 + foundDesignatedPdp);
400 private boolean isCurrent(DroolsPdp pdp) {
402 if (logger.isDebugEnabled()) {
403 logger.debug("isCurrent: Entering, pdpId="
407 boolean current = false;
409 // Return if the current PDP is considered "current" based on whatever
410 // time box that may be.
411 // If the the PDP is not current, we should mark it as not primary in
413 Date currentDate = new Date();
414 long difference = currentDate.getTime()
415 - pdp.getUpdatedDate().getTime();
416 // just set some kind of default here
417 long pdpTimeout = 15000;
419 pdpTimeout = Long.parseLong(IntegrityMonitorProperties
420 .getProperty(IntegrityMonitorProperties.PDP_TIMEOUT));
421 if (logger.isDebugEnabled()) {
422 logger.debug("isCurrent: pdp.timeout=" + pdpTimeout);
424 } catch (Exception e) {
426 (MessageCodes.EXCEPTION_ERROR, e,
427 "isCurrent: Could not get PDP timeout property, using default.");
429 current = difference < pdpTimeout;
431 if (logger.isDebugEnabled()) {
432 logger.debug("isCurrent: Exiting, difference="
433 + difference + ", pdpTimeout=" + pdpTimeout
434 + "; returning current=" + current);
442 * Currently this method is only used in a JUnit test environment. Gets a
443 * PDP record from droolspdpentity table.
446 public DroolsPdpEntity getPdp(String pdpId) {
448 if (logger.isDebugEnabled()) {
449 logger.debug("getPdp: Entering and getting PDP with pdpId='" + pdpId
453 DroolsPdpEntity droolsPdpEntity = null;
455 EntityManager em = null;
457 em = emf.createEntityManager();
458 em.getTransaction().begin();
459 Query droolsPdpsListQuery = em
460 .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
461 droolsPdpsListQuery.setParameter("pdpId", pdpId);
462 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(
463 LockModeType.PESSIMISTIC_WRITE).getResultList();
464 if (droolsPdpsList.size() == 1
465 && droolsPdpsList.get(0) instanceof DroolsPdpEntity) {
466 droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList.get(0);
467 if (logger.isDebugEnabled()) {
468 logger.debug("getPdp: PDP=" + pdpId
469 + " found, isDesignated="
470 + droolsPdpEntity.isDesignated() + ", updatedDate="
471 + droolsPdpEntity.getUpdatedDate() + ", priority="
472 + droolsPdpEntity.getPriority());
475 // Make sure the droolsPdpEntity is not a cached version
476 em.refresh(droolsPdpEntity);
478 em.getTransaction().commit();
480 logger.error("getPdp: PDP=" + pdpId + " not found!?");
482 } catch (Exception e) {
484 (MessageCodes.EXCEPTION_ERROR, e,"getPdp: Caught Exception attempting to get PDP, message='"
485 + e.getMessage() + "'");
487 cleanup(em, "getPdp");
490 if (logger.isDebugEnabled()) {
491 logger.debug("getPdp: Returning droolsPdpEntity=" + droolsPdpEntity);
493 return droolsPdpEntity;
498 * Normally this method should only be used in a JUnit test environment.
499 * Manually inserts a PDP record in droolspdpentity table.
502 public void insertPdp(DroolsPdp pdp) {
504 logger.info("insertPdp: Entering and manually inserting PDP");
509 EntityManager em = emf.createEntityManager();
511 em.getTransaction().begin();
516 DroolsPdpEntity droolsPdpEntity = new DroolsPdpEntity();
517 em.persist(droolsPdpEntity);
518 droolsPdpEntity.setPdpId(pdp.getPdpId());
519 droolsPdpEntity.setDesignated(pdp.isDesignated());
520 droolsPdpEntity.setPriority(pdp.getPriority());
521 droolsPdpEntity.setUpdatedDate(pdp.getUpdatedDate());
522 droolsPdpEntity.setSiteName(pdp.getSiteName());
527 em.getTransaction().commit();
529 cleanup(em, "insertPdp");
532 logger.info("insertPdp: Exiting");
537 * Normally this method should only be used in a JUnit test environment.
538 * Manually deletes all PDP records in droolspdpentity table.
541 public void deleteAllPdps() {
543 logger.info("deleteAllPdps: Entering");
548 EntityManager em = emf.createEntityManager();
550 em.getTransaction().begin();
552 Query droolsPdpsListQuery = em
553 .createQuery("SELECT p FROM DroolsPdpEntity p");
554 @SuppressWarnings("unchecked")
555 List<DroolsPdp> droolsPdpsList = droolsPdpsListQuery.setLockMode(
556 LockModeType.NONE).getResultList();
557 logger.info("deleteAllPdps: Deleting " + droolsPdpsList.size() + " PDPs");
558 for (DroolsPdp droolsPdp : droolsPdpsList) {
559 String pdpId = droolsPdp.getPdpId();
566 em.getTransaction().commit();
568 cleanup(em, "deleteAllPdps");
571 logger.info("deleteAllPdps: Exiting");
576 * Normally this method should only be used in a JUnit test environment.
577 * Manually deletes a PDP record in droolspdpentity table.
580 public void deletePdp(String pdpId) {
582 logger.info("deletePdp: Entering and manually deleting pdpId='" + pdpId
588 EntityManager em = emf.createEntityManager();
590 em.getTransaction().begin();
595 DroolsPdpEntity droolsPdpEntity = em.find(DroolsPdpEntity.class, pdpId);
596 if (droolsPdpEntity != null) {
597 logger.info("deletePdp: Removing PDP");
598 em.remove(droolsPdpEntity);
600 logger.info("deletePdp: PDP with ID='" + pdpId
601 + "' not currently in DB");
607 em.getTransaction().commit();
609 cleanup(em, "deletePdp");
612 logger.info("deletePdp: Exiting");
617 * Normally this method should only be used in a JUnit test environment.
618 * Manually deletes all records in droolsessionentity table.
621 public void deleteAllSessions() {
623 logger.info("deleteAllSessions: Entering");
628 EntityManager em = emf.createEntityManager();
631 em.getTransaction().begin();
633 Query droolsSessionListQuery = em
634 .createQuery("SELECT p FROM DroolsSessionEntity p");
635 @SuppressWarnings("unchecked")
636 List<DroolsSession> droolsSessionsList = droolsSessionListQuery.setLockMode(
637 LockModeType.NONE).getResultList();
638 logger.info("deleteAllSessions: Deleting " + droolsSessionsList.size() + " Sessions");
639 for (DroolsSession droolsSession : droolsSessionsList) {
640 logger.info("deleteAllSessions: Deleting droolsSession with pdpId="
641 + droolsSession.getPdpId() + " and sessionId="
642 + droolsSession.getSessionId());
643 em.remove(droolsSession);
649 em.getTransaction().commit();
651 cleanup(em, "deleteAllSessions");
653 logger.info("deleteAllSessions: Exiting");
659 * Close the specified EntityManager, rolling back any pending transaction
661 * @param em the EntityManager to close ('null' is OK)
662 * @param method the invoking Java method (used for log messages)
664 private static void cleanup(EntityManager em, String method)
668 if (em.getTransaction().isActive()) {
669 // there is an active EntityTransaction -- roll it back
671 em.getTransaction().rollback();
672 } catch (Exception e) {
673 logger.error(method + ": Caught Exception attempting to rollback EntityTransaction, message='"
674 + e.getMessage() + "'");
678 // now, close the EntityManager
681 } catch (Exception e) {
682 logger.error(method + ": Caught Exception attempting to close EntityManager, message='"
683 + e.getMessage() + "'");