To avoid leaks.
Fixes: http://tracker.ceph.com/issues/38324
Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
#define dout_context g_ceph_context
-LogEvent *LogEvent::decode(bufferlist& bl)
+std::unique_ptr<LogEvent> LogEvent::decode_event(bufferlist::const_iterator p)
{
// parse type, length
- auto p = bl.cbegin();
EventType type;
- LogEvent *event = NULL;
+ std::unique_ptr<LogEvent> event;
using ceph::decode;
decode(type, p);
try {
DECODE_START(1, p);
decode(type, p);
- event = decode_event(bl, p, type);
+ event = decode_event(p, type);
DECODE_FINISH(p);
}
catch (const buffer::error &e) {
return NULL;
}
} else { // we are using classic encoding
- event = decode_event(bl, p, type);
+ event = decode_event(p, type);
}
return event;
}
}
-LogEvent *LogEvent::decode_event(bufferlist& bl, bufferlist::const_iterator& p, LogEvent::EventType type)
+std::unique_ptr<LogEvent> LogEvent::decode_event(bufferlist::const_iterator& p, LogEvent::EventType type)
{
- int length = bl.length() - p.get_off();
+ const auto length = p.get_remaining();
generic_dout(15) << "decode_log_event type " << type << ", size " << length << dendl;
// create event
- LogEvent *le;
+ std::unique_ptr<LogEvent> le;
switch (type) {
- case EVENT_SUBTREEMAP: le = new ESubtreeMap; break;
+ case EVENT_SUBTREEMAP:
+ le = std::make_unique<ESubtreeMap>();
+ break;
case EVENT_SUBTREEMAP_TEST:
- le = new ESubtreeMap;
+ le = std::make_unique<ESubtreeMap>();
le->set_type(type);
break;
- case EVENT_EXPORT: le = new EExport; break;
- case EVENT_IMPORTSTART: le = new EImportStart; break;
- case EVENT_IMPORTFINISH: le = new EImportFinish; break;
- case EVENT_FRAGMENT: le = new EFragment; break;
-
- case EVENT_RESETJOURNAL: le = new EResetJournal; break;
-
- case EVENT_SESSION: le = new ESession; break;
- case EVENT_SESSIONS_OLD: le = new ESessions; (static_cast<ESessions *>(le))->mark_old_encoding(); break;
- case EVENT_SESSIONS: le = new ESessions; break;
-
- case EVENT_UPDATE: le = new EUpdate; break;
- case EVENT_SLAVEUPDATE: le = new ESlaveUpdate; break;
- case EVENT_OPEN: le = new EOpen; break;
- case EVENT_COMMITTED: le = new ECommitted; break;
-
- case EVENT_TABLECLIENT: le = new ETableClient; break;
- case EVENT_TABLESERVER: le = new ETableServer; break;
-
- case EVENT_NOOP: le = new ENoOp; break;
-
+ case EVENT_EXPORT:
+ le = std::make_unique<EExport>();
+ break;
+ case EVENT_IMPORTSTART:
+ le = std::make_unique<EImportStart>();
+ break;
+ case EVENT_IMPORTFINISH:
+ le = std::make_unique<EImportFinish>();
+ break;
+ case EVENT_FRAGMENT:
+ le = std::make_unique<EFragment>();
+ break;
+ case EVENT_RESETJOURNAL:
+ le = std::make_unique<EResetJournal>();
+ break;
+ case EVENT_SESSION:
+ le = std::make_unique<ESession>();
+ break;
+ case EVENT_SESSIONS_OLD:
+ {
+ auto e = std::make_unique<ESessions>();
+ e->mark_old_encoding();
+ le = std::move(e);
+ }
+ break;
+ case EVENT_SESSIONS:
+ le = std::make_unique<ESessions>();
+ break;
+ case EVENT_UPDATE:
+ le = std::make_unique<EUpdate>();
+ break;
+ case EVENT_SLAVEUPDATE:
+ le = std::make_unique<ESlaveUpdate>();
+ break;
+ case EVENT_OPEN:
+ le = std::make_unique<EOpen>();
+ break;
+ case EVENT_COMMITTED:
+ le = std::make_unique<ECommitted>();
+ break;
+ case EVENT_TABLECLIENT:
+ le = std::make_unique<ETableClient>();
+ break;
+ case EVENT_TABLESERVER:
+ le = std::make_unique<ETableServer>();
+ break;
+ case EVENT_NOOP:
+ le = std::make_unique<ENoOp>();
+ break;
default:
generic_dout(0) << "uh oh, unknown log event type " << type << " length " << length << dendl;
- return NULL;
+ return nullptr;
}
// decode
}
catch (const buffer::error &e) {
generic_dout(0) << "failed to decode LogEvent type " << type << dendl;
- delete le;
- return NULL;
+ return nullptr;
}
ceph_assert(p.end());
private:
EventType _type;
uint64_t _start_off;
- static LogEvent *decode_event(bufferlist& bl, bufferlist::const_iterator& p, EventType type);
+ static std::unique_ptr<LogEvent> decode_event(bufferlist::const_iterator&, EventType);
protected:
utime_t stamp;
// encoding
virtual void encode(bufferlist& bl, uint64_t features) const = 0;
- virtual void decode(bufferlist::const_iterator &bl) = 0;
- static LogEvent *decode(bufferlist &bl);
+ virtual void decode(bufferlist::const_iterator &) = 0;
+ static std::unique_ptr<LogEvent> decode_event(bufferlist::const_iterator);
virtual void dump(Formatter *f) const = 0;
void encode_with_header(bufferlist& bl, uint64_t features) {
ceph_assert(r);
// Update segment_pos_rewrite
- LogEvent *le = LogEvent::decode(bl);
+ auto le = LogEvent::decode_event(bl.cbegin());
if (le) {
bool modified = false;
if (le->get_type() == EVENT_SUBTREEMAP ||
le->get_type() == EVENT_RESETJOURNAL) {
- ESubtreeMap *sle = dynamic_cast<ESubtreeMap*>(le);
+ auto sle = dynamic_cast<ESubtreeMap*>(le.get());
if (sle == NULL || sle->event_seq == 0) {
// A non-explicit event seq: the effective sequence number
// of this segment is it's position in the old journal and
// (expire_pos is just an optimization so it's safe to eliminate it)
if (le->get_type() == EVENT_SUBTREEMAP
|| le->get_type() == EVENT_SUBTREEMAP_TEST) {
- ESubtreeMap *sle = dynamic_cast<ESubtreeMap*>(le);
- ceph_assert(sle != NULL);
+ auto& sle = dynamic_cast<ESubtreeMap&>(*le);
dout(20) << __func__ << " zeroing expire_pos in subtreemap event at "
- << le_pos << " seq=" << sle->event_seq << dendl;
- sle->expire_pos = 0;
+ << le_pos << " seq=" << sle.event_seq << dendl;
+ sle.expire_pos = 0;
modified = true;
}
bl.clear();
le->encode_with_header(bl, mds->mdsmap->get_up_features());
}
-
- delete le;
} else {
// Failure from LogEvent::decode, our job is to change the journal wrapper,
// not validate the contents, so pass it through.
ceph_assert(r);
// unpack event
- LogEvent *le = LogEvent::decode(bl);
+ auto le = LogEvent::decode_event(bl.cbegin());
if (!le) {
dout(0) << "_replay " << pos << "~" << bl.length() << " / " << journaler->get_write_pos()
<< " -- unable to decode event" << dendl;
// new segment?
if (le->get_type() == EVENT_SUBTREEMAP ||
le->get_type() == EVENT_RESETJOURNAL) {
- ESubtreeMap *sle = dynamic_cast<ESubtreeMap*>(le);
+ auto sle = dynamic_cast<ESubtreeMap*>(le.get());
if (sle && sle->event_seq > 0)
event_seq = sle->event_seq;
else
le->replay(mds);
}
}
- delete le;
logger->set(l_mdl_rdpos, pos);
}
for (JournalScanner::EventMap::const_iterator i = scan.events.begin(); i != scan.events.end(); ++i) {
bufferlist bin;
std::stringstream filename;
- if (i->second.log_event) {
- LogEvent *le = i->second.log_event;
+ if (auto& le = i->second.log_event; le) {
le->encode(bin, CEPH_FEATURES_SUPPORTED_DEFAULT);
filename << "0x" << std::hex << i->first << std::dec << "_" << le->get_type_str() << ".bin";
- } else if (i->second.pi) {
- PurgeItem* pi = i->second.pi;
+ } else if (auto& pi = i->second.pi; pi) {
pi->encode(bin);
filename << "0x" << std::hex << i->first << std::dec << "_" << pi->get_type_str() << ".bin";
}
jf.open_array_section("journal");
{
for (JournalScanner::EventMap::const_iterator i = scan.events.begin(); i != scan.events.end(); ++i) {
- if (i->second.log_event) {
- LogEvent *le = i->second.log_event;
+ if (auto& le = i->second.log_event; le) {
jf.open_object_section("log_event");
- {
- le->dump(&jf);
- }
+ le->dump(&jf);
jf.close_section(); // log_event
- } else if (i->second.pi) {
- PurgeItem* pi = i->second.pi;
+ } else if (auto& pi = i->second.pi; pi) {
jf.open_object_section("purge_action");
pi->dump(&jf);
jf.close_section();
void EventOutput::list() const
{
for (JournalScanner::EventMap::const_iterator i = scan.events.begin(); i != scan.events.end(); ++i) {
- if (i->second.log_event) {
+ if (auto& le = i->second.log_event; le) {
std::vector<std::string> ev_paths;
- EMetaBlob const *emb = i->second.log_event->get_metablob();
+ EMetaBlob const *emb = le->get_metablob();
if (emb) {
emb->get_paths(ev_paths);
}
std::string detail;
- if (i->second.log_event->get_type() == EVENT_UPDATE) {
- EUpdate *eu = reinterpret_cast<EUpdate*>(i->second.log_event);
- detail = eu->type;
+ if (le->get_type() == EVENT_UPDATE) {
+ auto& eu = reinterpret_cast<EUpdate&>(*le);
+ detail = eu.type;
}
- std::cout <<i->second.log_event->get_stamp() << " 0x"
+ std::cout << le->get_stamp() << " 0x"
<< std::hex << i->first << std::dec << " "
- << i->second.log_event->get_type_str() << ": "
+ << le->get_type_str() << ": "
<< " (" << detail << ")" << std::endl;
for (std::vector<std::string>::iterator i = ev_paths.begin(); i != ev_paths.end(); ++i) {
std::cout << " " << *i << std::endl;
}
- } else if (i->second.pi) {
- std::cout << i->second.pi->stamp << " 0x"
+ } else if (auto& pi = i->second.pi; pi) {
+ std::cout << pi->stamp << " 0x"
<< std::hex << i->first << std::dec << " "
- << i->second.pi->get_type_str() << std::endl;
+ << pi->get_type_str() << std::endl;
}
}
}
std::map<std::string, int> type_count;
for (JournalScanner::EventMap::const_iterator i = scan.events.begin(); i != scan.events.end(); ++i) {
std::string type;
- if (i->second.log_event)
- type = i->second.log_event->get_type_str();
- else if (i->second.pi)
- type = i->second.pi->get_type_str();
+ if (auto& le = i->second.log_event; le)
+ type = le->get_type_str();
+ else if (auto& pi = i->second.pi; pi)
+ type = pi->get_type_str();
if (type_count.count(type) == 0) {
type_count[type] = 0;
}
}
bool valid_entry = true;
if (is_mdlog) {
- LogEvent *le = LogEvent::decode(le_bl);
+ auto le = LogEvent::decode_event(le_bl.cbegin());
if (le) {
dout(10) << "Valid entry at 0x" << std::hex << read_offset << std::dec << dendl;
if (le->get_type() == EVENT_SUBTREEMAP
|| le->get_type() == EVENT_SUBTREEMAP_TEST) {
- ESubtreeMap *sle = dynamic_cast<ESubtreeMap*>(le);
- if (sle->expire_pos > read_offset) {
+ auto&& sle = dynamic_cast<ESubtreeMap&>(*le);
+ if (sle.expire_pos > read_offset) {
errors.insert(std::make_pair(
read_offset, EventError(
-ERANGE,
}
if (filter.apply(read_offset, *le)) {
- events[read_offset] = EventRecord(le, consumed);
- } else {
- delete le;
+ events.insert_or_assign(read_offset, EventRecord(std::move(le), consumed));
}
} else {
valid_entry = false;
}
} else if (type == "purge_queue"){
- PurgeItem* pi = new PurgeItem();
+ auto pi = std::make_unique<PurgeItem>();
try {
auto q = le_bl.cbegin();
pi->decode(q);
if (filter.apply(read_offset, *pi)) {
- events[read_offset] = EventRecord(pi, consumed);
- } else {
- delete pi;
+ events.insert_or_assign(read_offset, EventRecord(std::move(pi), consumed));
}
} catch (const buffer::error &err) {
valid_entry = false;
header = NULL;
}
dout(4) << events.size() << " events" << dendl;
- for (EventMap::iterator i = events.begin(); i != events.end(); ++i) {
- if (i->second.log_event)
- delete i->second.log_event;
- else if (i->second.pi)
- delete i->second.pi;
- }
events.clear();
}
// The results of the scan
inodeno_t ino; // Corresponds to journal ino according their type
- class EventRecord {
- public:
- EventRecord() : log_event(NULL), raw_size(0) {}
- EventRecord(LogEvent *le, uint32_t rs) : log_event(le), pi(NULL), raw_size(rs) {}
- EventRecord(PurgeItem* p, uint32_t rs) : log_event(NULL), pi(p), raw_size(rs) {}
- LogEvent *log_event;
- PurgeItem *pi;
- uint32_t raw_size; //< Size from start offset including all encoding overhead
+ struct EventRecord {
+ EventRecord(std::unique_ptr<LogEvent> le, uint32_t rs) : log_event(std::move(le)), raw_size(rs) {}
+ EventRecord(std::unique_ptr<PurgeItem> p, uint32_t rs) : pi(std::move(p)), raw_size(rs) {}
+ std::unique_ptr<LogEvent> log_event;
+ std::unique_ptr<PurgeItem> pi;
+ uint32_t raw_size = 0; //< Size from start offset including all encoding overhead
};
class EventError {
std::set<inodeno_t> consumed_inos;
for (JournalScanner::EventMap::iterator i = js.events.begin();
i != js.events.end(); ++i) {
- LogEvent *le = i->second.log_event;
+ auto& le = i->second.log_event;
EMetaBlob const *mb = le->get_metablob();
if (mb) {
int scav_r = recover_dentries(*mb, dry_run, &consumed_inos);