From 48efaf6645f6988b7b48dd8998ca618f2a1da0f3 Mon Sep 17 00:00:00 2001 From: Mikkel Krautz Date: Sat, 27 Aug 2011 16:44:29 +0200 Subject: [PATCH] Use a transaction for UserList updates. Support delta-updates for UserState changes. --- freeze.go | 40 +++++++++++++++++++++++++++++++-------- message.go | 55 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/freeze.go b/freeze.go index 498ca7a..996fef0 100644 --- a/freeze.go +++ b/freeze.go @@ -15,6 +15,7 @@ import ( "os" "path/filepath" "strconv" + "time" ) // Freeze a server to disk, and re-open the log, if needed. @@ -658,14 +659,37 @@ func NewServerFromFrozen(name string) (s *Server, err os.Error) { } // Update the datastore with the user's current state. -func (server *Server) UpdateFrozenUser(user *User) { - fu, err := user.Freeze() - if err != nil { - server.Fatal(err) - } - err = server.freezelog.Put(fu) - if err != nil { - server.Fatal(err) +func (server *Server) UpdateFrozenUser(user *User, state *mumbleproto.UserState) { + // Full sync If there's no userstate messgae provided, or if there is one, and + // it includes a registration operation. + nanos := time.Nanoseconds() + if state == nil || state.UserId != nil { + fu, err := user.Freeze() + if err != nil { + server.Fatal(err) + } + fu.LastActive = proto.Uint64(uint64(nanos)) + err = server.freezelog.Put(fu) + if err != nil { + server.Fatal(err) + } + } else { + fu := &freezer.User{} + fu.Id = proto.Uint32(user.Id) + if state.ChannelId != nil { + fu.LastChannelId = state.ChannelId + } + if state.TextureHash != nil { + fu.TextureBlob = proto.String(user.TextureBlob) + } + if state.CommentHash != nil { + fu.CommentBlob = proto.String(user.CommentBlob) + } + fu.LastActive = proto.Uint64(uint64(nanos)) + err := server.freezelog.Put(fu) + if err != nil { + server.Fatal(err) + } } server.numLogOps += 1 } diff --git a/message.go b/message.go index a8e34d3..7488223 100644 --- a/message.go +++ b/message.go @@ -7,12 +7,13 @@ package main import ( "crypto/aes" "crypto/tls" - "mumbleproto" - "goprotobuf.googlecode.com/hg/proto" - "net" "fmt" + "goprotobuf.googlecode.com/hg/proto" "grumble/ban" "grumble/blobstore" + "grumble/freezer" + "mumbleproto" + "net" "time" ) @@ -916,7 +917,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) { } if target.IsRegistered() { - server.UpdateFrozenUser(target.user) + server.UpdateFrozenUser(target.user, userstate) } } @@ -1543,24 +1544,36 @@ func (server *Server) handleUserList(client *Client, msg *Message) { } // Rename, registration removal } else { - for _, listUser := range userlist.Users { - uid := *listUser.UserId - if uid == 0 { - continue - } - user, ok := server.Users[uid] - if ok { - // De-register a user - if listUser.Name == nil { - server.RemoveRegistration(uid) - server.DeleteFrozenUser(user) - - // Rename user - } else { - // todo(mkrautz): Validate name. - user.Name = *listUser.Name - server.UpdateFrozenUser(user) + if len(userlist.Users) > 0 { + tx := server.freezelog.BeginTx() + for _, listUser := range userlist.Users { + uid := *listUser.UserId + if uid == 0 { + continue } + user, ok := server.Users[uid] + if ok { + if listUser.Name == nil { + // De-register + server.RemoveRegistration(uid) + err := tx.Put(&freezer.UserRemove{Id: listUser.UserId}) + if err != nil { + server.Fatal(err) + } + } else { + // Rename user + // todo(mkrautz): Validate name. + user.Name = *listUser.Name + err := tx.Put(&freezer.User{Id: listUser.UserId, Name: listUser.Name}) + if err != nil { + server.Fatal(err) + } + } + } + } + err := tx.Commit() + if err != nil { + server.Fatal(err) } } }