📄 edatabase.java
字号:
private Snapshot doBackup() {// long startTime = System.currentTimeMillis(); LibraryBackup[] libBackups = new LibraryBackup[linkedLibs.size()]; boolean libsChanged = libBackups.length != snapshot.libBackups.size(); for (int libIndex = 0; libIndex < libBackups.length; libIndex++) { Library lib = linkedLibs.get(libIndex); LibraryBackup libBackup = lib != null ? lib.backup() : null; libBackups[libIndex] = libBackup; libsChanged = libsChanged || snapshot.libBackups.get(libIndex) != libBackup; } if (!libsChanged) libBackups = null; CellBackup[] cellBackups = new CellBackup[linkedCells.size()]; ERectangle[] cellBounds = new ERectangle[cellBackups.length]; boolean cellsChanged = cellBackups.length != snapshot.cellBackups.size(); boolean cellBoundsChanged = cellsChanged; for (int cellIndex = 0; cellIndex < cellBackups.length; cellIndex++) { Cell cell = getCell(cellIndex); if (cell != null) { if (techPool != snapshot.techPool) cell.cellBackupFresh = false; cellBackups[cellIndex] = cell.backup(); cell.getMemoization(); cellBounds[cellIndex] = cell.getBounds(); cell.getTopology().getRTree(); assert cell.backup() == cellBackups[cellIndex]; assert cell.getBounds() == cellBounds[cellIndex]; } cellsChanged = cellsChanged || cellBackups[cellIndex] != snapshot.getCell(cellIndex); cellBoundsChanged = cellBoundsChanged || cellBounds[cellIndex] != snapshot.getCellBounds(cellIndex); } if (!cellsChanged) cellBackups = null; if (!cellBoundsChanged) cellBounds = null; setSnapshot(snapshot.withTechPool(techPool).with(changingTool, cellBackups, cellBounds, libBackups), true);// long endTime = System.currentTimeMillis();// if (Job.getDebug()) System.out.println("backup took: " + (endTime - startTime) + " msec"); return snapshot; } /** * Force database to specified state. * This method can recover currupted database. * @param snapshot snapshot to recover. */ public void recover(Snapshot snapshot) { long startTime = System.currentTimeMillis(); setSnapshot(snapshot, false); recoverLibraries(); recycleCells(); BitSet recovered = new BitSet(); for (CellBackup newBackup: snapshot.cellBackups) { if (newBackup != null) recoverRecursively(newBackup.cellRevision.d.cellId, recovered); } for (Library lib: libraries.values()) lib.collectCells(); recoverCellGroups(); snapshotFresh = true; long endTime = System.currentTimeMillis(); if (Job.getDebug()) { System.out.println("recover took: " + (endTime - startTime) + " msec"); checkInvariants(); } } private void recoverRecursively(CellId cellId, BitSet recovered) { int cellIndex = cellId.cellIndex; if (recovered.get(cellIndex)) return; CellBackup newBackup = snapshot.getCell(cellId); CellRevision newRevision = newBackup.cellRevision; for (int i = 0, numUsages = cellId.numUsagesIn(); i < numUsages; i++) { CellUsage u = cellId.getUsageIn(i); if (newRevision.getInstCount(u) <= 0) continue; recoverRecursively(u.protoId, recovered); } Cell cell = getCell(cellId); cell.recover(newBackup, snapshot.getCellBounds(cellId)); recovered.set(cellIndex); } /** * Force database to specified state. * This method assumes that database is in valid state. * @param snapshot snapshot to undo. */ public void undo(Snapshot snapshot) { long startTime = System.currentTimeMillis(); Snapshot oldSnapshot = backup(); if (oldSnapshot == snapshot) return; setSnapshot(snapshot, false); boolean cellGroupsChanged = oldSnapshot.cellGroups != snapshot.cellGroups; if (oldSnapshot.libBackups != snapshot.libBackups) { recoverLibraries(); cellGroupsChanged = true; } recycleCells(); BitSet cellNamesChangedInLibrary = new BitSet(); ImmutableArrayList<CellBackup> cellBackups = snapshot.cellBackups; if (oldSnapshot.cellBackups.size() == cellBackups.size()) { for (int cellIndex = 0; cellIndex < cellBackups.size(); cellIndex++) { CellBackup oldBackup = oldSnapshot.getCell(cellIndex); CellBackup newBackup = snapshot.getCell(cellIndex); if (oldBackup == newBackup) continue; if (oldBackup == null) { cellNamesChangedInLibrary.set(newBackup.cellRevision.d.getLibId().libIndex); assert cellGroupsChanged; } else if (newBackup == null) { cellNamesChangedInLibrary.set(oldBackup.cellRevision.d.getLibId().libIndex); assert cellGroupsChanged;// } else {// boolean moved = oldBackup.d.getLibId() != newBackup.d.getLibId();// if (moved || oldBackup.d.cellName != newBackup.d.cellName) {// cellNamesChangedInLibrary.set(newBackup.d.getLibId().libIndex);// cellNamesChangedInLibrary.set(oldBackup.d.getLibId().libIndex);// }// if (moved)// cellGroupsChanged = true; } } } else { cellGroupsChanged = true; if (snapshot.libBackups.size() > 0) // Bug in BitSet.set(int,int) on Sun JDK cellNamesChangedInLibrary.set(0, snapshot.libBackups.size()); } BitSet updated = new BitSet(); BitSet exportsModified = new BitSet(); BitSet boundsModified = new BitSet(); for (CellBackup newBackup: snapshot.cellBackups) { if (newBackup != null) undoRecursively(oldSnapshot, newBackup.cellRevision.d.cellId, updated, exportsModified, boundsModified); } if (!cellNamesChangedInLibrary.isEmpty()) { for (Library lib: libraries.values()) { if (cellNamesChangedInLibrary.get(lib.getId().libIndex)) lib.collectCells(); } } if (cellGroupsChanged) recoverCellGroups(); snapshotFresh = true; long endTime = System.currentTimeMillis(); if (Job.getDebug()) { System.out.println("undo took: " + (endTime - startTime) + " msec");// checkFresh(snapshot); } } private void undoRecursively(Snapshot oldSnapshot, CellId cellId, BitSet updated, BitSet exportsModified, BitSet boundsModified) { int cellIndex = cellId.cellIndex; if (updated.get(cellIndex)) return; CellBackup newBackup = snapshot.getCell(cellId); CellRevision newRevision = newBackup.cellRevision; assert cellId != null; boolean subCellsExportsModified = false; boolean subCellsBoundsModified = false; for (int i = 0, numUsages = cellId.numUsagesIn(); i < numUsages; i++) { CellUsage u = cellId.getUsageIn(i); if (newRevision.getInstCount(u) <= 0) continue; undoRecursively(oldSnapshot, u.protoId, updated, exportsModified, boundsModified); int subCellIndex = u.protoId.cellIndex; if (exportsModified.get(subCellIndex)) subCellsExportsModified = true; if (boundsModified.get(subCellIndex)) subCellsBoundsModified = true; } Cell cell = getCell(cellId); CellRevision oldRevision = oldSnapshot.getCellRevision(cellId); ERectangle oldBounds = oldSnapshot.getCellBounds(cellId); cell.undo(newBackup, snapshot.getCellBounds(cellId), subCellsExportsModified ? exportsModified : null, subCellsBoundsModified ? boundsModified : null); updated.set(cellIndex); if (oldRevision == null || !newRevision.sameExports(oldRevision)) exportsModified.set(cellIndex); if (oldRevision == null || snapshot.getCellBounds(cellId) != oldBounds) boundsModified.set(cellIndex); } private void recoverLibraries() { while (linkedLibs.size() > snapshot.libBackups.size()) { Library lib = linkedLibs.remove(linkedLibs.size() - 1); if (lib != null) lib.cells.clear(); } while (linkedLibs.size() < snapshot.libBackups.size()) linkedLibs.add(null); for (int libIndex = 0; libIndex < snapshot.libBackups.size(); libIndex++) { LibraryBackup libBackup = snapshot.libBackups.get(libIndex); Library lib = linkedLibs.get(libIndex); if (libBackup == null && lib != null) { linkedLibs.set(libIndex, null); } else if (libBackup != null && lib == null) { linkedLibs.set(libIndex, new Library(this, libBackup.d)); } /* } else { Library lib = linkedLibs.get(libIndex); String libName = lib.getName(); if (!oldBackup.d.libName.equals(libName)) { Cell curCell = lib.getCurCell(); lib.prefs = allPrefs.node(libName); lib.prefs.put("LIB", libName); lib.curCellPref = null; lib.setCurCell(curCell); } */ } libraries.clear(); for (int libIndex = 0; libIndex < snapshot.libBackups.size(); libIndex++) { LibraryBackup libBackup = snapshot.libBackups.get(libIndex); if (libBackup == null) continue; Library lib = linkedLibs.get(libIndex); lib.recover(libBackup); libraries.put(lib.getName(), lib); } /* ??? if (curLib == null || !curLib.isLinked()) { curLib = null; for(Library lib: libraries.values()) { if (lib.isHidden()) continue; curLib = lib; break; } } */ } private void recycleCells() { ImmutableArrayList<CellBackup> cellBackups = snapshot.cellBackups; while (linkedCells.size() > cellBackups.size()) linkedCells.remove(linkedCells.size() - 1); while (linkedCells.size() < cellBackups.size()) linkedCells.add(null); for (int cellIndex = 0; cellIndex < cellBackups.size(); cellIndex++) { CellBackup newBackup = cellBackups.get(cellIndex); Cell cell = linkedCells.get(cellIndex); if (newBackup == null) { if (cell != null) linkedCells.set(cellIndex, null); } else if (cell == null) { linkedCells.set(cellIndex, new Cell(this, newBackup.cellRevision.d)); } } } private void recoverCellGroups() { ArrayList<TreeSet<Cell>> groups = new ArrayList<TreeSet<Cell>>(); for (int cellIndex = 0; cellIndex < snapshot.cellBackups.size(); cellIndex++) { CellBackup cellBackup = snapshot.cellBackups.get(cellIndex); int cellGroupIndex = snapshot.cellGroups[cellIndex]; if (cellBackup == null) continue; if (cellGroupIndex == groups.size()) groups.add(new TreeSet<Cell>()); Cell cell = getCell(cellIndex); assert cell != null; groups.get(cellGroupIndex).add(cell); } for (int i = 0; i < groups.size(); i++) new Cell.CellGroup(groups.get(i)); } /** * Method to check invariants in all Libraries. * @return true if invariants are valid */ public boolean checkInvariants() { try { long startTime = System.currentTimeMillis(); idManager.checkInvariants(); backup(); snapshot.check(); check(); long endTime = System.currentTimeMillis(); float finalTime = (endTime - startTime) / 1000F; if (Job.getDebug()) System.out.println("**** Check Invariants took " + finalTime + " seconds"); return true; } catch (Throwable e) { if (!invariantsFailed) { System.out.println("Exception checking database invariants"); e.printStackTrace(); ActivityLogger.logException(e); invariantsFailed = true; } } return false; } /** * Method to check invariants in this EDatabase. * @exception AssertionError if invariants are not valid */ private void check() { if (snapshotFresh) { assert techPool == snapshot.techPool; assert linkedLibs.size() == snapshot.libBackups.size(); assert linkedCells.size() == snapshot.cellBackups.size(); } for (int libIndex = 0; libIndex < linkedLibs.size(); libIndex++) { Library lib = linkedLibs.get(libIndex); if (lib == null) { if (snapshotFresh) assert snapshot.libBackups.get(libIndex) == null; continue; } assert lib.getId() == getIdManager().getLibId(libIndex); assert libraries.get(lib.getName()) == lib; lib.check(); if (snapshotFresh) assert lib.backup == snapshot.libBackups.get(libIndex); } for (int cellIndex = 0; cellIndex < linkedCells.size(); cellIndex++) { Cell cell = linkedCells.get(cellIndex); if (cell == null) { if (snapshotFresh) assert snapshot.cellBackups.get(cellIndex) == null; continue; } CellId cellId = cell.getId(); assert cellId == idManager.getCellId(cellIndex); Library lib = cell.getLibrary(); assert lib.cells.get(cell.getCellName()) == cell; cell.check(); if (snapshotFresh) { assert cell.cellBackupFresh; assert cell.backup == snapshot.cellBackups.get(cellIndex); assert cell.getBounds() == snapshot.getCellBounds(cellId); cell.checkBoundsCorrect(); } }// TreeSet<String> libNames = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);// for (Map.Entry<String,Library> e : libraries.entrySet()) {// String libName = e.getKey();// Library lib = e.getValue();// assert libName == lib.getName();// assert linkedLibs.get(lib.getId().libIndex) == lib;//// assert !libNames.contains(libName) : "case insensitive " + libName;// libNames.add(libName);// } if (snapshotFresh) { HashMap<Cell.CellGroup,Integer> groupNums = new HashMap<Cell.CellGroup,Integer>(); for (int i = 0; i < snapshot.cellBackups.size(); i++) { CellBackup cellBackup = snapshot.getCell(i); if (cellBackup == null) { assert snapshot.cellGroups[i] == -1; continue; } Cell cell = getCell(cellBackup.cellRevision.d.cellId); Cell.CellGroup cellGroup = cell.getCellGroup(); Integer gn = groupNums.get(cellGroup); if (gn == null) { gn = Integer.valueOf(groupNums.size()); groupNums.put(cellGroup, gn); } int groupIndex = gn.intValue(); assert snapshot.cellGroups[i] == groupIndex; Cell mainSchematics = cellGroup.getMainSchematics(); assert snapshot.groupMainSchematics[groupIndex] == (mainSchematics != null ? mainSchematics.getId() : null); } } } /** * Checks that Electric database has the expected state. * @param expectedSnapshot expected state. */ public void checkFresh(Snapshot expectedSnapshot) { assert snapshotFresh && snapshot == expectedSnapshot; check(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -