Revision 2a3f6a3e snf-quotaholder-app/quotaholder_django/quotaholder_app/callpoint.py

b/snf-quotaholder-app/quotaholder_django/quotaholder_app/callpoint.py
43 43
    Callpoint, CorruptedError, InvalidDataError, ReturnButFail)
44 44
from synnefo.lib.commissioning.utils.newname import newname
45 45

  
46
from django.db.models import Q
46
from django.db.models import Q, Count
47 47
from django.db import transaction
48 48
from .models import (Entity, Policy, Holding,
49 49
                     Commission, Provision, ProvisionLog, CallSerial,
......
478 478
        rejected = []
479 479
        append = rejected.append
480 480

  
481
        q_holdings = Q()
482
        entities = []
483
        for (entity, resource, key, _, _, _, _, _) in set_quota:
484

  
485
            q_holdings |= Q(entity=entity, resource=resource)
486
            entities.append(entity)
487

  
488
        hs = Holding.objects.filter(q_holdings).select_for_update()
489
        holdings = {}
490
        for h in hs:
491
            holdings[(h.entity_id, h.resource)] = h
492

  
493
        entities = Entity.objects.in_bulk(entities)
494

  
495
        old_policies = []
496

  
481 497
        for (entity, resource, key,
482 498
             quantity, capacity,
483 499
             import_limit, export_limit, flags) in set_quota:
484 500

  
485
            try:
486
                e = Entity.objects.get(entity=entity, key=key)
487
            except Entity.DoesNotExist:
501
            e = entities.get(entity, None)
502
            if e is None or e.key != key:
488 503
                append((entity, resource))
489 504
                continue
490 505

  
......
496 511
                          export_limit=export_limit)
497 512

  
498 513
            try:
499
                h = db_get_holding(entity=entity, resource=resource,
500
                                   for_update=True)
501
                p = h.policy
514
                h = holdings[(entity, resource)]
515
                old_policies.append(h.policy_id)
502 516
                h.policy = newp
503 517
                h.flags = flags
504
            except Holding.DoesNotExist:
518
            except KeyError:
505 519
                h = Holding(entity=e, resource=resource,
506 520
                            policy=newp, flags=flags)
507
                p = None
508 521

  
509 522
            # the order is intentionally reversed so that it
510 523
            # would break if we are not within a transaction.
511 524
            # Has helped before.
512 525
            h.save()
513 526
            newp.save()
527
            holdings[(entity, resource)] = h
514 528

  
515
            if p is not None and p.holding_set.count() == 0:
516
                p.delete()
529
        objs = Policy.objects.annotate(refs=Count('holding'))
530
        objs.filter(policy__in=old_policies, refs=0).delete()
517 531

  
518 532
        if rejected:
519 533
            raise ReturnButFail(rejected)
......
536 550
            except CallSerial.DoesNotExist:
537 551
                pass
538 552

  
553
        sources = sub_quota + add_quota
554
        q_holdings = Q()
555
        entities = []
556
        for (entity, resource, key, _, _, _, _) in sources:
557

  
558
            q_holdings |= Q(entity=entity, resource=resource)
559
            entities.append(entity)
560

  
561
        hs = Holding.objects.filter(q_holdings).select_for_update()
562
        holdings = {}
563
        for h in hs:
564
            holdings[(h.entity_id, h.resource)] = h
565

  
566
        entities = Entity.objects.in_bulk(entities)
567

  
568
        pids = [h.policy_id for h in hs]
569
        policies = Policy.objects.in_bulk(pids)
570

  
571
        old_policies = []
572

  
539 573
        for removing, source in [(True, sub_quota), (False, add_quota)]:
540 574
            for (entity, resource, key,
541 575
                 quantity, capacity,
542 576
                 import_limit, export_limit) in source:
543 577

  
544
                try:
545
                    e = Entity.objects.get(entity=entity, key=key)
546
                except Entity.DoesNotExist:
578
                e = entities.get(entity, None)
579
                if e is None or e.key != key:
547 580
                    append((entity, resource))
548 581
                    continue
549 582

  
550 583
                try:
551
                    h = db_get_holding(entity=entity, resource=resource,
552
                                       for_update=True)
553
                    p = h.policy
554
                except Holding.DoesNotExist:
584
                    h = holdings[(entity, resource)]
585
                    old_policies.append(h.policy_id)
586
                    try:
587
                        p = policies[h.policy_id]
588
                    except KeyError:
589
                        raise AssertionError("no policy %s" % h.policy_id)
590
                except KeyError:
555 591
                    if removing:
556 592
                        append((entity, resource))
557 593
                        continue
......
583 619
                # Has helped before.
584 620
                h.save()
585 621
                newp.save()
622
                policies[policy] = newp
623
                holdings[(entity, resource)] = h
586 624

  
587
                if p is not None and p.holding_set.count() == 0:
588
                    p.delete()
625
        objs = Policy.objects.annotate(refs=Count('holding'))
626
        objs.filter(policy__in=old_policies, refs=0).delete()
589 627

  
590 628
        if rejected:
591 629
            raise ReturnButFail(rejected)

Also available in: Unified diff