From dcb3152ec5ce2a91033289c9d4c8db645976f769 Mon Sep 17 00:00:00 2001 From: Dana Van Aken Date: Wed, 9 Oct 2019 00:15:31 -0400 Subject: [PATCH] Added valid target objectives to the session create/edit form --- server/website/tests/test_parser.py | 2 +- server/website/tests/test_views.py | 2 +- server/website/website/db/base/parser.py | 2 +- .../website/db/base/target_objective.py | 19 +++++++++- server/website/website/db/myrocks/parser.py | 2 +- server/website/website/forms.py | 38 +++++++++++++------ server/website/website/models.py | 4 +- server/website/website/views.py | 2 +- 8 files changed, 51 insertions(+), 20 deletions(-) diff --git a/server/website/tests/test_parser.py b/server/website/tests/test_parser.py index a96ddeb..82c5e13 100644 --- a/server/website/tests/test_parser.py +++ b/server/website/tests/test_parser.py @@ -254,7 +254,7 @@ class PostgresParserTests(BaseParserTests, TestCase): super().test_convert_dbms_metrics() target_obj = target_objectives.THROUGHPUT - target_obj_instance = target_objectives.get_target_objective_instance( + target_obj_instance = target_objectives.get_instance( self.test_dbms.dbms_id, target_obj) txns_counter = target_obj_instance.transactions_counter diff --git a/server/website/tests/test_views.py b/server/website/tests/test_views.py index ab7e842..c9bf295 100644 --- a/server/website/tests/test_views.py +++ b/server/website/tests/test_views.py @@ -143,7 +143,7 @@ class SessionViewsTests(TestCase): 'name': 'test_create_basic_session', 'description': 'testing create basic session...', 'tuning_session': 'no_tuning_session', - 'target_objective': target_objectives.get_default_target_objective(), + 'target_objective': target_objectives.default(), 'algorithm': 1, 'cpu': '2', 'memory': '16', diff --git a/server/website/website/db/base/parser.py b/server/website/website/db/base/parser.py index 1d624d5..216905b 100644 --- a/server/website/website/db/base/parser.py +++ b/server/website/website/db/base/parser.py @@ -197,7 +197,7 @@ class BaseParser: raise ValueError( 'Unknown metric type for {}: {}'.format(name, metadata.metric_type)) - target_objective_instance = target_objectives.get_target_objective_instance( + target_objective_instance = target_objectives.get_instance( self.dbms_id, target_objective) metric_data[target_objective] = target_objective_instance.compute( base_metric_data, observation_time) diff --git a/server/website/website/db/base/target_objective.py b/server/website/website/db/base/target_objective.py index 6968762..21c1e3d 100644 --- a/server/website/website/db/base/target_objective.py +++ b/server/website/website/db/base/target_objective.py @@ -4,6 +4,7 @@ # Copyright (c) 2017-18, Carnegie Mellon University Database Group # +import copy import logging from collections import OrderedDict @@ -44,6 +45,10 @@ class BaseTargetObjective(BaseMetric): super().__init__(name=name, pprint=pprint, unit=unit, short_unit=short_unit, improvement=improvement, scale=scale) + @property + def label(self): + return '{} ({})'.format(self.pprint, self.short_unit) + def compute(self, metrics, observation_time): raise NotImplementedError() @@ -106,16 +111,26 @@ class TargetObjectives: metadata.insert(0, (target_objective, target_objective_instance)) return OrderedDict(metadata) - def get_default_target_objective(self): + def default(self): return self._default_target_objective - def get_target_objective_instance(self, dbms_id, target_objective): + def get_instance(self, dbms_id, target_objective): if not self.registered(): self.register() dbms_id = int(dbms_id) instance = self._registry[dbms_id][target_objective] return instance + def get_all(self, dbms_id=None): + if not self.registered(): + self.register() + if dbms_id is None: + res = copy.deepcopy(self._registry) + else: + dbms_id = int(dbms_id) + res = copy.deepcopy(self._registry[dbms_id]) + return res + def __repr__(self): s = 'TargetObjectives = (\n' for dbms_id, entry in self._registry.items(): # pylint: disable=not-an-iterable diff --git a/server/website/website/db/myrocks/parser.py b/server/website/website/db/myrocks/parser.py index c3fb6f0..114a599 100644 --- a/server/website/website/db/myrocks/parser.py +++ b/server/website/website/db/myrocks/parser.py @@ -169,7 +169,7 @@ class MyRocksParser(BaseParser): raise ValueError( 'Unknown metric type for {}: {}'.format(name, metadata.metric_type)) - target_objective_instance = target_objectives.get_target_objective_instance( + target_objective_instance = target_objectives.get_instance( self.dbms_id, target_objective) metric_data[target_objective] = target_objective_instance.compute( base_metric_data, observation_time) diff --git a/server/website/website/forms.py b/server/website/website/forms.py index c463a2e..ee21cdd 100644 --- a/server/website/website/forms.py +++ b/server/website/website/forms.py @@ -3,13 +3,10 @@ # # Copyright (c) 2017-18, Carnegie Mellon University Database Group # -''' -Created on Jul 25, 2017 -@author: dvanaken -''' from django import forms +from .db import target_objectives from .models import Session, Project, Hardware, SessionKnob from .types import StorageType @@ -73,12 +70,19 @@ class SessionForm(forms.ModelForm): super().__init__(*args, **kwargs) self.fields['description'].required = False - self.fields['target_objective'].required = False + self.fields['target_objective'].required = True self.fields['tuning_session'].required = True - self.fields['cpu'].initial = 4 - self.fields['memory'].initial = 16 - self.fields['storage'].initial = 32 - self.fields['storage_type'].initial = StorageType.SSD + self.initial.update(cpu=4, memory=16, storage=32, + storage_type=StorageType.SSD) + + target_objs = target_objectives.get_all() + choices = set() + for entry in target_objs.values(): + for name, obj in entry.items(): + choices.add((name, obj.label)) + target_obj_choices = sorted(choices) + self.fields['target_objective'].widget = forms.Select( + choices=target_obj_choices) def is_valid(self): valid = super().is_valid() @@ -91,6 +95,19 @@ class SessionForm(forms.ModelForm): if user_sessions.exists(): valid = False self._errors['name'] = ["Session '{}' already exists.".format(new_name)] + + if valid: + dbms = self.cleaned_data['dbms'] + assert dbms is not None + target_obj_name = self.cleaned_data['target_objective'] + try: + target_objectives.get_instance(dbms.pk, target_obj_name) + except KeyError: + self._errors['target_objective'] = \ + ["Invalid target objective '{}' for dbms {}.".format( + target_obj_name, dbms.full_name)] + valid = False + return valid def save(self, commit=True): @@ -121,8 +138,7 @@ class SessionForm(forms.ModelForm): widgets = { 'name': forms.TextInput(attrs={'required': True}), - 'description': forms.Textarea(attrs={'maxlength': 500, - 'rows': 5}), + 'description': forms.Textarea(attrs={'maxlength': 500, 'rows': 5}), } labels = { 'dbms': 'DBMS', diff --git a/server/website/website/models.py b/server/website/website/models.py index e5155f8..0692a83 100644 --- a/server/website/website/models.py +++ b/server/website/website/models.py @@ -159,11 +159,11 @@ class Session(BaseModel): verbose_name='session type') target_objective = models.CharField( - max_length=64, default=target_objectives.get_default_target_objective()) + max_length=64, default=target_objectives.default()) def clean(self): if self.target_objective is None: - self.target_objective = target_objectives.get_default_target_objective() + self.target_objective = target_objectives.default() def delete(self, using=DEFAULT_DB_ALIAS, keep_parents=False): SessionKnob.objects.get(session=self).delete() diff --git a/server/website/website/views.py b/server/website/website/views.py index 1c472f6..284dc75 100644 --- a/server/website/website/views.py +++ b/server/website/website/views.py @@ -330,7 +330,7 @@ def create_or_edit_session(request, project_id, session_id=''): 'dbms': DBMSCatalog.objects.get( type=DBMSType.POSTGRES, version='9.6'), 'algorithm': AlgorithmType.GPR, - 'target_objective': target_objectives.get_default_target_objective(), + 'target_objective': target_objectives.default(), }) form = SessionForm(**form_kwargs) context = {