ListArchiveFilesCmd.cpp 7.65 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * The CERN Tape Archive (CTA) project
 * Copyright (C) 2015  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 3 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, see <http://www.gnu.org/licenses/>.
 */

#include "xroot_plugins/ListArchiveFilesCmd.hpp"

21
#include <iomanip>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <sstream>
#include <stdint.h>

namespace cta {
namespace xrootPlugins {

//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
ListArchiveFilesCmd::ListArchiveFilesCmd(
  log::Logger &log,
  XrdOucErrInfo &xrdSfsFileError,
  const bool displayHeader,
  const catalogue::TapeFileSearchCriteria &searchCriteria,
  catalogue::Catalogue &catalogue):
  m_log(log),
  m_xrdSfsFileError(xrdSfsFileError),
  m_displayHeader(displayHeader),
  m_archiveFileItor(catalogue.getArchiveFileItor(searchCriteria)) {
}

//------------------------------------------------------------------------------
// read
//------------------------------------------------------------------------------
XrdSfsXferSize ListArchiveFilesCmd::read(XrdSfsFileOffset offset, char *buffer, XrdSfsXferSize size) {
  if(State::LISTED_LAST_ARCHIVE_FILE == m_state) {
    return SFS_OK;
  }

  if(State::WAITING_FOR_FIRST_READ == m_state) {
    m_state = State::LISTING_ARCHIVE_FILES;

    // The first character of the reply stream is the return code
55
    m_readBuffer << "0";
56
57

    if(m_displayHeader) {
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
      m_readBuffer <<
        "\x1b[31;1m" << // Change the colour of the output text to red
        std::setfill(' ') << std::setw(7) << std::right << "id" << " " <<
        std::setfill(' ') << std::setw(7) << std::right << "copy no" << " " <<
        std::setfill(' ') << std::setw(7) << std::right << "vid" << " " <<
        std::setfill(' ') << std::setw(7) << std::right << "fseq" << " " <<
        std::setfill(' ') << std::setw(8) << std::right << "block id" << " " <<
        std::setfill(' ') << std::setw(8) << std::right << "instance" << " " <<
        std::setfill(' ') << std::setw(7) << std::right << "disk id" << " " <<
        std::setfill(' ') << std::setw(7) << std::right << "size" << " " <<
        std::setfill(' ') << std::setw(13) << std::right << "checksum type" << " " <<
        std::setfill(' ') << std::setw(14) << std::right << "checksum value" << " " <<
        std::setfill(' ') << std::setw(13) << std::right << "storage class" << " " <<
        std::setfill(' ') << std::setw(8) << std::right << "owner" << " " <<
        std::setfill(' ') << std::setw(8) << std::right << "group" << " " <<
        std::setfill(' ') << std::setw(13) << std::right << "creation time" << " " <<
        "path" <<
        "\x1b[0m\n"; // Return the colour of the output text
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    }
  }

  if(offset != m_expectedFileOffset) {
    std::ostringstream errMsg;
    errMsg << "Unexpected read offset: expected=" << m_expectedFileOffset << " actual=" << offset;
    m_xrdSfsFileError.setErrInfo(ESPIPE, errMsg.str().c_str());
    return SFS_ERROR;
  }

  XrdSfsXferSize offSetIntoReadBuffer = offset - m_fileOffsetOfReadBuffer;
  if(0 > offSetIntoReadBuffer) {
    std::ostringstream errMsg;
    errMsg << "offSetIntoReadBuffer must be positive: actual=" << offSetIntoReadBuffer;
    m_xrdSfsFileError.setErrInfo(ESPIPE, errMsg.str().c_str());
    return SFS_ERROR;
  }

94
  XrdSfsXferSize nbBytesToBeReadFromBuffer = (XrdSfsXferSize)m_readBuffer.str().size() - offSetIntoReadBuffer;
95
96
97
98
99
100
101
102
103
  if(0 > nbBytesToBeReadFromBuffer) {
    std::ostringstream errMsg;
    errMsg << "nbBytesToBeReadFromBuffer must be positive: actual=" << nbBytesToBeReadFromBuffer;
    m_xrdSfsFileError.setErrInfo(ESPIPE, errMsg.str().c_str());
    return SFS_ERROR;
  }

  if(nbBytesToBeReadFromBuffer == 0) {
    refreshReadBuffer();
104
    if (m_readBuffer.str().empty()) {
105
106
107
108
109
      m_state = State::LISTED_LAST_ARCHIVE_FILE;
      return SFS_OK;
    }
    m_fileOffsetOfReadBuffer = offset;
    offSetIntoReadBuffer = 0;
110
    nbBytesToBeReadFromBuffer = m_readBuffer.str().size();
111
112
113
114
115
116
117
118
119
120
  }

  const XrdSfsXferSize actualNbBytesToRead = nbBytesToBeReadFromBuffer >= size ? size : nbBytesToBeReadFromBuffer;
  if(0 > actualNbBytesToRead) {
    std::ostringstream errMsg;
    errMsg << "actualNbBytesToRead must be positive: actual=" << actualNbBytesToRead;
    m_xrdSfsFileError.setErrInfo(ESPIPE, errMsg.str().c_str());
    return SFS_ERROR;
  }

121
  strncpy(buffer, m_readBuffer.str().c_str() + offSetIntoReadBuffer, actualNbBytesToRead);
122
123
124
125
126
127
128
129
130
  m_expectedFileOffset += actualNbBytesToRead;

  return actualNbBytesToRead;
}

//------------------------------------------------------------------------------
// refreshReadBuffer
//------------------------------------------------------------------------------
void ListArchiveFilesCmd::refreshReadBuffer() {
131
132
133
134
  // Note that one archive file may have more than one tape file
  const uint32_t nbArchiveFilesToFetch = 100;
  uint32_t nbFetchedArchiveFiles = 0;

135
136
  // Clear the read buffer
  m_readBuffer.str(std::string());
137

138
  while(m_archiveFileItor->hasMore() && nbArchiveFilesToFetch > nbFetchedArchiveFiles) {
139
    const common::dataStructures::ArchiveFile archiveFile = m_archiveFileItor->next();
140
    nbFetchedArchiveFiles++;
141
142
143
    for(auto copyNbToTapeFile: archiveFile.tapeFiles) {
      const auto copyNb = copyNbToTapeFile.first;
      const common::dataStructures::TapeFile &tapeFile = copyNbToTapeFile.second;
144
      m_readBuffer <<
145
146
147
148
149
150
151
152
153
154
155
156
157
158
        std::setfill(' ') << std::setw(7) << std::right << archiveFile.archiveFileID << " " <<
        std::setfill(' ') << std::setw(7) << std::right << copyNb << " " <<
        std::setfill(' ') << std::setw(7) << std::right << tapeFile.vid << " " <<
        std::setfill(' ') << std::setw(7) << std::right << tapeFile.fSeq << " " <<
        std::setfill(' ') << std::setw(8) << std::right << tapeFile.blockId << " " <<
        std::setfill(' ') << std::setw(8) << std::right << archiveFile.diskInstance << " " <<
        std::setfill(' ') << std::setw(7) << std::right << archiveFile.diskFileId << " " <<
        std::setfill(' ') << std::setw(7) << std::right << archiveFile.fileSize << " " <<
        std::setfill(' ') << std::setw(13) << std::right << archiveFile.checksumType << " " <<
        std::setfill(' ') << std::setw(14) << std::right << archiveFile.checksumValue << " " <<
        std::setfill(' ') << std::setw(13) << std::right << archiveFile.storageClass << " " <<
        std::setfill(' ') << std::setw(8) << std::right << archiveFile.diskFileInfo.owner << " " <<
        std::setfill(' ') << std::setw(8) << std::right << archiveFile.diskFileInfo.group << " " <<
        std::setfill(' ') << std::setw(13) << std::right << archiveFile.creationTime << " " <<
159
        archiveFile.diskFileInfo.path << "\n";
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    }
  }
}

//------------------------------------------------------------------------------
// stateToStr
//------------------------------------------------------------------------------
std::string ListArchiveFilesCmd::stateToStr(const State state) const {
  switch(state) {
  case WAITING_FOR_FIRST_READ:
    return "WAITING_FOR_FIRST_READ";
  case LISTING_ARCHIVE_FILES:
    return "LISTING_ARCHIVE_FILES";
  case LISTED_LAST_ARCHIVE_FILE:
    return "LISTED_LAST_ARCHIVE_FILE";
  default:
    return "UNKNOWN";
  }
}

} // namespace xrootPlugins
} // namespace cta