diff --git a/beat/web/experiments/migrations/0007_auto_20160701_0909.py b/beat/web/experiments/migrations/0007_auto_20160701_0909.py new file mode 100644 index 0000000000000000000000000000000000000000..5ba8c8ed0faa66cacf6a1ee299d618521a281237 --- /dev/null +++ b/beat/web/experiments/migrations/0007_auto_20160701_0909.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2016-07-01 09:09 +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings + +import simplejson +import beat.core.experiment +from ...common import storage + + +def set_block_order(apps, schema_editor): + '''Set block order for existing experiments''' + + Experiment = apps.get_model("experiments", "Experiment") + Block = apps.get_model("experiments", "Block") + + total = Experiment.objects.count() + for i, e in enumerate(Experiment.objects.order_by('id')): + + fullname = '%s/%s/%s/%d/%s' % ( + e.author.username, + e.toolchain.author.username, + e.toolchain.name, + e.toolchain.version, + e.name, + ) + + print("Updating blocks for experiment %d/%d (%s, id=%d)..." % \ + (i+1, total, fullname, e.id)) + + xp_decl = simplejson.loads(storage.get_file_content(e, + 'declaration_file')) + tc_decl = simplejson.loads(storage.get_file_content(e.toolchain, + 'declaration_file')) + + xp = beat.core.experiment.Experiment(settings.PREFIX, (xp_decl, + tc_decl)) + + if xp.errors: + message = "The experiment `%s' isn't valid (skipping " \ + "block update), due to the following errors:\n * %s" + print message % (fullname, '\n * '.join(xp.errors)) + continue + + # Goes, in order, setting block inner order + for order_0, block_name in enumerate(xp.setup().keys()): + + block = Block.objects.get(experiment=e, name=block_name) + block.execution_order = order_0 + 1 + block.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('experiments', '0006_auto_20160630_1644'), + ] + + operations = [ + migrations.AddField( + model_name='block', + name='execution_order', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AlterModelOptions( + name='block', + options={'ordering': ['experiment_id', 'execution_order']}, + ), + migrations.RunPython(set_block_order), + ] diff --git a/beat/web/experiments/models.py b/beat/web/experiments/models.py index b720441fb0da8a88a6f6886ca5e6c486ecb61279..c24da7822ac37f256780f825f500a30b67783c8b 100644 --- a/beat/web/experiments/models.py +++ b/beat/web/experiments/models.py @@ -506,7 +506,8 @@ class Experiment(Shareable): # Loads the experiment execution description, creating the Block's, # BlockInput's and BlockOutput's as required. - for block_name, description in corexp.setup().items(): + for order_0, (block_name, description) in \ + enumerate(corexp.setup().items()): # Checks that the Queue/Environment exists job_description = description['configuration'] @@ -553,6 +554,7 @@ class Experiment(Shareable): b = Block(experiment=self, name=block_name, algorithm=algorithm) else: b.algorithm = algorithm + b.execution_order = order_0 + 1 b.command=simplejson.dumps(job_description, indent=4) b.status=Block.NOT_CACHED b.analyzer=algorithm.analysis() @@ -919,6 +921,10 @@ class Block(models.Model): symmetrical=False, ) + # order of this block within the experiment - useful for the `backup' + # command, so we can dump the blocks in the right dependence order + execution_order = models.PositiveIntegerField(null=True, blank=True) + objects = BlockManager() @@ -926,7 +932,7 @@ class Block(models.Model): unique_together = ('experiment', 'name') # setup ordering so that the dump order respects self dependencies - ordering = ['id'] + ordering = ['experiment_id', 'execution_order'] def __str__(self):