package procfs
import (
"bufio"
"bytes"
"fmt"
"io"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
)
type Fscacheinfo struct {
IndexCookiesAllocated uint64
DataStorageCookiesAllocated uint64
SpecialCookiesAllocated uint64
ObjectsAllocated uint64
ObjectAllocationsFailure uint64
ObjectsAvailable uint64
ObjectsDead uint64
ObjectsWithoutCoherencyCheck uint64
ObjectsWithCoherencyCheck uint64
ObjectsNeedCoherencyCheckUpdate uint64
ObjectsDeclaredObsolete uint64
PagesMarkedAsBeingCached uint64
UncachePagesRequestSeen uint64
AcquireCookiesRequestSeen uint64
AcquireRequestsWithNullParent uint64
AcquireRequestsRejectedNoCacheAvailable uint64
AcquireRequestsSucceeded uint64
AcquireRequestsRejectedDueToError uint64
AcquireRequestsFailedDueToEnomem uint64
LookupsNumber uint64
LookupsNegative uint64
LookupsPositive uint64
ObjectsCreatedByLookup uint64
LookupsTimedOutAndRequed uint64
InvalidationsNumber uint64
InvalidationsRunning uint64
UpdateCookieRequestSeen uint64
UpdateRequestsWithNullParent uint64
UpdateRequestsRunning uint64
RelinquishCookiesRequestSeen uint64
RelinquishCookiesWithNullParent uint64
RelinquishRequestsWaitingCompleteCreation uint64
RelinquishRetries uint64
AttributeChangedRequestsSeen uint64
AttributeChangedRequestsQueued uint64
AttributeChangedRejectDueToEnobufs uint64
AttributeChangedFailedDueToEnomem uint64
AttributeChangedOps uint64
AllocationRequestsSeen uint64
AllocationOkRequests uint64
AllocationWaitingOnLookup uint64
AllocationsRejectedDueToEnobufs uint64
AllocationsAbortedDueToErestartsys uint64
AllocationOperationsSubmitted uint64
AllocationsWaitedForCPU uint64
AllocationsAbortedDueToObjectDeath uint64
RetrievalsReadRequests uint64
RetrievalsOk uint64
RetrievalsWaitingLookupCompletion uint64
RetrievalsReturnedEnodata uint64
RetrievalsRejectedDueToEnobufs uint64
RetrievalsAbortedDueToErestartsys uint64
RetrievalsFailedDueToEnomem uint64
RetrievalsRequests uint64
RetrievalsWaitingCPU uint64
RetrievalsAbortedDueToObjectDeath uint64
StoreWriteRequests uint64
StoreSuccessfulRequests uint64
StoreRequestsOnPendingStorage uint64
StoreRequestsRejectedDueToEnobufs uint64
StoreRequestsFailedDueToEnomem uint64
StoreRequestsSubmitted uint64
StoreRequestsRunning uint64
StorePagesWithRequestsProcessing uint64
StoreRequestsDeleted uint64
StoreRequestsOverStoreLimit uint64
ReleaseRequestsAgainstPagesWithNoPendingStorage uint64
ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
ReleaseRequestsIgnoredDueToInProgressStore uint64
PageStoresCancelledByReleaseRequests uint64
VmscanWaiting uint64
OpsPending uint64
OpsRunning uint64
OpsEnqueued uint64
OpsCancelled uint64
OpsRejected uint64
OpsInitialised uint64
OpsDeferred uint64
OpsReleased uint64
OpsGarbageCollected uint64
CacheopAllocationsinProgress uint64
CacheopLookupObjectInProgress uint64
CacheopLookupCompleteInPorgress uint64
CacheopGrabObjectInProgress uint64
CacheopInvalidations uint64
CacheopUpdateObjectInProgress uint64
CacheopDropObjectInProgress uint64
CacheopPutObjectInProgress uint64
CacheopAttributeChangeInProgress uint64
CacheopSyncCacheInProgress uint64
CacheopReadOrAllocPageInProgress uint64
CacheopReadOrAllocPagesInProgress uint64
CacheopAllocatePageInProgress uint64
CacheopAllocatePagesInProgress uint64
CacheopWritePagesInProgress uint64
CacheopUncachePagesInProgress uint64
CacheopDissociatePagesInProgress uint64
CacheevLookupsAndCreationsRejectedLackSpace uint64
CacheevStaleObjectsDeleted uint64
CacheevRetiredWhenReliquished uint64
CacheevObjectsCulled uint64
}
func (fs FS ) Fscacheinfo () (Fscacheinfo , error ) {
b , err := util .ReadFileNoStat (fs .proc .Path ("fs/fscache/stats" ))
if err != nil {
return Fscacheinfo {}, err
}
m , err := parseFscacheinfo (bytes .NewReader (b ))
if err != nil {
return Fscacheinfo {}, fmt .Errorf ("%w: Cannot parse %v: %w" , ErrFileParse , m , err )
}
return *m , nil
}
func setFSCacheFields(fields []string , setFields ...*uint64 ) error {
var err error
if len (fields ) < len (setFields ) {
return fmt .Errorf ("%w: Expected %d, but got %d: %w" , ErrFileParse , len (setFields ), len (fields ), err )
}
for i := range setFields {
*setFields [i ], err = strconv .ParseUint (strings .Split (fields [i ], "=" )[1 ], 0 , 64 )
if err != nil {
return err
}
}
return nil
}
func parseFscacheinfo(r io .Reader ) (*Fscacheinfo , error ) {
var m Fscacheinfo
s := bufio .NewScanner (r )
for s .Scan () {
fields := strings .Fields (s .Text ())
if len (fields ) < 2 {
return nil , fmt .Errorf ("%w: malformed Fscacheinfo line: %q" , ErrFileParse , s .Text ())
}
switch fields [0 ] {
case "Cookies:" :
err := setFSCacheFields (fields [1 :], &m .IndexCookiesAllocated , &m .DataStorageCookiesAllocated ,
&m .SpecialCookiesAllocated )
if err != nil {
return &m , err
}
case "Objects:" :
err := setFSCacheFields (fields [1 :], &m .ObjectsAllocated , &m .ObjectAllocationsFailure ,
&m .ObjectsAvailable , &m .ObjectsDead )
if err != nil {
return &m , err
}
case "ChkAux" :
err := setFSCacheFields (fields [2 :], &m .ObjectsWithoutCoherencyCheck , &m .ObjectsWithCoherencyCheck ,
&m .ObjectsNeedCoherencyCheckUpdate , &m .ObjectsDeclaredObsolete )
if err != nil {
return &m , err
}
case "Pages" :
err := setFSCacheFields (fields [2 :], &m .PagesMarkedAsBeingCached , &m .UncachePagesRequestSeen )
if err != nil {
return &m , err
}
case "Acquire:" :
err := setFSCacheFields (fields [1 :], &m .AcquireCookiesRequestSeen , &m .AcquireRequestsWithNullParent ,
&m .AcquireRequestsRejectedNoCacheAvailable , &m .AcquireRequestsSucceeded , &m .AcquireRequestsRejectedDueToError ,
&m .AcquireRequestsFailedDueToEnomem )
if err != nil {
return &m , err
}
case "Lookups:" :
err := setFSCacheFields (fields [1 :], &m .LookupsNumber , &m .LookupsNegative , &m .LookupsPositive ,
&m .ObjectsCreatedByLookup , &m .LookupsTimedOutAndRequed )
if err != nil {
return &m , err
}
case "Invals" :
err := setFSCacheFields (fields [2 :], &m .InvalidationsNumber , &m .InvalidationsRunning )
if err != nil {
return &m , err
}
case "Updates:" :
err := setFSCacheFields (fields [1 :], &m .UpdateCookieRequestSeen , &m .UpdateRequestsWithNullParent ,
&m .UpdateRequestsRunning )
if err != nil {
return &m , err
}
case "Relinqs:" :
err := setFSCacheFields (fields [1 :], &m .RelinquishCookiesRequestSeen , &m .RelinquishCookiesWithNullParent ,
&m .RelinquishRequestsWaitingCompleteCreation , &m .RelinquishRetries )
if err != nil {
return &m , err
}
case "AttrChg:" :
err := setFSCacheFields (fields [1 :], &m .AttributeChangedRequestsSeen , &m .AttributeChangedRequestsQueued ,
&m .AttributeChangedRejectDueToEnobufs , &m .AttributeChangedFailedDueToEnomem , &m .AttributeChangedOps )
if err != nil {
return &m , err
}
case "Allocs" :
if strings .Split (fields [2 ], "=" )[0 ] == "n" {
err := setFSCacheFields (fields [2 :], &m .AllocationRequestsSeen , &m .AllocationOkRequests ,
&m .AllocationWaitingOnLookup , &m .AllocationsRejectedDueToEnobufs , &m .AllocationsAbortedDueToErestartsys )
if err != nil {
return &m , err
}
} else {
err := setFSCacheFields (fields [2 :], &m .AllocationOperationsSubmitted , &m .AllocationsWaitedForCPU ,
&m .AllocationsAbortedDueToObjectDeath )
if err != nil {
return &m , err
}
}
case "Retrvls:" :
if strings .Split (fields [1 ], "=" )[0 ] == "n" {
err := setFSCacheFields (fields [1 :], &m .RetrievalsReadRequests , &m .RetrievalsOk , &m .RetrievalsWaitingLookupCompletion ,
&m .RetrievalsReturnedEnodata , &m .RetrievalsRejectedDueToEnobufs , &m .RetrievalsAbortedDueToErestartsys ,
&m .RetrievalsFailedDueToEnomem )
if err != nil {
return &m , err
}
} else {
err := setFSCacheFields (fields [1 :], &m .RetrievalsRequests , &m .RetrievalsWaitingCPU , &m .RetrievalsAbortedDueToObjectDeath )
if err != nil {
return &m , err
}
}
case "Stores" :
if strings .Split (fields [2 ], "=" )[0 ] == "n" {
err := setFSCacheFields (fields [2 :], &m .StoreWriteRequests , &m .StoreSuccessfulRequests ,
&m .StoreRequestsOnPendingStorage , &m .StoreRequestsRejectedDueToEnobufs , &m .StoreRequestsFailedDueToEnomem )
if err != nil {
return &m , err
}
} else {
err := setFSCacheFields (fields [2 :], &m .StoreRequestsSubmitted , &m .StoreRequestsRunning ,
&m .StorePagesWithRequestsProcessing , &m .StoreRequestsDeleted , &m .StoreRequestsOverStoreLimit )
if err != nil {
return &m , err
}
}
case "VmScan" :
err := setFSCacheFields (fields [2 :], &m .ReleaseRequestsAgainstPagesWithNoPendingStorage ,
&m .ReleaseRequestsAgainstPagesStoredByTimeLockGranted , &m .ReleaseRequestsIgnoredDueToInProgressStore ,
&m .PageStoresCancelledByReleaseRequests , &m .VmscanWaiting )
if err != nil {
return &m , err
}
case "Ops" :
if strings .Split (fields [2 ], "=" )[0 ] == "pend" {
err := setFSCacheFields (fields [2 :], &m .OpsPending , &m .OpsRunning , &m .OpsEnqueued , &m .OpsCancelled , &m .OpsRejected )
if err != nil {
return &m , err
}
} else {
err := setFSCacheFields (fields [2 :], &m .OpsInitialised , &m .OpsDeferred , &m .OpsReleased , &m .OpsGarbageCollected )
if err != nil {
return &m , err
}
}
case "CacheOp:" :
if strings .Split (fields [1 ], "=" )[0 ] == "alo" {
err := setFSCacheFields (fields [1 :], &m .CacheopAllocationsinProgress , &m .CacheopLookupObjectInProgress ,
&m .CacheopLookupCompleteInPorgress , &m .CacheopGrabObjectInProgress )
if err != nil {
return &m , err
}
} else if strings .Split (fields [1 ], "=" )[0 ] == "inv" {
err := setFSCacheFields (fields [1 :], &m .CacheopInvalidations , &m .CacheopUpdateObjectInProgress ,
&m .CacheopDropObjectInProgress , &m .CacheopPutObjectInProgress , &m .CacheopAttributeChangeInProgress ,
&m .CacheopSyncCacheInProgress )
if err != nil {
return &m , err
}
} else {
err := setFSCacheFields (fields [1 :], &m .CacheopReadOrAllocPageInProgress , &m .CacheopReadOrAllocPagesInProgress ,
&m .CacheopAllocatePageInProgress , &m .CacheopAllocatePagesInProgress , &m .CacheopWritePagesInProgress ,
&m .CacheopUncachePagesInProgress , &m .CacheopDissociatePagesInProgress )
if err != nil {
return &m , err
}
}
case "CacheEv:" :
err := setFSCacheFields (fields [1 :], &m .CacheevLookupsAndCreationsRejectedLackSpace , &m .CacheevStaleObjectsDeleted ,
&m .CacheevRetiredWhenReliquished , &m .CacheevObjectsCulled )
if err != nil {
return &m , err
}
}
}
return &m , nil
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .