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.FlushModeType;
31 import javax.persistence.LockModeType;
32 import javax.persistence.Query;
34 import org.openecomp.policy.drools.core.IntegrityMonitorProperties;
35 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
36 import org.openecomp.policy.common.logging.flexlogger.Logger;
37 import org.openecomp.policy.common.logging.eelf.MessageCodes;
40 public class JpaDroolsPdpsConnector implements DroolsPdpsConnector {
42 // get an instance of logger
43 private static Logger logger = FlexLogger.getLogger(JpaDroolsPdpsConnector.class);
44 private EntityManagerFactory emf;
47 //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
48 public JpaDroolsPdpsConnector(EntityManagerFactory emf){
52 public Collection<DroolsPdp> getDroolsPdps() {
53 //return a list of all the DroolsPdps in the database
54 EntityManager em = emf.createEntityManager();
56 em.getTransaction().begin();
57 Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p");
58 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
59 LinkedList<DroolsPdp> droolsPdpsReturnList = new LinkedList<DroolsPdp>();
60 for(Object o : droolsPdpsList){
61 if(o instanceof DroolsPdp){
62 //Make sure it is not a cached version
63 em.refresh((DroolsPdpEntity)o);
64 droolsPdpsReturnList.add((DroolsPdp)o);
65 if (logger.isDebugEnabled()) {
66 DroolsPdp droolsPdp = (DroolsPdp)o;
67 logger.debug("getDroolsPdps: PDP=" + droolsPdp.getPdpId()
68 + ", isDesignated=" + droolsPdp.isDesignated()
69 + ", updatedDate=" + droolsPdp.getUpdatedDate()
70 + ", priority=" + droolsPdp.getPriority());
75 em.getTransaction().commit();
78 (MessageCodes.EXCEPTION_ERROR, e,"Cannot commit getDroolsPdps() transaction");
80 return droolsPdpsReturnList;
82 cleanup(em, "getDroolsPdps");
86 private boolean nullSafeEquals(Object one, Object two){
87 if(one == null && two == null){
90 if(one != null && two != null){
91 return one.equals(two);
97 public void update(DroolsPdp pdp) {
99 if (logger.isDebugEnabled()) {
100 logger.debug("update: Entering, pdpId=" + pdp.getPdpId());
103 //this is to update our own pdp in the database
104 EntityManager em = emf.createEntityManager();
106 em.getTransaction().begin();
107 Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
108 droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId());
109 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
110 //em.getTransaction().begin();
111 DroolsPdpEntity droolsPdpEntity;
112 if(droolsPdpsList.size() == 1 && (droolsPdpsList.get(0) instanceof DroolsPdpEntity)){
113 droolsPdpEntity = (DroolsPdpEntity)droolsPdpsList.get(0);
114 //if(pdp.getSessionId() < 0){
115 //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
116 //pdp.setSessionId(droolsPdpEntity.getSessionId());
118 Date currentDate = new Date();
119 long difference = currentDate.getTime()-droolsPdpEntity.getUpdatedDate().getTime();
120 //just set some kind of default here
121 long pdpTimeout = 15000;
123 pdpTimeout = Long.parseLong(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_TIMEOUT));
126 (MessageCodes.EXCEPTION_ERROR, e,"Could not get PDP timeout property, using default.");
128 boolean isCurrent = difference<pdpTimeout;
129 if (logger.isDebugEnabled()) {
130 logger.debug("update: PDP=" + pdp.getPdpId() + ", isCurrent="
131 + isCurrent + ", difference=" + difference
132 + ", pdpTimeout=" + pdpTimeout + ", designated="
133 + droolsPdpEntity.isDesignated());
136 if (logger.isDebugEnabled()) {
137 logger.debug("update: For PDP=" + pdp.getPdpId()
138 + ", instantiating new DroolsPdpEntity");
140 droolsPdpEntity = new DroolsPdpEntity();
141 em.persist(droolsPdpEntity);
142 droolsPdpEntity.setPdpId(pdp.getPdpId());
144 if(droolsPdpEntity.getPriority() != pdp.getPriority()){
145 droolsPdpEntity.setPriority(pdp.getPriority());
147 if(!droolsPdpEntity.getUpdatedDate().equals(pdp.getUpdatedDate())){
148 droolsPdpEntity.setUpdatedDate(pdp.getUpdatedDate());
150 if(!droolsPdpEntity.getDesignatedDate().equals(pdp.getDesignatedDate())){
151 droolsPdpEntity.setDesignatedDate(pdp.getDesignatedDate());
153 if(!nullSafeEquals(droolsPdpEntity.getSiteName(),pdp.getSiteName())){
154 droolsPdpEntity.setSiteName(pdp.getSiteName());
156 List<DroolsSessionEntity> sessionsToAdd = new LinkedList<DroolsSessionEntity>();
157 for(DroolsSessionEntity localSession : pdp.getSessions()){
158 boolean found = false;
159 for(DroolsSessionEntity dbSession : droolsPdpEntity.getSessions()){
160 if(localSession.equals(dbSession)){
162 dbSession.setSessionId(localSession.getSessionId());
166 sessionsToAdd.add(localSession);
170 for(DroolsSessionEntity sessionToAdd : sessionsToAdd){
171 em.persist(sessionToAdd);
172 droolsPdpEntity.getSessions().add(sessionToAdd);
176 if(droolsPdpEntity.isDesignated() != pdp.isDesignated()){
177 if (logger.isDebugEnabled()) {
178 logger.debug("update: pdpId=" + pdp.getPdpId()
179 + ", pdp.isDesignated=" + pdp.isDesignated()
180 + ", droolsPdpEntity.pdpId="
181 + droolsPdpEntity.getPdpId()
182 + ", droolsPdpEntity.isDesignated="
183 + droolsPdpEntity.isDesignated());
185 droolsPdpEntity.setDesignated(pdp.isDesignated());
187 em.getTransaction().commit();
189 cleanup(em, "update");
192 if (logger.isDebugEnabled()) {
193 logger.debug("update: Exiting");
199 * Note: A side effect of this boolean method is that if the PDP is designated but not current, the
200 * droolspdpentity.DESIGNATED column will be set to false (the PDP will be un-designated, i.e. marked as
201 * being in standby mode)
204 public boolean isPdpCurrent(DroolsPdp pdp) {
206 boolean isCurrent = isCurrent(pdp);
208 EntityManager em = emf.createEntityManager();
210 if(!isCurrent && pdp.isDesignated()){
211 em.getTransaction().begin();
212 Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
213 droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId());
214 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
215 if(droolsPdpsList.size() == 1 && droolsPdpsList.get(0) instanceof DroolsPdpEntity){
216 if (logger.isDebugEnabled()) {
217 logger.debug("isPdpCurrent: PDP=" + pdp.getPdpId() + " designated but not current; setting designated to false");
219 DroolsPdpEntity droolsPdpEntity = (DroolsPdpEntity)droolsPdpsList.get(0);
220 droolsPdpEntity.setDesignated(false);
221 em.getTransaction().commit();
223 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!");
226 if (logger.isDebugEnabled()) {
227 logger.debug("isPdpCurrent: For PDP=" + pdp.getPdpId()
229 + pdp.isDesignated() + ", isCurrent=" + isCurrent);
234 (MessageCodes.EXCEPTION_ERROR, e,"Could not update expired record marked as designated in the database");
236 cleanup(em, "isPdpCurrent");
243 public void setDesignated(DroolsPdp pdp, boolean designated) {
245 if (logger.isDebugEnabled()) {
246 logger.debug("setDesignated: Entering, pdpId='" + pdp.getPdpId()
247 + "', designated=" + designated);
250 EntityManager em = null;
252 em = emf.createEntityManager();
253 em.getTransaction().begin();
254 Query droolsPdpsListQuery = em
255 .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
256 droolsPdpsListQuery.setParameter("pdpId", pdp.getPdpId());
257 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(
258 LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
259 if (droolsPdpsList.size() == 1
260 && droolsPdpsList.get(0) instanceof DroolsPdpEntity) {
261 DroolsPdpEntity droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList
263 if (logger.isDebugEnabled()) {
264 logger.debug("setDesignated: PDP=" + pdp.getPdpId()
265 + " found, designated="
266 + droolsPdpEntity.isDesignated() + ", setting to "
269 droolsPdpEntity.setDesignated(designated);
270 em.getTransaction().commit();
272 logger.error("setDesignated: PDP=" + pdp.getPdpId()
273 + " not in DB; cannot update designation");
275 } catch (Exception e) {
276 logger.error("setDesignated: Caught Exception, message='"
277 + e.getMessage() + "'");
279 cleanup(em, "setDesignated");
282 if (logger.isDebugEnabled()) {
283 logger.debug("setDesignated: Exiting");
290 public void standDownPdp(String pdpId) {
292 logger.info("standDownPdp: Entering, pdpId='" + pdpId + "'");
294 EntityManager em = null;
299 em = emf.createEntityManager();
300 em.getTransaction().begin();
303 * Get droolspdpentity record for this PDP and mark DESIGNATED as
306 Query droolsPdpsListQuery = em
307 .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
308 droolsPdpsListQuery.setParameter("pdpId", pdpId);
309 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(
310 LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
311 DroolsPdpEntity droolsPdpEntity;
312 if (droolsPdpsList.size() == 1
313 && (droolsPdpsList.get(0) instanceof DroolsPdpEntity)) {
314 droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList.get(0);
315 droolsPdpEntity.setDesignated(false);
316 em.persist(droolsPdpEntity);
317 logger.info("standDownPdp: PDP=" + pdpId + " persisted as non-designated.");
319 logger.error("standDownPdp: Missing record in droolspdpentity for pdpId="
320 + pdpId + "; cannot stand down PDP");
326 em.getTransaction().commit();
327 cleanup(em, "standDownPdp");
330 // Keep the election handler in sync with the DB
331 DroolsPdpsElectionHandler.setMyPdpDesignated(false);
333 } catch (Exception e) {
334 logger.error("standDownPdp: Unexpected Exception attempting to mark DESIGNATED as false for droolspdpentity, pdpId="
336 + ". Cannot stand down PDP; message="
339 cleanup(em, "standDownPdp");
342 logger.info("standDownPdp: Exiting");
347 * Determines whether or not a designated PDP has failed.
349 * Note: The update method, which is run periodically by the
350 * TimerUpdateClass, will un-designate a PDP that is stale.
353 public boolean hasDesignatedPdpFailed(Collection<DroolsPdp> pdps) {
355 if (logger.isDebugEnabled()) {
356 logger.debug("hasDesignatedPdpFailed: Entering, pdps.size()="
360 boolean failed = true;
361 boolean foundDesignatedPdp = false;
363 for (DroolsPdp pdp : pdps) {
366 * Normally, the update method will un-designate any stale PDP, but
367 * we check here to see if the PDP has gone stale since the update
370 * Even if we determine that the designated PDP is current, we keep
371 * going (we don't break), so we can get visibility into the other
372 * PDPs, when in DEBUG mode.
374 if (pdp.isDesignated() && isCurrent(pdp)) {
375 if (logger.isDebugEnabled()) {
376 logger.debug("hasDesignatedPdpFailed: Designated PDP="
377 + pdp.getPdpId() + " is current");
380 foundDesignatedPdp = true;
381 } else if (pdp.isDesignated() && !isCurrent(pdp)) {
382 logger.error("hasDesignatedPdpFailed: Designated PDP="
383 + pdp.getPdpId() + " has failed");
384 foundDesignatedPdp = true;
386 if (logger.isDebugEnabled()) {
387 logger.debug("hasDesignatedPdpFailed: PDP="
388 + pdp.getPdpId() + " is not designated");
393 if (logger.isDebugEnabled()) {
394 logger.debug("hasDesignatedPdpFailed: Exiting and returning, foundDesignatedPdp="
395 + foundDesignatedPdp);
401 private boolean isCurrent(DroolsPdp pdp) {
403 if (logger.isDebugEnabled()) {
404 logger.debug("isCurrent: Entering, pdpId="
408 boolean current = false;
410 // Return if the current PDP is considered "current" based on whatever
411 // time box that may be.
412 // If the the PDP is not current, we should mark it as not primary in
414 Date currentDate = new Date();
415 long difference = currentDate.getTime()
416 - pdp.getUpdatedDate().getTime();
417 // just set some kind of default here
418 long pdpTimeout = 15000;
420 pdpTimeout = Long.parseLong(IntegrityMonitorProperties
421 .getProperty(IntegrityMonitorProperties.PDP_TIMEOUT));
422 if (logger.isDebugEnabled()) {
423 logger.debug("isCurrent: pdp.timeout=" + pdpTimeout);
425 } catch (Exception e) {
427 (MessageCodes.EXCEPTION_ERROR, e,
428 "isCurrent: Could not get PDP timeout property, using default.");
430 current = difference < pdpTimeout;
432 if (logger.isDebugEnabled()) {
433 logger.debug("isCurrent: Exiting, difference="
434 + difference + ", pdpTimeout=" + pdpTimeout
435 + "; returning current=" + current);
443 * Currently this method is only used in a JUnit test environment. Gets a
444 * PDP record from droolspdpentity table.
447 public DroolsPdpEntity getPdp(String pdpId) {
449 if (logger.isDebugEnabled()) {
450 logger.debug("getPdp: Entering and getting PDP with pdpId='" + pdpId
454 DroolsPdpEntity droolsPdpEntity = null;
456 EntityManager em = null;
458 em = emf.createEntityManager();
459 em.getTransaction().begin();
460 Query droolsPdpsListQuery = em
461 .createQuery("SELECT p FROM DroolsPdpEntity p WHERE p.pdpId=:pdpId");
462 droolsPdpsListQuery.setParameter("pdpId", pdpId);
463 List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(
464 LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
465 if (droolsPdpsList.size() == 1
466 && droolsPdpsList.get(0) instanceof DroolsPdpEntity) {
467 droolsPdpEntity = (DroolsPdpEntity) droolsPdpsList.get(0);
468 if (logger.isDebugEnabled()) {
469 logger.debug("getPdp: PDP=" + pdpId
470 + " found, isDesignated="
471 + droolsPdpEntity.isDesignated() + ", updatedDate="
472 + droolsPdpEntity.getUpdatedDate() + ", priority="
473 + droolsPdpEntity.getPriority());
476 // Make sure the droolsPdpEntity is not a cached version
477 em.refresh(droolsPdpEntity);
479 em.getTransaction().commit();
481 logger.error("getPdp: PDP=" + pdpId + " not found!?");
483 } catch (Exception e) {
485 (MessageCodes.EXCEPTION_ERROR, e,"getPdp: Caught Exception attempting to get PDP, message='"
486 + e.getMessage() + "'");
488 cleanup(em, "getPdp");
491 if (logger.isDebugEnabled()) {
492 logger.debug("getPdp: Returning droolsPdpEntity=" + droolsPdpEntity);
494 return droolsPdpEntity;
499 * Normally this method should only be used in a JUnit test environment.
500 * Manually inserts a PDP record in droolspdpentity table.
503 public void insertPdp(DroolsPdp pdp) {
505 logger.info("insertPdp: Entering and manually inserting PDP");
510 EntityManager em = emf.createEntityManager();
512 em.getTransaction().begin();
517 DroolsPdpEntity droolsPdpEntity = new DroolsPdpEntity();
518 em.persist(droolsPdpEntity);
519 droolsPdpEntity.setPdpId(pdp.getPdpId());
520 droolsPdpEntity.setDesignated(pdp.isDesignated());
521 droolsPdpEntity.setPriority(pdp.getPriority());
522 droolsPdpEntity.setUpdatedDate(pdp.getUpdatedDate());
523 droolsPdpEntity.setSiteName(pdp.getSiteName());
528 em.getTransaction().commit();
530 cleanup(em, "insertPdp");
533 logger.info("insertPdp: Exiting");
538 * Normally this method should only be used in a JUnit test environment.
539 * Manually deletes all PDP records in droolspdpentity table.
542 public void deleteAllPdps() {
544 logger.info("deleteAllPdps: Entering");
549 EntityManager em = emf.createEntityManager();
551 em.getTransaction().begin();
553 Query droolsPdpsListQuery = em
554 .createQuery("SELECT p FROM DroolsPdpEntity p");
555 @SuppressWarnings("unchecked")
556 List<DroolsPdp> droolsPdpsList = droolsPdpsListQuery.setLockMode(
557 LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
558 logger.info("deleteAllPdps: Deleting " + droolsPdpsList.size() + " PDPs");
559 for (DroolsPdp droolsPdp : droolsPdpsList) {
560 String pdpId = droolsPdp.getPdpId();
567 em.getTransaction().commit();
569 cleanup(em, "deleteAllPdps");
572 logger.info("deleteAllPdps: Exiting");
577 * Normally this method should only be used in a JUnit test environment.
578 * Manually deletes a PDP record in droolspdpentity table.
581 public void deletePdp(String pdpId) {
583 logger.info("deletePdp: Entering and manually deleting pdpId='" + pdpId
589 EntityManager em = emf.createEntityManager();
591 em.getTransaction().begin();
596 DroolsPdpEntity droolsPdpEntity = em.find(DroolsPdpEntity.class, pdpId);
597 if (droolsPdpEntity != null) {
598 logger.info("deletePdp: Removing PDP");
599 em.remove(droolsPdpEntity);
601 logger.info("deletePdp: PDP with ID='" + pdpId
602 + "' not currently in DB");
608 em.getTransaction().commit();
610 cleanup(em, "deletePdp");
613 logger.info("deletePdp: Exiting");
618 * Normally this method should only be used in a JUnit test environment.
619 * Manually deletes all records in droolsessionentity table.
622 public void deleteAllSessions() {
624 logger.info("deleteAllSessions: Entering");
629 EntityManager em = emf.createEntityManager();
632 em.getTransaction().begin();
634 Query droolsSessionListQuery = em
635 .createQuery("SELECT p FROM DroolsSessionEntity p");
636 @SuppressWarnings("unchecked")
637 List<DroolsSession> droolsSessionsList = droolsSessionListQuery.setLockMode(
638 LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList();
639 logger.info("deleteAllSessions: Deleting " + droolsSessionsList.size() + " Sessions");
640 for (DroolsSession droolsSession : droolsSessionsList) {
641 logger.info("deleteAllSessions: Deleting droolsSession with pdpId="
642 + droolsSession.getPdpId() + " and sessionId="
643 + droolsSession.getSessionId());
644 em.remove(droolsSession);
650 em.getTransaction().commit();
652 cleanup(em, "deleteAllSessions");
654 logger.info("deleteAllSessions: Exiting");
660 * Close the specified EntityManager, rolling back any pending transaction
662 * @param em the EntityManager to close ('null' is OK)
663 * @param method the invoking Java method (used for log messages)
665 private static void cleanup(EntityManager em, String method)
669 if (em.getTransaction().isActive()) {
670 // there is an active EntityTransaction -- roll it back
672 em.getTransaction().rollback();
673 } catch (Exception e) {
674 logger.error(method + ": Caught Exception attempting to rollback EntityTransaction, message='"
675 + e.getMessage() + "'");
679 // now, close the EntityManager
682 } catch (Exception e) {
683 logger.error(method + ": Caught Exception attempting to close EntityManager, message='"
684 + e.getMessage() + "'");