Payload.hpp 4.79 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/******************************************************************************
 *                      Payload.hpp
 *
 * This file is part of the Castor project.
 * See http://castor.web.cern.ch/castor
 *
 * Copyright (C) 2003  CERN
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * 
 *
 * @author Castor Dev team, castor-dev@cern.ch
 *****************************************************************************/
#include <zlib.h>

#pragma once 

namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {
  
/**
 * Class managing a fixed size payload buffer. Some member functions also
 * allow read
 * @param capacity Size of the payload buffer in bytes
 */
class Payload
{
40
41
  Payload(const Payload&);
  Payload& operator=(const Payload&);
42
43
44
45
public:
  Payload(size_t capacity):
  m_payload(new (std::nothrow) unsigned char[capacity]),m_totalCapacity(capacity),m_size(0) {
    if(NULL == m_payload) {
46
      throw castor::tape::exceptions::MemException("Failed to allocate memory for a new MemBlock!");
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    }
  }
  ~Payload(){
    delete[] m_payload;
  }
  
  /** Amount of data present in the payload buffer */
  size_t size() const {
    return m_size;
  }
  
  /** Remaining free space in the payload buffer */
  size_t remainingFreeSpace() const {
    return m_totalCapacity - m_size;
  }
  
  /** Total size of the payload block */
  size_t totalCapacity() const {
    return m_totalCapacity;
  }
    
  /** Returns a pointer to the beginning of the payload block */
  unsigned char* get(){
    return m_payload;
  }
  
  /** Returns a pointer to the beginning of the payload block (readonly version) */
  unsigned char const*  get() const {
    return m_payload;
  }
  
  /** 
   * Reads all the buffer in one go from a diskFile::ReadFile object 
   * @param from reference to the diskFile::ReadFile
   */
  size_t read(tape::diskFile::ReadFile& from){
    m_size = from.read(m_payload,m_totalCapacity);
    return m_size;
  }
David COME's avatar
David COME committed
86

87
88
89
90
91
92
93
94
95
96
97
98
  /**
   * Reads one block from a tapeFile::readFile
   * @throws castor::tape::daemon::Payload::EOF
   * @param from reference to the tapeFile::ReadFile
   * @return whether another tape block will fit in the memory block.
   */
  bool append(tape::tapeFile::ReadFile & from){
    if (from.getBlockSize() > remainingFreeSpace()) {
      std::stringstream err;
      err << "Trying to read a tape file block with too little space left: BlockSize="
       << from.getBlockSize() << " remainingFreeSpace=" << remainingFreeSpace()
              << " (totalSize=" << m_totalCapacity << ")"; 
99
      throw castor::tape::exceptions::MemException(err.str());
100
101
102
103
104
    }
    size_t readSize;
    try {
      readSize = from.read(m_payload + m_size, from.getBlockSize());
    } catch (castor::tape::tapeFile::EndOfFile) {
David COME's avatar
David COME committed
105
      throw castor::tape::exceptions::EndOfFile("In castor::tape::tapeserver::daemon::Payload::append: reached end of file");
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    }
    m_size += readSize;
    return  from.getBlockSize() <= remainingFreeSpace();
  }
  
  /**
   * Write the complete buffer to a diskFile::WriteFile
   * @param to reference to the diskFile::WriteFile
   */
  void write(tape::diskFile::WriteFile& to){
    to.write(m_payload,m_size);
  }
  
  /**
   * Write the complete buffer to a tapeFile::WriteFile, tape block by
   * tape block
   * @param to reference to the tapeFile::WriteFile
   */
  void write(tape::tapeFile::WriteFile& to) {
    size_t blockSize = to.getBlockSize();
    size_t writePosition = 0;
    // Write all possible full tape blocks
    while (m_size - writePosition > blockSize) {
      to.write(m_payload + writePosition, blockSize);
      writePosition += blockSize;
    }
    // Write a remainder, if any
    if (m_size - writePosition) {
      to.write(m_payload + writePosition, m_size - writePosition);
    }
  }
   /**
    * Compute adler32 checksum on the current data hold.
    * @param previous The previous adler32 checksum from all previous datablock
    * @return the updated checksum
    */
  unsigned long  adler32(unsigned long previous){
    return ::adler32(previous,m_payload,m_size);
  }
David COME's avatar
David COME committed
145
146
147
  static unsigned long zeroAdler32() {
     return  ::adler32(0L,Z_NULL,0);
   }
148
149
150
151
152
153
154
private:
  unsigned char* m_payload;
  size_t m_totalCapacity;
  size_t m_size;
};

}}}}