[From nobody Wed Jan 21 23:40:38 2009 Return-Path: <alexander.pelov@gmail.com> Received: from eurus1.inria.fr ([unix socket]) by imap-sop.inria.fr (Cyrus v2.2.12) with LMTPA; Tue, 20 Jan 2009 20:04:56 +0100 X-Sieve: CMU Sieve 2.2 Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by eurus1.inria.fr (8.12.11.20060308/8.12.5) with ESMTP id n0KJ4qCC025913 for <mlacage@imap-sop.inria.fr>; Tue, 20 Jan 2009 20:04:56 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Au0AALSudUlIDtyYimdsb2JhbACTST4BAQEKCQwHDwWoKIEDjmgBAwEDhXA X-IronPort-AV: E=Sophos;i="4.37,295,1231110000"; d="scan'208";a="34035146" Received: from fg-out-1718.google.com ([72.14.220.152]) by mail4-smtp-sop.national.inria.fr with ESMTP; 20 Jan 2009 20:04:55 +0100 Received: by fg-out-1718.google.com with SMTP id l27so1623187fgb.27 for <mathieu.lacage@sophia.inria.fr>; Tue, 20 Jan 2009 11:04:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:cc:message-id:from:to :in-reply-to:content-type:content-transfer-encoding:mime-version :subject:date:references:x-mailer; bh=tIjZkoLEFjit8PAnk4Pi9htJTPrZVo7S8vMUSDv/1ds=; b=E+oPq/H8el9aUhZ4+WsMa737aByqT/d3+BgyohzpIt8OlPzY6D0Yref+0qk/xZ5QK6 x8QpIajDwmalP7xLtMV8y7tE3eNUdMncGCmnIS7981VMyee2n3uU8ni7TdlUp9XEX3pf IwpiJ3zWN5WK5rsuzlcHy/ZJ9qh5n1Y3aX2WM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=cc:message-id:from:to:in-reply-to:content-type :content-transfer-encoding:mime-version:subject:date:references :x-mailer; b=BlcQE3ttpJ9b6loq0059/eMiO+G5eLTzgldOWBGi9uWuvqzBNYzAX7hzkakAnDijuO s+I7VLM4+FWjtYiEwOKwD/MynQV4lURMqVQFw27YhPs8m6GZQRJdkV2fr7p70xRFUIao FhZqcysqfuRDIUQ9urhU92vhVBKhVH0XeFZ4I= Received: by 10.223.108.15 with SMTP id d15mr2193170fap.105.1232478291679; Tue, 20 Jan 2009 11:04:51 -0800 (PST) Received: from wifi-default-198-240.u-strasbg.fr (wifi-default-198-240.u-strasbg.fr [130.79.198.240]) by mx.google.com with ESMTPS id 13sm7047335fks.27.2009.01.20.11.04.48 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 20 Jan 2009 11:04:50 -0800 (PST) Cc: ns-developers@ISI.EDU Message-Id: <D15F48E2-40C5-4088-AFDA-FC2884BE0BE6@gmail.com> From: Alexander Pelov <alexander.pelov@gmail.com> To: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> In-Reply-To: <1232456342.20406.69.camel@diese.inria.fr> Content-Type: text/plain; charset=WINDOWS-1252; format=flowed; delsp=yes Mime-Version: 1.0 (Apple Message framework v930.3) Subject: Re: [Ns-developers] Cooperative ns-3 simulation with third party software via JSON-RPC Date: Tue, 20 Jan 2009 20:04:47 +0100 References: <496784D4.1080601@clarinet.u-strasbg.fr> <1231599918.25282.22.camel@mathieu.inria.fr> <496B38EC.3000108@clarinet.u-strasbg.fr> <1231764195.23296.4.camel@mathieu.inria.fr> <496DB8A8.1000005@clarinet.u-strasbg.fr> <496E11C3.1060801@clarinet.u-strasbg.fr> <1232456342.20406.69.camel@diese.inria.fr> X-Mailer: Apple Mail (2.930.3) Content-Transfer-Encoding: 8bit Hello Mathieu, everyone, I have been working with Sébastien on this project, and I was really hoping that this announcement would produce the kind of feedback you have provided in your mail. Constructive discussion is indeed what is needed for this initiative to succeed and become something useful for a maximal number of people. Thank you! I'm leaving the part regarding the code and naming conventions to Sébastien, as he has done the ns-3 programming. Le 20 janv. 09 à 13:59, Mathieu Lacage a écrit : > On Wed, 2009-01-14 at 17:24 +0100, Sébastien Vincent wrote: > .... > > If the purpose is to "get/set attributes in NS-3 objects", why not > name > UpdateAgent an AttributeAgent instead ? First, I must underline that all names are opened to discussion, especially the UpdateAgent. We were wondering about AttributeAgent, but were reluctant to use such a general name, as in its current form, this class does not provide the functionality to change all possible attributes of any given ns-3 object. > I went through the code and I > have to confess that I don't really see the relationship between the > code and the stated purpose of the class (in doxygen). This class > seems > to do a lot of very different things, a lot of which have nothing to > do > with setting and getting attributes in ns-3 objects. >>> ..... > ok. > > Overall, I have to confess that I positively dislike what you have > done > here. Code such as this: > > bool UpdateAgent::GetDirection(const Json::Value& msg, Json::Value& > response) > { > if(!msg.isMember("params") || > !msg["params"].isMember("nodeid") || ! > msg["params"]["nodeid"].isInt()) > { > /* error */ > Json::Value error; > response["jsonrpc"] = "2.0"; > error["code"] = Json::Rpc::INVALID_PARAMS; > error["message"] = "Invalid parameter(s)"; > response["id"] = msg["id"]; > response["error"] = error; > return false; > } > > uint32_t nodeId = msg["params"]["nodeid"].asInt(); > Json::Value params; > > Ptr<Node> object = GetNode(nodeId); > if(!object) > { > /* TODO send error message */ > return false; > } > > Ptr<RpcMobilityModel> model = object->GetObject<RpcMobilityModel> > (); > > if(!model) > { > /* no mobility model installed on this node */ > response["jsonrpc"] = "2.0"; > response["id"] = msg["id"]; > params["x"] = Json::Value::null; > params["y"] = Json::Value::null; > params["z"] = Json::Value::null; > response["params"] = params; > > return false; > > > Should not exist: you are implementing your own string-based RPC all > by > hand. This makes absolutely zero sense: the very large amount of code > dedicated to the sole purpose of marshalling and demarshalling all the > input and output arguments is scary and is going to be horribly > unmaintainable. The code is of course something that can always be improved - thanks to useful propositions and specific remarks/ideas. However, this may wait for the moment, because I feel that your next questions touch the most important aspects of the subject. > > > > The choice of API you export is also obviously very focused on solving > your own set of simulation scenarios. I mostly refer to > UpdateAgent::BuildSimulation which hardcodes all the simulation > topology > and most parameters. This is probably the biggest issue with the > approach you have chosen: I fail to see how it could be of much use > outside of your specific simulation scenarios to other people. More > specifically, I see how we could extend your current approach to make > the system export more flexbility to different kinds of users but I > also > see the huge implementation cost of doing so. The question about BuildSimulation was worrying us a lot - we wanted to make it as flexible as possible, yet Keep It Simple. The general idea of the whole solution from the beginning was, that the user would have to manually create the topology in ns-3, and the external software would be able to modify the behavior of the different nodes afterwards. Thus, the BuildSimulation is provided only as a convenience. I do agree that it should be more flexible, and I think that we may have a lot of useful discussions on this subject (for example - how to manage topologies in a non-IP environment, etc). Could you please sketch how can we make it as general as possible, while KISSing it? > > > Now, I understand that you might be reluctant to use RPC-XML for > various > reasons but: > - it is totally free because we have a complete python binding so, you > can trivially call RPC-XML services _today_ and remotely construct > arbitrary ns3 topologies > - it is orders of magnitude more extendable and flexible > - it will solve your problem (among others): your mobility simulator > is written in python so, you don't even have the excuse that you don't > have an XML-RPC layer in your target language > > I believe that you mentioned performance as a potential issue with > XML-RPC (other than sheer dislike of XML): do you have any hard > numbers > which show that this would be problematic for your use-case ? I mean, > sure, json is theoretically faster than an xml-based serialization, > but, > does it actually matter for your use-case ? The following part is discussing JSON-RPC vs XML-RPC - a subject I consider not worth getting much into, so if you're in a hurry you can skip it. ================================================== START SKIP SECION +++++++++++++++++++++++++++++++++ ================================================== Now, I don't want to turn this discussion into the n-th XML-RPC vs JSON-RPC that can be found on the Internet. In my personal opinion, the only genuine advantage of XML-RPC over JSON-RPC is the number of implementations. Indeed, XML-RPC has been well tested and is a great solution - that is, if you are building a web-store and have to interoperate with other businesses or already existing platform solutions. However, XML-RPC is much more verbose, not only because of the verboseness of XML, but also because it only runs over HTTP. JSON- RPC on the other hand may use much simpler protocols, such as Netstrings (which is basically STRING_LENGTH:string,). About the choice of JSON over XML (http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic3 ): """ Both JSON and XML can be used to represent native, in-memory objects in a text-based, human-readable, data exchange format. Furthermore, the two data exchange formats are isomorphic—given text in one format, an equivalent one is conceivable in the other. For example, when calling one of Yahoo!'s publicly accessible web services, you can indicate via a querystring parameter whether the response should be formatted as XML or JSON. Therefore, when deciding upon a data exchange format, it's not a simple matter of choosing one over the other as a silver bullet, but rather what format has the characteristics that make it the best choice for a particular application. For example, XML has its roots in marking-up document text and tends to shine very well in that space (as is evident with XHTML). JSON, on the other hand, has its roots in programming language types and structures and therefore provides a more natural and readily available mapping to exchange structured data. """ If you want a particular example, let's take the case of a single method invocation with both JSON-RPC and XML-RPC: (I've optimized the JSON-RPC request/response as to reflect the lack of named parameters in XML-RPC) ----------------------- 76:{"jsonrpc":"2.0", "id":5, "method":"setposition", "params": [2,1.0,2.0,3.0]}, 44:{"id":5,"jsonrpc":"2.0","result":"success"}, ----------------------- That is - a total of 4 + 76 + 4 + 44 = 128 bytes ----------------------- POST /RPC2 HTTP/1.0 User-Agent: Frontier/5.1.2 (WinNT) Host: betty.userland.com Content-Type: text/xml Content-length: 346 <?xml version="1.0"?> <methodCall> <methodName>setposition</methodName> <params> <param> <value><i4>2</i4></value> </param> </params> <param> <double>1.0</double> </params> <param> <double>2.0</double> </params> <param> <double>3.0</double> </params> </methodCall> HTTP/1.1 200 OK Connection: close Content-Length: 169 Content-Type: text/xml Date: Fri, 17 Jul 1998 19:55:08 GMT Server: UserLand Frontier/5.1.2-WinNT <?xml version="1.0"?> <methodResponse> <params> <param> <value><string>success</string></value> </param> </params> </methodResponse> ----------------------- Which is a total of (I've counted the characters after removing all unnecessary whitespaces) 373+279 = 652 bytes I'm not an XML-RPC specialist, and I'm sure these things can be optimized, but hey - 5x more data to transfer in a typical method call. A very different question is, if this is the bottleneck of the approach. ================================================== END SKIP SECION +++++++++++++++++++++++++++++++++++ ================================================== Why I see the question on XML-RPC vs JSON-RPC as a non-issue - once the functionality is there, it should be (mostly) trivial to change the specific information encoding. XML, JSON, binary - as you wish. Additionally, I would like to point out, that this is just the beginning of a more complete solution, and adding Python bindings is the next logical step. This way both the C++ and the Python parts of the ns-3 "world" would be able to use the same functionality with ease. > > > To summarize, I see very little added benefit in merging this code > and a > lot of downsides. I would much rather point users who wish to > inter-operate with ns-3 to XML-RPC than this very partial, complex, > and > hard to maintain solution. > If I have understood correctly (correct me if I'm wrong), the major issue which is bothering you is - why bother writing marshalling/ unmarshalling code at all? Why not "just" allow the third party to execute whatever function she likes and forget about all that crap? I should say that Python is a great language, so it would probably be feasible to write a single XML-RPC entry point that would go through all existing object in the Python namespace and execute that method on the fly. That's great - it would save us the need to write code for each RPC function we expose. However, I think that this is going to create a very convoluted way of calling the functions. But this will not solve the problems, as Python bindings are only what they are - bindings - the return value of a method invocation is a proxy to the underlying C++ object. You cannot automatically marshal/ unmarshal that (unless you force ALL methods to provide the necessary methods). This is going to create a true nightmare for all third party software authors - they are going to be forced to understand the way these objects serialize themselves OR stream the object back to ns-3 to call a particular function on it, and then get it back. And that is not guaranteed to work, unless you force all member functions that perform in-place changes to also return "this" (uploading an object to ns-3, just to receive an "OK" is not going to help the poor caml user on the other side of the fence). Lets look at the way mobility is implemented in the moment. There are two methods acting on node movement direction - GetDirection and SetDirection, which return/receive a Vector. The Vector does support an internal serialization format, but it does not have anything to do with XML. So, in the best case, the caller will obtain something she has to parse (after the whole XML-RPC over HTTP processing), change, then generate the fixed string format and send it over the net. And remember - all this is that easy just because there is a killer-all-in- one-state-of-the-art-reflection-using-python-based-single-entry-XML function. So, we are going to have to write several lines of code for each function exposed via RPC (which is what everyone does) - exactly the approach we have taken. I do agree that the code would be more succinct in Python than in C++, but I think that with the right helper functions the difference will be minimal, and the user will be able to harvest the full potential of the C++ roots of ns-3. I think that a better approach is to define interfaces - specify a set of universally accepted methods, along with their parameters and return values in a language-independent way. Doing so would have several benefits: 1) Implementing it in several network simulators would allow third party software to communicate interchangeably with all of them. It would become trivial to write an application in Java and see how it would behave in ns-3 and omnet++ for example. 2) Be implementation independent. Changing an implementation detail would be hidden from the external user. 3) Be easier to use. I'm sure this list could go on, but I think that these reasons are sufficient. > I am really very sorry to be so negative after the review :/ > > Mathieu > In conclusion I have to say, that maybe we didn't prepare the announcement to the full extent, and we have taken note from your remarks. We are going to prepare an additional document explaining the proposed RPC functions, so that we could have a fruitful discussion on concrete use-cases. Thank you again for your remarks and suggestions! Regards, Alexander PELOV]