TimeZoneSnapshot::TimeZoneSnapshot(thread_db* tdbb, MemoryPool& pool) : SnapshotData(pool) { RecordBuffer* tzBuffer = allocBuffer(tdbb, pool, rel_time_zones); Record* tzRecord = tzBuffer->getTempRecord(); tzRecord->nullify(); TimeZoneUtil::iterateRegions( [=] (USHORT id, const char* name) { SINT64 idValue = id; putField(tdbb, tzRecord, DumpField(f_tz_id, VALUE_INTEGER, sizeof(idValue), &idValue)); putField(tdbb, tzRecord, DumpField(f_tz_name, VALUE_STRING, static_cast<USHORT>(strlen(name)), name)); tzBuffer->store(tzRecord); } ); }
RecordBuffer* DbCreatorsList::getList(thread_db* tdbb, jrd_rel* relation) { fb_assert(relation); fb_assert(relation->rel_id == rel_sec_db_creators); RecordBuffer* buffer = getData(relation); if (buffer) { return buffer; } RefPtr<IAttachment> att; RefPtr<ITransaction> tra; const char* dbName = tdbb->getDatabase()->dbb_config->getSecurityDatabase(); if (!openDb(dbName, att, tra)) { // In embedded mode we are not raising any errors - silent return if (MasterInterfacePtr()->serverMode(-1) < 0) return makeBuffer(tdbb); (Arg::Gds(isc_crdb_nodb) << dbName).raise(); } Message gr; Field<ISC_SHORT> uType(gr); Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN); FbLocalStatus st; RefPtr<IResultSet> curs(att->openCursor(&st, tra, 0, "select RDB$USER_TYPE, RDB$USER from RDB$DB_CREATORS", SQL_DIALECT_V6, NULL, NULL, gr.getMetadata(), NULL, 0)); if (st->getState() & IStatus::STATE_ERRORS) { if (!fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err)) check("IAttachment::openCursor", &st); // isc_dsql_relation_err when opening cursor - i.e. table // is missing due to non-FB3 security DB // In embedded mode we are not raising any errors - silent return if (MasterInterfacePtr()->serverMode(-1) < 0) return makeBuffer(tdbb); (Arg::Gds(isc_crdb_notable) << dbName).raise(); } try { buffer = makeBuffer(tdbb); while (curs->fetchNext(&st, gr.getBuffer()) == IStatus::RESULT_OK) { Record* record = buffer->getTempRecord(); record->nullify(); putField(tdbb, record, DumpField(f_sec_crt_user, VALUE_STRING, u->len, u->data)); SINT64 v = uType; putField(tdbb, record, DumpField(f_sec_crt_u_type, VALUE_INTEGER, sizeof(v), &v)); buffer->store(record); } check("IResultSet::fetchNext", &st); } catch (const Exception&) { clearSnapshot(); throw; } return getData(relation); }
void UserManagement::list(IUser* u, unsigned cachePosition) { RecordBuffer* buffer = getData(rel_sec_users); Record* record = buffer->getTempRecord(); record->nullify(); const MetaName& plugName(managers[cachePosition].first); putField(threadDbb, record, DumpField(f_sec_plugin, VALUE_STRING, static_cast<USHORT>(plugName.length()), plugName.c_str())); bool su = false; if (u->userName()->entered()) { const char* uname = u->userName()->get(); putField(threadDbb, record, DumpField(f_sec_user_name, VALUE_STRING, static_cast<USHORT>(strlen(uname)), uname)); su = strcmp(uname, SYSDBA_USER_NAME) == 0; } if (u->firstName()->entered()) { putField(threadDbb, record, DumpField(f_sec_first_name, VALUE_STRING, static_cast<USHORT>(strlen(u->firstName()->get())), u->firstName()->get())); } if (u->middleName()->entered()) { putField(threadDbb, record, DumpField(f_sec_middle_name, VALUE_STRING, static_cast<USHORT>(strlen(u->middleName()->get())), u->middleName()->get())); } if (u->lastName()->entered()) { putField(threadDbb, record, DumpField(f_sec_last_name, VALUE_STRING, static_cast<USHORT>(strlen(u->lastName()->get())), u->lastName()->get())); } if (u->active()->entered()) { UCHAR v = u->active()->get() ? '\1' : '\0'; putField(threadDbb, record, DumpField(f_sec_active, VALUE_BOOLEAN, sizeof(v), &v)); } if (su || u->admin()->entered()) { UCHAR v = (su || u->admin()->get()) ? '\1' : '\0'; putField(threadDbb, record, DumpField(f_sec_admin, VALUE_BOOLEAN, sizeof(v), &v)); } if (u->comment()->entered()) { putField(threadDbb, record, DumpField(f_sec_comment, VALUE_STRING, static_cast<USHORT>(strlen(u->comment()->get())), u->comment()->get())); } buffer->store(record); if (u->userName()->entered() && u->attributes()->entered()) { buffer = getData(rel_sec_user_attributes); ConfigFile cf(ConfigFile::USE_TEXT, u->attributes()->get(), ConfigFile::NO_COMMENTS); ConfigFile::Parameters::const_iterator e(cf.getParameters().end()); for (ConfigFile::Parameters::const_iterator b(cf.getParameters().begin()); b != e; ++b) { record = buffer->getTempRecord(); record->nullify(); putField(threadDbb, record, DumpField(f_sec_attr_user, VALUE_STRING, static_cast<USHORT>(strlen(u->userName()->get())), u->userName()->get())); putField(threadDbb, record, DumpField(f_sec_attr_key, VALUE_STRING, b->name.length(), b->name.c_str())); putField(threadDbb, record, DumpField(f_sec_attr_value, VALUE_STRING, b->value.length(), b->value.c_str())); buffer->store(record); } } }
MonitoringSnapshot::MonitoringSnapshot(thread_db* tdbb, MemoryPool& pool) : SnapshotData(pool) { SET_TDBB(tdbb); PAG_header(tdbb, true); Database* const dbb = tdbb->getDatabase(); fb_assert(dbb); Attachment* const attachment = tdbb->getAttachment(); fb_assert(attachment); const AttNumber self_att_id = attachment->att_attachment_id; // Initialize record buffers RecordBuffer* const dbb_buffer = allocBuffer(tdbb, pool, rel_mon_database); RecordBuffer* const att_buffer = allocBuffer(tdbb, pool, rel_mon_attachments); RecordBuffer* const tra_buffer = allocBuffer(tdbb, pool, rel_mon_transactions); RecordBuffer* const stmt_buffer = allocBuffer(tdbb, pool, rel_mon_statements); RecordBuffer* const call_buffer = allocBuffer(tdbb, pool, rel_mon_calls); RecordBuffer* const io_stat_buffer = allocBuffer(tdbb, pool, rel_mon_io_stats); RecordBuffer* const rec_stat_buffer = allocBuffer(tdbb, pool, rel_mon_rec_stats); RecordBuffer* const ctx_var_buffer = allocBuffer(tdbb, pool, rel_mon_ctx_vars); RecordBuffer* const mem_usage_buffer = allocBuffer(tdbb, pool, rel_mon_mem_usage); RecordBuffer* const tab_stat_buffer = allocBuffer(tdbb, pool, rel_mon_tab_stats); // Dump our own data and downgrade the lock, if required Monitoring::dumpAttachment(tdbb, attachment); if (!(attachment->att_flags & ATT_monitor_done)) { LCK_convert(tdbb, attachment->att_monitor_lock, LCK_SR, LCK_NO_WAIT); attachment->att_flags |= ATT_monitor_done; } // Enumerate active sessions const string& user_name = attachment->att_user->usr_user_name; const bool locksmith = attachment->locksmith(); const char* user_name_ptr = locksmith ? NULL : user_name.c_str(); MonitoringData::SessionList sessions(pool); Lock temp_lock(tdbb, sizeof(AttNumber), LCK_monitor), *lock = &temp_lock; { // scope for the guard MonitoringData::Guard guard(dbb->dbb_monitoring_data); dbb->dbb_monitoring_data->enumerate(sessions, user_name_ptr); } // Signal other sessions to dump their state { // scope for the temporary status ThreadStatusGuard temp_status(tdbb); for (AttNumber* iter = sessions.begin(); iter != sessions.end(); iter++) { if (*iter != self_att_id) { lock->lck_key.lck_long = *iter; if (LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT)) LCK_release(tdbb, lock); } } } // Collect monitoring data. Start by gathering database-level info, // it goes directly to the temporary space (as it's not stored in the shared dump). TempSpace temp_space(pool, SCRATCH); { // scope for putDatabase and its utilities TempWriter writer(temp_space); SnapshotData::DumpRecord tempRecord(pool, writer); Monitoring::putDatabase(tdbb, tempRecord); } // Read the dump into a temporary space. While being there, // also check for dead sessions and garbage collect them. { // scope for the guard MonitoringData::Guard guard(dbb->dbb_monitoring_data); ThreadStatusGuard temp_status(tdbb); lock->lck_type = LCK_attachment; for (AttNumber* iter = sessions.begin(); iter != sessions.end(); iter++) { if (*iter != self_att_id) { lock->lck_key.lck_long = *iter; if (LCK_lock(tdbb, lock, LCK_EX, LCK_NO_WAIT)) { LCK_release(tdbb, lock); dbb->dbb_monitoring_data->cleanup(*iter); } } } dbb->dbb_monitoring_data->read(user_name_ptr, temp_space); } // Parse the dump MonitoringData::Reader reader(pool, temp_space); SnapshotData::DumpRecord dumpRecord(pool); while (reader.getRecord(dumpRecord)) { const int rid = dumpRecord.getRelationId(); RecordBuffer* buffer = NULL; Record* record = NULL; switch (rid) { case rel_mon_database: buffer = dbb_buffer; break; case rel_mon_attachments: buffer = att_buffer; break; case rel_mon_transactions: buffer = tra_buffer; break; case rel_mon_statements: buffer = stmt_buffer; break; case rel_mon_calls: buffer = call_buffer; break; case rel_mon_io_stats: buffer = io_stat_buffer; break; case rel_mon_rec_stats: buffer = rec_stat_buffer; break; case rel_mon_ctx_vars: buffer = ctx_var_buffer; break; case rel_mon_mem_usage: buffer = mem_usage_buffer; break; case rel_mon_tab_stats: buffer = tab_stat_buffer; break; default: fb_assert(false); } if (buffer) { record = buffer->getTempRecord(); record->nullify(); } bool store_record = false; SnapshotData::DumpField dumpField; while (dumpRecord.getField(dumpField)) { if (record) { putField(tdbb, record, dumpField); store_record = true; } } if (store_record) buffer->store(record); } }