package nsqd

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "io"
    "time"
)

const (
    MsgIDLength       = 16
    minValidMsgLength = MsgIDLength + 8 + 2 // Timestamp + Attempts
)

type MessageID [MsgIDLength]byte

type Message struct {
    ID        MessageID
    Body      []byte
    Timestamp int64
    Attempts  uint16

    // for in-flight handling
    deliveryTS time.Time
    clientID   int64
    pri        int64
    index      int
    deferred   time.Duration
}

func NewMessage(id MessageID, body []byte) *Message {
    return &Message{
        ID:        id,
        Body:      body,
        Timestamp: time.Now().UnixNano(),
    }
}

func (m *Message) WriteTo(w io.Writer) (int64, error) {
    var buf [10]byte
    var total int64

    binary.BigEndian.PutUint64(buf[:8], uint64(m.Timestamp))
    binary.BigEndian.PutUint16(buf[8:10], uint16(m.Attempts))

    n, err := w.Write(buf[:])
    total += int64(n)
    if err != nil {
        return total, err
    }

    n, err = w.Write(m.ID[:])
    total += int64(n)
    if err != nil {
        return total, err
    }

    n, err = w.Write(m.Body)
    total += int64(n)
    if err != nil {
        return total, err
    }

    return total, nil
}

// decodeMessage deserializes data (as []byte) and creates a new Message
// message format:
// [x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x][x]...
// |       (int64)        ||    ||      (hex string encoded in ASCII)           || (binary)
// |       8-byte         ||    ||                 16-byte                      || N-byte
// ------------------------------------------------------------------------------------------...
//   nanosecond timestamp    ^^                   message ID                       message body
//                        (uint16)
//                         2-byte
//                        attempts
func decodeMessage(b []byte) (*Message, error) {
    var msg Message

    if len(b) < minValidMsgLength {
        return nil, fmt.Errorf("invalid message buffer size (%d)", len(b))
    }

    msg.Timestamp = int64(binary.BigEndian.Uint64(b[:8]))
    msg.Attempts = binary.BigEndian.Uint16(b[8:10])
    copy(msg.ID[:], b[10:10+MsgIDLength])
    msg.Body = b[10+MsgIDLength:]

    return &msg, nil
}

func writeMessageToBackend(buf *bytes.Buffer, msg *Message, bq BackendQueue) error {
    buf.Reset()
    _, err := msg.WriteTo(buf)
    if err != nil {
        return err
    }
    return bq.Put(buf.Bytes())
}

message.go的更多相关文章

  1. Eclipse 4.2 failed to start after TEE is installed

    ---------------  VM Arguments---------------  jvm_args: -Dosgi.requiredJavaVersion=1.6 -Dhelp.lucene ...

  2. ABP文档 - Javascript Api - Message

    本节内容: 显示信息 确认 Message API给用户显示一个信息,或从用户那里获取一个确认信息. Message API默认使用sweetalert实现,为使sweetalert正常工作,你应该包 ...

  3. 代码的坏味道(20)——过度耦合的消息链(Message Chains)

    坏味道--过度耦合的消息链(Message Chains) 特征 消息链的形式类似于:obj.getA().getB().getC(). 问题原因 如果你看到用户向一个对象请求另一个对象,然后再向后者 ...

  4. java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE

    Android发出HTTP请求时出现了这个错误: java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INST ...

  5. POJ2774 Long Long Message [后缀数组]

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 29277   Accepted: 11 ...

  6. Android消息处理机制(Handler、Looper、MessageQueue与Message)

    Android是消息驱动的,实现消息驱动有几个要素: 消息的表示:Message 消息队列:MessageQueue 消息循环,用于循环取出消息进行处理:Looper 消息处理,消息循环从消息队列中取 ...

  7. Logstash时区、时间转换,message重组

    适用场景 获取日志本身时间 日志时间转Unix时间 重组message 示例日志: hellow@,@world@,@2011-11-01 18:46:43 logstash 配置文件: input{ ...

  8. Kafka消息时间戳(kafka message timestamp)

    最近碰到了消息时间戳的问题,于是花了一些功夫研究了一下,特此记录一下.   Kafka消息的时间戳 在消息中增加了一个时间戳字段和时间戳类型.目前支持的时间戳类型有两种: CreateTime 和 L ...

  9. infopath发布的提示“无法解析SOAP消息”(The SOAP message cannot be parsed)问题解决方案

    最近发现一个列表数据过大,每次发布infopath表单提示如下错误: 后来发现一个infopath表单通过list.asmx and Formsservice.asmx来进行发布的. This err ...

  10. 阶段一:用Handler和Message实现计时效果及其中一些疑问

    “阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 本来是打算继续做天气预报的优化的,但因为某些原因,我要先把之前做的小应用优化一下.所以今天就插播一下用Handle ...

随机推荐

  1. python 字典dict类型合并(不能错过哦)

    我要的字典的键值有些是数据库中表的字段名, 但是有些却不是, 我需要把它们整合到一起, 因此有些这篇文章.(非得凑够150个字,我也是没有办法,扯一点昨天的问题吧,话说python中的session就 ...

  2. javascript 调试 & console.table()

    通过console.table()打印数组.对象 一般我们都是通过console.log()打印数组或对象,但console.table()打印数组.对象更直观: console.table(empi ...

  3. oracle dmp数据导入

    11.245.2.55  root:root su  - pams --注意pams前面的空格 /cnaps2/pams/backup   exp_pams_20141219.dmp drop tab ...

  4. java使用Myeclipse创建Hibernate项目碰到的诸多问题总结

    这两天一直在搞Myeclipse创建Hibernate的1对多映射. 由于缺乏经验,可算是把我坑惨了.控制台是不停地报错啊~~~~我差点就崩溃了. 1.看的是慕课网的Hibernate一对多映射教程, ...

  5. Kali学习笔记4:Wireshark详细使用方法

    Kali Linux自带Wireshark工具使用介绍: 1.进入界面 这里Lua脚本报错,无需关注 开始使用: 双击第一个eth0:以太网0,开始抓包: 点击上边的这个按钮可以设置: 这里注意:需要 ...

  6. Python 装饰器(Decorator)

    装饰器的语法为 @dec_name ,置于函数定义之前.如: import atexit @atexit.register def goodbye(): print('Goodbye!') print ...

  7. CSS学习笔记二:css 画立体图形

    继上一次学了如何去运用css画平面图形,这一次学如何去画正方体,从2D向着3D学习,虽然有点满,但总是一个过程,一点一点积累,然后记录起来. Transfrom3D 在这一次中运用到了一下几种属性: ...

  8. java I/O流详解

    概况 I/O流主要分为二大类别:字符流和字节流. 字节流(基本流) 1.字节输入流    类名:FileInputStream    特点:读(对文件进行读取操作)    父类:InputStream ...

  9. 设计模式之模板方法(Template Method)

    在整理模板方法之前,先来说点废话吧.除了记录学习总结,也来记录一下生活吧. 我们公司的老板在北京,老板也会因为项目来公司,不过不是天天来.公司有个同事,只要老板不在就天天迟到,而且一天比一天晚,经常来 ...

  10. “史上更难就业季”暴露出啥隐情?

      如果说,2013年中国高校毕业生达到699万,被称为"史上最难就业季".那么2014年将成为去年之后的"更难就业季".据最新资料显示,2014年应届大学毕业 ...