public synchronized void gridletMove(int gridletId, int userId, int destId, boolean ack)
	    {
	        // cancels the Gridlet
	        ResGridlet rgl = cancel(gridletId, userId);

	        // if the Gridlet is not found
	        if (rgl == null)
	        {
	        	logger.log(Level.INFO, super.resName_ +
	                       ".PerfectCheckpointing.gridletMove(): Cannot find " +
	                       "Gridlet #" + gridletId + " for User #" + userId);

	            if (ack)   // sends back an ack if required
	            {
	                super.sendAck(GridSimTags.GRIDLET_SUBMIT_ACK, false,
	                              gridletId, userId);
	            }

	            return;
	        }

	        // if the Gridlet has finished beforehand
	        if (rgl.getGridletStatus() == Gridlet.SUCCESS)
	        {
	        	logger.log(Level.INFO, super.resName_
	                + ".PerfectCheckpointing.gridletMove(): Cannot move Gridlet #"
	                + gridletId + " for User #"+ userId+ " since it has FINISHED.");

	            if (ack) // sends back an ack if required
	            {
	                super.sendAck(GridSimTags.GRIDLET_SUBMIT_ACK, false,
	                              gridletId, userId);
	            }

	            gridletFinish(rgl, Gridlet.SUCCESS);
	        }
	        else   // otherwise moves this Gridlet to a different GridResource
	        {
	            rgl.finalizeGridlet();

	            // Set PE on which Gridlet finished to FREE
	            super.resource_.setStatusPE( PE.FREE, rgl.getMachineID(),
	                                         rgl.getPEID() );

	            super.gridletMigrate(rgl.getGridlet(), destId, ack);
	            allocateQueueGridlet();
	        }
	    }