Liran Zelkha has uploaded a new change for review.

Change subject: core: support materialized views in Java
......................................................................

core: support materialized views in Java

Add update listeners to any Dao implementation, and a MaterializedView listener 
that
can call relevant materialized views stored procedures to recreate them.

Change-Id: I745e934fde341bd1264e5e5fedaf59fc64ad4ad8
Signed-off-by: [email protected] <[email protected]>
---
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java
A 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MaterializedView.java
A 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListener.java
A 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/DaoDynamicWrapper.java
A 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateListener.java
A 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateMethod.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DaoFactory.java
A 
backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListenerTest.java
8 files changed, 170 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/05/16305/1

diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java
index 5e09d79..80c6fb7 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/DbFacade.java
@@ -41,6 +41,7 @@
 import 
org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface;
 import 
org.ovirt.engine.core.common.businessentities.network.VmNetworkStatistics;
 import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.dal.dbbroker.updateListeners.UpdateListener;
 import org.ovirt.engine.core.dao.ActionGroupDAO;
 import org.ovirt.engine.core.dao.AdGroupDAO;
 import org.ovirt.engine.core.dao.AsyncTaskDAO;
@@ -164,6 +165,8 @@
     private int onStartConnectionTimeout;
 
     private int connectionCheckInterval;
+
+    private List<UpdateListener> updateListeners = new ArrayList<>();
 
     public void setDbEngineDialect(DbEngineDialect dbEngineDialect) {
         this.dbEngineDialect = dbEngineDialect;
@@ -963,4 +966,22 @@
     public VmGuestAgentInterfaceDao getVmGuestAgentInterfaceDao() {
         return getDao(VmGuestAgentInterfaceDao.class);
     }
+
+    public void informUpdate(DAO originatingDao, String method, Object[] args) 
{
+        // TODO: Implement a queue
+        // TODO: Run all in seperate thread
+        // TODO: Eliminate queue duplicates
+
+        for (UpdateListener listener : updateListeners) {
+            listener.updateOccured(originatingDao, method, args);
+        }
+    }
+
+    public void registerListener(UpdateListener listener) {
+        updateListeners.add(listener);
+    }
+
+    public void removeListener(UpdateListener listener) {
+        updateListeners.remove(listener);
+    }
 }
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MaterializedView.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MaterializedView.java
new file mode 100644
index 0000000..2c7f512
--- /dev/null
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MaterializedView.java
@@ -0,0 +1,16 @@
+package org.ovirt.engine.core.dal.dbbroker.materializedviews;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used to mark Dao's that are based on Materialized Views
+ * @author lzelkha
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface MaterializedView {
+
+}
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListener.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListener.java
new file mode 100644
index 0000000..1d088be
--- /dev/null
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListener.java
@@ -0,0 +1,51 @@
+package org.ovirt.engine.core.dal.dbbroker.materializedviews;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import org.ovirt.engine.core.dal.dbbroker.updateListeners.UpdateListener;
+import org.ovirt.engine.core.dao.DAO;
+import org.ovirt.engine.core.utils.log.Log;
+import org.ovirt.engine.core.utils.log.LogFactory;
+
+public class MatrializedViewListener implements UpdateListener {
+    private static final Log log = 
LogFactory.getLog(MatrializedViewListener.class);
+
+    public MatrializedViewListener() {
+    }
+
+    @Override
+    public void updateOccured(DAO dao, String methodName, Object[] args) {
+        if (dao == null || 
!dao.getClass().isAnnotationPresent(MaterializedView.class)) {
+            return;
+        }
+
+        String entityName = null;
+
+        for (Class<?> clz : dao.getClass().getInterfaces()) {
+
+            if (DAO.class.isAssignableFrom(clz)) {
+                for (Type t : clz.getGenericInterfaces()) {
+                    if (t instanceof ParameterizedType) {
+                        ParameterizedType pt = (ParameterizedType) t;
+                        if (pt.getActualTypeArguments().length > 0) {
+                            Type actualParameter = 
pt.getActualTypeArguments()[0];
+                            if (actualParameter instanceof Class) {
+                                Class<?> entityClass = (Class<?>) 
actualParameter;
+                                entityName = entityClass.getSimpleName();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (entityName == null) {
+            log.error("MaterializedViewListener could not discover activated 
entity for DAO " + dao
+                    + " . Data inconsistency might occur.");
+        } else {
+            System.out.println(entityName);
+            // 
DbFacade.getInstance().getCallsHandler().executeModification("test", null);
+        }
+    }
+}
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/DaoDynamicWrapper.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/DaoDynamicWrapper.java
new file mode 100644
index 0000000..65161ea
--- /dev/null
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/DaoDynamicWrapper.java
@@ -0,0 +1,35 @@
+package org.ovirt.engine.core.dal.dbbroker.updateListeners;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dal.dbbroker.materializedviews.MaterializedView;
+import org.ovirt.engine.core.dao.DAO;
+
+/**
+ * This dynamic proxy is used to inform update listeners on update methods 
called on entities
+ * @author lzelkha
+ */
+public class DaoDynamicWrapper<T extends DAO> implements InvocationHandler {
+
+    private T originalDao;
+
+    public DaoDynamicWrapper(T originalDao) {
+        this.originalDao = originalDao;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
+        if (proxy != null && proxy instanceof DAO) {
+            if (proxy.getClass().isAnnotationPresent(MaterializedView.class)) {
+                if (method.getName().startsWith("update") || 
method.getName().startsWith("save")
+                        || method.isAnnotationPresent(UpdateMethod.class)) {
+                    DbFacade.getInstance().informUpdate((DAO) proxy, 
method.getName(), args);
+                }
+            }
+        }
+        return method.invoke(originalDao, args);
+    }
+
+}
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateListener.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateListener.java
new file mode 100644
index 0000000..ff5eb31
--- /dev/null
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateListener.java
@@ -0,0 +1,7 @@
+package org.ovirt.engine.core.dal.dbbroker.updateListeners;
+
+import org.ovirt.engine.core.dao.DAO;
+
+public interface UpdateListener {
+    public void updateOccured(DAO dao, String methodName, Object[] args);
+}
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateMethod.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateMethod.java
new file mode 100644
index 0000000..e8fb770
--- /dev/null
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dal/dbbroker/updateListeners/UpdateMethod.java
@@ -0,0 +1,17 @@
+package org.ovirt.engine.core.dal.dbbroker.updateListeners;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used to mark methods that update the database, and will 
require an update to depending
+ * materialized view objects
+ * @author lzelkha
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface UpdateMethod {
+
+}
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DaoFactory.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DaoFactory.java
index 3f4a5fe..07e919b 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DaoFactory.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DaoFactory.java
@@ -1,9 +1,11 @@
 package org.ovirt.engine.core.dao;
 
+import java.lang.reflect.Proxy;
 import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import org.ovirt.engine.core.dal.dbbroker.updateListeners.DaoDynamicWrapper;
 import org.ovirt.engine.core.utils.ResourceUtils;
 
 public class DaoFactory {
@@ -19,10 +21,13 @@
         return daoType.cast(daos.get(daoType));
     }
 
+    @SuppressWarnings("unchecked")
     private static <T extends DAO> T createDAO(Class<T> daoType) {
         try {
-            return newInstance(daoType,
-                    ResourceUtils.loadProperties(DaoFactory.class, 
ENGINE_DAOS_CONFIGURATION_FILE));
+            return (T) 
Proxy.newProxyInstance(DaoFactory.class.getClassLoader(),
+                    new Class[] { daoType },
+                    new DaoDynamicWrapper<T>(newInstance(daoType,
+                            ResourceUtils.loadProperties(DaoFactory.class, 
ENGINE_DAOS_CONFIGURATION_FILE))));
         } catch (Exception e) {
             throw new DaoFactoryException(daoType, 
ENGINE_DAOS_CONFIGURATION_FILE, e);
         }
diff --git 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListenerTest.java
 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListenerTest.java
new file mode 100644
index 0000000..fc2c53a
--- /dev/null
+++ 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dal/dbbroker/materializedviews/MatrializedViewListenerTest.java
@@ -0,0 +1,16 @@
+package org.ovirt.engine.core.dal.dbbroker.materializedviews;
+
+import org.junit.Test;
+import org.ovirt.engine.core.dao.AuditLogDAO;
+import org.ovirt.engine.core.dao.AuditLogDAODbFacadeImpl;
+
+public class MatrializedViewListenerTest {
+
+    @Test
+    public void testUpdateOccured() {
+        MatrializedViewListener listener = new MatrializedViewListener();
+        AuditLogDAO dao = new AuditLogDAODbFacadeImpl();
+        listener.updateOccured(dao, "save", null);
+    }
+
+}


-- 
To view, visit http://gerrit.ovirt.org/16305
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I745e934fde341bd1264e5e5fedaf59fc64ad4ad8
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Liran Zelkha <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to