diff -u README README --- README 2005-09-21 00:57:12.000000000 -0700 +++ README 2008-03-21 19:16:07.000000000 -0700 @@ -17,8 +17,8 @@ PREREQUISITES ------------- -This extension requires Spread >= 3.12 daemon and C libraries (with -headers), and Ruby >= 1.8 +This extension requires Spread >= 4.0 daemon and C libraries (with +headers), and Ruby >= 1.8.6 INSTALLATION ----------- @@ -44,6 +44,7 @@ patches from: Gavin Sherry + Benjamin Black (updates for Spread 4.0 and Ruby 1.9) LICENSE ------- diff -u spread.c spread.c --- spread.c 2005-09-21 00:58:13.000000000 -0700 +++ spread.c 2008-03-21 19:23:09.000000000 -0700 @@ -20,6 +20,7 @@ #include #define MAX_GROUPS 100 +#define MAX_GROUP_NAME_COUNT 256 struct SpreadConnection { char spread_name[MAX_PROC_NAME]; @@ -345,7 +346,7 @@ SafeStringValue(host_str); - if ((n = SP_connect(RSTRING(host_str)->ptr, + if ((n = SP_connect(RSTRING_PTR(host_str), c_name_str, 0, /* ignored */ BOOL2INT(all_msgs), @@ -354,7 +355,7 @@ raise_sp_error(n); snprintf(sp_conn->spread_name, MAX_PROC_NAME, "%s", - RSTRING(host_str)->ptr); + RSTRING_PTR(host_str)); sp_conn->connected = true; return Qnil; @@ -408,9 +409,9 @@ Data_Get_Struct(obj, struct SpreadConnection, sp); if (TYPE(group) == T_ARRAY) { - for (i = 0; i < RARRAY(group)->len; i++) + for (i = 0; i < RARRAY_LEN(group); i++) { - VALUE tmp = RARRAY(group)->ptr[i]; + VALUE tmp = RARRAY_PTR(group)[i]; if ((n = SP_join(sp->mbox, StringValuePtr(tmp))) < 0) raise_sp_error(n); } @@ -446,9 +447,9 @@ if (TYPE(group) == T_ARRAY) { int i; - for (i = 0; i < RARRAY(group)->len; i++) + for (i = 0; i < RARRAY_LEN(group); i++) { - VALUE tmp = RARRAY(group)->ptr[i]; + VALUE tmp = RARRAY_PTR(group)[i]; if ((n = SP_leave(sp->mbox, StringValuePtr(tmp))) < 0) raise_sp_error(n); } @@ -514,23 +515,23 @@ char groupnames[MAX_GROUPS][MAX_GROUP_NAME]; int i; - if (RARRAY(group)->len == 0) + if (RARRAY_LEN(group) == 0) return Qnil; - if (RARRAY(group)->len >= MAX_GROUPS) + if (RARRAY_LEN(group) >= MAX_GROUPS) rb_raise(rb_eArgError, "too many groups for multicast"); - for (i = 0; i < RARRAY(group)->len; i++) + for (i = 0; i < RARRAY_LEN(group); i++) { - VALUE tmp = RARRAY(group)->ptr[i]; + VALUE tmp = RARRAY_PTR(group)[i]; snprintf(groupnames[i], MAX_GROUP_NAME, "%s", StringValuePtr(tmp)); } if ((n = SP_multigroup_multicast(sp->mbox, service_type, - RARRAY(group)->len, + RARRAY_LEN(group), (const char (*)[]) groupnames, NUM2INT(mtype), - RSTRING(message)->len, - RSTRING(message)->ptr)) < 0) + RSTRING_LEN(message), + RSTRING_PTR(message))) < 0) raise_sp_error(n); } else @@ -540,8 +541,8 @@ service_type, StringValuePtr(group), NUM2INT(mtype), - RSTRING(message)->len, - RSTRING(message)->ptr)) < 0) + RSTRING_LEN(message), + RSTRING_PTR(message))) < 0) raise_sp_error(n); } @@ -1077,16 +1078,26 @@ /* First call, so initialize and cache the array */ int i; int num_members; - char *members; - - num_members = (int) sp_mess->message[SP_get_num_vs_offset_memb_mess()]; - members = sp_mess->message + SP_get_vs_set_offset_memb_mess(); + int num_vs_sets; + unsigned int my_vs_set_index; + char member_names[MAX_GROUP_NAME_COUNT][MAX_GROUP_NAME]; + membership_info memb_info; + + (void)SP_get_memb_info(sp_mess->message, + sp_mess->service_type, + &memb_info); + + num_members = memb_info.my_vs_set.num_members; + (void)SP_get_vs_set_members (sp_mess->message, + &(memb_info.my_vs_set), + member_names, + MAX_GROUP_NAME_COUNT); + sp_mess->rb_delta = rb_ary_new2(num_members); for (i = 0; i < num_members; i++) { - char *member = members + (i * MAX_GROUP_NAME); - rb_ary_store(sp_mess->rb_delta, i, rb_str_new2(member)); + rb_ary_store(sp_mess->rb_delta, i, rb_str_new2(member_names[i])); } } @@ -1184,6 +1195,7 @@ memb_caused_by_disconnect, 0); rb_define_method(rb_cSpreadMemberMessage, "caused_by_network?", memb_caused_by_network, 0); + /* XXX: need better name */ rb_define_method(rb_cSpreadMemberMessage, "delta", memb_delta, 0); @@ -1196,5 +1208,5 @@ /* Self-leave membership messages */ rb_cSpreadSelfLeaveMessage = rb_define_class_under(rb_mSpread, "SelfLeaveMessage", - rb_cSpreadMessage); + rb_cSpreadMessage); } diff -u tests.rb tests.rb --- tests.rb 2005-09-21 00:52:42.000000000 -0700 +++ tests.rb 2008-03-21 19:13:14.000000000 -0700 @@ -1,3 +1,5 @@ +#!/usr/bin/env ruby + require "test/unit" require "./spread" @@ -27,7 +29,10 @@ end def test_basic - with_group(@c1, @c1_fname) do |group| + fname = [] + fname << @c1_fname + + with_group(@c1, fname) do |group| msg = "hello, world" @c1.multicast(msg, group, Spread::RELIABLE_MESS) recv_data(@c1, msg, [group], Spread::RELIABLE_MESS) @@ -35,7 +40,10 @@ end def test_membership - with_group(@c1, @c1_fname) do |group| + fname = [] + fname << @c1_fname + + with_group(@c1, fname) do |group| with_group(@c2, @conn_names) do recv_membership(@c1, MEMBER_JOIN, @conn_names) @@ -45,12 +53,12 @@ recv_data(@c2, msg, [group], Spread::SAFE_MESS) end - recv_membership(@c1, MEMBER_LEAVE, @c1_fname) + recv_membership(@c1, MEMBER_LEAVE, fname) end end def test_msg_type - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| msg = "testing message type" msg_type = 128 @c1.multicast(msg, group, Spread::SAFE_MESS, msg_type) @@ -60,7 +68,7 @@ end def test_io - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| with_group(@c2, @conn_names) do recv_membership(@c1, MEMBER_JOIN, @conn_names) @@ -92,7 +100,7 @@ recv_data(@c2, msg, [group], Spread::SAFE_MESS) end - recv_membership(@c1, MEMBER_LEAVE, @c1_fname) + recv_membership(@c1, MEMBER_LEAVE, [@c1_fname]) end end @@ -124,7 +132,7 @@ # XXX: temporarily disabled, as this seems to fail on my machine. def NO_test_multi_threads_order - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| with_group(@c2, @conn_names) do recv_membership(@c1, MEMBER_JOIN, @conn_names) @@ -151,7 +159,7 @@ end end - recv_membership(@c1, MEMBER_LEAVE, @c1_fname) + recv_membership(@c1, MEMBER_LEAVE, [@c1_fname]) end end @@ -166,7 +174,7 @@ end def test_self_discard - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| with_group(@c2, @conn_names) do recv_membership(@c1, MEMBER_JOIN, @conn_names) @@ -176,12 +184,12 @@ recv_data(@c1, msg, [group], Spread::SAFE_MESS) end - recv_membership(@c1, MEMBER_LEAVE, @c1_fname) + recv_membership(@c1, MEMBER_LEAVE, [@c1_fname]) end end def test_private_group - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| with_group(@c2, @conn_names) do recv_membership(@c1, MEMBER_JOIN, @conn_names) @@ -197,12 +205,12 @@ recv_data(@c1, msg, [@c1.private_group], Spread::SAFE_MESS) end - recv_membership(@c1, MEMBER_LEAVE, @c1_fname) + recv_membership(@c1, MEMBER_LEAVE, [@c1_fname]) end end def test_large_message - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| with_group(@c2, @conn_names) do recv_membership(@c1, MEMBER_JOIN, @conn_names) @@ -214,12 +222,12 @@ recv_data(@c2, msg, [group], Spread::AGREED_MESS) end - recv_membership(@c1, MEMBER_LEAVE, @c1_fname) + recv_membership(@c1, MEMBER_LEAVE, [@c1_fname]) end end def test_memb_delta - with_group(@c1, @c1_fname) do |group| + with_group(@c1, [@c1_fname]) do |group| with_group(@c2, @conn_names) do m = @c1.receive assert(m.membership?) diff -u user.rb user.rb --- user.rb 2005-09-21 00:06:16.000000000 -0700 +++ /user.rb 2008-03-21 19:11:55.000000000 -0700 @@ -1,4 +1,4 @@ -#!/usr/local/bin/ruby +#!/usr/bin/env ruby #################################################################### # user.rb # This is a partial implementation of the demo program user distributed @@ -7,20 +7,28 @@ #################################################################### require "./spread" print "What name would you like to go by? " +STDOUT.flush name = gets.chomp print "What group would you like to join? " +STDOUT.flush group = gets.chomp conn = Spread::Connection.new("4803", name); conn.join(group) + fork do loop do recv_mess = conn.receive - puts "#{recv_mess.sender} says #{recv_mess.message.chomp}" + if recv_mess.is_a?(Spread::MembershipMessage) + puts "group #{recv_mess.group} has members #{recv_mess.members}" + else + puts "#{recv_mess.sender} says #{recv_mess.message.chomp}" + end end end loop do print "User> " + STDOUT.flush send_mess = gets break if send_mess.nil? if not send_mess.empty?