summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/api/leveldb/basho/perf_count.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/api/leveldb/basho/perf_count.cc')
-rw-r--r--src/third_party/wiredtiger/api/leveldb/basho/perf_count.cc657
1 files changed, 657 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/api/leveldb/basho/perf_count.cc b/src/third_party/wiredtiger/api/leveldb/basho/perf_count.cc
new file mode 100644
index 00000000000..0e666ac1dc0
--- /dev/null
+++ b/src/third_party/wiredtiger/api/leveldb/basho/perf_count.cc
@@ -0,0 +1,657 @@
+// -------------------------------------------------------------------
+//
+// perf_count.cc: performance counters LevelDB
+//
+// Copyright (c) 2012-2013 Basho Technologies, Inc. All Rights Reserved.
+//
+// This file is provided to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// -------------------------------------------------------------------
+
+#include <limits.h>
+#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <memory.h>
+#include <errno.h>
+
+#ifndef STORAGE_LEVELDB_INCLUDE_PERF_COUNT_H_
+#include "perf_count.h"
+#endif
+
+#include "util/coding.h"
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#ifdef OS_SOLARIS
+# include <atomic.h>
+#endif
+
+
+namespace leveldb
+{
+
+// always have something active in gPerfCounters, eliminates
+// need to test for "is shared object attached yet"
+static PerformanceCounters LocalStartupCounters;
+PerformanceCounters * gPerfCounters(&LocalStartupCounters);
+
+
+ SstCounters::SstCounters()
+ : m_IsReadOnly(false),
+ m_Version(eSstCountVersion),
+ m_CounterSize(eSstCountEnumSize)
+ {
+ memset(m_Counter, 0, sizeof(m_Counter));
+
+ m_Counter[eSstCountKeySmallest]=ULLONG_MAX;
+ m_Counter[eSstCountValueSmallest]=ULLONG_MAX;
+
+ return;
+
+ }; // SstCounters::SstCounters
+
+
+ void
+ SstCounters::EncodeTo(
+ std::string & Dst) const
+ {
+ unsigned loop;
+
+ PutVarint32(&Dst, m_Version);
+ PutVarint32(&Dst, m_CounterSize);
+
+ for(loop=0; loop<eSstCountEnumSize; ++loop)
+ PutVarint64(&Dst, m_Counter[loop]);
+ } // SstCounters::EncodeTo
+
+
+ Status
+ SstCounters::DecodeFrom(
+ const Slice& src)
+ {
+ Status ret_status;
+ Slice cursor;
+ bool good;
+ int loop;
+
+ cursor=src;
+ m_IsReadOnly=true;
+ good=GetVarint32(&cursor, &m_Version);
+ good=good && (m_Version<=eSstCountVersion);
+
+ // all lesser number of stats to be read
+ good=good && GetVarint32(&cursor, &m_CounterSize);
+ if (good && eSstCountEnumSize < m_CounterSize)
+ m_CounterSize=eSstCountEnumSize;
+
+ for (loop=0; good && loop<eSstCountEnumSize; ++loop)
+ {
+ good=GetVarint64(&cursor, &m_Counter[loop]);
+ } // for
+
+ // if (!good) change ret_status to bad
+
+ return(ret_status);
+
+ } // SstCounters::DecodeFrom
+
+
+ uint64_t
+ SstCounters::Inc(
+ unsigned Index)
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (!m_IsReadOnly && Index<m_CounterSize)
+ {
+ ++m_Counter[Index];
+ ret_val=m_Counter[Index];
+ } // if
+
+ return(ret_val);
+ } // SstCounters::Inc
+
+
+ uint64_t
+ SstCounters::Add(
+ unsigned Index,
+ uint64_t Amount)
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (!m_IsReadOnly && Index<m_CounterSize)
+ {
+ m_Counter[Index]+=Amount;
+ ret_val=m_Counter[Index];
+ } // if
+
+ return(ret_val);
+ } // SstCounters::Add
+
+
+ uint64_t
+ SstCounters::Value(
+ unsigned Index) const
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (Index<m_CounterSize)
+ {
+ ret_val=m_Counter[Index];
+ } // if
+
+ return(ret_val);
+ } // SstCounters::Value
+
+
+ void
+ SstCounters::Set(
+ unsigned Index,
+ uint64_t Value)
+ {
+ if (Index<m_CounterSize)
+ {
+ m_Counter[Index]=Value;
+ } // if
+
+ return;
+ } // SstCounters::Set
+
+
+ void
+ SstCounters::Dump() const
+ {
+ unsigned loop;
+
+ printf("SstCounters:\n");
+ printf(" m_IsReadOnly: %u\n", m_IsReadOnly);
+ printf(" m_Version: %u\n", m_Version);
+ printf(" m_CounterSize: %u\n", m_CounterSize);
+ for (loop=0; loop<m_CounterSize; ++loop)
+ printf(" Counter[%2u]: %" PRIu64 "\n", loop, m_Counter[loop]);
+
+ return;
+
+ } // SstCounters::Dump
+
+
+ // only used for local static objects, not shared memory objects
+ PerformanceCounters::PerformanceCounters()
+ {
+ m_Version=ePerfVersion;
+ m_CounterSize=ePerfCountEnumSize;
+ // cast away "volatile"
+ memset((void*)m_Counter, 0, sizeof(m_Counter));
+
+ return;
+
+ } // PerformanceCounters::PerformanceCounters
+
+
+ PerformanceCounters *
+ PerformanceCounters::Init(
+ bool IsReadOnly)
+ {
+ PerformanceCounters * ret_ptr;
+ bool should_create, good;
+ int ret_val, id;
+ struct shmid_ds shm_info;
+ size_t open_size;
+
+ ret_ptr=NULL;
+ memset(&shm_info, 0, sizeof(shm_info));
+ good=true;
+ open_size=sizeof(PerformanceCounters);
+
+ // first id attempt, minimal request
+ id=shmget(ePerfKey, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (-1!=id)
+ ret_val=shmctl(id, IPC_STAT, &shm_info);
+ else
+ ret_val=-1;
+
+ // does the shared memory already exists (and of proper size if writing)
+ should_create=(0!=ret_val || (shm_info.shm_segsz < sizeof(PerformanceCounters))) && !IsReadOnly;
+
+ // should old shared memory be deleted?
+ if (should_create && 0==ret_val)
+ {
+ ret_val=shmctl(id, IPC_RMID, &shm_info);
+ good=(0==ret_val);
+ if (0!=ret_val)
+ syslog(LOG_ERR, "shmctl IPC_RMID failed [%d, %m]", errno);
+ } // if
+
+ // else open the size that exists
+ else if (0==ret_val)
+ {
+ open_size=shm_info.shm_segsz;
+ } // else if
+
+ // attempt to attach/create to shared memory instance
+ if (good)
+ {
+ int flags;
+
+ if (IsReadOnly)
+ flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ else
+ flags = IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+ m_PerfSharedId=shmget(ePerfKey, open_size, flags);
+ good=(-1!=m_PerfSharedId);
+ } // if
+
+ // map shared memory instance
+ if (good)
+ {
+ ret_ptr=(PerformanceCounters *)shmat(m_PerfSharedId, NULL, (IsReadOnly ? SHM_RDONLY : 0));
+ if ((void*)-1 != ret_ptr)
+ {
+ // initialize?
+ if (should_create || ePerfVersion!=ret_ptr->m_Version)
+ {
+ if (!IsReadOnly)
+ {
+ memset(ret_ptr, 0, sizeof(PerformanceCounters));
+ ret_ptr->m_Version=ePerfVersion;
+ ret_ptr->m_CounterSize=ePerfCountEnumSize;
+ } // if
+
+ // bad version match to existing segment
+ else
+ {
+ good=false;
+ errno=EINVAL;
+ } // else
+ } // if
+ } // if
+ else
+ {
+ good=false;
+ syslog(LOG_ERR, "shmat failed [%d, %m]", errno);
+ } // else
+
+ if (good)
+ {
+ // make this available process wide
+ gPerfCounters=ret_ptr;
+ } // if
+ else
+ {
+ ret_ptr=NULL;
+ m_LastError=errno;
+ } // else
+ } // if
+ else
+ {
+ m_LastError=errno;
+ ret_ptr=NULL;
+ } // else
+
+ return(ret_ptr);
+
+ }; // PerformanceCounters::Init
+
+
+ int
+ PerformanceCounters::Close(
+ PerformanceCounters * Counts)
+ {
+ int ret_val;
+
+ if (NULL!=Counts && &LocalStartupCounters != Counts)
+ {
+ // keep gPerf valid
+ if (gPerfCounters==Counts)
+ gPerfCounters=&LocalStartupCounters;
+
+ ret_val=shmdt(Counts);
+ if (0!=ret_val)
+ ret_val=errno;
+ } // if
+ else
+ {
+ ret_val=EINVAL;
+ } // else
+
+ return(ret_val);
+ } // PerformanceCounters::Close
+
+
+ uint64_t
+ PerformanceCounters::Inc(
+ unsigned Index)
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (Index<m_CounterSize)
+ {
+ volatile uint64_t * val_ptr;
+
+ val_ptr=&m_Counter[Index];
+
+# if ULONG_MAX != 4294967295UL
+#ifdef OS_SOLARIS
+ atomic_inc_64(val_ptr);
+#else
+ __sync_add_and_fetch(val_ptr, 1);
+#endif
+#else
+ // hack fest for 64 bit semi-atomic on 32bit machine
+ uint32_t ret_32, * ptr_32;
+
+ ptr_32=(uint32_t *)&val_ptr;
+ ret_32=__sync_add_and_fetch(ptr_32, 1);
+ if (0==ret_32)
+ {
+ ++ptr_32;
+ __sync_add_and_fetch(ptr_32, 1);
+ } // if
+#endif
+ ret_val=*val_ptr;
+ } // if
+
+ return(ret_val);
+ } // PerformanceCounters::Inc
+
+
+ uint64_t
+ PerformanceCounters::Dec(
+ unsigned Index)
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (Index<m_CounterSize)
+ {
+ volatile uint64_t * val_ptr;
+
+ val_ptr=&m_Counter[Index];
+
+# if ULONG_MAX != 4294967295UL
+#ifdef OS_SOLARIS
+ atomic_dec_64(val_ptr);
+#else
+ __sync_sub_and_fetch(val_ptr, 1);
+#endif
+#else
+ // hack fest for 64 bit semi-atomic on 32bit machine
+ uint32_t ret_32, * ptr_32;
+
+ ptr_32=(uint32_t *)&val_ptr;
+ ret_32=__sync_sub_and_fetch(ptr_32, 1);
+ if (0xFFFFFFFF==ret_32)
+ {
+ ++ptr_32;
+ __sync_sub_and_fetch(ptr_32, 1);
+ } // if
+#endif
+ ret_val=*val_ptr;
+ } // if
+
+ return(ret_val);
+ } // PerformanceCounters::Dec
+
+
+ uint64_t
+ PerformanceCounters::Add(
+ unsigned Index,
+ uint64_t Amount)
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (Index<m_CounterSize)
+ {
+ volatile uint64_t * val_ptr;
+
+ val_ptr=&m_Counter[Index];
+
+# if ULONG_MAX != 4294967295UL
+#ifdef OS_SOLARIS
+ ret_val=atomic_add_64_nv(val_ptr, Amount);
+#else
+ ret_val=__sync_add_and_fetch(val_ptr, Amount);
+#endif
+#else
+ // hack fest for 64 bit semi-atomic on 32bit machine
+ uint32_t old_32, ret_32, * ptr_32;
+
+ ptr_32=(uint32_t *)&val_ptr;
+ old_32=*ptr_32;
+ ret_32=__sync_add_and_fetch(ptr_32, Amount);
+ if (ret_32<old_32)
+ {
+ ++ptr_32;
+ __sync_add_and_fetch(ptr_32, 1);
+ } // if
+
+ ret_val=*val_ptr;
+#endif
+ } // if
+
+ return(ret_val);
+ } // PerformanceCounters::Add
+
+
+ uint64_t
+ PerformanceCounters::Value(
+ unsigned Index) const
+ {
+ uint64_t ret_val;
+
+ ret_val=0;
+ if (Index<m_CounterSize)
+ {
+ ret_val=m_Counter[Index];
+ } // if
+
+ return(ret_val);
+ } // SstCounters::Value
+
+
+ void
+ PerformanceCounters::Set(
+ unsigned Index,
+ uint64_t Amount)
+ {
+ if (Index<m_CounterSize)
+ {
+ volatile uint64_t * val_ptr;
+
+ val_ptr=&m_Counter[Index];
+
+ *val_ptr=Amount;
+ } // if
+
+ return;
+ } // PerformanceCounters::Set
+
+
+ volatile const uint64_t *
+ PerformanceCounters::GetPtr(
+ unsigned Index) const
+ {
+ const volatile uint64_t * ret_ptr;
+
+ if (Index<m_CounterSize)
+ ret_ptr=&m_Counter[Index];
+ else
+ ret_ptr=&m_BogusCounter;
+
+ return(ret_ptr);
+
+ } // PerformanceCounters::GetPtr
+
+
+ const char *
+ PerformanceCounters::GetNamePtr(
+ unsigned Index)
+ {
+ const char * ret_ptr;
+
+ if (Index<ePerfCountEnumSize)
+ ret_ptr=m_PerfCounterNames[Index];
+ else
+ ret_ptr="???";
+
+ return(ret_ptr);
+
+ } // PerformanceCounters::GetPtr
+
+
+ int PerformanceCounters::m_PerfSharedId=-1;
+ int PerformanceCounters::m_LastError=0;
+ volatile uint64_t PerformanceCounters::m_BogusCounter=0;
+ const char * PerformanceCounters::m_PerfCounterNames[]=
+ {
+ "ROFileOpen",
+ "ROFileClose",
+ "ROFileUnmap",
+ "RWFileOpen",
+ "RWFileClose",
+ "RWFileUnmap",
+ "ApiOpen",
+ "ApiGet",
+ "ApiWrite",
+ "WriteSleep",
+ "WriteWaitImm",
+ "WriteWaitLevel0",
+ "WriteNewMem",
+ "WriteError",
+ "WriteNoWait",
+ "GetMem",
+ "GetImm",
+ "GetVersion",
+ "SearchLevel[0]",
+ "SearchLevel[1]",
+ "SearchLevel[2]",
+ "SearchLevel[3]",
+ "SearchLevel[4]",
+ "SearchLevel[5]",
+ "SearchLevel[6]",
+ "TableCached",
+ "TableOpened",
+ "TableGet",
+ "BGCloseUnmap",
+ "BGCompactImm",
+ "BGNormal",
+ "BGCompactLevel0",
+ "BlockFiltered",
+ "BlockFilterFalse",
+ "BlockCached",
+ "BlockRead",
+ "BlockFilterRead",
+ "BlockValidGet",
+ "Debug[0]",
+ "Debug[1]",
+ "Debug[2]",
+ "Debug[3]",
+ "Debug[4]",
+ "ReadBlockError",
+ "DBIterNew",
+ "DBIterNext",
+ "DBIterPrev",
+ "DBIterSeek",
+ "DBIterSeekFirst",
+ "DBIterSeekLast",
+ "DBIterDelete",
+ "eleveldbDirect",
+ "eleveldbQueued",
+ "eleveldbDequeued",
+ "elevelRefCreate",
+ "elevelRefDelete",
+ "ThrottleGauge",
+ "ThrottleCounter",
+ "ThrottleMicros0",
+ "ThrottleKeys0",
+ "ThrottleBacklog0",
+ "ThrottleCompacts0",
+ "ThrottleMicros1",
+ "ThrottleKeys1",
+ "ThrottleBacklog1",
+ "ThrottleCompacts1",
+ "BGWriteError",
+ "ThrottleWait",
+ "ThreadError",
+ "BGImmDirect",
+ "BGImmQueued",
+ "BGImmDequeued",
+ "BGImmWeighted",
+ "BGUnmapDirect",
+ "BGUnmapQueued",
+ "BGUnmapDequeued",
+ "BGUnmapWeighted",
+ "BGLevel0Direct",
+ "BGLevel0Queued",
+ "BGLevel0Dequeued",
+ "BGLevel0Weighted",
+ "BGCompactDirect",
+ "BGCompactQueued",
+ "BGCompactDequeued",
+ "BGCompactWeighted",
+ "FileCacheInsert",
+ "FileCacheRemove",
+ "BlockCacheInsert",
+ "BlockCacheRemove",
+ "ApiDelete"
+ };
+
+
+ int
+ PerformanceCounters::LookupCounter(
+ const char * Name)
+ {
+ int index,loop;
+
+ index=-1;
+
+ if (NULL!=Name && '\0'!=*Name)
+ {
+ for (loop=0; loop<ePerfCountEnumSize && -1==index; ++loop)
+ {
+ if (0==strcmp(m_PerfCounterNames[loop], Name))
+ index=loop;
+ } // loop
+ } // if
+
+ return(index);
+ };
+
+ void
+ PerformanceCounters::Dump()
+ {
+ int loop;
+
+ printf(" m_Version: %u\n", m_Version);
+ printf(" m_CounterSize: %u\n", m_CounterSize);
+
+ for (loop=0; loop<ePerfCountEnumSize; ++loop)
+ {
+ printf(" %s: %" PRIu64 "\n", m_PerfCounterNames[loop], m_Counter[loop]);
+ } // loop
+ }; // Dump
+
+} // namespace leveldb