script variable should not be used for call processing? - opensips

sir,
I am trying to create stateful proxy in opensips 2.4.
I just wanted a variable to hold received message information and process it.
So i checked "core variable" in opensips manual.it says, script variable are process wise. So i should not use to hold header value in script value like $var(Ruri)=$ru?? it will be overwritten by other call??
$var(userName)=$rU;
$var(removePlus) = '+';
# Search the string starting at 0 index
if($(var(userName){s.index, $var(removePlus)})==0){
$rU=$(var(userName){s.substr,1,0});
}

$var variables are process-local, meaning that you can't share them with other SIP workers even if you wanted to! In fact, they are so optimized that their starting value will often be what the same process left-behind during a previous SIP message processing (tip: you can prove this by running opensips with children = 1 and making two calls).
On the other hand, variables such as $avp are shared between processes, but not in a "dangerous" way that you have to worry about two INVITE retransmissions processing in parallel, each overwriting the other one's $avp, etc. No! That is taken care of under the hood. The "sharing" only means that, for example, during a 200 OK reply processed by a different process than the one which relayed the initial INVITE, you will still be able to read and write to the same $avp which you set during request processing.
Finally, your code seems correct, but it can be greatly simplified:
if ($rU =~ "^+")
strip(1);

Related

Reference vs pid?

I'm not entirely sure the differences between the PID and Reference and when to use which.
If I were to spawn a new process with spawn/1 pid. I can kill it with the PID no? Why would I need a reference?
Likewise I see monitor/1 receiving a message with a ref and pid number.
Thanks!
Pid is process identifier. You can get one when you create new process with spawn, or you can get Pid of yourself with self(). It allows you to interact with given process. Especially send messages to it by Pid ! Message. And some other stuff, like killing it explicitly (should not do) or obtaining some process information with erlang:process_info.
And you can create relations between process with erlang:link(Pid) and erlang:monitor(process, Pid) (that's between Pid process, and process execution this function). In short, it gives you "notifications" when another process dies.
Reference is just almost unique value (of different type). One might say, that it gives you some reference to here and now, which you could recognize later. For example, if we are sending a message to another process, and we expect a response, we would like to make sure, that the message we will receive is associated to our request, and not just any message from someone else. The easiest way to do it is to tag the message with a unique value, and wait until a response with exactly the same tag.
Tag = make_ref(),
Pid ! {Tag, Message},
receive
{Tag, Response} ->
....
In this code, with use of pattern matching, we make sure that (we wait in receive until) Response is exactly for the Message we sent. No matter other messages from other processes. This is the most common use of reference you can encounter.
And now back to monitor. When calling Ref = monitor(process, Pid) we make this special connection with Pid process. Ref that is returned is just some unique reference, that we could use to demonitor this process. That is all.
One might ask, if we are able to create monitor with Pid, why do we need Ref for demonitoring? Couldn't we just use Pid again. In theory we could, but monitors are implemented in such a way, that multiple monitors could be established between two same processes. So when demonitoring, we have to remove only one of such connections. It is done in this way to make monitoring more transparent. If you have library of function that's creating and removing one monitor, you would not like to interfere with other libraries and functions and monitors they might be using.
According this page:
References are erlang objects with exactly two properties:
They can be created by a program (using make_ref/0), and,
They can be compared for equality.
You should use it ever you need to bind an unique identifier to some "object". Any time you could generate new one using erlang:make_ref/0. Documentation says:
make_ref() -> reference()
Returns an almost unique reference.
The returned reference will re-occur after approximately 2^82 calls;
therefore it is unique enough for practical purposes.
When you call erlang:monitor/2 function, it returns you reference to give you availability to cancel monitor (erlang:demonitor/1 function). This reference only identifies certain call of erlang:monitor/1. If you need operate with process (kill it, for example), you still have to use process pid.
Likewise I see monitor/1 receiving a message with a ref and pid number.
Yep, monitor sends messages like {'DOWN', Ref, process, Pid, Reason}. What to use (pid or ref) is only depends on your application logic, but (IMO) in most usual cases, there is no matter what to use.

How Erlang access huge shared data structures like BTree in CouchDB

In CouchDB there's huge BTree data structure and multiple processes (one for each request).
Erlang processes can't share state - so it seems that there should be dedicated process responsible for accessing BTree and communicating with other processes via messages. But it would be inefficient - because there only one process who can access data.
So how such cases are handled in Erland, and how it's handled in this specific case with CouchDB?
Good question this. If you want an authoritative answer the
best place to ask a question about couchdb internals is the couchdb mailing list they are very quick and one of the core devs can probably give you a better answer. I will try to answer this as best as I can just keep in mind that I may be wrong :)
The first clue is provided by the couchdb config file. Start couchdb in the shell mode
couchdb -i
point your browser to
http://localhost:5984/_utils/config.html
You will find that under the daemon section there is a key value pair
index_server {couch_index_server, start_link, []}
aha! so the index is served by a server. What kind of server? We will have to dive into the code:-
It is a gen_server. All the operations to the couchdb view are handled by this gen_server.
A gen_server is an erlang generic implementation of the client server model. It is concurrent by default. So your observation is correct. All the requests to the view are distinct process managed with the help of gen_server.
index_server defines three ets tables. You can verify this by typing
ets:i() in the erlang shell we started earlier and you should see:-
couchdb_indexes_by_db couchdb_indexes_by_db bag 1 320 couch_index_server
couchdb_indexes_by_pid couchdb_indexes_by_pid set 1 316 couch_index_server
couchdb_indexes_by_sig couchdb_indexes_by_sig set 1 316 couch_index_server
When the index_server gets a call to get_index it adds a list of Waiters to the ets couchdb_indexes_by_sig. Or if a process requests it it simply sends a reply with the location of the index.
When the index_server gets a call to async_open it simply iterates over the list of Waiters and sends a reply to them with the location of the index
Similarly there are calls to reset_indexes and other ops on indexes which again send a reply with the location of the index.
When the index is created for the first time couchdb calls async_open to serve the index to all the waiting processes. Afterwards every process is given access to the index.
An important point to note here is that the index server does not do anything special except for making the index available to other processes(for example to couch_mr_view_util.erl). In that respect it acts as a gateway.Index write operations are handled by couch_index.erl, couch-index_updater.erl and couch_index_compactor.erl which (unsurprisingly) are all gen_servers!
When a view is being created for the first time only one process can access it. The query_server process(couchjs by default). After the view has been built it can be read and updated in a concurrent manner. The actual querying of views is handled by couch_mr_view which is exposed to us as the familliar http api.

How to check if queue with auto-generated name (amq.gen-*) exists?

In case of non-generated names it's enough to call #'queue.declare' to get newly created queue or existing one with given name. However, when using auto-generated names (beginning with amq.gen- prefix) it's not as trivial. First of all, amq. is restricted prefix, so there is no way to call #'queue.declare'{queue=<<"amq.gen-xxx">>}.
I also tried to play with passive=true option and although I may pass restricted name, I get an exit error when queue does not exists. Following is error report:
** Handler sse_handler terminating in init/3
for the reason exit:{{shutdown,
{server_initiated_close,404,
<<"NOT_FOUND - no queue 'amq.gen-wzPK0nIBPzr-dwtZ5Jy58V' in vhost '/'">>}},
{gen_server,call,
[<0.62.0>,
{call,
{'queue.declare',0,
<<"amq.gen-wzPK0nIBPzr-dwtZ5Jy58V">>,
true,false,false,false,false,[]},
none,<0.269.0>},
infinity]}}
Is there any way to solve this problem?
EDIT: Here is a short story behind this question. Disclaimer: I'm erlang newbie, so maybe there is better way to make it working :)
I have a gen_server based application holding SSE (server-side events) connections with web browsers. Each connection is bound to rabbitmq queue. SSE connection when broken, automatically tries to reconnect after given timeout - this is something that web browser supports out of the box. To reuse previously created queue I'm trying to check if queue of given name (taken from request cookie) already exists. It's all done in init callback.
You can declare a queue with the prefix amq. if the queue already exists. You would get Declare-Ok if the queue exists or access-refused if not. (My question is why would you, though? ;)
Furthermore, you can use the passive option to check if it already exists. According to AMQP reference the server treats it as not-found error if the queue doesn't exist. In order to catch this in your Erlang client you could try something around the lines of this:
try
%% declare queue with passive=true
queue_exists
catch exit:{{shutdown, {server_initiated_close,404,_},_,_} ->
queue_does_not_exist
end

Coroutines, multiple requests in Lua

I've been poring over this subject for the past 12 hours, and I simply cannot seem to get anywhere. I do not even know if this is possible, but I'm hoping it is because it would go a long way to continuing my project.
What I am attempting to do is create coroutines so the particular program I use does not freeze up due to its inability to perform asynchronous http requests. I've figured out how to do that part, even though my understanding of coroutines is still in the "Huh? How does that work?" phase. My issue now is being able to respond to multiple requests with the correct information. For instance, the following should produce three separate responses:
foo(a)
foo(b)
foo(c)
where foo initiates a coroutine with the parameters inside. If all requested separately, then it returns the proper results. However, if requested as a block, it will only return foo(c)'s result. Now, I understand the reasoning behind this, but I cannot find a way to make it return all three results when requested as a block. To help understand this problem a bit, here's the actual code:
function background_weather()
local loc = url.escape(querystring)
weatherpage = http.request("http://api.wunderground.com/api/004678614f27ceae/conditions/q/" .. loc .. ".json")
wresults = json.decode(weatherpage)
--process some stuff here, mainly datamining
end
--send datamined information as a response
coroutine.yield()
end
And the creation of the coroutine:
function getweather ()
-- see if backgrounder running
if background_task == nil or
coroutine.status (background_task) == "dead" then
-- not running, create it
background_task = coroutine.create (background_weather)
-- make timer to keep it going
AddTimer ("tickler", 0, 0, 1, "",
timer_flag.Enabled + timer_flag.Replace,
"tickle_it")
end -- if
end -- function
The querystring variable is set with the initial request. I didn't include it here, but for the sake of testing, use 12345 as the querystring variable. The timer is something that the original author of the script initialized to check if the coroutine was still running or not, poking the background every second until done. To be honest, I'm not even sure if I've done this correctly, though it seems to run asynchronously in the program.
So, is it possible to receive multiple requests in one block and return multiple responses, correctly? Or is this far too much a task for Lua to handle?
Coroutines don't work like that. They are, in fact, blocking.
The problem coroutines resolve is "I want to have a function I can execute for a while, then go back to do other thing, and then come back and have the same state I had when I left it".
Notice that I didn't say "I want it to keep running while I do other things"; the flow of code "stops" on the coroutine, and only continues on it when you go back to it.
Using coroutines you can modify (and in some cases facilitate) how the code behaves, to make it more evident or legible. But it is still strictly single-threaded.
Remember that what Lua implements must be specified by C99. Since this standard doesn't come with a thread implementation, Lua is strictly single-threaded by default. If you want multi-threading, you need to hook it to an external lib. For example, luvit hooks Luajit with the libuv lib to achieve this.
A couple good references:
http://lua-users.org/wiki/CoroutinesTutorial
http://lua-users.org/wiki/ThreadsTutorial
http://lua-users.org/wiki/MultiTasking
http://kotisivu.dnainternet.net/askok/bin/lanes/comparison.html
Chapter 9.4 of Programming in Lua contains a fairly good example of how to deal with this exact problem, using coroutines and LuaSocket's socket.select() function to prevent busylooping.
Unfortunately I don't believe there's any way to use the socket.http functions with socket.select; the code in the PiL example is often all you'll need, but it doesn't handle some fairly common cases such as the requested URL sending a redirect.

How to get the Process Environment Block (PEB) from extern process?

I want to get the PEB from the "notepad.exe" process. Does someone know how to do it?
I tried the GetModuleHandle API, but it doesn't return a valid pointer (it return zero every time) because I have to be the caller process of that module.
For that reason, I want to know how to get it to work with EnumProcessModules or CreateToolhelp32Snapshot.
Matt Pietrek described how to do that in a 1994 Under the Hood column. It was about how to get the environment variables of another process, where the first step is to get a pointer to the PEB. To do that, he says, call NtQueryInformationProcess. The PROCESS_BASIC_INFORMATION structure it fills contains the base address of the PEB structure. (You'll need to use ReadProcessMemory to read it since the address will be in the context of the external process's address space, not yours.)
To call NtQueryInformationProcess, you'll need a handle to the process. If you started the process yourself (by calling CreateProcess), then you already have a handle. Otherwise, you'll need to find the process ID and then call OpenProcess. To get the process ID, search for the process you want with EnumProcesses or Process32First/Process32Next. (I prefer the latter because it provides more information with less work.)

Resources