<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Juan Jose,<br>
<br>
Ah hah! Okay, now I understand where you're going. It makes a ton of
sense to re-use your Java code. It's best for the users if they're
service doesn't change. It's best for the developers to have
continuity in the codebase.<br>
<br>
The first thing you may want to look into is a module that reads the
dial plan from a MySQL database. You can do the updates in the
database and they're read out when each extension is accessed. It
gives more control for dynamically changing dial plans without the
performance hit of reloading a 50,000 line dial plan. On the other
hand, you lose the existing Java code base. Plus, the Dial Plan is a
really sucky language and coding in a saner language is good.<br>
<br>
I've been using the code changes I sent in a prior posting to integrate
AGI and Manager API. It allows you to control a channel and Asterisk
through a single socket connection. I've tested throughput and been
able to send 300,000 commands per second with proper ACK responses (it
was the 'ping' command). I have not seen any problems running many
channels (hundreds) through this hybrid connection. The key is that I
have a high priority Java thread reading from the socket and queuing
the Manager info to be handled by another thread. Asterisk will drop
information if the reader doesn't keep the socket clear. Reading the
information in is the most important thing you can do. That way you
can run your Java code in an application server and still control
Asterisk.<br>
<br>
If you need some example Java code, please let me know.<br>
<br>
Thanks,<br>
<br>
David<br>
<br>
<br>
Juan Jose Comellas wrote:<br>
<blockquote cite="mid200409161223.32706.juanjo@comellas.com.ar"
type="cite">
<pre wrap="">Thanks for all your recommendations. The immediate objective of the project
I'm working on is to use Asterisk to replace another product in a telephony
server. The previous version was based on Envox and ran on Windows with a DLL
that acted as a bridge between Envox and the Java code that implemented most
of the functionality for a lot of services (complex conferencing and
voicemail and a lot of additional services not found in Asterisk). We want to
reuse all the code we can from the previous version, so I'm trying to provide
a similar interface to the other system in an Asterisk module.
Initially we planned to use normal dialplans, but we have a highly dynamic
system, which has thousands of extensions and is updated constantly, and
reloading Asterisk's configuration frequently has some problems. In our
tests, reloading the dialplan took about 30 seconds and during that time new
connections failed. That is completely unacceptable for the service we
provide, so we decided to manage our own dialplan and reuse the functionality
of the previous version by writing a module that could act as a bridge
between Asterisk and the previous software (in Java). That seemed to be the
simplest solution because it allowed us to reuse what we already had
developed for the previous version.
When we first studied Asterisk we thought about using the Manager Interface,
but it did not seem stable enough to be able to make thousands of calls all
the time. Has this changed recently?
On Wednesday 15 September 2004 20:38, David Pollak wrote:
</pre>
<blockquote type="cite">
<pre wrap="">Juan Jose,
You should only have 1 JVM instance. You can put a pointer to your JVM
instance in a static (I forgot the C name for statics... sorry) variable
that can be accessed by any caller into your app.
You do a lookup for the "cookie" (the void * that you proposed in your
suggested change) based on the unique ID of the channel.
My strong recommendation for destroying the cookie when you destroy the
channel comes from making sure that there's no memory leak in the JVM
(or more specifically, no reference leak.) The cookie that you're
storing probably corresponds to a Java Object. That Object is marked as
referred to by an external JNI program (thus it will not be garbage
collected from the JVM.) Once the channel in Asterisk is destroyed,
you'll have to let the JVM know that the corresponding Java Object (and
its referenced object) can be garbage collected.
With all that being said, I'd recommend against running a JVM in the
Asterisk process. First, the JVM is not as stable as Asterisk. (As a
side-note, I'm a huge fan of Java. I was the first technologist to use
Java in a production system -- WebLogic ran NetGuide Live [the 11th most
trafficked site on the Internet] back in 1996. I wrote the worlds
fastest spreadsheet in Java. I think Java and the JVM are the best
combination for doing non-realtime systems. On the other hand, I'm
realistic about Java's weaknesses as well.) If the JVM goes down (and
JVMs go down in production once or twice a month), the Asterisk process
goes down. That's bad. Second, I don't know if the Sun JVM uses the
same thread primitives as Asterisk. If it doesn't, there'll be lots of
weird memory corruption, etc. Third, when the JVM does garbage
collection, it halts the current thread (and any other thread that's
doing a memory allocation -- which is all the time in a JVM.) Asterisk
mixes the media and logic on the same thread. You *have* to respond to
the media demands every 20ms. If the JVM is doing garbage collection
that takes more than 20ms, you're going to have bad sound quality.
With all that being said, why not use an external Java process that
communicates over AGI and/or the Manager API to control the channel?
What kind of application are you writing?
Thanks,
David
Juan Jose Comellas wrote:
</pre>
<blockquote type="cite">
<pre wrap="">But if I do what you propose, each Java module would be created and
destroyed when each channel is created and destroyed. I want to have Java
modules that last as long as C modules do and that are not tied to
specific channels.
The problem I'm facing is that I need to map the C callback for each
application to multiple Java classes in order to have only one instance of
the JVM for all the Java modules. The configuration file would look like
this:
--- java.conf
[commands]
JavaTransfer = org.asterisk.JavaTransferModule
JavaConference = org.asterisk.JavaConferenceModule
JavaDirectory = org.asterisk.JavaDirectoryModule
So, whenever the any of the commands is found in the dialplan and Asterisk
invokes the C callback for my bridge module I would like to invoke a
method of the corresponding Java class.
The reason for doing it this way is that I want to be able to dynamically
set the Java applications without having to write different C entry
points for the different Java Asterisk applications. Do you think this is
feasible with the current functionality in Asterisk?
BTW, how can I set up some kind of hook to be notified when Asterisk
creates and destroys a channel?
Thanks for your help.
On Tuesday 14 September 2004 19:34, David Pollak wrote:
</pre>
<blockquote type="cite">
<pre wrap="">Juan Jose,
You don't need to change Asterisk. In your glue layer between SWIG and
Asterisk, you can determine the unique identifier of the channel. Based
on this unique ID, you can look up the void * data structure in your own
store. Put another way, you manage your own cookies and use the
channel's unique ID as the lookup for the cookie. The only additional
bit of work is that you'll have to monitor to see when a channel is
destroyed so you can free the cookie entry for the destroyed channel.
Depending on exactly what you're using Java for, you might want to take
a look at a patch I made (enclosed) to Asterisk. This patch merges AGI
with the Manager API. It's useful to have a single socket open between
a Java app server and Asterisk and control all the Asterisk channels
through that socket.
If you've got more questions, please feel free to ping me.
Thanks,
David
Juan Jose Comellas wrote:
</pre>
<blockquote type="cite">
<pre wrap="">I am writing Java bindings for the Asterisk API using SWIG
(<a class="moz-txt-link-freetext" href="http://www.swig.org">http://www.swig.org</a>) so that I can create Asterisk modules written in
Java. The main problem I'm having is that in order to make this process
efficient I need to have more than one application per module (I load
only one instance of the JVM). To be able to build a generic solution
(where I don't have to add one entry point in C per Java application), I
need to make a slight change to the ast_register_application() function
and to the code that invokes each application's callback function.
Currently all application callbacks follow the following prototype:
int (*execute)(struct ast_channel *, void *data);
The problem is that when building Java modules this function acts as a
bridge to the Java invocation and I need extra data to be able to map
the call into a Java class/method. To solve this problem I need to make
the following changes to Asterisk's public interface:
1) Add one argument to the application callback to be able to pass the
"cookie" that will let me map to the Java class/method:
int (*execute)(struct ast_channel *, void *data, void *cookie);
2) Change the ast_app struct to be able to store the "cookie". With my
changes it looks like this:
struct ast_app {
char name[AST_MAX_APP]; /* Name of the application */
int (*execute)(struct ast_channel *chan, void *data, void *cookie);
char *synopsis; /* Synopsis text for 'show applications' */
char *description; /* Description (help text) for 'show application
<name>' */
void *cookie; /* Data used to map the call when using Java modules */
struct ast_app *next; /* Next app in list */
};
3) Change the ast_register_application() function to pass the cookie to
the ast_app struct:
int ast_register_application(char *app, int (*execute)(struct
ast_channel *, void *data, void *cookie), char *synopsis, char
*description, void *cookie);
Do these modifications have any chance of being accepted into Asterisk?
</pre>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<pre wrap=""><!---->
</pre>
</blockquote>
</body>
</html>