Added support to create arbitrary named lists of shared vars (separate from Engine's global). Added extra functions to shared vars list. Export in javascript.
git-svn-id: http://yate.null.ro/svn/yate/trunk@6521 acf43c95-373e-0410-b603-e72c3f656dc1divo
parent
ca208774e0
commit
de95fc5171
|
@ -109,6 +109,21 @@ public:
|
|||
static void doCompletion(Message &msg, const String& partLine, const String& partWord);
|
||||
};
|
||||
|
||||
class EngineSharedPrivate
|
||||
{
|
||||
public:
|
||||
inline EngineSharedPrivate()
|
||||
: vars(new SharedVars),
|
||||
varsListMutex(false,"SharedVarsList")
|
||||
{}
|
||||
inline ~EngineSharedPrivate()
|
||||
{ TelEngine::destruct(vars); }
|
||||
|
||||
SharedVars* vars;
|
||||
ObjList varsList;
|
||||
Mutex varsListMutex;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
using namespace TelEngine;
|
||||
|
@ -295,7 +310,7 @@ static int s_maxevents = 25;
|
|||
static Mutex s_eventsMutex(false,"EventsList");
|
||||
static ObjList s_events;
|
||||
static String s_startMsg;
|
||||
static SharedVars s_vars;
|
||||
static EngineSharedPrivate s_vars;
|
||||
static Mutex s_hooksMutex(true,"HooksList");
|
||||
static ObjList s_hooks;
|
||||
static Semaphore* s_semWorkers = 0;
|
||||
|
@ -1449,29 +1464,37 @@ void SharedVars::clear(const String& name)
|
|||
unlock();
|
||||
}
|
||||
|
||||
void SharedVars::clearAll()
|
||||
{
|
||||
if (this == &Engine::sharedVars())
|
||||
return;
|
||||
Lock mylock(this);
|
||||
m_vars.clearParams();
|
||||
}
|
||||
|
||||
bool SharedVars::exists(const String& name)
|
||||
{
|
||||
Lock mylock(this);
|
||||
return m_vars.getParam(name) != 0;
|
||||
}
|
||||
|
||||
unsigned int SharedVars::inc(const String& name, unsigned int wrap)
|
||||
uint64_t SharedVars::inc(const String& name, uint64_t wrap)
|
||||
{
|
||||
Lock mylock(this);
|
||||
unsigned int val = m_vars.getIntValue(name);
|
||||
uint64_t val = m_vars.getUInt64Value(name);
|
||||
if (wrap)
|
||||
val = val % (wrap + 1);
|
||||
unsigned int nval = val + 1;
|
||||
uint64_t nval = val + 1;
|
||||
if (wrap)
|
||||
nval = nval % (wrap + 1);
|
||||
m_vars.setParam(name,String(nval));
|
||||
return val;
|
||||
}
|
||||
|
||||
unsigned int SharedVars::dec(const String& name, unsigned int wrap)
|
||||
uint64_t SharedVars::dec(const String& name, uint64_t wrap)
|
||||
{
|
||||
Lock mylock(this);
|
||||
unsigned int val = m_vars.getIntValue(name);
|
||||
uint64_t val = m_vars.getUInt64Value(name);
|
||||
if (wrap)
|
||||
val = val ? ((val - 1) % (wrap + 1)) : wrap;
|
||||
else
|
||||
|
@ -1480,6 +1503,46 @@ unsigned int SharedVars::dec(const String& name, unsigned int wrap)
|
|||
return val;
|
||||
}
|
||||
|
||||
uint64_t SharedVars::add(const String& name, uint64_t value, uint64_t wrap)
|
||||
{
|
||||
Lock mylock(this);
|
||||
uint64_t val = m_vars.getUInt64Value(name);
|
||||
if (wrap)
|
||||
val = val % (wrap + 1);
|
||||
uint64_t nval = val + value;
|
||||
if (wrap)
|
||||
nval = nval % (wrap + 1);
|
||||
m_vars.setParam(name,String(nval));
|
||||
return val;
|
||||
}
|
||||
|
||||
uint64_t SharedVars::sub(const String& name, uint64_t value, uint64_t wrap)
|
||||
{
|
||||
Lock mylock(this);
|
||||
uint64_t val = m_vars.getUInt64Value(name);
|
||||
if (wrap)
|
||||
val = (val >= value) ? ((val - value) % (wrap + 1)) : wrap;
|
||||
else
|
||||
val = (val >= value) ? (val - value) : 0;
|
||||
m_vars.setParam(name,String(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
bool SharedVars::getList(RefPointer<SharedVars>& dest, const String& name)
|
||||
{
|
||||
if (!name)
|
||||
return false;
|
||||
Lock lck(s_vars.varsListMutex);
|
||||
ObjList* o = s_vars.varsList.find(name);
|
||||
if (o)
|
||||
dest = static_cast<SharedVars*>(o->get());
|
||||
else {
|
||||
dest = new SharedVars(name);
|
||||
s_vars.varsList.append(dest);
|
||||
}
|
||||
return 0 != dest;
|
||||
}
|
||||
|
||||
|
||||
Engine::Engine()
|
||||
: m_dispatchedLast(0), m_messageRate(0), m_maxMsgRate(0),
|
||||
|
@ -1697,7 +1760,7 @@ int Engine::engineInit()
|
|||
for (unsigned int i = 0; i < n; i++) {
|
||||
NamedString* v = vars->getParam(i);
|
||||
if (v)
|
||||
s_vars.set(v->name(),*v);
|
||||
s_vars.vars->set(v->name(),*v);
|
||||
}
|
||||
}
|
||||
DDebug(DebugAll,"Engine::run()");
|
||||
|
@ -2396,7 +2459,7 @@ void Engine::clearEvents(const String& type)
|
|||
|
||||
SharedVars& Engine::sharedVars()
|
||||
{
|
||||
return s_vars;
|
||||
return *(s_vars.vars);
|
||||
}
|
||||
|
||||
// Append command line arguments form current config.
|
||||
|
|
|
@ -190,17 +190,50 @@ class JsShared : public JsObject
|
|||
YCLASS(JsShared,JsObject)
|
||||
public:
|
||||
inline JsShared(ScriptMutex* mtx)
|
||||
: JsObject("Shared",mtx,true)
|
||||
: JsObject("SharedVars",mtx,true)
|
||||
{
|
||||
params().addParam(new ExpFunction("inc"));
|
||||
params().addParam(new ExpFunction("dec"));
|
||||
params().addParam(new ExpFunction("get"));
|
||||
params().addParam(new ExpFunction("set"));
|
||||
params().addParam(new ExpFunction("add"));
|
||||
params().addParam(new ExpFunction("sub"));
|
||||
params().addParam(new ExpFunction("clear"));
|
||||
params().addParam(new ExpFunction("clearAll"));
|
||||
params().addParam(new ExpFunction("exists"));
|
||||
params().addParam(new ExpFunction("getVars"));
|
||||
setVars(String::empty());
|
||||
}
|
||||
inline JsShared(ScriptMutex* mtx, unsigned int line, const String& varsName = String::empty())
|
||||
: JsObject(mtx,"[object SharedVars]",line)
|
||||
{ setVars(varsName); }
|
||||
virtual JsObject* runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
static void initialize(ScriptContext* context);
|
||||
static inline uint64_t modulo(ExpOperation* mod) {
|
||||
if (!(mod && mod->isInteger()))
|
||||
return 0;
|
||||
int64_t m = mod->number();
|
||||
return m > 1 ? --m : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void setVars(const String& name) {
|
||||
if (!name)
|
||||
m_vars = &Engine::sharedVars();
|
||||
else
|
||||
SharedVars::getList(m_vars,name);
|
||||
m_varsName = name;
|
||||
}
|
||||
inline JsShared(ScriptMutex* mtx, const char* name, unsigned int line, const String& varsName = String::empty())
|
||||
: JsObject(mtx,name,line)
|
||||
{ setVars(varsName); }
|
||||
virtual JsObject* clone(const char* name, const ExpOperation& oper) const
|
||||
{ return new JsShared(mutex(),name,oper.lineNumber(),m_varsName); }
|
||||
bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
|
||||
|
||||
private:
|
||||
RefPointer<SharedVars> m_vars;
|
||||
String m_varsName;
|
||||
};
|
||||
|
||||
class JsTimeEvent : public RefObject
|
||||
|
@ -459,9 +492,10 @@ public:
|
|||
params().addParam(new ExpFunction("htoa"));
|
||||
params().addParam(new ExpFunction("btoh"));
|
||||
params().addParam(new ExpFunction("htob"));
|
||||
addConstructor(params(), "Semaphore", new JsSemaphore(mtx));
|
||||
addConstructor(params(),"Semaphore",new JsSemaphore(mtx));
|
||||
addConstructor(params(),"HashList",new JsHashList(mtx));
|
||||
addConstructor(params(),"URI",new JsURI(mtx));
|
||||
addConstructor(params(),"SharedVars",new JsShared(mtx));
|
||||
}
|
||||
static void initialize(ScriptContext* context, const char* name = 0);
|
||||
inline void resetWorker()
|
||||
|
@ -1076,6 +1110,7 @@ static void contextInit(ScriptRun* runner, const char* name = 0, JsAssist* assis
|
|||
JsHasher::initialize(ctx);
|
||||
JsJSON::initialize(ctx);
|
||||
JsDNS::initialize(ctx);
|
||||
JsShared::initialize(ctx);
|
||||
if (s_autoExt)
|
||||
contextLoad(ctx,name);
|
||||
}
|
||||
|
@ -2142,43 +2177,25 @@ bool JsShared::runNative(ObjList& stack, const ExpOperation& oper, GenObject* co
|
|||
XDebug(&__plugin,DebugAll,"JsShared::runNative '%s'(" FMT64 ")",oper.name().c_str(),oper.number());
|
||||
if (oper.name() == YSTRING("inc")) {
|
||||
ObjList args;
|
||||
switch (extractArgs(stack,oper,context,args)) {
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
ExpOperation* param = static_cast<ExpOperation*>(args[0]);
|
||||
ExpOperation* modulo = static_cast<ExpOperation*>(args[1]);
|
||||
int mod = 0;
|
||||
if (modulo && modulo->isInteger())
|
||||
mod = (int)modulo->number();
|
||||
if (mod > 1)
|
||||
mod--;
|
||||
ExpOperation* param = 0;
|
||||
ExpOperation* mod = 0;
|
||||
if (!extractStackArgs(1,this,stack,oper,context,args,¶m,&mod))
|
||||
return false;
|
||||
if (m_vars)
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_vars->inc(*param,modulo(mod))));
|
||||
else
|
||||
mod = 0;
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)Engine::sharedVars().inc(*param,mod)));
|
||||
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
||||
}
|
||||
else if (oper.name() == YSTRING("dec")) {
|
||||
ObjList args;
|
||||
switch (extractArgs(stack,oper,context,args)) {
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
ExpOperation* param = static_cast<ExpOperation*>(args[0]);
|
||||
ExpOperation* modulo = static_cast<ExpOperation*>(args[1]);
|
||||
int mod = 0;
|
||||
if (modulo && modulo->isInteger())
|
||||
mod = (int)modulo->number();
|
||||
if (mod > 1)
|
||||
mod--;
|
||||
ExpOperation* param = 0;
|
||||
ExpOperation* mod = 0;
|
||||
if (!extractStackArgs(1,this,stack,oper,context,args,¶m,&mod))
|
||||
return false;
|
||||
if (m_vars)
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)m_vars->dec(*param,modulo(mod))));
|
||||
else
|
||||
mod = 0;
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation((int64_t)Engine::sharedVars().dec(*param,mod)));
|
||||
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
||||
}
|
||||
else if (oper.name() == YSTRING("get")) {
|
||||
if (oper.number() != 1)
|
||||
|
@ -2187,7 +2204,8 @@ bool JsShared::runNative(ObjList& stack, const ExpOperation& oper, GenObject* co
|
|||
if (!param)
|
||||
return false;
|
||||
String buf;
|
||||
Engine::sharedVars().get(*param,buf);
|
||||
if (m_vars)
|
||||
m_vars->get(*param,buf);
|
||||
TelEngine::destruct(param);
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(buf));
|
||||
}
|
||||
|
@ -2202,33 +2220,123 @@ bool JsShared::runNative(ObjList& stack, const ExpOperation& oper, GenObject* co
|
|||
TelEngine::destruct(val);
|
||||
return false;
|
||||
}
|
||||
Engine::sharedVars().set(*param,*val);
|
||||
if (m_vars)
|
||||
m_vars->set(*param,*val);
|
||||
TelEngine::destruct(param);
|
||||
TelEngine::destruct(val);
|
||||
}
|
||||
else if (oper.name() == YSTRING("add") || oper.name() == YSTRING("sub")) {
|
||||
ObjList args;
|
||||
ExpOperation* param = 0;
|
||||
ExpOperation* val = 0;
|
||||
ExpOperation* mod = 0;
|
||||
if (!extractStackArgs(2,this,stack,oper,context,args,¶m,&val,&mod))
|
||||
return false;
|
||||
if (m_vars) {
|
||||
int64_t value = val->isInteger() ? val->number() : 0;
|
||||
if (oper.name() == YSTRING("add"))
|
||||
value = (int64_t)m_vars->add(*param,value > 0 ? value : 0,modulo(mod));
|
||||
else
|
||||
value = (int64_t)m_vars->sub(*param,value > 0 ? value : 0,modulo(mod));
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(value));
|
||||
}
|
||||
else
|
||||
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
||||
}
|
||||
else if (oper.name() == YSTRING("clear")) {
|
||||
if (oper.number() != 1)
|
||||
return false;
|
||||
ExpOperation* param = popValue(stack,context);
|
||||
if (!param)
|
||||
return false;
|
||||
Engine::sharedVars().clear(*param);
|
||||
if (m_vars)
|
||||
m_vars->clear(*param);
|
||||
TelEngine::destruct(param);
|
||||
}
|
||||
else if (oper.name() == YSTRING("clearAll")) {
|
||||
if (m_vars)
|
||||
m_vars->clearAll();
|
||||
}
|
||||
else if (oper.name() == YSTRING("exists")) {
|
||||
if (oper.number() != 1)
|
||||
return false;
|
||||
ExpOperation* param = popValue(stack,context);
|
||||
if (!param)
|
||||
return false;
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(Engine::sharedVars().exists(*param)));
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(m_vars && m_vars->exists(*param)));
|
||||
TelEngine::destruct(param);
|
||||
}
|
||||
else if (oper.name() == YSTRING("getVars")) {
|
||||
// getVars([params])
|
||||
// params:
|
||||
// js_props: Boolean. Force Javascript ExpOperation in returned result. Default: true
|
||||
// autonum: Boolean. Force ExpOperation auto number in returned result. Default: false.
|
||||
// Ignored if not returning ExpOperation
|
||||
// prefix: String. Optional prefix for variables
|
||||
// skip_prefix: Boolean. Skip prefix when returned. Default: true. Ignored if prefix is empty
|
||||
ObjList args;
|
||||
ExpOperation* pOp = 0;
|
||||
if (!extractStackArgs(0,this,stack,oper,context,args,&pOp))
|
||||
return false;
|
||||
if (m_vars) {
|
||||
bool expOper = true;
|
||||
bool autoNum = false;
|
||||
String prefix;
|
||||
bool skipPrefix = true;
|
||||
JsObject* params = YOBJECT(JsObject,pOp);
|
||||
if (params) {
|
||||
params->getBoolField(YSTRING("js_props"),expOper);
|
||||
if (expOper)
|
||||
params->getBoolField(YSTRING("autonum"),autoNum);
|
||||
params->getStringField(YSTRING("prefix"),prefix);
|
||||
if (prefix)
|
||||
params->getBoolField(YSTRING("skip_prefix"),skipPrefix);
|
||||
}
|
||||
JsObject* jso = new JsObject(context,oper.lineNumber(),mutex());
|
||||
if (expOper) {
|
||||
NamedList tmp("");
|
||||
m_vars->copy(tmp,prefix,skipPrefix);
|
||||
for (ObjList* o = tmp.paramList()->skipNull(); o; o = o->skipNext()) {
|
||||
NamedString* ns = static_cast<NamedString*>(o->get());
|
||||
jso->params().addParam(new ExpOperation(*ns,ns->name(),autoNum));
|
||||
}
|
||||
}
|
||||
else
|
||||
m_vars->copy(jso->params(),prefix,skipPrefix);
|
||||
ExpEvaluator::pushOne(stack,new ExpWrapper(jso,"vars"));
|
||||
}
|
||||
else
|
||||
ExpEvaluator::pushOne(stack,JsParser::nullClone());
|
||||
}
|
||||
else
|
||||
return JsObject::runNative(stack,oper,context);
|
||||
return true;
|
||||
}
|
||||
|
||||
JsObject* JsShared::runConstructor(ObjList& stack, const ExpOperation& oper, GenObject* context)
|
||||
{
|
||||
ObjList args;
|
||||
ExpOperation* sharedOp = 0;
|
||||
if (!extractStackArgs(1,this,stack,oper,context,args,&sharedOp))
|
||||
return 0;
|
||||
JsShared* obj = new JsShared(mutex(),oper.lineNumber(),*sharedOp);
|
||||
if (ref())
|
||||
obj->params().addParam(new ExpWrapper(this,protoName()));
|
||||
else
|
||||
TelEngine::destruct(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
void JsShared::initialize(ScriptContext* context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
ScriptMutex* mtx = context->mutex();
|
||||
Lock mylock(mtx);
|
||||
NamedList& params = context->params();
|
||||
if (!params.getParam(YSTRING("SharedVars")))
|
||||
addObject(params,"SharedVars",new JsShared(mtx));
|
||||
}
|
||||
|
||||
void* JsMessage::getObject(const String& name) const
|
||||
{
|
||||
|
|
65
yatengine.h
65
yatengine.h
|
@ -236,14 +236,15 @@ private:
|
|||
* Class that implements atomic / locked access and operations to its shared variables
|
||||
* @short Atomic access and operations to shared variables
|
||||
*/
|
||||
class YATE_API SharedVars : public Mutex
|
||||
class YATE_API SharedVars : public Mutex, public RefObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name Optional name
|
||||
*/
|
||||
inline SharedVars()
|
||||
: Mutex(false,"SharedVars"), m_vars("")
|
||||
inline SharedVars(const char* name = 0)
|
||||
: Mutex(false,"SharedVars"), m_vars(name)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -274,6 +275,11 @@ public:
|
|||
*/
|
||||
void clear(const String& name);
|
||||
|
||||
/**
|
||||
* Clear all variables. Does nothing for Engine (global shared list)
|
||||
*/
|
||||
void clearAll();
|
||||
|
||||
/**
|
||||
* Check if a variable exists
|
||||
* @param name Name of the variable
|
||||
|
@ -287,7 +293,7 @@ public:
|
|||
* @param wrap Value to wrap around at, zero disables
|
||||
* @return Value of the variable before increment, zero if it was not defined or not numeric
|
||||
*/
|
||||
unsigned int inc(const String& name, unsigned int wrap = 0);
|
||||
uint64_t inc(const String& name, uint64_t wrap = 0);
|
||||
|
||||
/**
|
||||
* Atomically decrement a variable as unsigned integer
|
||||
|
@ -295,7 +301,56 @@ public:
|
|||
* @param wrap Value to wrap around at, zero disables (stucks at zero)
|
||||
* @return Value of the variable after decrement, zero if it was not defined or not numeric
|
||||
*/
|
||||
unsigned int dec(const String& name, unsigned int wrap = 0);
|
||||
uint64_t dec(const String& name, uint64_t wrap = 0);
|
||||
|
||||
/**
|
||||
* Atomically add a value to a variable as unsigned integer
|
||||
* @param name Name of the variable
|
||||
* @param val Value to add
|
||||
* @param wrap Value to wrap around at, zero disables
|
||||
* @return Value of the variable before addition, zero if it was not defined or not numeric
|
||||
*/
|
||||
uint64_t add(const String& name, uint64_t val, uint64_t wrap = 0);
|
||||
|
||||
/**
|
||||
* Atomically substract a value from a variable as unsigned integer
|
||||
* @param name Name of the variable
|
||||
* @param val Value to substract
|
||||
* @param wrap Value to wrap around at, zero disables
|
||||
* @return Value of the variable after substraction, zero if it was not defined or not numeric
|
||||
*/
|
||||
uint64_t sub(const String& name, uint64_t val, uint64_t wrap = 0);
|
||||
|
||||
/**
|
||||
* Atomically copy parameters to destination
|
||||
* @param dest Destination list
|
||||
* @param prefix Optional prefix to match in parameter names
|
||||
* @param skipPrefix Skip over the prefix when building new parameter name
|
||||
* @param replace Set to true to replace list parameter instead of adding a new one
|
||||
*/
|
||||
inline void copy(NamedList& dest, const String& prefix = String::empty(),
|
||||
bool skipPrefix = true, bool replace = false) {
|
||||
Lock lck(this);
|
||||
if (prefix)
|
||||
dest.copySubParams(m_vars,prefix,skipPrefix,replace);
|
||||
else
|
||||
dest.copyParams(m_vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve list name
|
||||
* @return List name
|
||||
*/
|
||||
virtual const String& toString() const
|
||||
{ return m_vars; }
|
||||
|
||||
/**
|
||||
* Retrieve a named list of SharedVars. Create it if not found
|
||||
* @param dest Destination to be filled with requested list
|
||||
* @param name Name of the list
|
||||
* @return True id destination is iset. The function will fail if name is empty
|
||||
*/
|
||||
static bool getList(RefPointer<SharedVars>& dest, const String& name);
|
||||
|
||||
private:
|
||||
NamedList m_vars;
|
||||
|
|
Loading…
Reference in New Issue