📄 edatabase.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: EDatabase.java * Written by: Dmitry Nadezhin, Sun Microsystems. * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.database.hierarchy;import com.sun.electric.database.CellBackup;import com.sun.electric.database.CellRevision;import com.sun.electric.database.LibraryBackup;import com.sun.electric.database.Snapshot;import com.sun.electric.database.geometry.ERectangle;import com.sun.electric.database.id.CellId;import com.sun.electric.database.id.CellUsage;import com.sun.electric.database.id.IdManager;import com.sun.electric.database.id.LibId;import com.sun.electric.database.id.TechId;import com.sun.electric.database.network.NetworkManager;import com.sun.electric.database.text.ImmutableArrayList;import com.sun.electric.database.text.TextUtils;import com.sun.electric.technology.TechPool;import com.sun.electric.technology.Technology;import com.sun.electric.technology.technologies.Artwork;import com.sun.electric.technology.technologies.Generic;import com.sun.electric.technology.technologies.Schematics;import com.sun.electric.tool.Job;import com.sun.electric.tool.Tool;import com.sun.electric.tool.user.ActivityLogger;import java.util.ArrayList;import java.util.BitSet;import java.util.Collection;import java.util.Collections;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.TreeMap;import java.util.TreeSet;import java.util.logging.Level;import java.util.logging.Logger;/** * Electric run-time database is a graph of ElectricObjects. */public class EDatabase { private static final Logger logger = Logger.getLogger("com.sun.electric.database"); private static final String CLASS_NAME = EDatabase.class.getName(); public static EDatabase theDatabase = new EDatabase(new IdManager()); public static EDatabase serverDatabase() { return theDatabase; } public static EDatabase clientDatabase() { return theDatabase; } /** IdManager which keeps Ids of objects in this database.*/private final IdManager idManager; /** list of linked technologies indexed by techId. */ private TechPool techPool; /** list of linked libraries indexed by libId. */ private final ArrayList<Library> linkedLibs = new ArrayList<Library>(); /** map of libraries sorted by name */ final TreeMap<String,Library> libraries = new TreeMap<String,Library>(TextUtils.STRING_NUMBER_ORDER); /** static list of all linked cells indexed by CellId. */ final ArrayList<Cell> linkedCells = new ArrayList<Cell>(); /** Last snapshot */ private Snapshot snapshot; /** True if database matches snapshot. */ private boolean snapshotFresh; /** Flag set when database invariants failed. */ private boolean invariantsFailed; /** Network manager for this database. */ private final NetworkManager networkManager; /** Thread which locked database for writing. */ private volatile Thread writingThread; /** True if writing thread can changing. */ private boolean canChanging; /** True if writing thread can undoing. */ private boolean canUndoing; /** Tool which initiated changing. */ private Tool changingTool; /** Creates a new instance of EDatabase */ public EDatabase(IdManager idManager) { this.idManager = idManager; techPool = idManager.getInitialTechPool(); setSnapshot(getInitialSnapshot(), true); networkManager = new NetworkManager(this); } public IdManager getIdManager() { return idManager; } public Snapshot getInitialSnapshot() { return idManager.getInitialSnapshot(); } public NetworkManager getNetworkManager() { return networkManager; } public void addTech(Technology tech) { assert getTech(tech.getId()) == null; techPool = techPool.withTech(tech); snapshotFresh = false; } /** Returns TechPool of this database */ public TechPool getTechPool() { return techPool; } public Collection<Technology> getTechnologies() { return techPool.values(); } /** * Get Technology by TechId * TechId must belong to same IdManager as TechPool * @param techId TechId to find * @return Technology b giben TechId or null * @throws IllegalArgumentException of TechId is not from this IdManager */ public Technology getTech(TechId techId) { return techPool.getTech(techId); } /** Return Artwork technology in this database */ public Artwork getArtwork() { return techPool.getArtwork(); } /** Return Generic technology in this database */ public Generic getGeneric() { return techPool.getGeneric(); } /** Return Schematic technology in this database */ public Schematics getSchematics() { return techPool.getSchematics(); } public Library getLib(LibId libId) { return getLib(libId.libIndex); } void addLib(Library lib) { int libIndex = lib.getId().libIndex; while (libIndex >= linkedLibs.size()) linkedLibs.add(null); Library oldLib = linkedLibs.set(libIndex, lib); assert oldLib == null; libraries.put(lib.getName(), lib); } void removeLib(LibId libId) { Library oldLib = linkedLibs.set(libId.libIndex, null); while (!linkedLibs.isEmpty() && linkedLibs.get(linkedLibs.size() - 1) == null) linkedLibs.remove(linkedLibs.size() - 1); libraries.remove(oldLib.getName()); } public Cell getCell(CellId cellId) { return getCell(cellId.cellIndex); } void addCell(Cell cell) { int cellIndex = cell.getCellIndex(); while (cellIndex >= linkedCells.size()) linkedCells.add(null); Cell oldCell = linkedCells.set(cellIndex, cell); assert oldCell == null; } void removeCell(CellId cellId) { Cell oldCell = linkedCells.set(cellId.cellIndex, null); assert oldCell != null; while (!linkedCells.isEmpty() && linkedCells.get(linkedCells.size() - 1) == null) linkedCells.remove(linkedCells.size() - 1); }// Technology getTech(int techIndex) { return techIndex < linkedTechs.size() ? linkedTechs.get(techIndex) : null; } Library getLib(int libIndex) { return libIndex < linkedLibs.size() ? linkedLibs.get(libIndex) : null; } Cell getCell(int cellIndex) { return cellIndex < linkedCells.size() ? linkedCells.get(cellIndex) : null; } /** * Locks the database. * Lock may be either exclusive (for writing) or shared (for reading). * @param exclusive true if lock is for writing. */ public void lock(boolean exclusive) { assert writingThread == null; if (exclusive) writingThread = Thread.currentThread(); canChanging = canUndoing = false; } /** * Unlocks the database. */ public void unlock() { writingThread = null; } /** * Method to check whether changing of database is allowed by current thread. * @throws IllegalStateException if changes are not allowed. */ public void checkChanging() { if (Thread.currentThread() == writingThread && canChanging) return; IllegalStateException e = new IllegalStateException("Database changes are forbidden"); logger.logp(Level.WARNING, CLASS_NAME, "checkChanging", e.getMessage(), e); throw e; } /** * Method to check whether changing of whole database is allowed. * @throws IllegalStateException if changes are not allowed. */ public void checkUndoing() { if (Thread.currentThread() == writingThread && canUndoing) return; IllegalStateException e = new IllegalStateException("Database undo is forbidden"); logger.logp(Level.WARNING, CLASS_NAME, "checkUndoing", e.getMessage(), e); throw e; } public boolean canComputeBounds() { return Thread.currentThread() == writingThread && (canChanging || canUndoing); } public boolean canComputeNetlist() { return Thread.currentThread() == writingThread && (canChanging || canUndoing); } /** * Method to check whether examining of database is allowed. */ public void checkExamine() { if (writingThread == null || Thread.currentThread() == writingThread) return; IllegalStateException e = new IllegalStateException("Cuncurrent database examine");// e.printStackTrace(); logger.logp(Level.FINE, CLASS_NAME, "checkExamine", e.getMessage(), e);// throw e; } /** * Low-level method to begin changes in database. * @param changingTool tool which initiated */ public void lowLevelBeginChanging(Tool changingTool) { if (Thread.currentThread() != writingThread) checkChanging(); canChanging = true; this.changingTool = changingTool; } /** * Low-level method to permit changes in database. */ public void lowLevelEndChanging() { if (Thread.currentThread() != writingThread) checkChanging(); changingTool = null; canChanging = false; } /** * Low-level method to permit undos in database. */ public void lowLevelSetCanUndoing(boolean b) { if (Thread.currentThread() != writingThread) checkUndoing(); canUndoing = b; } /** * Get list of cells contained in other libraries * that refer to cells contained in this library * @param elib to search for * @return list of cells refering to elements in this library */ public Set<Cell> findReferenceInCell(Library elib) { TreeSet<Cell> set = new TreeSet<Cell>(); for (Library l : libraries.values()) { // skip itself if (l == elib) continue; for (Cell cell : l.cells.values()) { cell.findReferenceInCell(elib, set); } } return set; } /** * Method to find a Library with the specified name. * @param libName the name of the Library. * Note that this is the Library name, and not the Library file. * @return the Library, or null if there is no known Library by that name. */ public Library findLibrary(String libName) { if (libName == null) return null; return libraries.get(libName);// Library lib = libraries.get(libName);// if (lib != null) return lib;//// for (Library l : libraries.values())// {// if (l.getName().equalsIgnoreCase(libName))// return l;// }// return null; } /** * Method to return an iterator over all libraries. * @return an iterator over all libraries. */ public Iterator<Library> getLibraries() { synchronized(libraries) { ArrayList<Library> librariesCopy = new ArrayList<Library>(libraries.values()); return librariesCopy.iterator(); } } /** * Method to return the number of libraries. * @return the number of libraries. */ public int getNumLibraries() { return libraries.size(); } /** * Method to return an iterator over all visible libraries. * @return an iterator over all visible libraries. */ public List<Library> getVisibleLibraries() { synchronized(libraries) { ArrayList<Library> visibleLibraries = new ArrayList<Library>(); for (Library lib : libraries.values()) { if (!lib.isHidden()) visibleLibraries.add(lib); } return visibleLibraries; } } void unfreshSnapshot() { checkChanging(); snapshotFresh = false; } private synchronized void setSnapshot(Snapshot snapshot, boolean fresh) { this.snapshot = snapshot; this.snapshotFresh = fresh; } /** * Low-level method to atomically get fresh snapshot. * @return fresh snapshot of the database, or null if nop fresh snapshot exists. */ public synchronized Snapshot getFreshSnapshot() { return snapshotFresh ? snapshot : null; } /** * Create Snapshot from the current state of Electric database. * @return snapshot of the current state of Electric database. * @throws IllegalStateException if recalculation of Snapshot is requred in thread which is not enabled to do it. */ public Snapshot backup() { if (snapshotFresh) return snapshot; if (!canComputeBounds()) throw new IllegalStateException(); return doBackup(); } /** * Create Snapshot from the current state of Electric database. * If there is no fresh snapshot for this database and thread is not enabled to calculate snspshot, returns the latest snapshot. * @return snapshot of the current state of Electric database. */ public Snapshot backupUnsafe() { if (snapshotFresh || !canComputeBounds()) return snapshot; return doBackup(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -