mkmonfs_LDADD = libmon.a libcommon.a libcrush.a
monmaptool_SOURCES = monmaptool.cc
monmaptool_LDADD = libcommon.a
-#crushtool_SOURCES = crushtool.cc
-#crushtool_LDADD = libcommon.a libcrush.a
+crushtool_SOURCES = crushtool.cc
+crushtool_LDADD = libcommon.a libcrush.a
osdmaptool_SOURCES = osdmaptool.cc
osdmaptool_LDADD = libmon.a libcommon.a libcrush.a
bin_PROGRAMS = \
cmon cmds cosd csyn \
cmonctl \
- mkmonfs monmaptool osdmaptool \
+ mkmonfs monmaptool osdmaptool crushtool \
fakesyn \
streamtest dupstore \
$(FUSEBIN) $(NEWSYN)
libos.a libebofs.a
# extra bits
-EXTRA_DIST = start.sh stop.sh crushtool
+EXTRA_DIST = start.sh stop.sh crushtool.pl
# cleaning
clean-local:
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef __CRUSH_GRAMMAR
+#define __CRUSH_GRAMMAR
+
+using namespace boost::spirit;
+
+struct crush_grammar : public grammar<crush_grammar>
+{
+ static const int integerID = 1;
+ static const int factorID = 2;
+ static const int termID = 3;
+ static const int expressionID = 4;
+
+ template <typename ScannerT>
+ struct definition
+ {
+ definition(crush_grammar const& /*self*/)
+ {
+ // Start grammar definition
+ integer = leaf_node_d[ lexeme_d[
+ (!ch_p('-') >> +digit_p)
+ ] ];
+
+ factor = integer
+ | inner_node_d[ch_p('(') >> expression >> ch_p(')')]
+ | (root_node_d[ch_p('-')] >> factor);
+
+ term = factor >>
+ *( (root_node_d[ch_p('*')] >> factor)
+ | (root_node_d[ch_p('/')] >> factor)
+ );
+
+ expression = term >>
+ *( (root_node_d[ch_p('+')] >> term)
+ | (root_node_d[ch_p('-')] >> term)
+ );
+ // End grammar definition
+
+ // turn on the debugging info.
+ BOOST_SPIRIT_DEBUG_RULE(integer);
+ BOOST_SPIRIT_DEBUG_RULE(factor);
+ BOOST_SPIRIT_DEBUG_RULE(term);
+ BOOST_SPIRIT_DEBUG_RULE(expression);
+ }
+
+ rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression;
+ rule<ScannerT, parser_context<>, parser_tag<termID> > term;
+ rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
+ rule<ScannerT, parser_context<>, parser_tag<integerID> > integer;
+
+ rule<ScannerT, parser_context<>, parser_tag<expressionID> > const&
+ start() const { return expression; }
+ };
+};
+
+#endif
+++ /dev/null
-#!/usr/bin/perl
-
-use Config::General;
-use Tie::IxHash;
-use Data::Dumper;
-
-use strict;
-
-use CrushWrapper;
-
-my $usage = "crushtool infile\n";
-my $fn = shift @ARGV || die $usage;
-
-my $alg_types = {
- uniform => 1,
- list => 2,
- tree => 3,
- straw => 4
-};
-my $alg_names = {
- 1 => 'uniform',
- 2 => 'list',
- 3 => 'tree',
- 4 => 'straw' };
-
-my $wrap = new CrushWrapper::CrushWrapper;
-
-&compile_crush($fn, "$fn.out");
-&decompile_crush("$fn.out", "$fn.out.out");
-
-# find lowest id number used
-sub get_lowest {
- my $item = shift;
- return unless ref $item;
-
- my $lowest = 0;
-
- if (ref $item eq 'HASH') {
- $lowest = $item->{'id'} if $lowest > $item->{'id'};
- foreach my $key (keys %{$item}) {
- #next if grep { $key eq $_ } qw(type rule);
- my $sublowest = get_lowest($item->{$key});
- $lowest = $sublowest if $lowest > $sublowest;
- }
- } elsif (ref $item eq 'ARRAY') {
- foreach my $element (@{$item}) {
- my $sublowest = get_lowest($element);
- $lowest = $sublowest if $lowest > $sublowest;
- }
- }
-
- return $lowest;
-}
-
-
-sub decompile_crush {
- my $infn = shift @_;
- my $outfn = shift @_;
-
- $wrap->create();
-
- print "reading...\n";
- my $r = $wrap->read_from_file($infn);
-
- die "can't read file $infn ($r)\n" if ($r != 0);
-
- my $arr;
-
- # types
- my $types = $wrap->get_num_type_names();
- my %type_map;
- for (my $id=0; $types > 0; $id++) {
- my $name = $wrap->get_type_name($id);
- next if $name eq '';
- $types--;
- $type_map{$id} = $name;
- print "type $id is '$name'\n";
- $arr->{'types'}->{'type'}->{$name}->{'type_id'} = $id;
- }
-
- # devices
- my $max_devices = $wrap->get_max_devices();
- my %device_weight;
- my %name_map;
- for (my $id=0; $id < $max_devices; $id++) {
- my $name = $wrap->get_item_name($id);
- next if $name eq '';
- $name_map{$id} = $name;
- print "device $id '$name'\n";
- $arr->{'devices'}->{$type_map{0}}->{$name}->{'id'} = $id;
- my $off = $wrap->get_device_offload($id);
- if ($off) {
- my $off = (0x10000 - $off) / 0x10000;
- $arr->{'devices'}->{$type_map{0}}->{$name}->{'offload'} = $off;
- }
- }
-
- # get bucket names
- my $max_buckets = $wrap->get_max_buckets();
- for (my $id=-1; $id > -1-$max_buckets; $id--) {
- my $name = $wrap->get_item_name($id);
- next if $name eq '';
- $name_map{$id} = $name;
- }
-
- # do buckets
- my $max_buckets = $wrap->get_max_buckets();
- for (my $id=-1; $id > -1-$max_buckets; $id--) {
- my $name = $wrap->get_item_name($id);
- next if $name eq '';
- print "bucket $id '$name'\n";
- my $alg = $wrap->get_bucket_alg($id);
- my $type = $wrap->get_bucket_type($id);
- $arr->{'buckets'}->{$type_map{$type}}->{$name}->{'id'} = $id;
- $arr->{'buckets'}->{$type_map{$type}}->{$name}->{'alg'} = $alg_names->{$alg};
- my $n = $wrap->get_bucket_size($id);
- for (my $i=0; $i<$n; $i++) {
- my $item = $wrap->get_bucket_item($id, $i);
- my $weight = $wrap->get_bucket_item_weight($id, $i);
- next unless $weight;
- $weight /= 0x10000;
- $arr->{'buckets'}->{$type_map{$type}}->{$name}->{'item'}->{$name_map{$item}}->{'weight'} = $weight;
- }
- }
-
-
-
- print Dumper $arr;
-
-}
-
-sub compile_crush {
- my $infn = shift @_;
- my $outfn = shift @_;
-
- $wrap->create();
-
- tie my %conf, "Tie::IxHash";
- %conf = Config::General::ParseConfig( -ConfigFile => $fn,
- -Tie => "Tie::IxHash",
- -MergeDuplicateBlocks => 1 );
-
- my $arr = \%conf;
- print Dumper $arr;
-
- my $lowest = get_lowest($arr);
- #print "lowest is $lowest\n";
-
- my %weights; # item id -> weight
-
- # types
- my %type_ids;
- foreach my $item_type (keys %{$arr->{'types'}->{'type'}}) {
- my $type_id = $arr->{'types'}->{'type'}->{$item_type}->{'type_id'};
- print "type $type_id '$item_type'\n";
- $type_ids{$item_type} = $type_id;
- $wrap->set_type_name($type_id, $item_type);
- }
-
- # build device table
- my %device_ids; # name -> id
- foreach my $item_type (keys %{$arr->{'devices'}}) {
- foreach my $name (keys %{$arr->{'devices'}->{$item_type}}) {
- my $id = $arr->{'devices'}->{$item_type}->{$name}->{'id'};
- if (!defined $id || $id < 0) {
- die "invalid device id for $item_type $name: id is required and must be non-negative";
- }
- $wrap->set_item_name($id, $name);
-
- my $w = $arr->{'devices'}->{$item_type}->{$name}->{'weight'};
- $weights{$id} = $w;
- $device_ids{$name} = $id;
- print "device $id '$name' weight $w\n";
- }
- }
-
- # build bucket table
- my %bucket_ids;
- foreach my $bucket_type (keys %{$arr->{'buckets'}}) {
- foreach my $name (keys %{$arr->{'buckets'}->{$bucket_type}}) {
- # verify type
- unless (defined $type_ids{$bucket_type}) {
- die "invalid bucket type $bucket_type\n";
- }
-
- # id
- my $id = $arr->{'buckets'}->{$bucket_type}->{$name}->{'id'};
- if (defined $id && $id > -1) {
- die "invalid bucket id for $bucket_type $name: id must be negative";
- } elsif (!defined $id) {
- # get the next lower ID number and inject it into the config hash
- $id = --$lowest;
- $arr->{'buckets'}->{$bucket_type}->{$name}->{'id'} = $id;
- }
-
- $wrap->set_item_name($id, $name);
- $bucket_ids{$name} = $id;
-
- my @item_ids;
- my @weights;
- my $myweight;
- foreach my $item_name (keys %{$arr->{'buckets'}->{$bucket_type}->{$name}->{'item'}}) {
- my $id = $wrap->get_item_id($item_name);
- push @item_ids, $id;
- my $weight = $arr->{'buckets'}->{$bucket_type}->{$name}->{'item'}->{$item_name}->{'weight'};
- $weight ||= $weights{$id};
- push(@weights, $weight * 65536); # 16.16 fixed point
- $myweight += $weight;
- }
-
- my $alg = $arr->{'buckets'}->{$bucket_type}->{$name}->{'alg'};
- $alg = 'straw' if !$alg;
- die "invalid bucket alg $alg\n"
- unless $alg_types->{$alg};
-
- my $typeid = $type_ids{$bucket_type};
- my $algid = $alg_types->{$alg};
- print "\tid $id\n";
- print "\talg $alg ($algid)\n";
- print "\ttype $bucket_type ($typeid)\n";
- print "\titems @item_ids\n";
- print "\tweights @weights\n";
-
- # id, alg, type, size, items, weights
- #TODO: pass the correct value for type to add_bucket
- my $result = $wrap->add_bucket($id, $algid, $typeid,
- scalar(@item_ids), \@item_ids, \@weights);
- #print "\t.. $result\n\n";
- print "\tweight $myweight\n";
- $weights{$id} = $myweight;
- }
- }
-
- # rules
- for my $rule_name (keys %{$arr->{'rules'}->{'rule'}}) {
- my $r = $arr->{'rules'}->{'rule'}->{$rule_name};
- my $pool = $r->{'pool'};
- my $typeid = $rule_types{$r->{'type'}};
- my $min_size = $r->{'min_size'};
- my $max_size = $r->{'max_size'};
-
- }
-
- $wrap->finalize;
- $wrap->write_to_file($outfn);
- 1;
-}
-
-
-
-print "Line: " . __LINE__ ."\n";
-
-
-=item
-
-/*** BUCKETS ***/
-enum {
- CRUSH_BUCKET_UNIFORM = 1,
- CRUSH_BUCKET_LIST = 2,
- CRUSH_BUCKET_TREE = 3,
- CRUSH_BUCKET_STRAW = 4
-};
-
-/*** RULES ***/
-enum {
- CRUSH_RULE_NOOP = 0,
- CRUSH_RULE_TAKE = 1, /* arg1 = value to start with */
- CRUSH_RULE_CHOOSE_FIRSTN = 2, /* arg1 = num items to pick */
- /* arg2 = type */
- CRUSH_RULE_CHOOSE_INDEP = 3, /* same */
- CRUSH_RULE_EMIT = 4 /* no args */
-};
-
-=cut
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <boost/spirit/core.hpp>
+#include <boost/spirit/tree/ast.hpp>
+#include <boost/spirit/tree/tree_to_xml.hpp>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#include "config.h"
+
+#include "crush/CrushWrapper.h"
+#include "crush/grammar.h"
+
+#include <iostream>
+#include <stack>
+#include <functional>
+#include <string>
+#include <cassert>
+#include <map>
+using namespace std;
+
+
+using namespace boost::spirit;
+
+typedef char const* iterator_t;
+typedef tree_match<iterator_t> parse_tree_match_t;
+typedef parse_tree_match_t::tree_iterator iter_t;
+
+
+//
+long evaluate(parse_tree_match_t hit);
+long eval_expression(iter_t const& i);
+
+long evaluate(tree_parse_info<> info)
+{
+ return eval_expression(info.trees.begin());
+}
+
+long eval_expression(iter_t const& i)
+{
+ cout << "In eval_expression. i->value = "
+ << string(i->value.begin(), i->value.end())
+ << " i->children.size() = " << i->children.size() << std::endl;
+
+ if (i->value.id() == crush_grammar::integerID)
+ {
+ assert(i->children.size() == 0);
+
+ // extract integer (not always delimited by '\0')
+ string integer(i->value.begin(), i->value.end());
+
+ return strtol(integer.c_str(), 0, 10);
+ }
+ else if (i->value.id() == crush_grammar::factorID)
+ {
+ // factor can only be unary minus
+ assert(*i->value.begin() == '-');
+ return - eval_expression(i->children.begin());
+ }
+ else if (i->value.id() == crush_grammar::termID)
+ {
+ if (*i->value.begin() == '*')
+ {
+ assert(i->children.size() == 2);
+ return eval_expression(i->children.begin()) *
+ eval_expression(i->children.begin()+1);
+ }
+ else if (*i->value.begin() == '/')
+ {
+ assert(i->children.size() == 2);
+ return eval_expression(i->children.begin()) /
+ eval_expression(i->children.begin()+1);
+ }
+ else
+ assert(0);
+ }
+ else if (i->value.id() == crush_grammar::expressionID)
+ {
+ if (*i->value.begin() == '+')
+ {
+ assert(i->children.size() == 2);
+ return eval_expression(i->children.begin()) +
+ eval_expression(i->children.begin()+1);
+ }
+ else if (*i->value.begin() == '-')
+ {
+ assert(i->children.size() == 2);
+ return eval_expression(i->children.begin()) -
+ eval_expression(i->children.begin()+1);
+ }
+ else
+ assert(0);
+ }
+ else
+ {
+ assert(0); // error
+ }
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ // look in tree_calc_grammar for the definition of crush_grammar
+ crush_grammar calc;
+
+ cout << "/////////////////////////////////////////////////////////\n\n";
+ cout << "\t\tThe simplest working crush_grammar...\n\n";
+ cout << "/////////////////////////////////////////////////////////\n\n";
+ cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ string str;
+ while (getline(cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ tree_parse_info<> info = ast_parse(str.c_str(), calc);
+
+ if (info.full)
+ {
+#if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML)
+ // dump parse tree as XML
+ std::map<parser_id, std::string> rule_names;
+ rule_names[crush_grammar::integerID] = "integer";
+ rule_names[crush_grammar::factorID] = "factor";
+ rule_names[crush_grammar::termID] = "term";
+ rule_names[crush_grammar::expressionID] = "expression";
+ tree_to_xml(cout, info.trees, str.c_str(), rule_names);
+#endif
+
+ // print the result
+ cout << "parsing succeeded\n";
+ cout << "result = " << evaluate(info) << "\n\n";
+ }
+ else
+ {
+ cout << "parsing failed\n";
+ }
+ }
+
+ cout << "Bye... :-) \n\n";
+ return 0;
+}
+
--- /dev/null
+#!/usr/bin/perl
+
+use Config::General;
+use Tie::IxHash;
+use Data::Dumper;
+
+use strict;
+
+use CrushWrapper;
+
+my $usage = "crushtool infile\n";
+my $fn = shift @ARGV || die $usage;
+
+my $alg_types = {
+ uniform => 1,
+ list => 2,
+ tree => 3,
+ straw => 4
+};
+my $alg_names = {
+ 1 => 'uniform',
+ 2 => 'list',
+ 3 => 'tree',
+ 4 => 'straw' };
+
+my $wrap = new CrushWrapper::CrushWrapper;
+
+&compile_crush($fn, "$fn.out");
+&decompile_crush("$fn.out", "$fn.out.out");
+
+# find lowest id number used
+sub get_lowest {
+ my $item = shift;
+ return unless ref $item;
+
+ my $lowest = 0;
+
+ if (ref $item eq 'HASH') {
+ $lowest = $item->{'id'} if $lowest > $item->{'id'};
+ foreach my $key (keys %{$item}) {
+ #next if grep { $key eq $_ } qw(type rule);
+ my $sublowest = get_lowest($item->{$key});
+ $lowest = $sublowest if $lowest > $sublowest;
+ }
+ } elsif (ref $item eq 'ARRAY') {
+ foreach my $element (@{$item}) {
+ my $sublowest = get_lowest($element);
+ $lowest = $sublowest if $lowest > $sublowest;
+ }
+ }
+
+ return $lowest;
+}
+
+
+sub decompile_crush {
+ my $infn = shift @_;
+ my $outfn = shift @_;
+
+ $wrap->create();
+
+ print "reading...\n";
+ my $r = $wrap->read_from_file($infn);
+
+ die "can't read file $infn ($r)\n" if ($r != 0);
+
+ my $arr;
+
+ # types
+ my $types = $wrap->get_num_type_names();
+ my %type_map;
+ for (my $id=0; $types > 0; $id++) {
+ my $name = $wrap->get_type_name($id);
+ next if $name eq '';
+ $types--;
+ $type_map{$id} = $name;
+ print "type $id is '$name'\n";
+ $arr->{'types'}->{'type'}->{$name}->{'type_id'} = $id;
+ }
+
+ # devices
+ my $max_devices = $wrap->get_max_devices();
+ my %device_weight;
+ my %name_map;
+ for (my $id=0; $id < $max_devices; $id++) {
+ my $name = $wrap->get_item_name($id);
+ next if $name eq '';
+ $name_map{$id} = $name;
+ print "device $id '$name'\n";
+ $arr->{'devices'}->{$type_map{0}}->{$name}->{'id'} = $id;
+ my $off = $wrap->get_device_offload($id);
+ if ($off) {
+ my $off = (0x10000 - $off) / 0x10000;
+ $arr->{'devices'}->{$type_map{0}}->{$name}->{'offload'} = $off;
+ }
+ }
+
+ # get bucket names
+ my $max_buckets = $wrap->get_max_buckets();
+ for (my $id=-1; $id > -1-$max_buckets; $id--) {
+ my $name = $wrap->get_item_name($id);
+ next if $name eq '';
+ $name_map{$id} = $name;
+ }
+
+ # do buckets
+ my $max_buckets = $wrap->get_max_buckets();
+ for (my $id=-1; $id > -1-$max_buckets; $id--) {
+ my $name = $wrap->get_item_name($id);
+ next if $name eq '';
+ print "bucket $id '$name'\n";
+ my $alg = $wrap->get_bucket_alg($id);
+ my $type = $wrap->get_bucket_type($id);
+ $arr->{'buckets'}->{$type_map{$type}}->{$name}->{'id'} = $id;
+ $arr->{'buckets'}->{$type_map{$type}}->{$name}->{'alg'} = $alg_names->{$alg};
+ my $n = $wrap->get_bucket_size($id);
+ for (my $i=0; $i<$n; $i++) {
+ my $item = $wrap->get_bucket_item($id, $i);
+ my $weight = $wrap->get_bucket_item_weight($id, $i);
+ next unless $weight;
+ $weight /= 0x10000;
+ $arr->{'buckets'}->{$type_map{$type}}->{$name}->{'item'}->{$name_map{$item}}->{'weight'} = $weight;
+ }
+ }
+
+
+
+ print Dumper $arr;
+
+}
+
+sub compile_crush {
+ my $infn = shift @_;
+ my $outfn = shift @_;
+
+ $wrap->create();
+
+ tie my %conf, "Tie::IxHash";
+ %conf = Config::General::ParseConfig( -ConfigFile => $fn,
+ -Tie => "Tie::IxHash",
+ -MergeDuplicateBlocks => 1 );
+
+ my $arr = \%conf;
+ print Dumper $arr;
+
+ my $lowest = get_lowest($arr);
+ #print "lowest is $lowest\n";
+
+ my %weights; # item id -> weight
+
+ # types
+ my %type_ids;
+ foreach my $item_type (keys %{$arr->{'types'}->{'type'}}) {
+ my $type_id = $arr->{'types'}->{'type'}->{$item_type}->{'type_id'};
+ print "type $type_id '$item_type'\n";
+ $type_ids{$item_type} = $type_id;
+ $wrap->set_type_name($type_id, $item_type);
+ }
+
+ # build device table
+ my %device_ids; # name -> id
+ foreach my $item_type (keys %{$arr->{'devices'}}) {
+ foreach my $name (keys %{$arr->{'devices'}->{$item_type}}) {
+ my $id = $arr->{'devices'}->{$item_type}->{$name}->{'id'};
+ if (!defined $id || $id < 0) {
+ die "invalid device id for $item_type $name: id is required and must be non-negative";
+ }
+ $wrap->set_item_name($id, $name);
+
+ my $w = $arr->{'devices'}->{$item_type}->{$name}->{'weight'};
+ $weights{$id} = $w;
+ $device_ids{$name} = $id;
+ print "device $id '$name' weight $w\n";
+ }
+ }
+
+ # build bucket table
+ my %bucket_ids;
+ foreach my $bucket_type (keys %{$arr->{'buckets'}}) {
+ foreach my $name (keys %{$arr->{'buckets'}->{$bucket_type}}) {
+ # verify type
+ unless (defined $type_ids{$bucket_type}) {
+ die "invalid bucket type $bucket_type\n";
+ }
+
+ # id
+ my $id = $arr->{'buckets'}->{$bucket_type}->{$name}->{'id'};
+ if (defined $id && $id > -1) {
+ die "invalid bucket id for $bucket_type $name: id must be negative";
+ } elsif (!defined $id) {
+ # get the next lower ID number and inject it into the config hash
+ $id = --$lowest;
+ $arr->{'buckets'}->{$bucket_type}->{$name}->{'id'} = $id;
+ }
+
+ $wrap->set_item_name($id, $name);
+ $bucket_ids{$name} = $id;
+
+ my @item_ids;
+ my @weights;
+ my $myweight;
+ foreach my $item_name (keys %{$arr->{'buckets'}->{$bucket_type}->{$name}->{'item'}}) {
+ my $id = $wrap->get_item_id($item_name);
+ push @item_ids, $id;
+ my $weight = $arr->{'buckets'}->{$bucket_type}->{$name}->{'item'}->{$item_name}->{'weight'};
+ $weight ||= $weights{$id};
+ push(@weights, $weight * 65536); # 16.16 fixed point
+ $myweight += $weight;
+ }
+
+ my $alg = $arr->{'buckets'}->{$bucket_type}->{$name}->{'alg'};
+ $alg = 'straw' if !$alg;
+ die "invalid bucket alg $alg\n"
+ unless $alg_types->{$alg};
+
+ my $typeid = $type_ids{$bucket_type};
+ my $algid = $alg_types->{$alg};
+ print "\tid $id\n";
+ print "\talg $alg ($algid)\n";
+ print "\ttype $bucket_type ($typeid)\n";
+ print "\titems @item_ids\n";
+ print "\tweights @weights\n";
+
+ # id, alg, type, size, items, weights
+ #TODO: pass the correct value for type to add_bucket
+ my $result = $wrap->add_bucket($id, $algid, $typeid,
+ scalar(@item_ids), \@item_ids, \@weights);
+ #print "\t.. $result\n\n";
+ print "\tweight $myweight\n";
+ $weights{$id} = $myweight;
+ }
+ }
+
+ # rules
+ for my $rule_name (keys %{$arr->{'rules'}->{'rule'}}) {
+ my $r = $arr->{'rules'}->{'rule'}->{$rule_name};
+ my $pool = $r->{'pool'};
+ my $typeid = $rule_types{$r->{'type'}};
+ my $min_size = $r->{'min_size'};
+ my $max_size = $r->{'max_size'};
+
+ }
+
+ $wrap->finalize;
+ $wrap->write_to_file($outfn);
+ 1;
+}
+
+
+
+print "Line: " . __LINE__ ."\n";
+
+
+=item
+
+/*** BUCKETS ***/
+enum {
+ CRUSH_BUCKET_UNIFORM = 1,
+ CRUSH_BUCKET_LIST = 2,
+ CRUSH_BUCKET_TREE = 3,
+ CRUSH_BUCKET_STRAW = 4
+};
+
+/*** RULES ***/
+enum {
+ CRUSH_RULE_NOOP = 0,
+ CRUSH_RULE_TAKE = 1, /* arg1 = value to start with */
+ CRUSH_RULE_CHOOSE_FIRSTN = 2, /* arg1 = num items to pick */
+ /* arg2 = type */
+ CRUSH_RULE_CHOOSE_INDEP = 3, /* same */
+ CRUSH_RULE_EMIT = 4 /* no args */
+};
+
+=cut