// record.cpp #include "pch.h" #include "pdfile.h" #include "../util/processinfo.h" #include "../util/net/listen.h" namespace mongo { namespace ps { enum State { In , Out, Unk }; enum Constants { SliceSize = 65536 , MaxChain = 20 , // intentionally very low NumSlices = 10 , RotateTimeSecs = 90 }; int hash( size_t region ) { return abs( ( ( 7 + (int)(region & 0xFFFF) ) * ( 11 + (int)( ( region >> 16 ) & 0xFFFF ) ) #if defined(_WIN64) || defined(__amd64__) * ( 13 + (int)( ( region >> 32 ) & 0xFFFF ) ) * ( 17 + (int)( ( region >> 48 ) & 0xFFFF ) ) #endif ) % SliceSize ); } /** * simple hash map for region -> status * this constitures a single region of time * it does chaining, but very short chains */ class Slice { struct Entry { size_t region; unsigned long long value; }; public: Slice() { reset(); } void reset() { memset( _data , 0 , SliceSize * sizeof(Entry) ); } State get( int regionHash , size_t region , short offset ) { DEV assert( hash( region ) == regionHash ); Entry * e = _get( regionHash , region , false ); if ( ! e ) return Unk; return ( e->value & ( ((unsigned long long)1) << offset ) ) ? In : Out; } /** * @return true if added, false if full */ bool in( int regionHash , size_t region , short offset ) { DEV assert( hash( region ) == regionHash ); Entry * e = _get( regionHash , region , true ); if ( ! e ) return false; e->value |= ((unsigned long long)1) << offset; return true; } private: Entry* _get( int start , size_t region , bool add ) { for ( int i=0; i ( 1000 * RotateTimeSecs ) ) { _rotate(); } } for ( int i=0; i HeaderSize ) { // this also makes sure lengthWithHeaders is in memory char * addr = data; char * end = data + netLength(); for ( ; addr <= end ; addr += 2048 ) { __record_touch_dummy += addr[0]; break; // TODO: remove this, pending SERVER-3711 if ( ! entireRecrd ) break; } } } bool Record::likelyInPhysicalMemory() { if ( ! MemoryTrackingEnabled ) return true; static bool blockSupported = ProcessInfo::blockCheckSupported(); const size_t page = (size_t)data >> 12; const size_t region = page >> 6; const size_t offset = page & 0x3f; if ( ps::rolling.access( region , offset , false ) ) return true; if ( ! blockSupported ) return false; return ProcessInfo::blockInMemory( data ); } Record* Record::accessed() { const size_t page = (size_t)data >> 12; const size_t region = page >> 6; const size_t offset = page & 0x3f; ps::rolling.access( region , offset , true ); return this; } }