public synchronized ReservationMessage createReservation(ReservationMessage message) {
		Reservation reserv = message.getReservation();
		ServerReservation sRes = new ServerReservation(reserv); 
		
    	//-------------- FOR DEBUGGING PURPOSES ONLY ---------------
		visualizer.notifyListeners(this.get_id(), ActionType.ITEM_ARRIVED, true, sRes);
        //----------------------------------------------------------

		ReservationMessage response = message.createResponse(); // creates a response

		if(!validateReservation(sRes)) {
    	    reserv.setStatus(ReservationStatus.FAILED);
        	response.setErrorCode(ErrorType.OPERATION_FAILURE);
        	return response;
		}

        double currentTime = GridSim.clock();
		double startTime = Math.max(reserv.getStartTime(), currentTime);
		//TODO: To check this exptime (Marcos)
		double expTime = sRes.getActualFinishTime();
		int duration = reserv.getDurationTime();
        sRes.setStartTime(startTime);
        
        // check the availability in the profile
        ProfileEntry entry = profile.checkAvailability(reserv.getNumPE(), startTime, duration);

        // if entry is null, it means that there are not enough PEs 
        if(entry == null) {
        	logger.warning("Reservation #" + reserv.getID() + " from " + 
        			GridSim.getEntityName(message.getSourceID()) + 
        			" user requires " + reserv.getNumPE() + 
	                " PEs from " + startTime + " to " + (startTime + duration) + 
        			" could not be accepted");

        	// the availability information is passed as scheduling options
        	Collection<TimeSlot> availability = getReservationAlternatives(sRes);
        	reserv.setStatus(ReservationStatus.FAILED);
        	
        	if(availability != null) {
        		reserv.setReservationOptions(availability);
        		response.setErrorCode(ErrorType.OPERATION_FAILURE_BUT_OPTIONS);
        	} else {
        		response.setErrorCode(ErrorType.OPERATION_FAILURE);
        	}
        } else { 
            PERangeList selected = entry.getAvailRanges().selectPEs(reserv.getNumPE());
            profile.allocatePERanges(selected, startTime, sRes.getExpectedFinishTime());
            sRes.setPERangeList(selected);
            
            if(Double.compare(currentTime, startTime)  == 0) {
    	        // if start time = current time, reservation is immediate. A event
            	// is scheduled to start the reservation and it commits the reservation
	        	sRes.setStatus(ReservationStatus.COMMITTED);
		        super.sendInternalEvent(GridSimTags.SCHEDULE_NOW, ConservativeBackfill.UPT_SCHEDULE);
	        } else {
                // expiration time is used only for non-immediate reservations
                // expiry time can't be greater than the reservation's start time
            	expTime = Math.min(startTime, currentTime + commitPeriod);
            	
            	sRes.setStatus(ReservationStatus.NOT_COMMITTED);
		        // to check for expired reservations
		        super.sendInternalEvent(expTime - currentTime, EXPIRY_TIME);
	        }
	        
	        sRes.setExpiryTime(expTime);
	        reservTable.put(new Integer(sRes.getID()), sRes);

	        //-------------- FOR DEBUGGING PURPOSES ONLY  --------------
	        visualizer.notifyListeners(this.get_id(), ActionType.ITEM_SCHEDULED, true, sRes);
	        //----------------------------------------------------------
        }
        
    	return response;
	}