TapeReadFileTask.hpp 6.04 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
/******************************************************************************
 *                      TapeReadFileTask.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
 *****************************************************************************/

#pragma once

#include "castor/tape/tapeserver/daemon/TapeReadTask.hpp"
#include "castor/tape/tapeserver/daemon/DataFifo.hpp"
29
#include "castor/tape/tapeserver/daemon/RecallMemoryManager.hpp"
30
#include "castor/tape/tapeserver/daemon/DataConsumer.hpp"
David COME's avatar
David COME committed
31
#include "castor/tape/tapeserver/exception/Exception.hpp"
32

33

34
35
36
37
namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {
38
39
class TapeReadFileTask: public TapeReadTask {
public:
40
41
42
  TapeReadFileTask(castor::tape::tapegateway::FileToRecallStruct * ftr,
    DataConsumer & destination, RecallMemoryManager & mm): 
    m_fileToRecall(ftr), m_fifo(destination), m_mm(mm) {}
43
44
  /* Implementation of the TapeReadTask interface*/
  virtual bool endOfWork() { return false; }
45
46
47
48
49
  virtual void execute(castor::tape::tapeFile::ReadSession & rs,
    castor::log::LogContext & lc) {
    using castor::log::Param;
    typedef castor::log::LogContext::ScopedParam ScopedParam;
    // Placeholder for the tape file read
David COME's avatar
David COME committed
50
    
51
52
53
54
55
56
    // Set the common context for all the omming logs (file info)
    ScopedParam sp0(lc, Param("NSHOSTNAME", m_fileToRecall->nshost()));
    ScopedParam sp1(lc, Param("NSFILEID", m_fileToRecall->fileid()));
    ScopedParam sp2(lc, Param("BlockId", castor::tape::tapeFile::BlockId::extract(*m_fileToRecall)));
    ScopedParam sp3(lc, Param("fSeq", m_fileToRecall->fseq()));
    ScopedParam sp4(lc, Param("fileTransactionId", m_fileToRecall->fileTransactionId()));
David COME's avatar
David COME committed
57
    
58
59
60
61
    // Read the file and transmit it
    bool stillReading = true;
    int fileBlock = 0;
    int tapeBlock = 0;
David COME's avatar
David COME committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    try {
      std::auto_ptr<castor::tape::tapeFile::ReadFile> rf(openReadFile(rs,lc));
      while (stillReading) {
        // Get a memory block and add information to its metadata
        std::auto_ptr<MemBlock> mb(m_mm.getFreeBlock());
        mb->m_fSeq = m_fileToRecall->fseq();
        mb->m_failed = false;
        mb->m_fileBlock = fileBlock++;
        mb->m_fileid = m_fileToRecall->fileid();
        mb->m_tapeFileBlock = tapeBlock;
        mb->m_tapeBlockSize = rf->getBlockSize();
        try {
          // Fill up the memory block with tape block
          // append conveniently returns false when there will not be more space
          // for an extra tape block, and throws an exception if we reached the
          // end of file. append() also protects against reading too big tape blocks.
          while (mb->m_payload.append(*rf)) {
79
          tapeBlock++;
David COME's avatar
David COME committed
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
          }
          // Pass the block to the disk write task
          m_fifo.pushDataBlock(mb.release());
        } catch (const castor::tape::exceptions::EndOfFile&) {
          // append() signaled the end of the file.
          stillReading = false;
        } 
        
      } //end of while(stillReading)
    
      } //end of try
      catch (castor::exception::Exception & ex) {
        //we end there because :
        //openReadFile brought us here (cant put the tape into position)
        //m_payload.append brought us here (error while reading the file)
95
96
97
98
99
100
101
102
103
104
105
        // This is an error case. Log and signal to the disk write task
        { 
          castor::log::LogContext::ScopedParam sp0(lc, Param("fileBlock", fileBlock));
          castor::log::LogContext::ScopedParam sp1(lc, Param("ErrorMessage", ex.getMessageValue()));
          castor::log::LogContext::ScopedParam sp2(lc, Param("ErrorCode", ex.code()));
          lc.log(LOG_ERR, "Error reading a file block in TapeReadFileTask (backtrace follows)");
        }
        {
          castor::log::LogContext lc2(lc.logger());
          lc2.logBacktrace(LOG_ERR, ex.backtrace());
        }
David COME's avatar
David COME committed
106
107
        
        //write the block 
108
109
110
111
112
113
114
        std::auto_ptr<MemBlock> mb(m_mm.getFreeBlock());
        mb->m_fSeq = m_fileToRecall->fseq();
        mb->m_failed = true;
        mb->m_fileBlock = -1;
        mb->m_fileid = m_fileToRecall->fileid();
        mb->m_tapeFileBlock = -1;
        m_fifo.pushDataBlock(mb.release());
David COME's avatar
David COME committed
115
116
        m_fifo.pushDataBlock(NULL);
        return;
117
118
119
120
121
      }
    // In all cases, we have to signal the end of the tape read to the disk write
    // task.
    m_fifo.pushDataBlock(NULL);
    lc.log(LOG_DEBUG, "File read completed");
122
123
  }
private:
David COME's avatar
David COME committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  
  // Open the file and manage failure (if any)
  std::auto_ptr<castor::tape::tapeFile::ReadFile> openReadFile(
  castor::tape::tapeFile::ReadSession & rs, castor::log::LogContext & lc){

    using castor::log::Param;
    typedef castor::log::LogContext::ScopedParam ScopedParam;

    std::auto_ptr<castor::tape::tapeFile::ReadFile> rf;
    try {
      rf.reset(new castor::tape::tapeFile::ReadFile(&rs, *m_fileToRecall));
      lc.log(LOG_DEBUG, "Successfully opened the tape file");
    } catch (castor::exception::Exception & ex) {
      // Log the error
      ScopedParam sp0(lc, Param("ErrorMessage", ex.getMessageValue()));
      ScopedParam sp1(lc, Param("ErrorCode", ex.code()));
      lc.log(LOG_ERR, "Failed to open tape file for reading");
      throw;
    }
    return rf;
  }
145
146
147
148
  std::auto_ptr<castor::tape::tapegateway::FileToRecallStruct> m_fileToRecall;
  DataConsumer & m_fifo;
  RecallMemoryManager & m_mm;

149
};
150
151
152
153
}
}
}
}
154