func (c *Client) recv() { var headBuf = make([]byte, proto.HeadSize) var head proto.PkgHead var pkg []byte var err error for err == nil { pkg, err = proto.ReadPkg(c.r, headBuf, &head, nil) if err != nil { break } var call *Call var ok bool c.mtx.Lock() if call, ok = c.pending[head.Seq]; ok { delete(c.pending, head.Seq) } c.mtx.Unlock() if proto.CmdAuth == head.Cmd { c.cachAuth(pkg) } if call != nil { call.pkg = pkg call.ready = true call.done() } } // Terminate pending calls. c.mtx.Lock() c.shutdown = true if err == io.EOF { if c.closing { err = ErrShutdown } else { err = io.ErrUnexpectedEOF } } for _, call := range c.pending { call.err = err call.ready = true call.done() } c.mtx.Unlock() c.doClose() }
func (bin *BinLog) fixSeqFile(idx uint64) (fileInfo, error) { var fi fileInfo var name = bin.GetBinFileName(idx) file, err := os.Open(name) if err != nil { return fi, err } var r = bufio.NewReader(file) var headBuf = make([]byte, proto.HeadSize) var head proto.PkgHead for { _, err := proto.ReadPkg(r, headBuf, &head, nil) if err != nil { break } if fi.MinSeq == 0 { fi.MinSeq = head.Seq fi.Idx = idx fi.Done = true } if fi.MaxSeq < head.Seq { fi.MaxSeq = head.Seq } } file.Close() if fi.Idx == 0 { os.Remove(bin.GetBinFileName(idx)) os.Remove(bin.GetSeqFileName(idx)) return fi, fmt.Errorf("no record in bin file id %d", idx) } return fi, bin.writeSeqFile(&fi) }
func (c *Client) GoRecvRequest(ch *RequestChan, slv *slave) { var headBuf = make([]byte, proto.HeadSize) var head proto.PkgHead for { pkg, err := proto.ReadPkg(c.r, headBuf, &head, nil) if err != nil { if !c.IsClosed() && err != io.EOF && err != io.ErrUnexpectedEOF { log.Printf("ReadPkg failed: %s, close client!\n", err) } c.Close() return } //log.Printf("recv(%s): [0x%X\t%d\t%d]\n", // c.c.RemoteAddr(), head.Cmd, head.DbId, head.Seq) var req = Request{c, slv, store.PkgArgs{head.Cmd, head.DbId, head.Seq, pkg}} switch head.Cmd { case proto.CmdAuth: fallthrough case proto.CmdPing: fallthrough case proto.CmdScan: fallthrough case proto.CmdMGet: fallthrough case proto.CmdGet: ch.ReadReqChan <- &req case proto.CmdMIncr: fallthrough case proto.CmdMDel: fallthrough case proto.CmdMSet: fallthrough case proto.CmdIncr: fallthrough case proto.CmdDel: fallthrough case proto.CmdSet: if ClientTypeNormal == c.ClientType() { ch.WriteReqChan <- &req } else { ch.SyncReqChan <- &req } case proto.CmdSyncSt: fallthrough case proto.CmdSync: if ClientTypeNormal != c.ClientType() { ch.SyncReqChan <- &req } case proto.CmdDump: ch.DumpReqChan <- &req case proto.CmdDelSlot: fallthrough case proto.CmdSlaveSt: fallthrough case proto.CmdMigrate: fallthrough case proto.CmdSlaveOf: ch.CtrlReqChan <- &req default: log.Printf("Invalid cmd 0x%X\n", head.Cmd) c.Close() return } } }
func (r *Reader) Init(lastSeq uint64) error { var err error r.bin.mtx.Lock() r.bin.rseqs = append(r.bin.rseqs, r.rseq) r.rseq.seq = lastSeq var index = -1 for i, f := range r.bin.infos { index = i if lastSeq < f.MinSeq { break } if f.MaxSeq >= lastSeq || f.MaxSeq == 0 { break } } if index < 0 { r.bin.mtx.Unlock() // unlock immediately if lastSeq > 0 && lastSeq != MinNormalSeq { return ErrLogMissing } r.curMemPos = -1 r.curInfo.Idx = 0 return nil } else { r.curInfo = *r.bin.infos[index] if lastSeq > 0 && lastSeq != MinNormalSeq && r.curInfo.MinSeq > lastSeq+1 { r.bin.mtx.Unlock() // unlock immediately return ErrLogMissing } } r.rseq.seq = r.curInfo.MinSeq if r.curInfo.Done { r.bin.mtx.Unlock() // unlock immediately var name = r.bin.GetBinFileName(r.curInfo.Idx) r.curFile, err = os.Open(name) if err != nil { log.Printf("open file failed: (%s) %s\n", name, err) return err } if r.curBufR == nil { r.curBufR = bufio.NewReader(r.curFile) } else { r.curBufR.Reset(r.curFile) } if r.curInfo.MinSeq < lastSeq+1 { var pkgBuf = make([]byte, 4096) for { _, err = proto.ReadPkg(r.curBufR, r.headBuf, &r.head, pkgBuf) if err != nil { return err } if r.head.Seq >= lastSeq { break } } } } else { defer r.bin.mtx.Unlock() // wait until func finished if r.curInfo.Idx != r.bin.fileIdx { log.Printf("invalid file index (%d, %d)\n", r.curInfo.Idx, r.bin.fileIdx) return ErrUnexpected } r.curMemPos = 0 if r.curInfo.MinSeq < lastSeq+1 { for { if r.curMemPos+proto.HeadSize > r.bin.usedLen { return ErrUnexpected } _, err = r.head.Decode(r.bin.memlog[r.curMemPos:]) if err != nil { return ErrUnexpected } if r.curMemPos+int(r.head.PkgLen) > r.bin.usedLen { return ErrUnexpected } r.curMemPos += int(r.head.PkgLen) if r.head.Seq >= lastSeq { break } } } } return nil }
func (r *Reader) next() []byte { var err error if r.curFile != nil { pkg, err := proto.ReadPkg(r.curBufR, r.headBuf, &r.head, nil) if err != nil { return r.nextFile() } return pkg } else if r.curMemPos >= 0 { r.bin.mtx.Lock() if r.curInfo.Idx != r.bin.fileIdx { for _, f := range r.bin.infos { if f.Idx == r.curInfo.Idx { r.curInfo = *f break } } r.bin.mtx.Unlock() // unlock immediately var name = r.bin.GetBinFileName(r.curInfo.Idx) r.curFile, err = os.Open(name) if err != nil { log.Printf("open file failed: (%s) %s\n", name, err) return nil } if r.curBufR == nil { r.curBufR = bufio.NewReader(r.curFile) } else { r.curBufR.Reset(r.curFile) } r.curFile.Seek(int64(r.curMemPos), 0) r.curMemPos = -1 return r.next() } defer r.bin.mtx.Unlock() // wait to finish if r.curMemPos+proto.HeadSize > r.bin.usedLen { return nil } _, err = r.head.Decode(r.bin.memlog[r.curMemPos:]) if err != nil { return nil } if r.curMemPos+int(r.head.PkgLen) > r.bin.usedLen { return nil } var pkg = make([]byte, int(r.head.PkgLen)) copy(pkg, r.bin.memlog[r.curMemPos:]) r.curMemPos += int(r.head.PkgLen) return pkg } else { return r.nextFile() } return nil }