📄 objectheader.hxx
字号:
* thread. * * If ANY of the pin counts is nonzero, the 'pinned' bit is set. * */ static uint8_t CurrentTransaction; /* current transaction number */ inline static void BeginTransaction() { CurrentTransaction += 2; } uint8_t userPin; uint8_t kernPin; void KernPin(); /* object is pinned for kernel reasons */ void KernUnpin(); /* object is pinned for kernel reasons */#ifdef NDEBUG inline void TransLock() /* lock for current transaction */ { userPin = CurrentTransaction; } inline void TransUnlock() { userPin = 0; }#else void TransLock(); /* lock for current transaction */ void TransUnlock();#endif static inline void ReleasePinnedObjects() { } inline bool IsUserPinned() { return (userPin == CurrentTransaction); } inline bool IsKernelPinned() { return (kernPin != 0); } public: ObjectHeader* hashChainNext; void ResetKeyRing() { kr.ResetRing(); } void Intern(); /* intern object on the ObList. */ void Unintern(); /* remove object from the ObList. */ void FlushIfCkpt(); void MakeObjectDirty(); void Rescind(); void ZapResumeKeys();#if 0 /* This is very important, but I am still sorting out * implementation. In any case, it is probably an ObjectCache * function rather than an ObjectHeader function. */ void DoCopyOnWrite();#endif void InvalidateProducts(); ObjectHeader *FindProduct(SegWalk& wi, uint32_t ndx, bool rw, bool ca); void AddProduct(ObjectHeader *product); void DelProduct(ObjectHeader *product); static ObjectHeader * Lookup(ObType::Type, OID oid); static Node * LookupNode(OID oid) { return (Node *) Lookup(ObType::NtUnprepared, oid); } static struct ThreadPile& ObjectSleepQueue(uint32_t ndx); static struct ThreadPile& ObjectSleepQueue(OID oid) { uint32_t ndx = oid % KTUNE_NOBSLEEPQ; return ObjectSleepQueue(ndx); } inline struct ThreadPile& ObjectSleepQueue() { return ObjectSleepQueue(ob.oid); } inline ObjectHeader() { kr.ResetRing(); flags = 0; userPin = 0; obType = ObType::PtFreeFrame; /* Node constructor overrides... */ } #if 0 void StartIO(); void FinishObjectIO(bool wasInbound, ObType::Type oty, OID oid, ObCount allocCount);#endif #ifdef OPTION_DDB void ddb_dump(); static void ddb_dump_hash_hist(); static void ddb_dump_bucket(uint32_t bucket);#endif};/* MEANINGS OF FLAGS FIELDS: * * free object is on free list, and may be reclaimed. ObjectTable* * points to a free list linkage. * * dirty object has been mutated, and needs to be written to disk. * * pinned object is pinned in memory, and should not be reclaimed. * * current object is the current version of the object. * * chkpt object is the version that was current as of the last * checkpoint. When the chkpt logic runs, it checks to see * if the object is current and dirty. If so, it sets the * chkpt, pageOut, and wHazard bits. * * wHazard Object must not be modified, either because their is an * outbound I/O using its contents or it is scheduled for * pageOut. * * rHazard Object content is undefined because an I/O is in progress * into the object. Read/Write at your own risk, without * any guarantees. * * ioActive One or more I/Os are in progress on this object. Implies * ioCount > 0. * * pageOut Object is marked for pageout. Pageout will proceed to * either the current area or the chkpt area depending on the * chkpt bit value. When pageout is complete, pageOut and * dirty bits will be cleared (assuming no other I/O is in * progress). * * It is usually a side-effect of pageout completion that * ioCount goes to zero. Whenever ioCount goes to zero, * wHazard and rHazard are cleared. * * If object is no longer current and object is not already * free, its age will be set to Age::Free and it will be * placed on the free list. * * When a user goes to modify an object the wHazard bit is first * checked to see if the modification can proceed. If it can, dirty * is set to 1. If it cannot, the object may be COW'd or the user may * be forced to wait. * * When the checkpointer starts up, it marks all dirty objects with * chkpt=1, pageout=1, and wHazard=1. As they are paged out, pageout * and wHazard are cleared. * * When all pages have gone out, the migrator comes along and starts * to migrate the pages. Before it reloads each page from the * checkpoint area, it checks to see if a version of the page is in * memory with chkpt=1 and dirty=0. If so, that version is the same * as the one in the log, and the log version does not need to be * reloaded. Otherwise, it reloads the necessary objects from the * log. In either case, if a version was found in memory the chkpt * bit is turned off. * * By the end of the migration phase, no chkpt bits should be on. * *//* FREE LIST HANDLING * * Objects marked for pageout can be on the free list before they are * cleaned. This creates a problem. On the one hand, you don't want * to preferentially steal clean pages from the free list, because * this has the effect of preferentially removing code pages (which * are often shared) from memory. On the other hand, you need to know * that there are enough free objects to satisfy any pending disk * reads. * * The way we handle this is a bit crufty, but it pretty much works. * When an object is "placed on the free list", it is first placed on * the "free pageout list", WHETHER OR NOT it is dirty. Pages on the * free pageout list are preferentially cleaned by the pageing daemon, * and moved to the "real" free list. If a user-initiated operation * would lower the number of objects on the "real" free list below the * number of pending read requests, the operation is stalled until * there are more clean free objects. * * Two optimizations can be done without inducing priority inversion: * if an object is clean and not current when it is freed, it can be * placed directly onto the "real" free list. If it is dirty and not * current, it is placed at the front of the "free pageout list." The * idea is to preferentially free stale object versions. * * To understand the implications of the dual free list design, we * need to consider which operations remove objects from the free * list: * * 1. COW processing * 2. Object resurrection * 3. Reading in new objects. * * Case 1 is relatively simple -- if there aren't enough free frames * to COW an object without jeopardizing pending reads, then COWing * the object was the wrong thing to do in any case. The design * decision to make is whether the user should wait for a free frame * and COW or should wait for the object to go out. The answer is to * wait on the free list. * * Case 2 is fairly easy - it doesn't matter what free list the object * is on, just hand the user back the object and it will turn into the * COW case if the object is dirty. That's actually good. If the COW * succeeds, the user will proceed, and the dirty object will get * moved to the front of the dirty free list for prompt writeout, * making it available. If the COW fails, the next clean page will * get allocated to this process, which will probably happen faster * than their page will get written out, and in the worst case will * only delay them by one write. In either case, the COW operation * will now succeed, and a page has been freed as a result. * * Case 3 is also simple - if there are not enough free frames on the * clean free list, the reader should block until there are more. * * Note that all of this is fairly unlikely, as the pageout daemon * tries fairly hard to force dirty pages to the disk before they get * to the free list. */#endif /* __OBJECTHEADER_HXX__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -