Initial commit
This commit is contained in:
commit
ceb66315e7
4 changed files with 338 additions and 0 deletions
28
Rakefile
Normal file
28
Rakefile
Normal file
|
@ -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]
|
||||||
|
|
175
base.rake
Normal file
175
base.rake
Normal file
|
@ -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
|
107
c_src/bdberl_drv.c
Normal file
107
c_src/bdberl_drv.c
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/* -------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* bdberl: Berkeley DB Driver for Erlang
|
||||||
|
* Copyright (c) 2008 The Hive. All rights reserved.
|
||||||
|
*
|
||||||
|
* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#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;
|
||||||
|
}
|
28
c_src/buildlib.sh
Executable file
28
c_src/buildlib.sh
Executable file
|
@ -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}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue