blob: 41926129d18686e97f70d7a992fc0d7796cb8e5b [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
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 "libts.h"
#include "ProxyConfig.h"
#include "P_EventSystem.h"
ConfigProcessor configProcessor;
void *
config_int_cb(void *data, void *value)
{
*(int *) data = *(int64_t *) value;
return NULL;
}
void *
config_float_cb(void *data, void *value)
{
*(float *) data = *(float *) value;
return NULL;
}
void *
config_long_long_cb(void *data, void *value)
{
*(int64_t *) data = *(int64_t *) value;
return NULL;
}
/////////////////////////////////////////////////////////////
//
// config_string_alloc_cb()
//
// configuration callback function. The function is called
// by the manager when a string configuration variable
// changed. It allocates new memory for the new data.
// the old variable is scheduled to be freed using
// ConfigFreerContinuation which will free the memory
// used for this variable after long time, assuming that
// during all this time all the users of this memory will
// disappear.
/////////////////////////////////////////////////////////////
void *
config_string_alloc_cb(void *data, void *value)
{
char *_ss = (char *) value;
char *_new_value = 0;
//#define DEBUG_CONFIG_STRING_UPDATE
#if defined (DEBUG_CONFIG_STRING_UPDATE)
printf("config callback [new, old] = [%s : %s]\n",
(_ss) ? (_ss) : (""), (*(char **) data) ? (*(char **) data) : (""));
#endif
int len = -1;
if (_ss) {
len = strlen(_ss);
_new_value = (char *) xmalloc(len + 1);
memcpy(_new_value, _ss, len + 1);
}
char *_temp2 = *(char **) data;
*(char **) data = _new_value;
// free old data
if (_temp2 != 0)
new_Freer(_temp2, HRTIME_DAY);
return NULL;
}
class ConfigInfoReleaser:public Continuation
{
public:
ConfigInfoReleaser(unsigned int id, ConfigInfo * info)
: Continuation(new_ProxyMutex()), m_id(id), m_info(info)
{
SET_HANDLER(&ConfigInfoReleaser::handle_event);
}
int handle_event(int event, void *edata)
{
NOWARN_UNUSED(event);
NOWARN_UNUSED(edata);
configProcessor.release(m_id, m_info);
delete this;
return 0;
}
public:
unsigned int m_id;
ConfigInfo *m_info;
};
ConfigProcessor::ConfigProcessor()
: ninfos(0)
{
int i;
for (i = 0; i < MAX_CONFIGS; i++) {
infos[i] = NULL;
}
}
unsigned int
ConfigProcessor::set(unsigned int id, ConfigInfo * info)
{
ConfigInfo *old_info;
int idx;
if (id == 0) {
id = ink_atomic_increment((int *) &ninfos, 1) + 1;
ink_assert(id != 0);
ink_assert(id <= MAX_CONFIGS);
}
info->m_refcount = 1;
if (id > MAX_CONFIGS) {
// invalid index
Error("[ConfigProcessor::set] invalid index");
return 0;
}
idx = id - 1;
do {
old_info = (ConfigInfo *) infos[idx];
} while (!ink_atomic_cas_ptr((pvvoidp) & infos[idx], old_info, info));
if (old_info) {
eventProcessor.schedule_in(NEW(new ConfigInfoReleaser(id, old_info)), HRTIME_SECONDS(60));
}
return id;
}
ConfigInfo *
ConfigProcessor::get(unsigned int id)
{
ConfigInfo *info;
int idx;
ink_assert(id != 0);
ink_assert(id <= MAX_CONFIGS);
if (id == 0 || id > MAX_CONFIGS) {
// return NULL, because we of an invalid index
return NULL;
}
idx = id - 1;
info = (ConfigInfo *) infos[idx];
if (ink_atomic_increment((int *) &info->m_refcount, 1) < 0) {
ink_assert(!"not reached");
}
return info;
}
void
ConfigProcessor::release(unsigned int id, ConfigInfo * info)
{
int val;
int idx;
ink_assert(id != 0);
ink_assert(id <= MAX_CONFIGS);
if (id == 0 || id > MAX_CONFIGS) {
// nothing to delete since we have an invalid index
return;
}
idx = id - 1;
val = ink_atomic_increment((int *) &info->m_refcount, -1);
if ((infos[idx] != info) && (val == 1)) {
delete info;
}
}