Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions python/adelphi/adelphi/nb.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import logging
import yaml

from itertools import chain

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a bit of cleanup... apparently this wasn't used anymore

from adelphi.exceptions import KeyspaceSelectionException, TableSelectionException, ExportException
from adelphi.export import BaseExporter

MAX_NUMERIC_VAL = 1000 ** 3
RAMPUP_SCENARIO = "run driver=cql tags=phase:rampup cycles={} threads=auto"
MAIN_SCENARIO = "run driver=cql tags=phase:main cycles={} threads=auto"

TEMPLATEVAR_RAMPUP_CYCLES = "TEMPLATE(rampup-cycles,1000)"
TEMPLATEVAR_MAIN_CYCLES = "TEMPLATE(main-cycles,1000)"
TEMPLATEVAR_SCENARIO_NAME = "TEMPLATE(scenarioname,default)"

CQL_TYPES={}
CQL_TYPES["text"] = "Mod({}); ToString() -> String"
CQL_TYPES["ascii"] = "Mod({}); ToString() -> String"
Expand Down Expand Up @@ -89,7 +91,12 @@ def __init__(self, cluster, props):

self.rampup_cycles = props["rampup-cycles"]
self.main_cycles = props["main-cycles"]
self.numeric_max = min((self.rampup_cycles + self.main_cycles) * 1000, MAX_NUMERIC_VAL)
self.scenario_name = props["scenario-name"]
self.numeric_max = \
min((self.rampup_cycles + self.main_cycles) * 1000, MAX_NUMERIC_VAL) \
if self.rampup_cycles and self.main_cycles \
else MAX_NUMERIC_VAL
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reflects the maximum size we can get for numeric values. If the number of cycles is specified we can use this to constrain the number of values in order to increase the likelihood of hits when we do selects on primary keys.



# Always disable anonymization when generating nosqlbench configs
real_props = props.copy()
Expand All @@ -107,8 +114,10 @@ def __init__(self, cluster, props):
self.table = next(iter(self.keyspace.tables.values()))

log.info("Creating nosqlbench config for {}.{}".format(self.keyspace.name, self.table.name))
log.info("Number of cycles for rampup phase = {}".format(self.rampup_cycles))
log.info("Number of cycles for main phase = {}".format(self.main_cycles))
if self.rampup_cycles:
log.info("Number of cycles for rampup phase = {}".format(self.rampup_cycles))
if self.main_cycles:
log.info("Number of cycles for main phase = {}".format(self.main_cycles))
log.info("Max numeric value = {}".format(self.numeric_max))


Expand All @@ -125,11 +134,11 @@ def each_keyspace(self, ks_fn):


def __get_rampup_scenario(self):
return RAMPUP_SCENARIO.format(self.rampup_cycles)
return RAMPUP_SCENARIO.format(self.rampup_cycles or TEMPLATEVAR_RAMPUP_CYCLES)


def __get_main_scenario(self):
return MAIN_SCENARIO.format(self.main_cycles)
return MAIN_SCENARIO.format(self.main_cycles or TEMPLATEVAR_MAIN_CYCLES)


def __get_dist(self, typename):
Expand Down Expand Up @@ -172,7 +181,7 @@ def __build_schema(self):
"""Really more of a config than a schema, but we'll allow it"""
root = {}

root["scenarios"] = {"TEMPLATE(scenarioname,default)":[self.__get_rampup_scenario(), self.__get_main_scenario()]}
root["scenarios"] = {self.scenario_name or TEMPLATEVAR_SCENARIO_NAME:[self.__get_rampup_scenario(), self.__get_main_scenario()]}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that in all three cases the template var is the default case. If the user doesn't explicitly specify a val via the CLI args we use the template var instead.


root["bindings"] = self.__build_bindings(self.table)

Expand All @@ -185,4 +194,4 @@ def __build_schema(self):
main_write_block = {"name":"main-write", "tags":{"phase":"main", "type":"write"}, "params":cl_ratio_map, "statements": [self.__build_main_write_statement()]}
root["blocks"] = [rampup_block, main_read_block, main_write_block]

return yaml.dump(root, default_flow_style=False)
return yaml.safe_dump(root, default_flow_style=False)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were seeing cases in which the YAML dump was writing a serialized Python Unicode string here which wound up with something like "!!python/unicode foo". PyYAML supports serializing arbitrary Python types; safe_dump() requires the output to be a base string, which is exactly what we want here.

8 changes: 5 additions & 3 deletions python/adelphi/bin/adelphi
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,17 @@ def contribute(ctx, token):


@export.command()
@click.option('--rampup-cycles', type=int, default=1000, help='Number of cycles to use for the nosqlbench rampup phase')
@click.option('--main-cycles', type=int, default=1000, help='Number of cycles to use for the nosqlbench main phase')
@click.option('--rampup-cycles', type=int, help='Number of cycles to use for the nosqlbench rampup phase')
@click.option('--main-cycles', type=int, help='Number of cycles to use for the nosqlbench main phase')
@click.option('--scenario-name', type=str, help='Name of the nosqlbench scenario')
@click.pass_context
def export_nb(ctx, rampup_cycles, main_cycles):
def export_nb(ctx, rampup_cycles, main_cycles, scenario_name):
"""Export a schema in a format suitable for use with the the nosqlbench performance test framework"""

ctx.obj["include-metadata"] = False
ctx.obj["rampup-cycles"] = rampup_cycles
ctx.obj["main-cycles"] = main_cycles
ctx.obj["scenario-name"] = scenario_name

try:
exporter = build_exporter(NbExporter, ctx.obj)
Expand Down
15 changes: 15 additions & 0 deletions python/adelphi/tests/integration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@

class SchemaTestMixin:

# Resource directory management logic
def cqlReferenceSchema(self, version):
return "tests/integration/resources/cql-schemas/{}.cql".format(version)


def nbReferenceYaml(self, version):
return "tests/integration/resources/nb-schemas/{}.yaml".format(version)


def nbBaseSchema(self):
return "tests/integration/resources/nb-base-schema.cql"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some file cleanup. Patterns were developing in the tests around referencing base + expected CQL/YAML but many of the tests were still manipulating raw paths. Goal here is to consolidate that logic in the framework so that it only has to be implemented once.



# Temp dir logic
def basePath(self, name):
return os.path.join(self.dirs.basePath, name)

Expand All @@ -45,6 +59,7 @@ def makeTempDirs(self):
self.dirs = TempDirs(base, outputDir)


# Cassandra connection logic
def connectToLocalCassandra(self):
session = None
while not session:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ def runAdelphi(self, version):


def evalAdelphiOutput(self, version):
referencePath = "tests/integration/resources/cql-schemas/{}.cql".format(version)

# Basic idea here is to find all schemas written to the output dir and aggregate them into a single schema
# file. We then compare this aggregated file to the reference schema. Ordering is important here but
# the current keyspace names hash to something that causes individual keyspaces to be discovered in the
Expand All @@ -50,4 +48,4 @@ def evalAdelphiOutput(self, version):
with open(outputSchema) as outputSchemaFile:
shutil.copyfileobj(outputSchemaFile, allOutputFile)
allOutputFile.write("\n")
self.compareToReferenceCql(referencePath, allOutputPath)
self.compareToReferenceCql(self.cqlReferenceSchema(version), allOutputPath)
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ def runAdelphi(self, version):


def evalAdelphiOutput(self, version):
referencePath = "tests/integration/resources/cql-schemas/{}-ks0.cql".format(version)
outputDirPath = self.outputDirPath(version)
outputSchemas = glob.glob("{}/*/schema".format(outputDirPath))
self.assertEqual(len(outputSchemas), 1)
self.compareToReferenceCql(referencePath, outputSchemas[0])
self.compareToReferenceCql(self.cqlReferenceSchema("{}-ks0".format(version)), outputSchemas[0])
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,4 @@ def runAdelphi(self, version):


def evalAdelphiOutput(self, version):
referencePath = "tests/integration/resources/cql-schemas/{}.cql".format(version)
self.compareToReferenceCql(referencePath, self.stdoutPath(version))


self.compareToReferenceCql(self.cqlReferenceSchema(version), self.stdoutPath(version))
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,4 @@ def runAdelphi(self, version):


def evalAdelphiOutput(self, version):
referencePath = "tests/integration/resources/cql-schemas/{}-ks0.cql".format(version)
self.compareToReferenceCql(referencePath, self.stdoutPath(version))


self.compareToReferenceCql(self.cqlReferenceSchema("{}-ks0".format(version)), self.stdoutPath(version))
3 changes: 1 addition & 2 deletions python/adelphi/tests/integration/nb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

class ExportNbMixin:

def compareToReferenceYaml(self, comparePath, version=None):
referencePath = "tests/integration/resources/nb-schemas/{}.yaml".format(version)
def compareToReferenceYaml(self, referencePath, comparePath):
# Loader specification here to avoid a deprecation warning... see https://msg.pyyaml.org/load
referenceYaml = yaml.load(open(referencePath), Loader=yaml.FullLoader)
compareYaml = yaml.load(open(comparePath), Loader=yaml.FullLoader)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import logging
import os
import sys
import yaml

try:
import unittest2 as unittest
Expand All @@ -26,18 +25,19 @@ def setUp(self):


def getBaseSchemaPath(self):
return "tests/integration/resources/nb-base-schema.cql"
return self.nbBaseSchema()


def runAdelphi(self, version=None):
stderrPath = self.stderrPath(version)
outputDirPath = self.outputDirPath(version)
os.mkdir(outputDirPath)
subprocess.run("adelphi --output-dir={} export-nb 2>> {}".format(outputDirPath, stderrPath), shell=True)
cmdStr = "adelphi --output-dir={} export-nb --rampup-cycles=1000 --main-cycles=1000 --scenario-name=foobar 2>> {}"
subprocess.run(cmdStr.format(outputDirPath, stderrPath), shell=True)


def evalAdelphiOutput(self, version=None):
outputDirPath = self.outputDirPath(version)
outputSchemas = glob.glob("{}/*/schema".format(outputDirPath))
self.assertEqual(len(outputSchemas), 1, "Export of nosqlbench config only supports a single keyspace")
self.compareToReferenceYaml(outputSchemas[0], version)
self.compareToReferenceYaml(self.nbReferenceYaml(version), outputSchemas[0])
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import glob
import logging
import os
import sys

try:
import unittest2 as unittest
except ImportError:
import unittest

if os.name == 'posix' and sys.version_info[0] < 3:
import subprocess32 as subprocess
else:
import subprocess

from tests.integration import SchemaTestMixin
from tests.integration.nb import ExportNbMixin

log = logging.getLogger('adelphi')

class TestNbExportOutputDirTemplateVars(unittest.TestCase, SchemaTestMixin, ExportNbMixin):

def setUp(self):
super(TestNbExportOutputDirTemplateVars, self).setUp()


def getBaseSchemaPath(self):
return self.nbBaseSchema()


def runAdelphi(self, version=None):
stderrPath = self.stderrPath(version)
outputDirPath = self.outputDirPath(version)
os.mkdir(outputDirPath)
cmdStr = "adelphi --output-dir={} export-nb 2>> {}"
subprocess.run(cmdStr.format(outputDirPath, stderrPath), shell=True)


def evalAdelphiOutput(self, version=None):
outputDirPath = self.outputDirPath(version)
outputSchemas = glob.glob("{}/*/schema".format(outputDirPath))
self.assertEqual(len(outputSchemas), 1, "Export of nosqlbench config only supports a single keyspace")
self.compareToReferenceYaml(self.nbReferenceYaml("{}-templatevars".format(version)), outputSchemas[0])
7 changes: 4 additions & 3 deletions python/adelphi/tests/integration/nb/test_nb_export_stdout.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ def setUp(self):


def getBaseSchemaPath(self):
return "tests/integration/resources/nb-base-schema.cql"
return self.nbBaseSchema()


def runAdelphi(self, version=None):
stdoutPath = self.stdoutPath(version)
stderrPath = self.stderrPath(version)
subprocess.run("adelphi export-nb > {} 2>> {}".format(stdoutPath, stderrPath), shell=True)
cmdStr = "adelphi export-nb --rampup-cycles=1000 --main-cycles=1000 --scenario-name=foobar > {} 2>> {}"
subprocess.run(cmdStr.format(stdoutPath, stderrPath), shell=True)


def evalAdelphiOutput(self, version=None):
self.compareToReferenceYaml(self.stdoutPath(version), version)
self.compareToReferenceYaml(self.nbReferenceYaml(version), self.stdoutPath(version))
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import logging
import os
import sys

try:
import unittest2 as unittest
except ImportError:
import unittest

if os.name == 'posix' and sys.version_info[0] < 3:
import subprocess32 as subprocess
else:
import subprocess

from tests.integration import SchemaTestMixin
from tests.integration.nb import ExportNbMixin

log = logging.getLogger('adelphi')

class TestNbExportStdoutTemplateVars(unittest.TestCase, SchemaTestMixin, ExportNbMixin):

def setUp(self):
super(TestNbExportStdoutTemplateVars, self).setUp()


def getBaseSchemaPath(self):
return self.nbBaseSchema()


def runAdelphi(self, version=None):
stdoutPath = self.stdoutPath(version)
stderrPath = self.stderrPath(version)
cmdStr = "adelphi export-nb > {} 2>> {}"
subprocess.run(cmdStr.format(stdoutPath, stderrPath), shell=True)


def evalAdelphiOutput(self, version=None):
self.maxDiff = None
self.compareToReferenceYaml(self.nbReferenceYaml("{}-templatevars".format(version)), self.stdoutPath(version))
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
bindings:
key1_dist: Hash(); Mod(1000000000); ToString() -> String
key1_seq: Mod(1000000000); ToString() -> String
key2_dist: Hash(); Mod(1000000000); ToString() -> String
key2_seq: Mod(1000000000); ToString() -> String
value_dist: Hash(); Mod(1000000000); ToString() -> String
blocks:
- name: rampup
params:
cl: LOCAL_QUORUM
statements:
- rampup-insert: insert into "testkeyspace"."testtable" ("key1","key2","value")
values ({key1_seq},{key2_seq},{value_dist})
tags:
name: rampup-insert
tags:
phase: rampup
- name: main-read
params: &id001
cl: LOCAL_QUORUM
ratio: 5
statements:
- main-select: select * from "testkeyspace"."testtable" where "key1" = {key1_dist}
and "key2" = {key2_dist}
tags:
name: main-select
tags:
phase: main
type: read
- name: main-write
params: *id001
statements:
- main-insert: insert into "testkeyspace"."testtable" ("key1","key2","value") values
({key1_seq},{key2_seq},{value_dist})
tags:
name: main-insert
tags:
phase: main
type: write
scenarios:
TEMPLATE(scenarioname,default):
- run driver=cql tags=phase:rampup cycles=TEMPLATE(rampup-cycles,1000) threads=auto
- run driver=cql tags=phase:main cycles=TEMPLATE(main-cycles,1000) threads=auto
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ blocks:
phase: main
type: write
scenarios:
TEMPLATE(scenarioname,default):
foobar:
- run driver=cql tags=phase:rampup cycles=1000 threads=auto
- run driver=cql tags=phase:main cycles=1000 threads=auto
Loading