commit ceb66315e77119d0b081a23d15d6a497ab9dc333 Author: Dave Smith Date: Fri Dec 5 23:20:26 2008 -0700 Initial commit diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..abb3f63 --- /dev/null +++ b/Rakefile @@ -0,0 +1,28 @@ +load "base.rake" + +C_SRCS = FileList["c_src/bdberl_drv.c"] +C_OBJS = FileList["c_src/bdberl_drv.o"] + +CLEAN.include %w( c_src/*.o priv/*.so ) +CLOBBER.include %w( c_src/system ) + +directory 'c_src' + +DB_LIB = "c_src/system/lib/libdb.a" + +file DB_LIB do + sh "cd c_src && ./buildlib.sh 2>&1" +end + +rule ".o" => ["%X.c"] do |t| + puts "compiling #{t.source}..." + sh "gcc -c -Wall -Werror -Ic_src/system/include -I#{erts_dir()}/include #{t.source} -o #{t.name}", :verbose => false +end + +task :compile_c => ['c_src'] + C_OBJS do + puts "linking c_src/bdberl_drv.so..." + sh "gcc #{erts_link_cflags()} c_src/*.o c_src/system/lib/libdb-*.a -o priv/bdberl_drv.so", :verbose => false +end + +task :compile => [DB_LIB, :compile_c] + diff --git a/base.rake b/base.rake new file mode 100644 index 0000000..4b2e868 --- /dev/null +++ b/base.rake @@ -0,0 +1,175 @@ +require 'rake/clean' +require 'set' + +PWD = Dir.getwd +BASE_DIR = File.expand_path "#{PWD}/../" + +SRC = FileList['src/*.erl'] +OBJ = SRC.pathmap("%{src,ebin}X.beam") +EBIN = FileList["#{BASE_DIR}/**/ebin"] +APP = FileList["#{PWD}/ebin/*.app"][0] + +INCLUDE = "./include" +ERLC_FLAGS = "-I#{INCLUDE} -pa #{EBIN.join(' -pa ')} +debug_info " + +CLEAN.include %w( **/*.beam **/erl_crash.dump ) +CLOBBER.include %w( perf_test/logs int_test/logs test/logs doc ) + +directory 'ebin' + +rule ".beam" => ["%{ebin,src}X.erl"] do |t| + puts "compiling #{t.source}..." + sh "erlc -W #{ERLC_FLAGS} -o ebin #{t.source}", :verbose => false +end + +desc "Compile Erlang sources to .beam files" +task :compile => ['ebin'] + OBJ do + do_validate_app +end + +desc "Do a fresh build from scratch" +task :rebuild => [:clean, :compile] + +task :default => [:compile] + +task :compile_tests do + do_compile_tests("test") +end + +desc "Run unit tests" +task :test => [:compile, :compile_tests] + +task :compile_int_tests do + do_compile_tests("int_test") +end + +desc "Run integration tests" +task :int_test => [:compile, :compile_int_tests] + +def erl_run(script, args = "") + `erl -eval '#{script}' -s erlang halt #{args} -noshell 2>&1`.strip +end + +def erl_where(lib) + script = <<-ERL + io:format("~s\n", [filename:join(code:lib_dir(#{lib}), "include")]) + ERL + erl_run(script) +end + +def erl_app_modules(app) + script = <<-ERL + ok = application:load(#{app}), + {ok, M} = application:get_key(#{app}, modules), + [io:format("~s\\n", [Mod]) || Mod <- M]. + ERL + + output = erl_run(script, "-pa ebin") + puts output + if output[/badmatch/] + fail "Error processing .app file: ", output + "" + else + output.split("\n") + end +end + +def erts_dir() + script = <<-ERL + io:format("~s\n", [lists:concat([code:root_dir(), "/erts-", erlang:system_info(version)])]) + ERL + erl_run(script) +end + +def erts_link_cflags() + if `uname`.strip() == "Darwin" + " -fPIC -bundle -flat_namespace -undefined suppress " + else + " -fpic -shared" + end +end + +def do_validate_app() + # Setup app name and build sets of modules from the .app as well as + # beams that got compiled + if APP == nil + puts "No .app file found; skipping validation." + return + end + + app = File.basename(APP, ".app") + modules = Set.new(erl_app_modules(app)) + beams = Set.new(OBJ.pathmap("%n").to_a) + + puts "validating #{app}.app..." + + # Identify .beam files which are listed in the .app, but not present in ebin/ + missing_beams = (modules - beams) + if not missing_beams.empty? + msg = "One or more modules listed in #{app}.app do not exist as .beam:\n" + missing_beams.each { |m| msg << " * #{m}\n" } + fail msg + end + + # Identify modules which are not listed in the .app, but are present in ebin/ + missing_modules = (beams - modules) + if not missing_modules.empty? + msg = "One or more .beam files exist that are not listed in #{app}.app:\n" + missing_modules.each { |m| msg << " * #{m}\n" } + fail msg + end +end + + +def do_compile_tests(dir) + if File.directory?(dir) + compile_cmd = "erlc #{ERLC_FLAGS} -I#{erl_where('common_test')} \ + -I#{erl_where('test_server')} -o #{dir} #{dir}/*.erl".squeeze(" ") + + sh compile_cmd, :verbose => false + + Dir.mkdir "#{dir}/logs" unless File.directory?("#{dir}/logs") + end +end + +def run_tests(dir, rest = "") + sh "erl -pa #{EBIN.join(' ')} #{PWD}/ebin #{PWD}/include \ + -noshell -s ct_run script_start -s erlang halt \ + #{get_cover(dir)} \ + #{get_suites(dir)} -logdir #{dir}/logs -env TEST_DIR #{PWD}/#{dir} \ + #{rest}" + + fail if $?.exitstatus != 0 && !ENV["stop_on_fail"].nil? + + File.open("#{PWD}/#{dir}/logs/raw.log", "w") do |file| + file.write "--- Test run on #{Time.now.to_s} ---\n" + file.write output + file.write "\n\n" + end + + if output[/, 0 failed/] && ENV["verbose"].nil? + puts "==> " + output[/TEST COMPLETE,.*test cases$/] + else + puts output + end +end + +def get_cover(dir) + use_cover = ENV["use_cover"] + if use_cover + "-cover #{dir}/cover.spec" + else + "" + end +end + +def get_suites(dir) + suites = ENV['suites'] + if suites + all_suites = "" + suites.each(' ') {|s| all_suites << "#{PWD}/#{dir}/#{s.strip}_SUITE "} + "-suite #{all_suites}" + else + "-dir #{dir}" + end +end diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c new file mode 100644 index 0000000..764adba --- /dev/null +++ b/c_src/bdberl_drv.c @@ -0,0 +1,107 @@ +/* ------------------------------------------------------------------- + * + * bdberl: Berkeley DB Driver for Erlang + * Copyright (c) 2008 The Hive. All rights reserved. + * + * ------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include "erl_driver.h" + +#include "db.h" + +/** + * Driver functions + */ +static ErlDrvData bdberl_drv_start(ErlDrvPort port, char* buffer); + +static void bdberl_drv_stop(ErlDrvData handle); + +static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, + char* inbuf, int inbuf_sz, + char** outbuf, int outbuf_sz); + +/** + * Command codes + */ +#define CMD_PARSE 0 + +/** + * Driver Entry + */ +ErlDrvEntry bdberl_drv_entry = +{ + NULL, /* F_PTR init, N/A */ + bdberl_drv_start, /* L_PTR start, called when port is opened */ + bdberl_drv_stop, /* F_PTR stop, called when port is closed */ + NULL, /* F_PTR output, called when erlang has sent */ + NULL, /* F_PTR ready_input, called when input descriptor ready */ + NULL, /* F_PTR ready_output, called when output descriptor ready */ + "bdberl_drv", /* driver_name */ + NULL, /* F_PTR finish, called when unloaded */ + NULL, /* handle */ + bdberl_drv_control, /* F_PTR control, port_command callback */ + NULL, /* F_PTR timeout, reserved */ + NULL, /* F_PTR outputv, reserved */ + NULL, /* F_PTR ready_async */ + NULL, /* F_PTR flush */ + NULL, /* F_PTR call */ + NULL, /* F_PTR event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL, /* Reserved */ + NULL /* F_PTR process_exit */ +}; + +/** + * Structure for holding port instance data + */ +typedef struct +{ + ErlDrvPort port; +} PortData; + +DRIVER_INIT(bdberl_drv) +{ + return &bdberl_drv_entry; +} + +static ErlDrvData bdberl_drv_start(ErlDrvPort port, char* buffer) +{ + PortData* d = (PortData*)driver_alloc(sizeof(PortData)); + memset(d, '\0', sizeof(PortData)); + + // Save handle to the port + d->port = port; + + // Make sure port is running in binary mode + set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); + + return (ErlDrvData)d; +} + +static void bdberl_drv_stop(ErlDrvData handle) +{ + // Release the port instance data + driver_free(handle); +} + +static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, + char* inbuf, int inbuf_sz, + char** outbuf, int outbuf_sz) +{ + //PortData* d = (PortData*)handle; + DB* dbp; + db_create(&dbp, NULL, 0); + + switch(cmd) + { + } + *outbuf = 0; + return 0; +} diff --git a/c_src/buildlib.sh b/c_src/buildlib.sh new file mode 100755 index 0000000..cf9a5a2 --- /dev/null +++ b/c_src/buildlib.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +WORKDIR=`pwd`/system +TARGETDIR=`(cd .. && pwd)`/priv + +DB_VER="4.7.25" + +## Check for necessary tarball +if [ ! -f "db-${DB_VER}.tar.gz" ]; then + echo "Could not find db tarball. Aborting..." + exit 1 +fi + +## Make sure target directory exists +mkdir -p $TARGETDIR + +## Remove existing directories +rm -rf system db-${DB_VER} + +## Untar and build everything +tar -xzf db-${DB_VER}.tar.gz && \ +(cd db-${DB_VER}/build_unix && \ + ../dist/configure --prefix=$WORKDIR --disable-shared && make && ranlib libdb-*.a && make install) && \ +rm -rf db-${DB_VER} + + + +