diff --git a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py index 248d0e5a0786d59f6e11a5f59327d46839f6a13f..ed3d7ba68e196cc9ce5fe28f28d3351d564e05b8 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py +++ b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb.py @@ -424,6 +424,13 @@ class RADatabase: return self.cursor.rowcount > 0 def updateTask(self, task_id, mom_id=None, otdb_id=None, task_status=None, task_type=None, specification_id=None, commit=True): + '''Update the given paramenters for the task with given task_id. + Inside the database consistency checks are made. + When one or more claims of a task are in conflict status, then its task is set to conflict as well, and hence cannot be scheduled. + When all claims of a task are not in conflict status anymore, then the task is set to approved, and hence it is possible the schedule the task. + + When a task is unscheduled (set to approved) then the claimed claims are set to tentative. + ''' task_status, task_type = self._convertTaskTypeAndStatusToIds(task_status, task_type) fields = [] @@ -1265,6 +1272,16 @@ class RADatabase: def updateResourceClaims(self, where_resource_claim_ids=None, where_task_ids=None, resource_id=None, task_id=None, starttime=None, endtime=None, status=None, claim_size=None, username=None, used_rcus=None, user_id=None, commit=True): + '''Update the given paramenters on all resource claims given/delimited by where_resource_claim_ids and/or where_task_ids. + Inside the database consistency checks are made. For example, in case you want to set a claim's status to 'claimed', but it does not fit in the free capacity of the claim's resource, then the claim goes to 'conflict'. + + A claim fits, (and hence can be claimed) only if the claim_size < resource.free_capacity within the claims time window. + When a claim is released (claimed->tentative) then all overlapping conflicting claims are checked again if they fit because there is more capacity available. + When a claim is claimed (tentative->claimed) then all overlapping tentative claims are checked again if they still fit because there is less capacity available. + + When one or more claims of a task are in conflict status, then its task is set to conflict as well, and hence cannot be scheduled. + When all claims of a task are not in conflict status anymore, then the task is set to approved, and hence it is possible the schedule the task. + ''' logger.info("updateResourceClaims") status_id = status @@ -1347,6 +1364,7 @@ class RADatabase: def updateTaskAndResourceClaims(self, task_id, starttime=None, endtime=None, task_status=None, claim_status=None, username=None, used_rcus=None, user_id=None, commit=True): + '''combination of updateResourceClaims and updateTask in one transaction''' updated = True if (starttime or endtime or claim_status is not None or diff --git a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql index 4b7ae66d01fb0adfb2c39e4f11bb701c1d2b545e..eabae3893ccaafc09d95e67f17935f7eb27daa30 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql +++ b/SAS/ResourceAssignment/ResourceAssignmentDatabase/radb/sql/add_functions_and_triggers.sql @@ -391,6 +391,7 @@ BEGIN WHERE ru.resource_id = old_claim.resource_id AND ru.status_id = old_claim.status_id AND ru.as_of_timestamp < old_claim.starttime + ORDER BY ru.as_of_timestamp DESC LIMIT 1 INTO usage_before_start; @@ -517,7 +518,7 @@ BEGIN -- this function is quite similar to resource_allocation.get_conflicting_overlapping_claims -- for performance reasons we repeat the common code here instead of wrapping the common code in a function - --get all overlapping_claims, whether they cause a conflict or not. + --get all overlapping_claims, check whether they cause a conflict or not. SET LOCAL client_min_messages=warning; --prevent "table overlapping_claims does not exist, skipping" message DROP TABLE IF EXISTS overlapping_claims; -- TODO: use CREATE TEMPORARY TABLE IF NOT EXISTS when we will use postgres 9.5+ CREATE TEMPORARY TABLE overlapping_claims @@ -527,13 +528,14 @@ BEGIN AND rc.status_id = claim_claimed_status_id AND rc.id <> claim.id AND rc.endtime >= claim.starttime - AND rc.starttime <= claim.endtime; + AND rc.starttime < claim.endtime; --get the full time window of the overlapping claims SELECT min(starttime) FROM overlapping_claims INTO overlapping_claims_min_starttime; - SELECT max(starttime) FROM overlapping_claims INTO overlapping_claims_max_endtime; + SELECT max(endtime) FROM overlapping_claims INTO overlapping_claims_max_endtime; -- get the free free_claimable_capacity for this resource for the full overlapping claim time window + -- this does not include the current claim which is (or at least should be) tentative. SELECT * FROM resource_allocation.get_resource_claimable_capacity_between(claim.resource_id, overlapping_claims_min_starttime, overlapping_claims_max_endtime) INTO free_claimable_capacity; return claim.claim_size > free_claimable_capacity; @@ -541,7 +543,7 @@ END; $$ LANGUAGE plpgsql; ALTER FUNCTION resource_allocation.has_conflict_with_overlapping_claims(claim resource_allocation.resource_claim) OWNER TO resourceassignment; COMMENT ON FUNCTION resource_allocation.has_conflict_with_overlapping_claims(claim resource_allocation.resource_claim) - IS 'helper function which is called by resource_claim table insert and update triggers, which checks if the new claim fits in the free capacity of its resource.'; + IS 'checks if the claim fits in the free capacity of its resource.'; --------------------------------------------------------------------------------------------------------------------- @@ -574,7 +576,7 @@ BEGIN -- this function is quite similar to resource_allocation.has_conflict_with_overlapping_claims -- for performance reasons we repeat the common code here instead of wrapping the common code in a function - --get all overlapping_claims, whether they cause a conflict or not. + --get all overlapping_claims, check whether they cause a conflict or not. SET LOCAL client_min_messages=warning; --prevent "table overlapping_claims does not exist, skipping" message DROP TABLE IF EXISTS overlapping_claims; -- TODO: use CREATE TEMPORARY TABLE IF NOT EXISTS when we will use postgres 9.5+ CREATE TEMPORARY TABLE overlapping_claims @@ -584,7 +586,7 @@ BEGIN AND rc.status_id = claim_claimed_status_id AND rc.id <> claim.id AND rc.endtime >= claim.starttime - AND rc.starttime <= claim.endtime; + AND rc.starttime < claim.endtime; RETURN QUERY SELECT * FROM overlapping_claims oc @@ -630,7 +632,7 @@ BEGIN END IF; IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN - --only check claim if in tentative/conflict status, and status or start/end time changed + --only check claim if in tentative/conflict status, and status or claim_size or start/end time changed IF NEW.status_id = claim_tentative_status_id OR NEW.status_id = claim_conflict_status_id THEN IF TG_OP = 'INSERT' OR (TG_OP = 'UPDATE' AND (OLD.status_id <> NEW.status_id OR OLD.claim_size <> NEW.claim_size OR @@ -712,14 +714,14 @@ BEGIN -- if this claim was moved or went from claimed to other status -- then check all other claims in conflict which might be affected by this change -- maybe they can be updated from conflict status to tentative... - IF (TG_OP = 'UPDATE' AND (OLD.status_id = claim_claimed_status_id OR OLD.starttime <> NEW.starttime OR OLD.endtime <> NEW.endtime)) OR + IF (TG_OP = 'UPDATE' AND (OLD.status_id = claim_claimed_status_id OR OLD.starttime <> NEW.starttime OR OLD.endtime <> NEW.endtime OR OLD.claim_size <> NEW.claim_size)) OR TG_OP = 'DELETE' THEN FOR affected_claim IN SELECT * FROM resource_allocation.resource_claim rc WHERE rc.resource_id = OLD.resource_id AND rc.status_id = claim_conflict_status_id AND rc.id <> OLD.id AND rc.endtime >= OLD.starttime - AND rc.starttime <= OLD.endtime LOOP + AND rc.starttime < OLD.endtime LOOP --check if claim fits or has conflicts SELECT * FROM resource_allocation.has_conflict_with_overlapping_claims(affected_claim) INTO claim_has_conflicts; @@ -734,13 +736,13 @@ BEGIN -- if this claim went from to claimed status -- then check all other claims in tentative state which might be affected by this change -- maybe they should be updated from tentative status to conflict... - IF TG_OP = 'UPDATE' AND NEW.status_id = claim_claimed_status_id AND OLD.status_id <> NEW.status_id THEN + IF TG_OP = 'UPDATE' AND NEW.status_id = claim_claimed_status_id AND (OLD.status_id <> NEW.status_id OR OLD.claim_size <> NEW.claim_size)THEN FOR affected_claim IN SELECT * FROM resource_allocation.resource_claim rc WHERE rc.resource_id = NEW.resource_id AND rc.status_id = claim_tentative_status_id AND rc.id <> NEW.id AND rc.endtime >= NEW.starttime - AND rc.starttime <= NEW.endtime LOOP + AND rc.starttime < NEW.endtime LOOP --check if claim fits or has conflicts SELECT * FROM resource_allocation.has_conflict_with_overlapping_claims(affected_claim) INTO claim_has_conflicts;