Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
897bd5a7
Commit
897bd5a7
authored
Jan 29, 2021
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
775fce3a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
75 additions
and
81 deletions
+75
-81
go/neo/mastered.go
go/neo/mastered.go
+75
-81
No files found.
go/neo/mastered.go
View file @
897bd5a7
...
...
@@ -77,9 +77,9 @@ type _MasteredNode struct {
opReady
chan
struct
{}
// reinitialized each time state becomes non-operational
operational
bool
// cache for state.IsOperational()
flags
_MasteredNodeFlags
rxm
chan
_RxM
// TalkMaster -> RecvM1
rxm
chan
_RxM
// TalkMaster -> RecvM1
rxmFlags
_MasteredNodeFlags
// if e.g. δPartTab messages should be delivered to RecvM1
// XXX just use `.myInfo.NodeType == STORAGE` instead?
}
// _RxM represents a request or event received from master.
...
...
@@ -133,9 +133,9 @@ func newMasteredNode(typ proto.NodeType, clusterName string, net xnet.Networker,
// Notifications to node/partition tables and cluster state are automatically
// handled, while other notifications and requests are passed through to RecvM1.
//
//
The connection to master is persisted by redial
as needed.
//
Master link is persisted by redialing
as needed.
//
// f is called on every reconnection after identification and protocol prologue.
// f is called on every reconnection
to master
after identification and protocol prologue.
//
// See top-level _MasteredNode overview for details.
//
...
...
@@ -156,6 +156,9 @@ func (node *_MasteredNode) TalkMaster(ctx context.Context, f func(context.Contex
defer
task
.
Runningf
(
&
ctx
,
"%s: talk master(%s)"
,
me0
,
node
.
MasterAddr
)(
&
err
)
for
{
node
.
updateOperational
(
func
()
{
node
.
mlink
=
nil
})
err
:=
node
.
talkMaster1
(
ctx
,
ctx0
,
f
)
log
.
Warning
(
ctx
,
err
)
// XXX Warning ok? -> Error?
// TODO if err == "reject identification / protocol error" -> shutdown client
...
...
@@ -221,24 +224,19 @@ func (node *_MasteredNode) talkMaster1(ctx, ctxPreTalkM context.Context, f func(
// update cluster state
// XXX locking
node
.
opMu
.
Lock
()
err
=
node
.
updateNodeTab
(
ctx
,
&
mnt
)
node
.
state
.
PartTab
=
pt
// XXX update "operational"
/*
// update .operational + notify those who was waiting for it
opready := c.updateOperational()
c.node.StateMu.Unlock()
opready()
*/
node
.
opMu
.
Unlock
()
if
err
!=
nil
{
// might be command to shutdown
node
.
updateOperational
(
func
()
{
err
=
node
.
updateNodeTab
(
ctx
,
&
mnt
)
// the only err is cmdShutdown
node
.
state
.
PartTab
=
pt
if
err
!=
nil
{
// keep mlink=nil on shutdown so that
// .operational does not change to y.
node
.
mlink
=
mlink
}
})
if
err
!=
nil
{
return
err
}
// XXX update .masterLink + notify waiters
wg
:=
xsync
.
NewWorkGroup
(
ctx
)
// receive and handle notifications from master
wg
.
Go
(
func
(
ctx
context
.
Context
)
error
{
...
...
@@ -279,7 +277,7 @@ func (node *_MasteredNode) recvMaster1(ctx context.Context, req neonet.Request)
if
δstate
{
δpt
,
err
:=
node
.
recvδstate
(
ctx
,
req
.
Msg
)
toRecvM1
:=
false
if
δpt
&&
(
node
.
f
lags
&
δPartTabPassThrough
!=
0
)
{
if
δpt
&&
(
node
.
rxmF
lags
&
δPartTabPassThrough
!=
0
)
{
toRecvM1
=
true
}
if
!
toRecvM1
{
...
...
@@ -318,74 +316,70 @@ func (node *_MasteredNode) RecvM1() (neonet.Request, error) {
func
(
node
*
_MasteredNode
)
recvδstate
(
ctx
context
.
Context
,
msg
proto
.
Msg
)
(
δpt
bool
,
err
error
)
{
δpt
=
false
node
.
opMu
.
Lock
()
// XXX defer unlock ?
switch
msg
:=
msg
.
(
type
)
{
default
:
node
.
opMu
.
Unlock
()
panic
(
fmt
.
Sprintf
(
"unexpected message: %T"
,
msg
))
// <- whole partTab
case
*
proto
.
SendPartitionTable
:
δpt
=
true
pt
:=
xneo
.
PartTabFromDump
(
msg
.
PTid
,
msg
.
RowList
)
// FIXME handle msg.NumReplicas
// XXX logging under lock ok?
log
.
Infof
(
ctx
,
"parttab update: %s"
,
pt
)
node
.
state
.
PartTab
=
pt
// <- δ(partTab)
case
*
proto
.
NotifyPartitionChanges
:
δpt
=
true
panic
(
"TODO δ(partTab)"
)
// <- δ(nodeTab)
case
*
proto
.
NotifyNodeInformation
:
err
=
node
.
updateNodeTab
(
ctx
,
msg
)
// XXX recheck return (might be command to shutdown)
case
*
proto
.
NotifyClusterState
:
log
.
Infof
(
ctx
,
"state update: %s"
,
msg
.
State
)
node
.
state
.
Code
=
msg
.
State
traceClusterStateChanged
(
&
node
.
state
.
Code
)
}
// update .operational + notify those who was waiting for it
opready
:=
node
.
updateOperational
()
node
.
opMu
.
Unlock
()
opready
()
node
.
updateOperational
(
func
()
{
switch
msg
:=
msg
.
(
type
)
{
default
:
node
.
opMu
.
Unlock
()
panic
(
fmt
.
Sprintf
(
"unexpected message: %T"
,
msg
))
// <- whole partTab
case
*
proto
.
SendPartitionTable
:
δpt
=
true
pt
:=
xneo
.
PartTabFromDump
(
msg
.
PTid
,
msg
.
RowList
)
// FIXME handle msg.NumReplicas
// XXX logging under lock ok?
log
.
Infof
(
ctx
,
"parttab update: %s"
,
pt
)
node
.
state
.
PartTab
=
pt
// <- δ(partTab)
case
*
proto
.
NotifyPartitionChanges
:
δpt
=
true
panic
(
"TODO δ(partTab)"
)
// <- δ(nodeTab)
case
*
proto
.
NotifyNodeInformation
:
err
=
node
.
updateNodeTab
(
ctx
,
msg
)
// XXX recheck return (might be command to shutdown)
case
*
proto
.
NotifyClusterState
:
log
.
Infof
(
ctx
,
"state update: %s"
,
msg
.
State
)
node
.
state
.
Code
=
msg
.
State
traceClusterStateChanged
(
&
node
.
state
.
Code
)
}
})
return
δpt
,
err
}
// updateOperational updates .operational from current state.
//
// Must be called with .opMu lock held.
//
// Returned sendReady func must be called by updateOperational caller after
// .node.StateMu lock is released - it will close current .opReady this way
// notifying .operational waiters.
func
(
node
*
_MasteredNode
)
updateOperational
()
(
sendReady
func
())
{
operational
:=
node
.
state
.
IsOperational
()
//fmt.Printf("\nupdateOperatinal: %v\n", operational)
//fmt.Println(node.partTab)
//fmt.Println(node.nodeTab)
// updateOperational calls δf under .opMu and updates .operational from current state.
// it also notifies those who was waiting for it if operational state becomes ready.
func
(
node
*
_MasteredNode
)
updateOperational
(
δf
func
())
{
var
opready
chan
struct
{}
if
operational
!=
node
.
operational
{
node
.
operational
=
operational
if
operational
{
opready
=
node
.
opReady
// don't close from under opMu
}
else
{
node
.
opReady
=
make
(
chan
struct
{})
// remake for next operational waiters
}
}
return
func
()
{
if
opready
!=
nil
{
//fmt.Println("updateOperational - notifying %v\n", opready)
close
(
opready
)
node
.
opMu
.
Lock
()
func
()
{
defer
node
.
opMu
.
Unlock
()
δf
()
operational
:=
(
node
.
mlink
!=
nil
)
&&
node
.
state
.
IsOperational
()
//fmt.Printf("\nupdateOperatinal: %v\n", operational)
//fmt.Println(node.partTab)
//fmt.Println(node.nodeTab)
if
operational
!=
node
.
operational
{
node
.
operational
=
operational
if
operational
{
opready
=
node
.
opReady
// don't close from under opMu
}
else
{
node
.
opReady
=
make
(
chan
struct
{})
// remake for next operational waiters
}
}
}()
if
opready
!=
nil
{
//fmt.Println("updateOperational - notifying %v\n", opready)
close
(
opready
)
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment