1/********************************************************************
2 * Copyright (c) 2013 - 2014, Pivotal Inc.
3 * All rights reserved.
4 *
5 * Author: Zhanwei Wang
6 ********************************************************************/
7/********************************************************************
8 * 2014 -
9 * open source under Apache License Version 2.0
10 ********************************************************************/
11/**
12 * Licensed to the Apache Software Foundation (ASF) under one
13 * or more contributor license agreements. See the NOTICE file
14 * distributed with this work for additional information
15 * regarding copyright ownership. The ASF licenses this file
16 * to you under the Apache License, Version 2.0 (the
17 * "License"); you may not use this file except in compliance
18 * with the License. You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28#include "BigEndian.h"
29#include "Exception.h"
30#include "ExceptionInternal.h"
31#include "PacketHeader.h"
32
33namespace Hdfs {
34namespace Internal {
35
36int PacketHeader::PkgHeaderSize = PacketHeader::CalcPkgHeaderSize();
37
38int PacketHeader::CalcPkgHeaderSize() {
39 PacketHeaderProto header;
40 header.set_offsetinblock(0);
41 header.set_datalen(0);
42 header.set_lastpacketinblock(false);
43 header.set_seqno(0);
44 return header.ByteSize() + sizeof(int32_t) /*packet length*/ + sizeof(int16_t)/* proto length */;
45}
46
47int PacketHeader::GetPkgHeaderSize() {
48 return PkgHeaderSize;
49}
50
51PacketHeader::PacketHeader() :
52 packetLen(0) {
53}
54
55PacketHeader::PacketHeader(int packetLen, int64_t offsetInBlock, int64_t seqno,
56 bool lastPacketInBlock, int dataLen) :
57 packetLen(packetLen) {
58 proto.set_offsetinblock(offsetInBlock);
59 proto.set_seqno(seqno);
60 proto.set_lastpacketinblock(lastPacketInBlock);
61 proto.set_datalen(dataLen);
62}
63
64int PacketHeader::getDataLen() {
65 return proto.datalen();
66}
67
68bool PacketHeader::isLastPacketInBlock() {
69 return proto.lastpacketinblock();
70}
71
72bool PacketHeader::sanityCheck(int64_t lastSeqNo) {
73 // We should only have a non-positive data length for the last packet
74 if (proto.datalen() <= 0 && !proto.lastpacketinblock())
75 return false;
76
77 // The last packet should not contain data
78 if (proto.lastpacketinblock() && proto.datalen() != 0)
79 return false;
80
81 // Seqnos should always increase by 1 with each packet received
82 if (proto.seqno() != lastSeqNo + 1)
83 return false;
84
85 return true;
86}
87
88int64_t PacketHeader::getSeqno() {
89 return proto.seqno();
90}
91
92int64_t PacketHeader::getOffsetInBlock() {
93 return proto.offsetinblock();
94}
95
96int PacketHeader::getPacketLen() {
97 return packetLen;
98}
99
100void PacketHeader::readFields(const char * buf, size_t size) {
101 int16_t protoLen;
102 assert(size > sizeof(packetLen) + sizeof(protoLen));
103 packetLen = ReadBigEndian32FromArray(buf);
104 protoLen = ReadBigEndian16FromArray(buf + sizeof(packetLen));
105
106 if (packetLen < static_cast<int>(sizeof(int32_t)) || protoLen < 0
107 || static_cast<int>(sizeof(packetLen) + sizeof(protoLen)) + protoLen > static_cast<int>(size)) {
108 THROW(HdfsIOException, "Invalid PacketHeader, packetLen is %d, protoLen is %hd, buf size is %zu", packetLen,
109 protoLen, size);
110 }
111
112 if (!proto.ParseFromArray(buf + sizeof(packetLen) + sizeof(protoLen),
113 protoLen)) {
114 THROW(HdfsIOException,
115 "PacketHeader cannot parse PacketHeaderProto from datanode response.");
116 }
117}
118
119void PacketHeader::writeInBuffer(char * buf, size_t size) {
120 buf = WriteBigEndian32ToArray(packetLen, buf);
121 buf = WriteBigEndian16ToArray(proto.ByteSize(), buf);
122 proto.SerializeToArray(buf, size - sizeof(int32_t) - sizeof(int16_t));
123}
124
125}
126}
127