-
-
Notifications
You must be signed in to change notification settings - Fork 261
Shared metadata cache #8819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Shared metadata cache #8819
Conversation
…s related fixes around
src/common/dsc.h
Outdated
| { | ||
| if (dsc_sub_type == isc_blob_text) | ||
| return dsc_scale | (dsc_flags & 0xFF00); | ||
| return TTypeId(CSetId(dsc_scale), CollId(dsc_flags > 8)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess bitshift was intended here?
Same at 305 line.
src/burp/restore.epp
Outdated
|
|
||
| } // namespace | ||
|
|
||
|
|
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
|
||
| namespace Firebird { | ||
|
|
||
| namespace Firebird { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change
| const UCHAR* pos; | ||
| }; | ||
|
|
||
|
|
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| return 0; | ||
| } | ||
|
|
||
| SSHORT getBlobSubType() const noexcept |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getBlobSubType & setBlobSubType got close to each other after it
| dsc_address = address; | ||
| } | ||
|
|
||
| bool operator==(const dsc& v) const noexcept |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The presence of DSC_EQUIV and this overload operator is a bit confusing. While this may not be relevant to this PR, it would be a nice to remove external functions related to dsc, such as DSC_EQUIV and DTYPE_IS_TEXT.
src/dsql/DsqlBatch.cpp
Outdated
| { | ||
| DEB_BATCH(fprintf(stderr, "BLOBs %d were not used in messages\n", m_blobMap.count())); | ||
| ERR_post_warning(Arg::Warning(isc_random) << "m_blobMap.count() BLOBs were not used in messages"); // !!!!!!! new warning | ||
| ERR_post_warning(Arg::Warning(isc_random) << "m_blobMap.count() BLOBs were not used in messages"); // @@@@@@ new warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change. Or am I misunderstanding this
| @@ -2188,7 +2188,6 @@ void SortOwner::releaseBuffer(UCHAR* memory) | |||
| buffers.push(memory); | |||
| } | |||
|
|
|||
|
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change
| @@ -2442,3 +2441,4 @@ sort_record* PartitionedSort::getMerge() | |||
|
|
|||
| return eof ? NULL : record; | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change
| return node; | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary change
| ValueExprNode* UdfCallNode::pass2(thread_db* tdbb, CompilerScratch* csb) | ||
| { | ||
| if (function->fun_deterministic) | ||
| Function* f = function(tdbb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably better to be consistent with the names and call it func, as in UdfCallNode::execute below
src/include/fb_exception.h
Outdated
| [[noreturn]] static void raise(const ISC_STATUS* status_vector); | ||
| [[noreturn]] static void raise(const Arg::StatusVector& statusVector); | ||
| [[noreturn]] static void raise(const IStatus* status); | ||
| static void raise [[noreturn]] (const ISC_STATUS* status_vector); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, I've never seen this style before and didn't know it was a valid format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both correct, see https://en.cppreference.com/w/cpp/language/attributes/noreturn.html
But taking into an account that other style is used else where I change such places
| #define CS_ASCII 2 /* ASCII */ | ||
| #define CS_UNICODE_FSS 3 /* UNICODE in FSS format */ | ||
| #define CS_UTF8 4 /* UTF-8 */ | ||
| #define CS_NONE CSetId(0) /* No Character Set */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason to keep this consatnts as defines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doubt that - but it worked and works
|
|
||
| att_database->dbb_mdc->invalidateReplSet(tdbb); | ||
|
|
||
| /* !!!!!!!!!!!!!!!!!!!!!!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some Work In Progress code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, looks like replication code required some more care to be taken.
| void Collation::destroy(thread_db* tdbb) | ||
| { | ||
| fb_assert(useCount == 0); | ||
| fprintf(stderr, "Collation::destroy(%p) tt=%p\n", this, tt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some debug print?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, should be removed long ago. Fixed.
| { | ||
| DEB_BATCH(fprintf(stderr, "BLOBs %d were not used in messages\n", m_blobMap.count())); | ||
| ERR_post_warning(Arg::Warning(isc_random) << "m_blobMap.count() BLOBs were not used in messages"); // !!!!!!! new warning | ||
| ERR_post_warning(Arg::Warning(isc_random) << "m_blobMap.count() BLOBs were not used in messages"); // !!!!!! new warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this line changed on porpuse? Is there something wrong with it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only wrong here is that isc_random to be replaced here with some special warning code.
| { | ||
| fb_assert(which == IRQ_REQUESTS || which == DYN_REQUESTS || which == CACHED_REQUESTS); | ||
|
|
||
| //Database::CheckoutLockGuard guard(this, dbb_cmp_clone_mutex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Temporaly change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really not needed - cleaned up
| ExternalInfo charSetExternalInfo; | ||
| ExternalInfo collationExternalInfo; | ||
| char statusBuffer[BUFFER_LARGE] = ""; | ||
| char statusBufferBig[BUFFER_LARGE] = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe using std::array will be a litle bit handy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure - called functions are plain text oriented.
To be precise - everything (well almost everything) related with intl support worth redesign and new code. But as long as existing works I prefer to touch it as minimal as possible.
| viewProcedure = tail->csb_procedure(); | ||
|
|
||
| // If the plan references the view itself, make sure that | ||
| // If the plan references the view itself, make sure that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo
Tasks to be solved.
The old metadata cache is essentially single-threaded. For me, the problem I faced with attempts to introduce synchronization into this structure and get off with relatively little blood was taking into account the use of procedures and functions using a second reference counter, and in order to decide whether to delete an object, a global recalculation of these references is required throughout the cache. dsqlcache is also extremely unsympathetic, which puts objects created and still unmixed in a single transaction for all transactions of the same attach. An additional consideration is that objects stored in the cache are used in a huge number of places in the code, and they can be modified from other places (and threads) during MET_scan_xxx. This could still be dealt with using CopyOnWrite, but how to approach the first two points was unclear.
The new metadata cache is versioned. Each object is divided into 2 parts - a constant and a variable. For relation, for example, the type (table, view, external table, etc.), name, all locks (GCLock, partners lock, rescan lock) will be constant, and format, list of fields, triggers will be variable. The list of versions is linked to a permanent part of the object. As versions become obsolete, the list is cleared (although I won't say that it's very active - only as the cache is accessed, there is no special garbage collector).
In order to access the desired object for reading without locks, it was possible to allocate memory for the entire cache at once. In principle, there are not so many - 64K pointers to each type of cached objects. But I kept in mind the possible increase in the number of objects in the database and therefore made a 2-level array - each lower-level block of N objects is allocated once and for all (until the database is closed), and the upper-level block has the right to grow when the required number of lower-level blocks does not fit there. Therefore, the upper level is implemented using a read-safe array. For reading, we would take a slice of the current state of the array and this slice remains unchanged while we work with it. An external mutex is used to modify the array. This array (SharedReadVector) turned out to be very convenient, I also use it for requests in a statement and a list of formats in a relation. The 2-level arrays (CacheVector) for all objects are the same (template), and all this ultimately lives in DBB.
Ideally, I would like to remove dsqlcache altogether. So far, it has been removed for relations, procedures, and functions. At the same time, I did not abandon the dsql_rel format and the like - they are needed in order to be able to work with it when creating/changing an object (dsql_rel), although there is no such object in the metadata cache yet / or the format is not the same. Temporary objects of this format are created in dsqlScratch and die with it (by pool).
libcds is used to implement secure pointers (HazardPtr), they are needed for version headers in the list of object versions and for a slice in the SharedReadVector.
In all requests, instead of a pointer directly to objects, the cache stores a structure of 2 elements - a pointer to the permanent part of the object and a index in an array of pointers to versions of objects. These arrays may differ in different query clones. To reduce duplication, a RefCounted array is used. rpb_relation's are registered in rpb when creating a clone. The decision on whether to update a set of versions in a clone of the request is made in GetRequest, that is, when a clone of the request is received.
At the moment, TCS is fully working. QA makes mistakes - but I think it's time to pour metacache into the master so as not to prevent merge of other branches. And it's probably time to decide with the indexes of the system tables, which ones are needed and which ones are not very necessary. For example, I need to add indexes by ID for relations and other cached tables.