xref: /3.0.3-GA/ep-engine/src/objectregistry.cc (revision 392ba27e)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2011 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#include "config.h"
19
20#include "threadlocal.h"
21#include "ep_engine.h"
22#include "objectregistry.h"
23
24static ThreadLocal<EventuallyPersistentEngine*> *th;
25static ThreadLocal<AtomicValue<size_t>*> *initial_track;
26
27/**
28 * Object registry link hook for getting the registry thread local
29 * installed.
30 */
31class installer {
32public:
33   installer() {
34      if (th == NULL) {
35         th = new ThreadLocal<EventuallyPersistentEngine*>();
36         initial_track = new ThreadLocal<AtomicValue<size_t>*>();
37      }
38   }
39} install;
40
41static bool verifyEngine(EventuallyPersistentEngine *engine)
42{
43   if (engine == NULL) {
44       if (getenv("ALLOW_NO_STATS_UPDATE") != NULL) {
45           return false;
46       } else {
47           cb_assert(engine);
48       }
49   }
50   return true;
51}
52
53
54void ObjectRegistry::onCreateBlob(Blob *blob)
55{
56   EventuallyPersistentEngine *engine = th->get();
57   if (verifyEngine(engine)) {
58       EPStats &stats = engine->getEpStats();
59       stats.currentSize.fetch_add(blob->getSize());
60       stats.totalValueSize.fetch_add(blob->getSize());
61       cb_assert(stats.currentSize.load() < GIGANTOR);
62   }
63}
64
65void ObjectRegistry::onDeleteBlob(Blob *blob)
66{
67   EventuallyPersistentEngine *engine = th->get();
68   if (verifyEngine(engine)) {
69       EPStats &stats = engine->getEpStats();
70       stats.currentSize.fetch_sub(blob->getSize());
71       stats.totalValueSize.fetch_sub(blob->getSize());
72       cb_assert(stats.currentSize.load() < GIGANTOR);
73   }
74}
75
76void ObjectRegistry::onCreateItem(Item *pItem)
77{
78   EventuallyPersistentEngine *engine = th->get();
79   if (verifyEngine(engine)) {
80       EPStats &stats = engine->getEpStats();
81       stats.memOverhead.fetch_add(pItem->size() - pItem->getValMemSize());
82       cb_assert(stats.memOverhead.load() < GIGANTOR);
83   }
84}
85
86void ObjectRegistry::onDeleteItem(Item *pItem)
87{
88   EventuallyPersistentEngine *engine = th->get();
89   if (verifyEngine(engine)) {
90       EPStats &stats = engine->getEpStats();
91       stats.memOverhead.fetch_sub(pItem->size() - pItem->getValMemSize());
92       cb_assert(stats.memOverhead.load() < GIGANTOR);
93   }
94}
95
96EventuallyPersistentEngine *ObjectRegistry::getCurrentEngine() {
97    return th->get();
98}
99
100EventuallyPersistentEngine *ObjectRegistry::onSwitchThread(
101                                            EventuallyPersistentEngine *engine,
102                                            bool want_old_thread_local)
103{
104    EventuallyPersistentEngine *old_engine = NULL;
105    if (want_old_thread_local) {
106        old_engine = th->get();
107    }
108    th->set(engine);
109    return old_engine;
110}
111
112void ObjectRegistry::setStats(AtomicValue<size_t>* init_track) {
113    initial_track->set(init_track);
114}
115
116bool ObjectRegistry::memoryAllocated(size_t mem) {
117    EventuallyPersistentEngine *engine = th->get();
118    if (initial_track->get()) {
119        initial_track->get()->fetch_add(mem);
120    }
121    if (!engine) {
122        return false;
123    }
124    EPStats &stats = engine->getEpStats();
125    stats.totalMemory.fetch_add(mem);
126    if (stats.memoryTrackerEnabled && stats.totalMemory.load() >= GIGANTOR) {
127        LOG(EXTENSION_LOG_WARNING,
128            "Total memory in memoryAllocated() >= GIGANTOR !!! "
129            "Disable the memory tracker...\n");
130        stats.memoryTrackerEnabled.store(false);
131    }
132    return true;
133}
134
135bool ObjectRegistry::memoryDeallocated(size_t mem) {
136    EventuallyPersistentEngine *engine = th->get();
137    if (initial_track->get()) {
138        initial_track->get()->fetch_sub(mem);
139    }
140    if (!engine) {
141        return false;
142    }
143    EPStats &stats = engine->getEpStats();
144    stats.totalMemory.fetch_sub(mem);
145    if (stats.memoryTrackerEnabled && stats.totalMemory.load() >= GIGANTOR) {
146        EXTENSION_LOG_LEVEL logSeverity = EXTENSION_LOG_WARNING;
147        if (stats.isShutdown && !stats.forceShutdown) {
148            logSeverity = EXTENSION_LOG_INFO;
149        }
150        LOG(logSeverity,
151            "Total memory in memoryDeallocated() >= GIGANTOR !!! "
152            "Disable the memory tracker...\n");
153        stats.memoryTrackerEnabled.store(false);
154    }
155    return true;
156}
157