17aada74aSTrond Norbye/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
27aada74aSTrond Norbye/*
38b7221cbSDave Rigby *     Copyright 2015 Couchbase, Inc
47aada74aSTrond Norbye *
57aada74aSTrond Norbye *   Licensed under the Apache License, Version 2.0 (the "License");
67aada74aSTrond Norbye *   you may not use this file except in compliance with the License.
77aada74aSTrond Norbye *   You may obtain a copy of the License at
87aada74aSTrond Norbye *
97aada74aSTrond Norbye *       http://www.apache.org/licenses/LICENSE-2.0
107aada74aSTrond Norbye *
117aada74aSTrond Norbye *   Unless required by applicable law or agreed to in writing, software
127aada74aSTrond Norbye *   distributed under the License is distributed on an "AS IS" BASIS,
137aada74aSTrond Norbye *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147aada74aSTrond Norbye *   See the License for the specific language governing permissions and
157aada74aSTrond Norbye *   limitations under the License.
167aada74aSTrond Norbye */
1766eb94d0SMike Wiederhold
187aada74aSTrond Norbye#include "config.h"
19244c0146SMike Wiederhold
2066bb41adSDave Rigby#include "objectregistry.h"
2166bb41adSDave Rigby
227aada74aSTrond Norbye#include "ep_engine.h"
23da4e3493SDave Rigby#include "item.h"
241cb55ca0STrond Norbye#include "stored-value.h"
25da4e3493SDave Rigby#include "threadlocal.h"
267aada74aSTrond Norbye
2766bb41adSDave Rigby#if 1
287aada74aSTrond Norbyestatic ThreadLocal<EventuallyPersistentEngine*> *th;
2966bb41adSDave Rigbystatic ThreadLocal<std::atomic<size_t>*> *initial_track;
307aada74aSTrond Norbye
3171ff82fbSTrond Norbyeextern "C" {
3271ff82fbSTrond Norbye    static size_t defaultGetAllocSize(const void *) {
3371ff82fbSTrond Norbye        return 0;
3471ff82fbSTrond Norbye    }
3571ff82fbSTrond Norbye}
3671ff82fbSTrond Norbye
3771ff82fbSTrond Norbyestatic get_allocation_size getAllocSize = defaultGetAllocSize;
3871ff82fbSTrond Norbye
3971ff82fbSTrond Norbye
4071ff82fbSTrond Norbye
414d05a0cbSDustin Sallings/**
424d05a0cbSDustin Sallings * Object registry link hook for getting the registry thread local
434d05a0cbSDustin Sallings * installed.
444d05a0cbSDustin Sallings */
457aada74aSTrond Norbyeclass installer {
467aada74aSTrond Norbyepublic:
477aada74aSTrond Norbye   installer() {
487aada74aSTrond Norbye      if (th == NULL) {
497aada74aSTrond Norbye         th = new ThreadLocal<EventuallyPersistentEngine*>();
5066bb41adSDave Rigby         initial_track = new ThreadLocal<std::atomic<size_t>*>();
517aada74aSTrond Norbye      }
527aada74aSTrond Norbye   }
53d50b3d45SDave Rigby
54d50b3d45SDave Rigby   ~installer() {
55d50b3d45SDave Rigby       delete initial_track;
56d50b3d45SDave Rigby       delete th;
57d50b3d45SDave Rigby   }
587aada74aSTrond Norbye} install;
597aada74aSTrond Norbye
607aada74aSTrond Norbyestatic bool verifyEngine(EventuallyPersistentEngine *engine)
617aada74aSTrond Norbye{
627aada74aSTrond Norbye   if (engine == NULL) {
637aada74aSTrond Norbye       if (getenv("ALLOW_NO_STATS_UPDATE") != NULL) {
647aada74aSTrond Norbye           return false;
657aada74aSTrond Norbye       } else {
668b7221cbSDave Rigby           throw std::logic_error("verifyEngine: engine should be non-NULL");
677aada74aSTrond Norbye       }
687aada74aSTrond Norbye   }
697aada74aSTrond Norbye   return true;
707aada74aSTrond Norbye}
717aada74aSTrond Norbye
7271ff82fbSTrond Norbyevoid ObjectRegistry::initialize(get_allocation_size func) {
7371ff82fbSTrond Norbye    getAllocSize = func;
7471ff82fbSTrond Norbye}
7571ff82fbSTrond Norbye
765e513286SDave Rigbyvoid ObjectRegistry::reset() {
775e513286SDave Rigby    getAllocSize = defaultGetAllocSize;
785e513286SDave Rigby}
797aada74aSTrond Norbye
808a277c1fSTrond Norbyevoid ObjectRegistry::onCreateBlob(const Blob *blob)
817aada74aSTrond Norbye{
827aada74aSTrond Norbye   EventuallyPersistentEngine *engine = th->get();
837aada74aSTrond Norbye   if (verifyEngine(engine)) {
8461b6f9a7SDave Rigby       auto& coreLocalStats = engine->getEpStats().coreLocal.get();
8561b6f9a7SDave Rigby
8671ff82fbSTrond Norbye       size_t size = getAllocSize(blob);
8771ff82fbSTrond Norbye       if (size == 0) {
8871ff82fbSTrond Norbye           size = blob->getSize();
8971ff82fbSTrond Norbye       } else {
9061b6f9a7SDave Rigby           coreLocalStats->blobOverhead.fetch_add(size - blob->getSize());
9171ff82fbSTrond Norbye       }
9261b6f9a7SDave Rigby       coreLocalStats->currentSize.fetch_add(size);
9361b6f9a7SDave Rigby       coreLocalStats->totalValueSize.fetch_add(size);
9461b6f9a7SDave Rigby       coreLocalStats->numBlob++;
957aada74aSTrond Norbye   }
967aada74aSTrond Norbye}
977aada74aSTrond Norbye
988a277c1fSTrond Norbyevoid ObjectRegistry::onDeleteBlob(const Blob *blob)
997aada74aSTrond Norbye{
1007aada74aSTrond Norbye   EventuallyPersistentEngine *engine = th->get();
1017aada74aSTrond Norbye   if (verifyEngine(engine)) {
10261b6f9a7SDave Rigby       auto& coreLocalStats = engine->getEpStats().coreLocal.get();
10361b6f9a7SDave Rigby
10471ff82fbSTrond Norbye       size_t size = getAllocSize(blob);
10571ff82fbSTrond Norbye       if (size == 0) {
10671ff82fbSTrond Norbye           size = blob->getSize();
10771ff82fbSTrond Norbye       } else {
10861b6f9a7SDave Rigby           coreLocalStats->blobOverhead.fetch_sub(size - blob->getSize());
10971ff82fbSTrond Norbye       }
11061b6f9a7SDave Rigby       coreLocalStats->currentSize.fetch_sub(size);
11161b6f9a7SDave Rigby       coreLocalStats->totalValueSize.fetch_sub(size);
11261b6f9a7SDave Rigby       coreLocalStats->numBlob--;
1137aada74aSTrond Norbye   }
1147aada74aSTrond Norbye}
1157aada74aSTrond Norbye
1161cb55ca0STrond Norbyevoid ObjectRegistry::onCreateStoredValue(const StoredValue *sv)
1171cb55ca0STrond Norbye{
1181cb55ca0STrond Norbye   EventuallyPersistentEngine *engine = th->get();
1191cb55ca0STrond Norbye   if (verifyEngine(engine)) {
12061b6f9a7SDave Rigby       auto& coreLocalStats = engine->getEpStats().coreLocal.get();
12161b6f9a7SDave Rigby
1221cb55ca0STrond Norbye       size_t size = getAllocSize(sv);
1231cb55ca0STrond Norbye       if (size == 0) {
1241cb55ca0STrond Norbye           size = sv->getObjectSize();
1251cb55ca0STrond Norbye       } else {
12661b6f9a7SDave Rigby           coreLocalStats->storedValOverhead.fetch_add(size -
12761b6f9a7SDave Rigby                                                       sv->getObjectSize());
1281cb55ca0STrond Norbye       }
12961b6f9a7SDave Rigby       coreLocalStats->numStoredVal++;
13061b6f9a7SDave Rigby       coreLocalStats->totalStoredValSize.fetch_add(size);
1311cb55ca0STrond Norbye   }
1321cb55ca0STrond Norbye}
1331cb55ca0STrond Norbye
1341cb55ca0STrond Norbyevoid ObjectRegistry::onDeleteStoredValue(const StoredValue *sv)
1351cb55ca0STrond Norbye{
1361cb55ca0STrond Norbye   EventuallyPersistentEngine *engine = th->get();
1371cb55ca0STrond Norbye   if (verifyEngine(engine)) {
13861b6f9a7SDave Rigby       auto& coreLocalStats = engine->getEpStats().coreLocal.get();
13961b6f9a7SDave Rigby
1401cb55ca0STrond Norbye       size_t size = getAllocSize(sv);
1411cb55ca0STrond Norbye       if (size == 0) {
1421cb55ca0STrond Norbye           size = sv->getObjectSize();
1431cb55ca0STrond Norbye       } else {
14461b6f9a7SDave Rigby           coreLocalStats->storedValOverhead.fetch_sub(size -
14561b6f9a7SDave Rigby                                                       sv->getObjectSize());
1461cb55ca0STrond Norbye       }
14761b6f9a7SDave Rigby       coreLocalStats->totalStoredValSize.fetch_sub(size);
14861b6f9a7SDave Rigby       coreLocalStats->numStoredVal--;
1491cb55ca0STrond Norbye   }
1501cb55ca0STrond Norbye}
1511cb55ca0STrond Norbye
1521cb55ca0STrond Norbye
1538a277c1fSTrond Norbyevoid ObjectRegistry::onCreateItem(const Item *pItem)
1546da82cedSChiyoung Seo{
1556da82cedSChiyoung Seo   EventuallyPersistentEngine *engine = th->get();
1566da82cedSChiyoung Seo   if (verifyEngine(engine)) {
15761b6f9a7SDave Rigby       auto& coreLocalStats = engine->getEpStats().coreLocal.get();
15861b6f9a7SDave Rigby       coreLocalStats->memOverhead.fetch_add(pItem->size() -
15961b6f9a7SDave Rigby                                             pItem->getValMemSize());
16061b6f9a7SDave Rigby       ++coreLocalStats->numItem;
1616da82cedSChiyoung Seo   }
1626da82cedSChiyoung Seo}
1636da82cedSChiyoung Seo
1648a277c1fSTrond Norbyevoid ObjectRegistry::onDeleteItem(const Item *pItem)
1656da82cedSChiyoung Seo{
1666da82cedSChiyoung Seo   EventuallyPersistentEngine *engine = th->get();
1676da82cedSChiyoung Seo   if (verifyEngine(engine)) {
16861b6f9a7SDave Rigby       auto& coreLocalStats = engine->getEpStats().coreLocal.get();
16961b6f9a7SDave Rigby       coreLocalStats->memOverhead.fetch_sub(pItem->size() -
17061b6f9a7SDave Rigby                                             pItem->getValMemSize());
17161b6f9a7SDave Rigby       --coreLocalStats->numItem;
1727aada74aSTrond Norbye   }
1737aada74aSTrond Norbye}
1747aada74aSTrond Norbye
175a1213f50SMike WiederholdEventuallyPersistentEngine *ObjectRegistry::getCurrentEngine() {
176a1213f50SMike Wiederhold    return th->get();
177a1213f50SMike Wiederhold}
178a1213f50SMike Wiederhold
17918770839SSundar SridharanEventuallyPersistentEngine *ObjectRegistry::onSwitchThread(
18018770839SSundar Sridharan                                            EventuallyPersistentEngine *engine,
1810bfe5364SPremkumar Thangamani                                            bool want_old_thread_local) {
1825ff0677dSChiyoung Seo    EventuallyPersistentEngine *old_engine = NULL;
1830bfe5364SPremkumar Thangamani
1845ff0677dSChiyoung Seo    if (want_old_thread_local) {
1855ff0677dSChiyoung Seo        old_engine = th->get();
1865ff0677dSChiyoung Seo    }
1870bfe5364SPremkumar Thangamani
1885ff0677dSChiyoung Seo    th->set(engine);
1895ff0677dSChiyoung Seo    return old_engine;
1907aada74aSTrond Norbye}
19160265a2aSMike Wiederhold
19266bb41adSDave Rigbyvoid ObjectRegistry::setStats(std::atomic<size_t>* init_track) {
1935db40253SMike Wiederhold    initial_track->set(init_track);
1945db40253SMike Wiederhold}
1955db40253SMike Wiederhold
19660265a2aSMike Wiederholdbool ObjectRegistry::memoryAllocated(size_t mem) {
1975f235682SChiyoung Seo    EventuallyPersistentEngine *engine = th->get();
1985db40253SMike Wiederhold    if (initial_track->get()) {
1997c6809d2STrond Norbye        initial_track->get()->fetch_add(mem);
2005db40253SMike Wiederhold    }
2015f235682SChiyoung Seo    if (!engine) {
20260265a2aSMike Wiederhold        return false;
2035f235682SChiyoung Seo    }
2045f235682SChiyoung Seo    EPStats &stats = engine->getEpStats();
2050bfe5364SPremkumar Thangamani    stats.memAllocated(mem);
2065f235682SChiyoung Seo    return true;
20760265a2aSMike Wiederhold}
20860265a2aSMike Wiederhold
20960265a2aSMike Wiederholdbool ObjectRegistry::memoryDeallocated(size_t mem) {
2105f235682SChiyoung Seo    EventuallyPersistentEngine *engine = th->get();
2115db40253SMike Wiederhold    if (initial_track->get()) {
2127c6809d2STrond Norbye        initial_track->get()->fetch_sub(mem);
2135db40253SMike Wiederhold    }
2145f235682SChiyoung Seo    if (!engine) {
21560265a2aSMike Wiederhold        return false;
2165f235682SChiyoung Seo    }
2175f235682SChiyoung Seo    EPStats &stats = engine->getEpStats();
2180bfe5364SPremkumar Thangamani    stats.memDeallocated(mem);
2195f235682SChiyoung Seo    return true;
22060265a2aSMike Wiederhold}
2210bfe5364SPremkumar Thangamani
2220bfe5364SPremkumar ThangamaniSystemAllocationGuard::SystemAllocationGuard() {
2230bfe5364SPremkumar Thangamani    engine = th->get();
2240bfe5364SPremkumar Thangamani    th->set(nullptr);
2250bfe5364SPremkumar Thangamani}
2260bfe5364SPremkumar Thangamani
2270bfe5364SPremkumar ThangamaniSystemAllocationGuard::~SystemAllocationGuard() {
2280bfe5364SPremkumar Thangamani    th->set(engine);
2290bfe5364SPremkumar Thangamani}
2300bfe5364SPremkumar Thangamani
23166bb41adSDave Rigby#endif
232