/** Initiate a page flush to advance the log checkpoint.
@param flush_lsn target checkpoint LSN, the LSB set for "furious flush" */
ATTRIBUTE_NOINLINE ATTRIBUTE_COLD void mtr_flush_ahead(lsn_t flush_lsn) noexcept;
/** Mini-transaction memo stack slot. */ struct mtr_memo_slot_t
{ /** pointer to the object */ void *object; /** type of the stored object */
mtr_memo_type_t type;
/** Release the object */ void release() const;
};
/** Commit the mini-transaction. */ void commit();
/** Release latches of unmodified buffer pages. @parambeginfirstslottorelease
@param end last slot to release, or get_savepoint() */ void rollback_to_savepoint(ulint begin, ulint end);
/** Release latches of unmodified buffer pages.
@param begin first slot to release */ void rollback_to_savepoint(ulint begin)
{ rollback_to_savepoint(begin, m_memo.size()); }
/** Release the last acquired buffer page latch. */ void release_last_page()
{ auto s= m_memo.size(); rollback_to_savepoint(s - 1, s); }
/** Commit a mini-transaction that is shrinking a tablespace. @paramspacetablespacethatisbeingshrunk
@param size new size in pages */
ATTRIBUTE_COLD void commit_shrink(fil_space_t &space, uint32_t size);
/** Commit a mini-transaction that is deleting or renaming a file. @paramspacetablespacethatisbeingrenamedordeleted @paramnamenewfilename(nullptr=thefilewillbedeleted)
@return whether the operation succeeded */
ATTRIBUTE_COLD bool commit_file(fil_space_t &space, constchar *name);
/** Commit a mini-transaction that did not modify any pages, butgeneratedsomeredologonahigherlevel,suchas FILE_MODIFYrecordsandanoptionalFILE_CHECKPOINTmarker. Thecallermustholdexclusivelog_sys.latch. Thisistobeusedatlog_checkpoint(). @paramcheckpoint_lsnthelogsequencenumberofacheckpoint,or0
@return current LSN */
ATTRIBUTE_COLD lsn_t commit_files(lsn_t checkpoint_lsn= 0);
/** Get the block at a savepoint */
buf_block_t *at_savepoint(ulint savepoint) const
{
ut_ad(is_active()); const mtr_memo_slot_t &slot= m_memo[savepoint];
ut_ad(slot.type < MTR_MEMO_S_LOCK);
ut_ad(slot.object); returnstatic_cast<buf_block_t*>(slot.object);
}
/** Try to get a block at a savepoint. @paramsavepointthesavepointrightbeforetheblockwasacquired @returntheblockatthesavepoint
@retval nullptr if no buffer block was registered at that savepoint */
buf_block_t *block_at_savepoint(ulint savepoint) const
{
ut_ad(is_active()); const mtr_memo_slot_t &slot= m_memo[savepoint]; return slot.type < MTR_MEMO_S_LOCK
? static_cast<buf_block_t*>(slot.object)
: nullptr;
}
/** Retrieve a page that has already been latched. @paramidpageidentifier @paramtypepagelatchtype @returnblock
@retval nullptr if the block had not been latched yet */
buf_block_t *get_already_latched(const page_id_t id, mtr_memo_type_t type) const;
/** Set the log mode of a sub-minitransaction
@param mtr parent mini-transaction */ void set_log_mode_sub(const mtr_t &mtr)
{
ut_ad(mtr.m_log_mode == MTR_LOG_ALL || mtr.m_log_mode == MTR_LOG_NO_REDO);
m_log_mode= mtr.m_log_mode | MTR_LOG_SUB;
static_assert((MTR_LOG_SUB | MTR_LOG_NO_REDO) == MTR_LOG_NO_REDO, "");
}
/** Check if we are holding a block latch in exclusive mode
@param block buffer pool block to search for */ bool have_x_latch(const buf_block_t &block) const;
/** Check if we are holding a block latch in S or U mode
@param block buffer pool block to search for */ bool have_u_or_x_latch(const buf_block_t &block) const;
/** Copy the tablespaces associated with the mini-transaction (neededforgeneratingFILE_MODIFYrecords) @param[in]mtrmini-transactionthatmaymodify
the same set of tablespaces as this one */ void set_spaces(const mtr_t& mtr)
{
ut_ad(!m_user_space_id);
ut_ad(!m_user_space);
/** Set the tablespace associated with the mini-transaction (neededforgeneratingaFILE_MODIFYrecord) @param[in]space_iduserorsystemtablespaceID
@return the tablespace */
fil_space_t* set_named_space_id(uint32_t space_id)
{
ut_ad(!m_user_space_id);
ut_d(m_user_space_id = space_id); if (!space_id) { return fil_system.sys_space;
} else {
ut_ad(m_user_space_id == space_id);
ut_ad(!m_user_space);
m_user_space = fil_space_get(space_id);
ut_ad(m_user_space); return m_user_space;
}
}
/** Set the tablespace associated with the mini-transaction (neededforgeneratingaFILE_MODIFYrecord)
@param[in] space user or system tablespace */ void set_named_space(fil_space_t* space)
{
ut_ad(!m_user_space_id);
ut_d(m_user_space_id = space->id); if (space->id) {
m_user_space = space;
}
}
#ifdef UNIV_DEBUG /** Check the tablespace associated with the mini-transaction (neededforgeneratingaFILE_MODIFYrecord) @param[in]spacetablespace
@return whether the mini-transaction is associated with the space */ bool is_named_space(uint32_t space) const; /** Check the tablespace associated with the mini-transaction (neededforgeneratingaFILE_MODIFYrecord) @param[in]spacetablespace
@return whether the mini-transaction is associated with the space */ bool is_named_space(const fil_space_t* space) const; #endif/* UNIV_DEBUG */
/** Acquire a tablespace X-latch. @paramspace_idtablespaceID
@return the tablespace object (never NULL) */
fil_space_t *x_lock_space(uint32_t space_id);
/** Acquire an exclusive tablespace latch.
@param space tablespace */ void x_lock_space(fil_space_t *space);
/** Release an index latch. */ void release(const index_lock &lock) { release(&lock); } /** Release a latch to an unmodified page. */ void release(const buf_block_t &block) { release(&block); } private: /** Release an unmodified object. */ void release(constvoid *object); public: /** Mark the given latched page as modified.
@param block page that will be modified */ void set_modified(const buf_block_t &block);
/** Set the state to not-modified. This will not log the changes.
This is only used during redo log apply, to avoid logging the changes. */ void discard_modifications() { m_modifications= false; }
/** Get the LSN of commit(). @returnthecommitLSN
@retval 0 if the transaction only modified temporary tablespaces */
lsn_t commit_lsn() const { ut_ad(has_committed()); return m_commit_lsn; }
/** Note that some pages have been freed */ void set_trim_pages() { m_trim_pages= true; }
/** Latch a buffer pool block. @paramblockblocktobelatched @paramrw_latchRW_S_LATCH,RW_SX_LATCH,RW_X_LATCH,RW_NO_LATCH
@return block */
buf_block_t *page_lock(buf_block_t *block, ulint rw_latch) noexcept;
/** Acquire a latch on a buffer-fixed buffer pool block. @paramsavepointsavepointlocationofthebuffer-fixedblock
@param rw_latch latch to acquire */ void upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch) noexcept;
/** Register a change to the page latch state. */ void lock_register(ulint savepoint, mtr_memo_type_t type)
{
mtr_memo_slot_t &slot= m_memo[savepoint];
ut_ad(slot.type <= MTR_MEMO_BUF_FIX);
ut_ad(type < MTR_MEMO_S_LOCK);
slot.type= type;
}
/** Upgrade U locks on a block to X @paramblockblockonwhichtoupgrade
@return &block */
buf_block_t *page_lock_upgrade(const buf_block_t &block) noexcept;
/** Upgrade index U lock to X */
ATTRIBUTE_COLD void index_lock_upgrade();
/** Check if we are holding tablespace latch @paramspacetablespacetosearchfor
@return whether space.latch is being held */ bool memo_contains(const fil_space_t& space) const
MY_ATTRIBUTE((warn_unused_result)); #ifdef UNIV_DEBUG /** Check if we are holding an rw-latch in this mini-transaction @paramlocklatchtosearchfor @paramtypeheldlatchtype
@return whether (lock,type) is contained */ bool memo_contains(const index_lock &lock, mtr_memo_type_t type) const
MY_ATTRIBUTE((warn_unused_result));
/** Check if memo contains an index or buffer block latch. @paramobjectobjecttosearch @paramflagsspecifytypesofobjectlatches
@return true if contains */ bool memo_contains_flagged(constvoid *object, ulint flags) const
MY_ATTRIBUTE((warn_unused_result, nonnull));
/** Check if memo contains the given page. @paramptrpointertowithinpageframe @paramflagstypeslatchtolookfor @returntheblock
@retval nullptr if not found */
buf_block_t *memo_contains_page_flagged(const byte *ptr, ulint flags) const;
/** @return whether this mini-transaction modifies persistent data */ bool has_modifications() const { return m_modifications; } #endif/* UNIV_DEBUG */
/** Push a buffer page to an the memo. @paramblockbufferblock
@param type object type: MTR_MEMO_S_LOCK, ... */ void memo_push(buf_block_t *block, mtr_memo_type_t type)
__attribute__((nonnull))
{
ut_ad(is_active());
ut_ad(type <= MTR_MEMO_PAGE_SX_MODIFY);
ut_ad(block->page.buf_fix_count());
ut_ad(block->page.in_file()); #ifdef UNIV_DEBUG switch (type) { case MTR_MEMO_PAGE_S_FIX:
ut_ad(block->page.lock.have_s()); break; case MTR_MEMO_PAGE_X_FIX: case MTR_MEMO_PAGE_X_MODIFY:
ut_ad(block->page.lock.have_x()); break; case MTR_MEMO_PAGE_SX_FIX: case MTR_MEMO_PAGE_SX_MODIFY:
ut_ad(block->page.lock.have_u_or_x()); break; case MTR_MEMO_BUF_FIX: break; case MTR_MEMO_MODIFY: case MTR_MEMO_S_LOCK: case MTR_MEMO_X_LOCK: case MTR_MEMO_SX_LOCK: case MTR_MEMO_SPACE_X_LOCK:
ut_ad("invalid type" == 0);
} #endif if (!(type & MTR_MEMO_MODIFY)); elseif (block->page.id().space() >= SRV_TMP_SPACE_ID)
{
block->page.set_temp_modified();
type= mtr_memo_type_t(type & ~MTR_MEMO_MODIFY);
} else
{
m_modifications= true; if (!m_made_dirty) /* If we are going to modify a previously clean persistent page, wemustsetm_made_dirty,sothatcommit()willacquire log_sys.flush_order_mutexandinserttheblockinto
buf_pool.flush_list. */
m_made_dirty= block->page.oldest_modification() <= 1;
}
m_memo.emplace_back(mtr_memo_slot_t{block, type});
}
/** Push an index lock or tablespace latch to the memo. @paramobjectindexlockortablespacelatch
@param type object type: MTR_MEMO_S_LOCK, ... */ void memo_push(void *object, mtr_memo_type_t type) __attribute__((nonnull))
{
ut_ad(is_active());
ut_ad(type >= MTR_MEMO_S_LOCK);
m_memo.emplace_back(mtr_memo_slot_t{object, type});
}
/** @return the size of the log */
size_t get_log_size() const noexcept
{
size_t len= 0; for (const mtr_buf_t::block_t &b : m_log)
len+= b.used(); return len;
} /** @return whether the log and memo are empty */ bool is_empty() const { return !get_savepoint() && m_log.empty(); }
/** @return whether no redo log has been written in this
mini-transaction */ bool has_no_log() const { return m_log.empty(); }
/** Write an OPT_PAGE_CHECKSUM record. */ inlinevoid page_checksum(const buf_page_t &bpage);
/** Write request types */ enum write_type
{ /** the page is guaranteed to always change */
NORMAL= 0, /** optional: the page contents might not change */
MAYBE_NOP, /** force a write, even if the page contents is not changing */
FORCED
};
/** Write 1, 2, 4, or 8 bytes to a file page. @param[in]blockfilepage @param[in,out]ptrpointerinfilepage @param[in]valvaluetowrite @tparamlnumberofbytestowrite @tparamwwriterequesttype @tparamVtypeofval
@return whether any log was written */ template<unsigned l,write_type w= NORMAL,typename V> inlinebool write(const buf_block_t &block, void *ptr, V val)
MY_ATTRIBUTE((nonnull));
/** Log a write of a byte string to a page. @param[in]bbufferpage @param[in]ofsbyteoffsetfromb->frame
@param[in] len length of the data to write */ inlinevoid memcpy(const buf_block_t &b, ulint ofs, ulint len);
/** Write a byte string to a page. @param[in,out]bbufferpage @param[in]destdestinationwithinb.frame @param[in]strthedatatowrite @param[in]lenlengthofthedatatowrite
@tparam w write request type */ template<write_type w= NORMAL> inlinevoid memcpy(const buf_block_t &b, void *dest, constvoid *str,
ulint len);
/** Log a write of a byte string to a ROW_FORMAT=COMPRESSED page. @param[in]bROW_FORMAT=COMPRESSEDindexpage @param[in]offsetbyteoffsetfromb.zip.data
@param[in] len length of the data to write */ inlinevoid zmemcpy(const buf_block_t &b, ulint offset, ulint len);
/** Write a byte string to a ROW_FORMAT=COMPRESSED page. @param[in]bROW_FORMAT=COMPRESSEDindexpage @param[in]destdestinationwithinb.zip.data @param[in]strthedatatowrite @param[in]lenlengthofthedatatowrite
@tparam w write request type */ template<write_type w= NORMAL> inlinevoid zmemcpy(const buf_block_t &b, void *dest, constvoid *str,
ulint len);
/** Log an initialization of a string of bytes. @param[in]bbufferpage @param[in]ofsbyteoffsetfromb->frame @param[in]lenlengthofthedatatowrite
@param[in] val the data byte to write */ inlinevoid memset(const buf_block_t &b, ulint ofs, ulint len, byte val);
/** Initialize a string of bytes. @param[in,out]bbufferpage @param[in]ofsbyteoffsetfromb->frame @param[in]lenlengthofthedatatowrite
@param[in] val the data byte to write */ inlinevoid memset(const buf_block_t *b, ulint ofs, ulint len, byte val);
/** Log an initialization of a repeating string of bytes. @param[in]bbufferpage @param[in]ofsbyteoffsetfromb->frame @param[in]lenlengthofthedatatowrite,inbytes @param[in]strthestringtowrite
@param[in] size size of str, in bytes */ inlinevoid memset(const buf_block_t &b, ulint ofs, size_t len, constvoid *str, size_t size);
/** Initialize a repeating string of bytes. @param[in,out]bbufferpage @param[in]ofsbyteoffsetfromb->frame @param[in]lenlengthofthedatatowrite,inbytes @param[in]strthestringtowrite
@param[in] size size of str, in bytes */ inlinevoid memset(const buf_block_t *b, ulint ofs, size_t len, constvoid *str, size_t size);
/** Log that a string of bytes was copied from the same page. @param[in]bbufferpage @param[in]ddestinationoffsetwithinthepage @param[in]ssourceoffsetwithinthepage
@param[in] len length of the data to copy */ inlinevoid memmove(const buf_block_t &b, ulint d, ulint s, ulint len);
/** Initialize an entire page.
@param[in,out] b buffer page */ void init(buf_block_t *b); /** Free a page. @paramspacetablespace
@param offset offset of the page to be freed */ void free(const fil_space_t &space, uint32_t offset); /** Write log for partly initializing a B-tree or R-tree page. @paramblockB-treeorR-treepage
@param comp false=ROW_FORMAT=REDUNDANT, true=COMPACT or DYNAMIC */ inlinevoid page_create(const buf_block_t &block, bool comp);
/** Write log for inserting a B-tree or R-tree record in ROW_FORMAT=REDUNDANT. @paramblockB-treeorR-treepage @paramreusefalse=allocatefromPAGE_HEAP_TOP;true=reusePAGE_FREE @paramprev_recbyteoffsetofthepredecessoroftherecordtoinsert, startingfromPAGE_OLD_INFIMUM @paraminfo_bitsinfo_bitsoftherecord @paramn_fields_snumberoffields<<1|rec_get_1byte_offs_flag() @paramhdr_cnumberofcommonrecordheaderbyteswithprev_rec @paramdata_cnumberofcommondatabyteswithprev_rec @paramhdrrecordheaderbytestocopytothelog @paramhdr_lnumberofcopiedrecordheaderbytes @paramdatarecordpayloadbytestocopytothelog
@param data_l number of copied record data bytes */ inlinevoid page_insert(const buf_block_t &block, bool reuse,
ulint prev_rec, byte info_bits,
ulint n_fields_s, size_t hdr_c, size_t data_c, const byte *hdr, size_t hdr_l, const byte *data, size_t data_l); /** Write log for inserting a B-tree or R-tree record in ROW_FORMAT=COMPACTorROW_FORMAT=DYNAMIC. @paramblockB-treeorR-treepage @paramreusefalse=allocatefromPAGE_HEAP_TOP;true=reusePAGE_FREE @paramprev_recbyteoffsetofthepredecessoroftherecordtoinsert, startingfromPAGE_NEW_INFIMUM @paraminfo_statusrec_get_info_and_status_bits() @paramshiftunless!reuse:numberofbytesthePAGE_FREEismoving @paramhdr_cnumberofcommonrecordheaderbyteswithprev_rec @paramdata_cnumberofcommondatabyteswithprev_rec @paramhdrrecordheaderbytestocopytothelog @paramhdr_lnumberofcopiedrecordheaderbytes @paramdatarecordpayloadbytestocopytothelog
@param data_l number of copied record data bytes */ inlinevoid page_insert(const buf_block_t &block, bool reuse,
ulint prev_rec, byte info_status,
ssize_t shift, size_t hdr_c, size_t data_c, const byte *hdr, size_t hdr_l, const byte *data, size_t data_l); /** Write log for deleting a B-tree or R-tree record in ROW_FORMAT=REDUNDANT. @paramblockB-treeorR-treepage @paramprev_recbyteoffsetofthepredecessoroftherecordtodelete,
starting from PAGE_OLD_INFIMUM */ inlinevoid page_delete(const buf_block_t &block, ulint prev_rec); /** Write log for deleting a COMPACT or DYNAMIC B-tree or R-tree record. @paramblockB-treeorR-treepage @paramprev_recbyteoffsetofthepredecessoroftherecordtodelete, startingfromPAGE_NEW_INFIMUM @paramhdr_sizerecordheadersize,excludingREC_N_NEW_EXTRA_BYTES
@param data_size data payload size, in bytes */ inlinevoid page_delete(const buf_block_t &block, ulint prev_rec,
size_t hdr_size, size_t data_size);
/** Write log for initializing an undo log page.
@param block undo page */ inlinevoid undo_create(const buf_block_t &block); /** Write log for appending an undo log record. @paramblockundopage @paramdatarecordwithintheundopage
@param len length of the undo record, in bytes */ inlinevoid undo_append(const buf_block_t &block, constvoid *data, size_t len); /** Trim the end of a tablespace.
@param id first page identifier that will not be in the file */ inlinevoid trim_pages(const page_id_t id);
/** Write a log record about a file operation. @paramtypefileoperation @paramspace_idtablespaceidentifier @parampathfilepath @paramnew_pathnewfilepathfortype=FILE_RENAME
@return number of bytes written */ inline size_t log_file_op(mfile_type_t type, uint32_t space_id, constchar *path, constchar *new_path= nullptr) noexcept;
/** Determine the added buffer fix count of a block. @paramblockblocktobechecked
@return number of buffer count added by this mtr */
uint32_t get_fix_count(const buf_block_t *block) const;
/** Note that log_sys.latch is no longer being held exclusively. */ void flag_wr_unlock() noexcept { ut_ad(m_latch_ex); m_latch_ex= false; }
private: /** Handle any pages that were freed during the mini-transaction. */ void process_freed_pages(); /** Release modified pages when no log was written. */ void release_unlogged();
/** Log a write of a byte string to a page. @paramblockbufferpage @paramoffsetbyteoffsetwithinpage @paramdatadatatobewritten
@param len length of the data, in bytes */ inlinevoid memcpy_low(const buf_block_t &block, uint16_t offset, constvoid *data, size_t len); /** Writealogrecord. @tparamtyperedologrecordtype @paramidpersistentpageidentifier @parambpagebufferpoolpage,ornullptr @paramlennumberofadditionalbytestowrite @paramallocwhethertoallocatetheadditionalbytes @paramoffsetbyteoffset,or0iftherecordtypedoesnotallowone
@return end of mini-transaction log, minus len */ template<byte type> inline byte *log_write(const page_id_t id, const buf_page_t *bpage,
size_t len= 0, bool alloc= false, size_t offset= 0);
/** Write an EXTENDED log record. @paramblockbufferpoolpage
@param type extended record subtype; @see mrec_ext_t */ inlinevoid log_write_extended(const buf_block_t &block, byte type);
/** Write a FILE_MODIFY record when a non-predefined persistent
tablespace was modified for the first time since fil_names_clear(). */
ATTRIBUTE_NOINLINE ATTRIBUTE_COLD void name_write() noexcept;
/** Encrypt the log
@return the total size in bytes, excluding the 8-byte nonce */
ATTRIBUTE_NOINLINE size_t encrypt() noexcept;
/** Calculate m_crc of m_log.
@return the total size in bytes, including the 5-byte trailer and CRC-32C */
ATTRIBUTE_NOINLINE size_t crc32c() noexcept;
/** Append the redo log records to the redo log buffer.
@return {start_lsn,flush_ahead_lsn} */
std::pair<lsn_t,lsn_t> do_write() noexcept;
/** Append the redo log records to the redo log buffer. @tparamhowhowtowrite @parammtrmini-transaction @paramlennumberofbytestowrite
@return {start_lsn,flush_ahead_lsn} */ template<log_t::write how> static
std::pair<lsn_t,lsn_t> finish_writer(mtr_t *mtr, size_t len);
/** The applicable variant of commit_log() */ staticvoid (*commit_logger)(mtr_t *, std::pair<lsn_t,lsn_t>); /** The applicable variant of finish_writer() */ static std::pair<lsn_t,lsn_t> (*finisher)(mtr_t *, size_t);
std::pair<lsn_t,lsn_t> finish_write(size_t len)
{ return finisher(this, len); } public: /** Update finisher when spin_wait_delay is changing to or from 0. */ staticvoid finisher_update();
/** Decode the length of a record. @paramllogrecord @paramsizetotalsizeoftherecord
@return the log record payload after the encoded length */ staticconst byte *parse_length(const byte *l, uint32_t *size) noexcept;
/** Release all latches. */ void release(); /** Release the resources */ inlinevoid release_resources();
#ifdef UNIV_DEBUG public: /** @return whether the mini-transaction is active */ bool is_active() const
{ ut_ad(!m_commit || m_start); return m_start && !m_commit; } /** @return whether the mini-transaction has been committed */ bool has_committed() const { ut_ad(!m_commit || m_start); return m_commit; } /** @return whether the mini-transaction is freeing an index tree */ bool is_freeing_tree() const { return m_freeing_tree; } /** Notify that the mini-transaction is freeing an index tree */ void freeing_tree() { m_freeing_tree= true; } private: /** whether start() has been called */ bool m_start= false; /** whether commit() has been called */ bool m_commit= false; /** whether freeing_tree() has been called */ bool m_freeing_tree= false; #endif private: /** The page of the most recent m_log record written, or NULL */ const buf_page_t* m_last; /** The current byte offset in m_last, or 0 */
uint16_t m_last_offset;
/** specifies which operations should be logged; default MTR_LOG_ALL */
uint16_t m_log_mode:2;
/** whether at least one persistent page was written to */
uint16_t m_modifications:1;
/** whether at least one previously clean buffer pool page was written to */
uint16_t m_made_dirty:1;
/** whether log_sys.latch is locked exclusively */
uint16_t m_latch_ex:1;
/** whether the pages has been trimmed */
uint16_t m_trim_pages:1;
/** CRC-32C of m_log */
uint32_t m_crc; public: /** dummy or real transaction associated with the mini-transaction */
trx_t *const trx; private: /** user tablespace that is being modified by the mini-transaction */
fil_space_t *m_user_space;
#ifdef UNIV_DEBUG /** Persistent user tablespace associated with the
mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */
uint32_t m_user_space_id; #endif/* UNIV_DEBUG */
/** tablespace where pages have been freed */
fil_space_t *m_freed_space= nullptr; /** set of freed page ids */
range_set *m_freed_pages= nullptr; /** Latched binlog page to release at mtr commit*/
fsp_binlog_page_entry *m_binlog_page;
};
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.