internal QuerySnapshot(ExecutingQuery query, CompilerInfo compilerInfo, PageCounterValues page, long compilationTimeMicros, long elapsedTimeMicros, long cpuTimeMicros, long waitTimeMicros, string status, IDictionary <string, object> resourceInfo, IList <ActiveLock> waitingLocks, long activeLockCount, long allocatedBytes) { this._query = query; this._compilerInfo = compilerInfo; this._page = page; this._compilationTimeMicros = compilationTimeMicros; this._elapsedTimeMicros = elapsedTimeMicros; this._cpuTimeMicros = cpuTimeMicros; this._waitTimeMicros = waitTimeMicros; this._status = status; this._resourceInfo = resourceInfo; this._waitingLocks = waitingLocks; this._activeLockCount = activeLockCount; this._allocatedBytes = allocatedBytes; }
// snapshot state public virtual QuerySnapshot Snapshot() { // capture a consistent snapshot of the "live" state ExecutingQueryStatus status; long waitTimeNanos; long currentTimeNanos; long cpuTimeNanos; do { status = this._status; // read barrier, must be first waitTimeNanos = this._waitTimeNanos; // the reason for the retry loop: don't count the wait time twice cpuTimeNanos = _cpuClock.cpuTimeNanos(_threadExecutingTheQueryId); currentTimeNanos = _clock.nanos(); // capture the time as close to the snapshot as possible } while (this._status != status); // guarded by barrier - unused if status is planning, stable otherwise long compilationCompletedNanos = this._compilationCompletedNanos; // guarded by barrier - like compilationCompletedNanos CompilerInfo planner = status.Planning ? null : this._compilerInfo; IList <ActiveLock> waitingOnLocks = status.WaitingOnLocks ? status.WaitingOnLocks() : Collections.emptyList(); // activeLockCount is not atomic to capture, so we capture it after the most sensitive part. long totalActiveLocks = this._activeLockCount.AsLong; // just needs to be captured at some point... long heapAllocatedBytes = _heapAllocation.allocatedBytes(_threadExecutingTheQueryId); PageCounterValues pageCounters = new PageCounterValues(_pageCursorCounters); // - at this point we are done capturing the "live" state, and can start computing the snapshot - long compilationTimeNanos = (status.Planning ? currentTimeNanos : compilationCompletedNanos) - _startTimeNanos; long elapsedTimeNanos = currentTimeNanos - _startTimeNanos; cpuTimeNanos -= _cpuTimeNanosWhenQueryStarted; waitTimeNanos += status.WaitTimeNanos(currentTimeNanos); // TODO: when we start allocating native memory as well during query execution, // we should have a tracer that keeps track of how much memory we have allocated for the query, // and get the value from that here. heapAllocatedBytes = _heapAllocatedBytesWhenQueryStarted < 0 ? -1 : heapAllocatedBytes - _heapAllocatedBytesWhenQueryStarted; return(new QuerySnapshot(this, planner, pageCounters, NANOSECONDS.toMicros(compilationTimeNanos), NANOSECONDS.toMicros(elapsedTimeNanos), cpuTimeNanos == 0 && _cpuTimeNanosWhenQueryStarted == -1 ? -1 : NANOSECONDS.toMicros(cpuTimeNanos), NANOSECONDS.toMicros(waitTimeNanos), status.Name(), status.ToMap(currentTimeNanos), waitingOnLocks, totalActiveLocks - _initialActiveLocks, heapAllocatedBytes)); }