Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Examples/JPA/Simulation

< EclipseLink‎ | Examples‎ | JPA
Revision as of 16:10, 1 September 2009 by Unnamed Poltroon (Talk) (Purpose)

Simulation JPA Application Example

Purpose

  • This sumulation will serve as a near real world enterprise application that showcases utilizing JPA as the persistence or integration layer - specifically using EclipseLink JPA as the provider.
  • This enterprise application will offer the services of a simulated connection machine (Ref: Thinking Machines CM-2) symbolic vector processor.
    • Why are we choosing an older architecture to simulate?
      • a) The architecture is very clean and even though it is very large - is simple enough to implement.
      • b) The Design by Danny Hillis in his dissertation is out of print as of 2005 and Thinking Machines no longer exists - so we are free to simulate the device.
      • b) The design is proven and static - as it has been superceeded by more powerfull designs).
      • c) The massively parallel processing design of the CM-2 matches our goal of utilizing parallelism at both the thread and multi-core processor level on our host machine.

Goals

  • We would like to explore the following limits of the JPA provider and hosting application server.
    • Performance and Volumetrics: We require 65536 processor objects.

Infrastructure

  • OS: Windows XP or Vista 32/64 bit
  • Database: Oracle 11gR1
  • JPA provider: EclipseLink 1.2
  • JDK: Sun 1.6.0_14

Analysis

Data Model

Processor Architecture

  • Each CM-2 processor is composed of up to 64k (65536) 1-bit processors arranged in a 12-dimensional hypercube.
    • There are 16 1-bit processors per chip along with 1 routing processor per chip.
      • There are 32 cpu chips and 32 ram chips per backplane board
        • There are 16 boards per quadrant
          • There are 8 quadrands to a CM-2
    • We therefore have (2^4=16) x (2^5=32) x (2^4=16) x (2^3=8) = 2^16 = 65536 possible processors in a fully configured system.

Hierarchy

  • Hypercube (quadrants(1:M), input, output, program)
  • Quadrant (boards(1:M), hypercube(1:1))
  • Board (processorChips(1:M), ramChips(1:M))
  • Chip(A)
    • ProcessorChip (processors (1:M), router (1:1))
    • MemoryChip
  • Processor(A)
    • VectorProcessor(alu, stateMachine, uProgram)
    • RouterProcessor (routers(1:M))

Design

JPA Data Model

Board.java

@Entity
@Table(name="CM_BOARD")
public class Board implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="BOARD_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="BOARD_CM_TABLE_GENERATOR", 
        table="CM_BOARD_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="BOARD_ID")    
    private Integer id;
 
    @Version
    @Column(name="BOARD_VERSION")
    private int version;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="board")
    private List<ProcessorChip> processorChips = new ArrayList<ProcessorChip>();
 
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_QUADRANT_CM_BOARD", 
            joinColumns = @JoinColumn(name="BOARD_ID"), 
            inverseJoinColumns =@JoinColumn(name="QUADRANT_ID"))   
    private Quadrant quadrant;
 
    public List<VectorProcessor> getVectorProcessors() {
        List<VectorProcessor> allProcessors = new ArrayList<VectorProcessor>();
        for(ProcessorChip aProcessorChip : processorChips) {
            allProcessors.addAll(aProcessorChip.getVectorProcessors());
        }
        return allProcessors;
    }

Chip.java

@MappedSuperclass
public abstract class Chip implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="CHIP_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="CHIP_CM_TABLE_GENERATOR", 
        table="CM_CHIP_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="CHIP_ID")    
    private Integer id;
 
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_BOARD_CM_CHIP", 
            joinColumns = @JoinColumn(name="CHIP_ID"), 
            inverseJoinColumns =@JoinColumn(name="BOARD_ID"))   
    private Board board;

Hypercube.java

@Entity
@Table(name="CM_HYPERCUBE")
public class Hypercube implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="HYPERCUBE_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="HYPERCUBE_CM_TABLE_GENERATOR", 
        table="CM_HYPERCUBE_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="HYPERCUBE_ID")    
    private Integer id;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="hypercube")
    private List<Quadrant> quadrants = new ArrayList<Quadrant>();
 
    public List<VectorProcessor> getVectorProcessors() {
        List<VectorProcessor> allProcessors = new ArrayList<VectorProcessor>();
        for(Quadrant aQuadrant : quadrants) {
            allProcessors.addAll(aQuadrant.getVectorProcessors());
        }
        return allProcessors;
    }

Processor.java

@MappedSuperclass
public abstract class Processor implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="PROCESSOR_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="PROCESSOR_CM_TABLE_GENERATOR", 
        table="CM_PROCESSOR_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="PROCESSOR_ID")    
    private Integer id;

ProcessorChip.java

@Entity
@Table(name="CM_PROCESSORCHIP")
public class ProcessorChip extends Chip implements Serializable {
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="processorChip")
    private List<VectorProcessor> vectorProcessors = new ArrayList<VectorProcessor>();

Quadrant.java

@Entity
@Table(name="CM_QUADRANT")
public class Quadrant implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="QUADRANT_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="QUADRANT_CM_TABLE_GENERATOR", 
        table="CM_QUADRANT_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="QUADRANT_ID")    
    private Integer id;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="quadrant")
    private List<Board> boards = new ArrayList<Board>();
 
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_HYPERCUBE_CM_QUADRANT", 
            joinColumns = @JoinColumn(name="QUADRANT_ID"), 
            inverseJoinColumns =@JoinColumn(name="HYPERCUBE_ID"))   
    private Hypercube hypercube;
 
 
    public List<VectorProcessor> getVectorProcessors() {
        List<VectorProcessor> allProcessors = new ArrayList<VectorProcessor>();
        for(Board aBoard : boards) {
            allProcessors.addAll(aBoard.getVectorProcessors());
        }
        return allProcessors;
    }

VectorProcessor.java

@Entity
@Table(name="CM_VECTORPROCESSOR")
public class VectorProcessor extends Processor implements Serializable {
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_CHIP_CM_PROCESSOR", 
            joinColumns = @JoinColumn(name="PROCESSOR_ID"), 
            inverseJoinColumns =@JoinColumn(name="CHIP_ID"))   
    private ProcessorChip processorChip;

CM2Console.java

  • This is a minimum Java SE JPA client
package org.eclipse.persistence.example.jpa.cm.presentation;
 
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.metamodel.Metamodel;
 
import org.eclipse.persistence.example.jpa.cm.business.Board;
import org.eclipse.persistence.example.jpa.cm.business.Hypercube;
import org.eclipse.persistence.example.jpa.cm.business.ProcessorChip;
import org.eclipse.persistence.example.jpa.cm.business.Quadrant;
import org.eclipse.persistence.example.jpa.cm.business.VectorProcessor;
import org.eclipse.persistence.example.jpa.cm.integration.CM2;
 
public class CM2Console {
 
    CM2 connectionMachine;
 
    public CM2Console() {
        connectionMachine = new CM2();
    }
 
   public CM2 getConnectionMachine() {
        return connectionMachine;
    }
 
    public void setConnectionMachine(CM2 connectionMachine) {
        this.connectionMachine = connectionMachine;
    }
 
    // Application managed EMF and EM
    public EntityManagerFactory emf  = null;
    public EntityManager entityManager = null;
    // Reference the database specific persistence unit in persistence.xml
    public static final String PU_NAME_CREATE = "CMJPA_create";    
 
    /**
     * Create the EMF and EM and start a transaction (out of container context)
     * @param puName
     */
    private void initialize(String puName) {
        try {
            // Initialize an application managed JPA emf and em via META-INF
            emf  = Persistence.createEntityManagerFactory(puName);
            entityManager = emf.createEntityManager();            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /**
     * Close the application managed EM and EMF
     */
    @Override
    public void finalize() {
        // close JPA
        try {
            if(null != getEntityManager()) {
                getEntityManager().close();
                getEmf().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    private void populate(PrintWriter out) {
        // register atomic entities first before creating relationships
        try {
            EntityManager em = getEntityManager();
            if(null == em) {
                System.out.println("EntityManager is null: Check your persistence.xml properties");
            } else {
                EntityTransaction transaction = em.getTransaction();
                if(null == transaction) {
                    System.out.println("Cannot get a transaction from entityManager: " + em);
                } else {                    
                    transaction.begin();
 
                    // Insert schema and classes into the database
                    CM2 cm2 = new CM2();
                    // 1 Hypercube
                    Hypercube hypercube = new Hypercube();        
                    // 8 Quadrants
                    List<Quadrant> quadrants = new ArrayList<Quadrant>();
                    for(int i=0; i<8; i++) {
                        Quadrant aQuadrant = new Quadrant();
                        aQuadrant.setHypercube(hypercube);
                        quadrants.add(aQuadrant);
                        // 16 Backplane Boards
                        List<Board> boards = new ArrayList<Board>();
                        for(int j=0; j<16; j++) {
                            Board aBoard = new Board();
                            aBoard.setQuadrant(aQuadrant);
                            boards.add(aBoard);
                            // 32 processor chips per board
                            List<ProcessorChip> chips = new ArrayList<ProcessorChip>();
                            for(int k=0; k<32; k++) {
                                ProcessorChip aChip = new ProcessorChip();
                                aChip.setBoard(aBoard);
                                chips.add(aChip);
                                // 16 vector processors per chip
                                List<VectorProcessor> processors = new ArrayList<VectorProcessor>();
                                for(int l=0; l<16; l++) {
                                    VectorProcessor aProcessor = new VectorProcessor();
                                    aProcessor.setProcessorChip(aChip);
                                    processors.add(aProcessor);
                                    em.merge(aProcessor);
                                }
                                aChip.setProcessors(processors);
                                em.merge(aChip);
                            }
                            aBoard.setChips(chips);
                            em.merge(aBoard);
                        }
                        aQuadrant.setBoards(boards);
                        em.merge(aQuadrant);
                    }
                    hypercube.setQuadrants(quadrants);        
                    cm2.setHypercube(hypercube);                    
                    em.merge(hypercube);
 
                    // 8 Quadrants
                    long processorCount = 0;
                    em.persist(hypercube);
                    for(Quadrant aQuadrant : hypercube.getQuadrants()) {
                        em.persist(aQuadrant);
                        // 16 Backplane Boards
                        for(Board aBoard : aQuadrant.getBoards()) {
                            em.persist(aBoard);
                            // 32 processor chips per board
                            for(ProcessorChip aChip : aBoard.getProcessorChips()) {
                                em.persist(aChip);
                                // 16 vector processors per chip
                                for(VectorProcessor aProcessor : aChip.getVectorProcessors()) {
                                    //System.out.println("_persisting: " + count++ + " : " + aProcessor);                                    
                                    em.persist(aProcessor);
                                    processorCount++;
                                }                                
                            }                            
                        }                        
                    }
                    System.out.println("_persisted " + processorCount + " Processor Entities");
                    System.out.println("_All Processors: " + hypercube.getVectorProcessors().size());
                    Metamodel aMetamodel = em.getMetamodel();
                    System.out.println("_Metamodel: " + aMetamodel);
                }
 
                // Store objects        
                transaction.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }        
    }
 
    public EntityManagerFactory getEmf() {
        return emf;
    }
 
    public void setEmf(EntityManagerFactory emf) {
        this.emf = emf;
    }
 
    public EntityManager getEntityManager() {
        return entityManager;
    }
 
    public void setEntifyManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
 
    public static void main(String[] args) {
        CM2Console aConsole = new CM2Console();
        aConsole.initialize(PU_NAME_CREATE);
        aConsole.populate(null);
        aConsole.finalize();
        System.out.println(aConsole.getConnectionMachine());
        System.exit(0);
 
    }
}

Implementation

Schema Model

Persistence Unit

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
	<persistence-unit name="CMJPA_create" transaction-type="RESOURCE_LOCAL">
	<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
		<class>org.eclipse.persistence.example.jpa.cm.business.Board</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.Hypercube</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.MemoryChip</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.ProcessorChip</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.Quadrant</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.RouterProcessor</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.VectorProcessor</class>
       <properties>
            <property name="eclipselink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
            <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.oracle.OraclePlatform"/>            
            <property name="eclipselink.jdbc.url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
            <property name="eclipselink.jdbc.user" value="scott"/>
            <property name="eclipselink.jdbc.password" value="pw"/>
            <!-- property name="eclipselink.logging.level" value="ALL"/-->            
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="database"/>
       </properties>
	</persistence-unit>
</persistence>

Testing

  • In order to accommidate a 65MB heap size use the JVM parameter
    • -Xmx1024m

Console Output

Logs

_persisted 65536 Processor Entities
_All Processors: 65536
_Metamodel: MetamodelImpl@31301308 [ 11 Types: , 9 ManagedTypes: , 7 EntityTypes: , 2 MappedSuperclassTypes: , 0 EmbeddableTypes: ]
[EL Info]: 2009-09-01 15:52:30.633--ServerSession(23979164)--file:/E:/wse/view_w35a/CM2JPA/bin/-CMJPA_create logout successful
org.eclipse.persistence.example.jpa.cm.integration.CM2@2a72b6

Appendices

References

Back to the top