⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 garbagecollector.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
    /**
        Checks wether the current transaction has to be committed (because it accumulated too much changes)
        and if so, commits it and closes it. Afterwards (or if there has not been a current transaction already),
        it creates a new current transaction.
    */
    protected void renewTransactionIfRequired() throws IOException,ClassNotFoundException,TransactionException {
        if (actionsWithinTransactionCount>=100) { // We renew if we had 100 or more actions within this transaction.
            completeTransaction();

            env.getLogWriter().newEntry(this,"toBeProcessedCount="+surelyReachableObjectsWhichHaveToBeMarkedAsSuch.size()+".",env.getLogWriter().DEBUG1);

        }

        if (transaction==null) {
            transaction = env.getTransactionManager().newTransaction(env.getUserManager().getGarbageCollectorUser());
        }
    }

    /**
        Completes the current transaction and releases it.
    */
    protected void completeTransaction() throws IOException,ClassNotFoundException {
        if (transaction!=null) {
            internalCompleteTransaction(transaction);
            actionsWithinTransactionCount   =   0;
            env.getTransactionManager().deleteTransaction();
            transaction = null;
        }
    }


    protected void internalCompleteTransaction(Transaction transaction) throws IOException,ClassNotFoundException {
        boolean allright = false;
        try {
            transaction.prepareCommit();
            allright = true;
        } finally {
            if (!allright) {
                internalAbortTransaction(transaction);
            }
        }

        internalFinishTransaction(transaction);
    }

    protected void internalFinishTransaction(Transaction transaction) throws IOException,ClassNotFoundException {
        TransactionManager transactionManager = transaction.getManager();

        try {
            transactionManager.beginExclusion();
            transaction.commit();
        } finally {
            transactionManager.endExclusion();
            transactionManager.notifyWaitingTransactions();
        }
    }

    protected void internalAbortTransaction(Transaction transaction) throws IOException,ClassNotFoundException {
        TransactionManager transactionManager = transaction.getManager();
        try {
            transactionManager.beginExclusion();
            transaction.abort(null);
        } finally {
            transactionManager.endExclusion();
            transactionManager.notifyWaitingTransactions();
        }
    }

    protected synchronized void setPhase(int to) {
        phase = to;
        env.getLogWriter().newEntry(this,"setPhase("+to+")",env.getLogWriter().DEBUG2);
    }

    protected synchronized void waitForPhase(int newPhase) throws InterruptedException {
        while (phase!=newPhase) {
            wait();
        }
    }

    protected void addRootSetElementsToSurelyReachableSet() {
        startFilterDatabaseObjectReferencesAtExternalDatabaseGates();
        addAllNamedObjectsToSurelyReachableSet();
    }


    protected void startFilterDatabaseObjectReferencesAtExternalDatabaseGates() {
        env.getInvokeServer().startFilterDatabaseObjectReferencesExports(this);
        env.getLocalClientTracker().startFilterDatabaseObjectReferencesExports(this);
    }

    public void notifyDatabaseObjectIsExported(ObjectID id) {
        notifyDatabaseObjectIsAboutToBeExported(id);
    }

    /**
        This method is called by DbInvokeClient to notify this garbageCollector
        that there is a reference which is to be exported to a client.
    */
    public void notifyDatabaseObjectIsAboutToBeExported(ObjectID id) {
        // These object referenced belong, because they are used, to the surelyReachable set.
        ensureSurelyReachable(id);
    }

    /**
        This method walks through all named objects and adds each of them to the surelyReachable set.
    */
    protected void addAllNamedObjectsToSurelyReachableSet() {
        env.getStoreManager().reportNamedObjectsToGarbageCollector();
    }

    /**
        This method is called by StoreManager to indicate that the object
        with the given id is a named object.
    */
    public void notifyNamedObject(ObjectID id) {
        ensureSurelyReachable(id);
    }

    /**
        This method is called by StoreManager in the event an unnamed object receives a name.
        This is the case if an object which was formerly unnamed gets a name.
    */
    public void notifyNewObjectName(ObjectContainer objectContainer) {
        ensureSurelyReachable(objectContainer);
    }

    /**
        This method is called by StoreManager in the event an object is freshly created.
    */
    public void notifyNewObjectContainer(/*Transaction transaction,*/ObjectContainer objectContainer) {
        ensureDoneReachable(/*transaction,*/objectContainer);
    }

    /**
        Calling this method makes sure that the object which is referenced by the given ID is
        at least surely reachable.
    */
    protected void ensureSurelyReachable(ObjectID id) {
        synchronized (this) {
            if (isRunning()) {
                addObjectIDToSurelyReachableObjectsWhichHaveToBeMarkedAsSuch(id);
            }
        }
    }

    /**
        This method may be called both from transaction threads and from GarbageCollector-Threads.
    */
    protected void addObjectIDToSurelyReachableObjectsWhichHaveToBeMarkedAsSuch(ObjectID id) {
        synchronized (surelyReachableObjectsWhichHaveToBeMarkedAsSuch) {
//          env.getLogWriter().newEntry(this,"addObjectID(): adding "+id+".",new Exception(),env.getLogWriter().DEBUG3);
            surelyReachableObjectsWhichHaveToBeMarkedAsSuch.push(id);
        }
    }

    /**
        Calling this method makes sure that the object which is referenced by the given ID is
        at least surely reachable. This method is called by non-GarbageCollector-Threads.
    */
    protected void ensureSurelyReachable(ObjectContainer objectContainer) {
        // This is not possible because processing has to be done within a GarbageCollector transaction and not within any other transaction.
        /*
        objectContainer.pin();
        processObjectContainerWhichWantsToBeSurelyReachable(objectContainer);
        */
        addObjectIDToSurelyReachableObjectsWhichHaveToBeMarkedAsSuch(objectContainer.id());
    }

    /**
        Returns wether this GarbageCollector is running. This method
        must be called during synchronization on this GarbageCollector.
    */
    protected boolean isRunning() {
        return phase!=PHASE_IDLE;
    }

    /**
        This is the "main()" method of the mark phase.
    */
    protected void processSurelyReachableObjectsWhichHaveToBeMarkedAsSuch() {
        ObjectID id;

        int surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContentedSize = -1;

        retryLoop:
        for (;;) {
            for (;;) {
                if (kill) {
                    break retryLoop;
                }
                synchronized (surelyReachableObjectsWhichHaveToBeMarkedAsSuch) {
                    id = (ObjectID) surelyReachableObjectsWhichHaveToBeMarkedAsSuch.pop();
                }

                if (id==null) {
                    break;
                }

                try {
                    /*
                    ObjectContainer container = env.getStoreManager().containerForID(null,id);

                    processObjectContainerWhichWantsToBeSurelyReachable(container);
                    */

                    // We should acquire the container via our transaction
                    notifyAboutTransactionActionAndRenewTransactionIfRequired();

//                  env.getLogWriter().newEntry(this,"process(): processing "+id+".",env.getLogWriter().DEBUG3);

                    ObjectContainer container = transaction.acquireObject(id,Lock.LEVEL_READ);

                    processObjectContainerWhichWantsToBeSurelyReachable(transaction,container);
//              } catch (ObjNotFoundException e) {
                } catch (ObjectNotFoundException e) {
                } catch (ClassNotFoundException e) {
                } catch (IOException e) {
                    // It does not matter if the object is gone in the meantime. This is the best case for a garbage collector :-)
                } catch (TransactionException e) {
                    env.getLogWriter().newEntry(this,"caught: ",e,env.getLogWriter().ERROR);
                    // FIXME. What do we in this case?
                }
            }

            boolean waitRecommended;

            synchronized (surelyReachableObjectsWhichHaveToBeMarkedAsSuch) {
                waitRecommended = surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContentedSize==surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContented.size();

                surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContentedSize = surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContented.size();

                while (!surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContented.isEmpty()) {
                    surelyReachableObjectsWhichHaveToBeMarkedAsSuch.push(surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContented.getFirst());
                }
            }

            if (surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContentedSize>0) {
                if (waitRecommended) {
                    try {
                        try {
                            completeTransaction(); // We should finish our transaction so that other transactions may complete.
                        } catch (ClassNotFoundException e) {
                            env.getLogWriter().newEntry(this,"caught: ",e,env.getLogWriter().ERROR);
                        } catch (IOException e) {
                            env.getLogWriter().newEntry(this,"caught: ",e,env.getLogWriter().ERROR);
                        }

                        // We're waiting less if there are more lock-contented objects, but at least 100ms
                        Thread.sleep(100+2000/(surelyReachableObjectsWhichShouldHaveBeenProcessedButWereLockContentedSize));
                    } catch (InterruptedException e) {
                    }
                }
            } else {
                break;
            }
        }

        try {
            completeTransaction();
        } catch (ClassNotFoundException e) {
            env.getLogWriter().newEntry(this,"caught: ",e,env.getLogWriter().ERROR);
        } catch (IOException e) {
            env.getLogWriter().newEntry(this,"caught: ",e,env.getLogWriter().ERROR);
        }
        // Pheew. We're done. Now sweep the unreachable objects.
    }

    /**
        Internally ensures that the given object is at least surelyReachable.

        @return
            <0 if this object has been updated. If this is the case, this object has to join a transaction which will complete successfully.
            =0 if this object has not been updated, it is surelyReachable
            >0 if this object has not been updated, it is processedReachable
    */
    protected int internalEnsureSurelyReachable(ObjectContainer objectContainer) {
        synchronized (garbageCollectionLevelsLock) {
            return objectContainer.ensureGarbageCollectionLevel(currentGarbageCollectionLevel);
        }
    }

    /**
        Ensures that the given object is doneReachable.
    */
    protected void ensureDoneReachable(/*Transaction transaction,*/ObjectContainer objectContainer) {
        internalEnsureDoneReachable(objectContainer);
    }

    /**
        Internally ensures that the given object is doneReachable.
    */
    protected void internalEnsureDoneReachable(ObjectContainer objectContainer) {
        synchronized (garbageCollectionLevelsLock) {
            objectContainer.ensureGarbageCollectionLevel(doneReachableGarbageCollectionLevel);
        }
    }


    /**
     *   Processes an ObjectContainer which possibly has not already been registered as surely reachable.
     *   This method may be called only by the garbage collector thread.
     *
     * @param transaction
     * @param objectContainer
     */
    protected void processObjectContainerWhichWantsToBeSurelyReachable(Transaction transaction,ObjectContainer objectContainer) {
        try {
            int difference = internalEnsureSurelyReachable(objectContainer);

//          env.getLogWriter().newEntry(this,"processObjectContainerWhichWantsToBeSurelyReachable("+objectContainer+"), difference="+difference+".",env.getLogWriter().DEBUG3);

            if (difference<=0) {
                processReferencesByThisObject(transaction,objectContainer);
            }
        } finally {
            objectContainer.unpin();
        }
    }

    /**
        Determines all references which are "contained" within the given object,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -