Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add SELF transaction type #34

Merged
merged 2 commits into from Mar 7, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
119 changes: 119 additions & 0 deletions bin/doozer_init
@@ -0,0 +1,119 @@
#!/bin/bash
set -o pipefail

function log() {
echo "[`date +'%Y%m%d %H:%M:%S'`] $@"
}

# doozer cluster initialization script

DOOZERCLI="/usr/local/bin/doozer"
DOOZERD_NODES=""
HOST="127.0.0.1"
PORT="9200"

while [ "$1" != "" ]; do
PARAM=`echo $1 | awk -F= '{print $1}'`
VALUE=`echo $1 | awk -F= '{print $2}'`
case $PARAM in
--doozer-cli)
DOOZERCLI="$VALUE"
;;
--doozerd-nodes)
DOOZERD_NODES="$VALUE"
;;
--port)
PORT="$VALUE"
;;
--host)
HOST="$VALUE"
;;
esac
shift
done

if [ -z $PORT ]; then
log "ERROR: --port cannot be empty"
exit 1
fi

if [ -z $HOST ]; then
log "ERROR: --host cannot be empty"
exit 1
fi

if [ -z $DOOZERD_NODES ]; then
log "ERROR: --doozerd-nodes cannot be empty"
exit 1
fi

log "DOOZERD_NODES: $DOOZERD_NODES"

# first identify which node to bind to (ie. the root node)
bind_node=""
for doozerd_node in $DOOZERD_NODES; do
doozerd_node_hostname=`echo $doozerd_node | awk -F: '{print $1}'`
doozerd_node_port=`echo $doozerd_node | awk -F: '{print $2}'`

# resolve the ip (doozerd needs the exact ip to bind to, does not work with 0.0.0.0)
doozerd_node_ip=`host $doozerd_node_hostname 2>/dev/null | tail -1 | awk '{print $NF}'`
if $DOOZERCLI -a="doozer:?ca=$doozerd_node_ip:$doozerd_node_port" nop; then
bind_node="$doozerd_node_ip:$doozerd_node_port"
break
fi
done

if [ -z $bind_node ]; then
log "ERROR: could not find node to bind to"
exit 1
fi

log "bind_node: $bind_node"

this_node_ip=`host $FQ_HOSTNAME 2>/dev/null | tail -1 | awk '{print $NF}'`
host_node="$this_node_ip:$PORT"

log "host_node: $host_node"

my_self=`$DOOZERCLI -a="doozer:?ca=$host_node" self`
if [ -z $my_self ]; then
log "ERROR: could not identify self"
exit 1
fi

log "my_self: $my_self"

my_cal=$(printf %d $(expr $(echo $FQ_HOSTNAME | awk -F. '{print $1}' | tail -c -3) - 1))
if [ -z $my_cal ]; then
log "ERROR: could not identify cal"
exit 1
fi

log "my_cal: $my_cal"

log "checking /ctl/cal/$my_cal"
stat_output=`$DOOZERCLI -a="doozer:?ca=$bind_node" stat /ctl/cal/$my_cal 2>/dev/null`
if [ "$?" == "0" ]; then
log "/ctl/cal/$my_cal exists"
cal_self=`$DOOZERCLI -a="doozer:?ca=$bind_node" get /ctl/cal/$my_cal 2>/dev/null`
if [ "$cal_self" == "$my_self" ]; then
log "NOTICE: nothing to do (we're already active in the cluster)"
exit 0
fi
rev=`echo $stat_output | awk '{print $1}'`
log "deleting /ctl/cal/$my_cal @ $rev"
$DOOZERCLI -a="doozer:?ca=$bind_node" del /ctl/cal/$my_cal $rev >/dev/null 2>&1
if [ "$?" != "0" ]; then
log "ERROR: failed to delete /ctl/cal/$my_cal"
exit 1
fi
fi

log "adding /ctl/cal/$my_cal"
echo -n | $DOOZERCLI -a="doozer:?ca=$bind_node" add /ctl/cal/$my_cal
if [ "$?" != "0" ]; then
log "ERROR: failed to add /ctl/cal/$my_cal"
exit 1
fi

log "SUCCESS"
2 changes: 1 addition & 1 deletion peer/peer.go
Expand Up @@ -151,7 +151,7 @@ func Main(clusterName, self, buri, rwsk, rosk string, cl *doozer.Conn, udpConn *


shun := make(chan string, 3) // sufficient for a cluster of 7 shun := make(chan string, 3) // sufficient for a cluster of 7
go member.Clean(shun, st, pr) go member.Clean(shun, st, pr)
go server.ListenAndServe(listener, canWrite, st, pr, rwsk, rosk) go server.ListenAndServe(listener, canWrite, st, pr, rwsk, rosk, self)


if rwsk == "" && rosk == "" && webListener != nil { if rwsk == "" && rosk == "" && webListener != nil {
web.Store = st web.Store = st
Expand Down
1 change: 1 addition & 0 deletions server/conn.go
Expand Up @@ -21,6 +21,7 @@ type conn struct {
rosk string rosk string
waccess bool waccess bool
raccess bool raccess bool
self string
} }


func (c *conn) serve() { func (c *conn) serve() {
Expand Down
3 changes: 3 additions & 0 deletions server/msg.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/msg.proto
Expand Up @@ -14,6 +14,7 @@ message Request {
WALK = 9; WALK = 9;
GETDIR = 14; GETDIR = 14;
STAT = 16; STAT = 16;
SELF = 20;
ACCESS = 99; ACCESS = 99;
} }
optional Verb verb = 2; optional Verb verb = 2;
Expand Down
7 changes: 4 additions & 3 deletions server/server.go
Expand Up @@ -10,7 +10,7 @@ import (


// ListenAndServe listens on l, accepts network connections, and // ListenAndServe listens on l, accepts network connections, and
// handles requests according to the doozer protocol. // handles requests according to the doozer protocol.
func ListenAndServe(l net.Listener, canWrite chan bool, st *store.Store, p consensus.Proposer, rwsk, rosk string) { func ListenAndServe(l net.Listener, canWrite chan bool, st *store.Store, p consensus.Proposer, rwsk, rosk string, self string) {
var w bool var w bool
for { for {
c, err := l.Accept() c, err := l.Accept()
Expand All @@ -32,11 +32,11 @@ func ListenAndServe(l net.Listener, canWrite chan bool, st *store.Store, p conse
default: default:
} }


go serve(c, st, p, w, rwsk, rosk) go serve(c, st, p, w, rwsk, rosk, self)
} }
} }


func serve(nc net.Conn, st *store.Store, p consensus.Proposer, w bool, rwsk, rosk string) { func serve(nc net.Conn, st *store.Store, p consensus.Proposer, w bool, rwsk, rosk string, self string) {
c := &conn{ c := &conn{
c: nc, c: nc,
addr: nc.RemoteAddr().String(), addr: nc.RemoteAddr().String(),
Expand All @@ -45,6 +45,7 @@ func serve(nc net.Conn, st *store.Store, p consensus.Proposer, w bool, rwsk, ros
canWrite: w, canWrite: w,
rwsk: rwsk, rwsk: rwsk,
rosk: rosk, rosk: rosk,
self: self,
} }


c.grant("") // start as if the client supplied a blank password c.grant("") // start as if the client supplied a blank password
Expand Down
6 changes: 6 additions & 0 deletions server/txn.go
Expand Up @@ -24,6 +24,7 @@ var ops = map[int32]func(*txn){
int32(request_REV): (*txn).rev, int32(request_REV): (*txn).rev,
int32(request_SET): (*txn).set, int32(request_SET): (*txn).set,
int32(request_STAT): (*txn).stat, int32(request_STAT): (*txn).stat,
int32(request_SELF): (*txn).self,
int32(request_WAIT): (*txn).wait, int32(request_WAIT): (*txn).wait,
int32(request_WALK): (*txn).walk, int32(request_WALK): (*txn).walk,
int32(request_ACCESS): (*txn).access, int32(request_ACCESS): (*txn).access,
Expand Down Expand Up @@ -154,6 +155,11 @@ func (t *txn) rev() {
t.respond() t.respond()
} }


func (t *txn) self() {
t.resp.Value = []byte(t.c.self)
t.respond()
}

func (t *txn) stat() { func (t *txn) stat() {
if !t.c.raccess { if !t.c.raccess {
t.respondOsError(syscall.EACCES) t.respondOsError(syscall.EACCES)
Expand Down