GenericObject.cpp 7.42 KB
Newer Older
1
/*
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 * 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/>.
 */

19
#include "GenericObject.hpp"
20
#include "AgentRegister.hpp"
21
#include "Agent.hpp"
22
#include "ArchiveRequest.hpp"
23
#include "DriveRegister.hpp"
24
#include "DriveState.hpp"
25
26
#include "RootEntry.hpp"
#include "SchedulerGlobalLock.hpp"
27
28
#include "ArchiveQueue.hpp"
#include "RetrieveQueue.hpp"
29
#include "DriveRegister.hpp"
Eric Cano's avatar
Eric Cano committed
30
#include <stdexcept>
31
#include <google/protobuf/util/json_util.h>
32
33
34

namespace cta {  namespace objectstore {

35
36
37
38
39
40
serializers::ObjectType GenericObject::type() {
  checkHeaderReadable();
  return m_header.type();
}

void GenericObject::getHeaderFromObjectData(const std::string& objData) {
41
  if (!m_header.ParseFromString(objData)) {
42
    // Use the tolerant parser to assess the situation.
43
    m_header.ParsePartialFromString(objData);
44
45
46
47
48
49
50
51
52
53
    // Base64 encode the header for diagnostics.
    const bool noNewLineInBase64Output = false;
    std::string objDataBase64;
    CryptoPP::StringSource ss1(objData, true,
      new CryptoPP::Base64Encoder(
         new CryptoPP::StringSink(objDataBase64), noNewLineInBase64Output));
    throw cta::exception::Exception(std::string("In <GenericObject::getHeaderFromObjectData(): could not parse header: ") + 
            m_header.InitializationErrorString() + 
            " size=" + std::to_string(objData.size()) + " data(b64)=\"" + 
            objDataBase64 + "\"");
54
  }
55
56
57
58
59
  m_headerInterpreted = true;
}

void GenericObject::commit() {
  checkHeaderWritable();
60
  m_objectStore.atomicOverwrite(getAddressIfSet(), m_header.SerializeAsString());
61
62
63
64
65
66
67
68
69
70
}

void GenericObject::insert() {
  throw ForbiddenOperation("In GenericObject::insert: this operation is not possible");
}

void GenericObject::initialize() {
  throw ForbiddenOperation("In GenericObject::initialize: this operation is not possible");
}

71
72
73
74
75
76
void GenericObject::transplantHeader(ObjectOpsBase& destination) {
  destination.m_header = m_header;
  destination.m_existingObject = m_existingObject;
  destination.m_headerInterpreted = m_headerInterpreted;
  destination.m_name = m_name;
  destination.m_nameSet = m_nameSet;
77
  destination.m_noLock = m_noLock;
78
  destination.m_payloadInterpreted = false;
79
}
80
81
82
83
84

Backend& GenericObject::objectStore() {
  return m_objectStore;
}

85
86
87
88
89
namespace {
  using cta::objectstore::GenericObject;
  using cta::objectstore::ScopedExclusiveLock;
  template <class C>
  void garbageCollectWithType(GenericObject * gop, ScopedExclusiveLock& lock,
90
91
      const std::string &presumedOwner, AgentReference & agentReference, log::LogContext & lc,
    cta::catalogue::Catalogue & catalogue) {
92
93
    C typedObject(*gop);
    lock.transfer(typedObject);
94
    typedObject.garbageCollect(presumedOwner, agentReference, lc, catalogue);
95
96
97
98
99
    // Release the lock now as if we let the caller do, it will point
    // to the then-removed typedObject.
    lock.release();
  }
}
100

101
102
void GenericObject::garbageCollect(const std::string& presumedOwner, AgentReference & agentReference, log::LogContext & lc,
    cta::catalogue::Catalogue & catalogue) {
103
104
105
106
  throw ForbiddenOperation("In GenericObject::garbageCollect(): GenericObject cannot be garbage collected");
}

void GenericObject::garbageCollectDispatcher(ScopedExclusiveLock& lock, 
107
108
    const std::string &presumedOwner, AgentReference & agentReference, log::LogContext & lc,
    cta::catalogue::Catalogue & catalogue) {
109
110
  checkHeaderWritable();
  switch(m_header.type()) {
111
    case serializers::AgentRegister_t:
112
      garbageCollectWithType<AgentRegister>(this, lock, presumedOwner, agentReference, lc, catalogue);
113
      break;
114
    case serializers::Agent_t:
115
      garbageCollectWithType<Agent>(this, lock, presumedOwner, agentReference, lc, catalogue);
116
      break;
117
    case serializers::DriveRegister_t:
118
      garbageCollectWithType<DriveRegister>(this, lock, presumedOwner, agentReference, lc, catalogue);
119
120
121
      break;
    case serializers::DriveState_t:
      garbageCollectWithType<DriveState>(this, lock, presumedOwner, agentReference, lc, catalogue);
122
      break;
123
    case serializers::SchedulerGlobalLock_t:
124
      garbageCollectWithType<SchedulerGlobalLock>(this, lock, presumedOwner, agentReference, lc, catalogue);
125
      break;
126
    case serializers::ArchiveRequest_t:
127
      garbageCollectWithType<ArchiveRequest>(this, lock, presumedOwner, agentReference, lc, catalogue);
128
      break;
129
    case serializers::RetrieveRequest_t:
130
      garbageCollectWithType<RetrieveRequest>(this, lock, presumedOwner, agentReference, lc, catalogue);
131
      break;
132
    case serializers::ArchiveQueue_t:
133
      garbageCollectWithType<ArchiveQueue>(this, lock, presumedOwner, agentReference, lc, catalogue);
134
      break;
135
    case serializers::RetrieveQueue_t:
136
      garbageCollectWithType<RetrieveQueue>(this, lock, presumedOwner, agentReference, lc, catalogue);
137
      break;
138
139
140
141
142
143
144
145
146
    default: {
      std::stringstream err;
      err << "In GenericObject::garbageCollect, unsupported type: "
          << m_header.type();
      throw UnsupportedType(err.str());
    }
  }
}

Eric Cano's avatar
Eric Cano committed
147
148
149
150
namespace {
  using cta::objectstore::GenericObject;
  using cta::objectstore::ScopedExclusiveLock;
  template <class C>
151
  std::string dumpWithType(GenericObject * gop) {
Eric Cano's avatar
Eric Cano committed
152
    C typedObject(*gop);
153
    ScopedLock::transfer(*gop, typedObject);
Eric Cano's avatar
Eric Cano committed
154
155
156
157
158
159
160
    std::string ret = typedObject.dump();
    // Release the lock now as if we let the caller do, it will point
    // to the then-removed typedObject.
    return ret;
  }
}

161
std::string GenericObject::dump() {
Eric Cano's avatar
Eric Cano committed
162
  checkHeaderReadable();
163
164
165
166
167
168
  google::protobuf::util::JsonPrintOptions options;
  options.add_whitespace = true;
  options.always_print_primitive_fields = true;
  std::string headerDump;
  std::string bodyDump;
  google::protobuf::util::MessageToJsonString(m_header, &headerDump, options);
Eric Cano's avatar
Eric Cano committed
169
  switch(m_header.type()) {
170
    case serializers::RootEntry_t:
171
      bodyDump = dumpWithType<RootEntry>(this);
172
      break;
Eric Cano's avatar
Eric Cano committed
173
    case serializers::AgentRegister_t:
174
      bodyDump = dumpWithType<AgentRegister>(this);
175
      break;
176
    case serializers::Agent_t:
177
      bodyDump = dumpWithType<Agent>(this);
178
      break;
179
    case serializers::DriveRegister_t:
180
      bodyDump = dumpWithType<DriveRegister>(this);
181
      break;
182
    case serializers::ArchiveQueue_t:
183
      bodyDump = dumpWithType<cta::objectstore::ArchiveQueue>(this);
184
      break;
185
    case serializers::RetrieveQueue_t:
186
      bodyDump = dumpWithType<cta::objectstore::RetrieveQueue>(this);
187
      break;
188
    case serializers::ArchiveRequest_t:
189
      bodyDump = dumpWithType<ArchiveRequest>(this);
190
      break;
Eric Cano's avatar
Eric Cano committed
191
    case serializers::RetrieveRequest_t:
192
      bodyDump = dumpWithType<RetrieveRequest>(this);
193
      break;
194
    case serializers::SchedulerGlobalLock_t:
195
      bodyDump = dumpWithType<SchedulerGlobalLock>(this);
196
      break;
Eric Cano's avatar
Eric Cano committed
197
    default:
198
199
200
      std::stringstream err;
      err << "Unsupported type: " << m_header.type();
      throw std::runtime_error(err.str());
Eric Cano's avatar
Eric Cano committed
201
  }
202
  return std::string ("Header dump:\n") + headerDump + "Body dump:\n" + bodyDump;
Eric Cano's avatar
Eric Cano committed
203
}
204

205
}}