Skip to content

Commit

Permalink
[thrift] spruce up Erlang binding for tonight's release
Browse files Browse the repository at this point in the history
Summary:
 * got rid of most of the otp_base jonx ... save that for a future release unfortunately
 * cleaned up the tutorial server, added -erl to tutorial.thrift's shebang
 * made better README and TODO

Test Plan: checked out a copy, read my directions, built and ran the tutorial, and pretended that it didn't blow


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665273 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
cpiro committed Sep 18, 2007
1 parent 37d71f0 commit c9ef99f
Show file tree
Hide file tree
Showing 108 changed files with 118 additions and 9,094 deletions.
File renamed without changes.
File renamed without changes.
15 changes: 4 additions & 11 deletions lib/erl/Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
MODULES = lib # release
MODULES = \
src

all clean:
@for dir in $(MODULES); do \
all clean docs:
for dir in $(MODULES); do \
(cd $$dir; ${MAKE} $@); \
if [ "$$?" -ne "0" ]; then ERROR=$$?; echo "Error Code $$ERROR"; exit $$ERROR; fi; \
done

docs:
(cd lib; ${MAKE} $@); \
if [ "$$?" -ne "0" ]; then ERROR=$$?; echo "Error Code $$ERROR"; exit $$ERROR; fi;

install:
echo NO OP
150 changes: 82 additions & 68 deletions lib/erl/README
Original file line number Diff line number Diff line change
@@ -1,68 +1,82 @@
Much more information on these topics can be found at www.erlware.org


Building the tree
=================

To build, type make, it should all work from there.

NOTE** if your system has erlang installed in a directory other than /usr/local/lib/erlang
then you must set the environment variable ERL_RUN_TOP to that directory. For example
if you have erlang installed in /home/jdoe/erlang then you should
export ERL_RUN_TOP=/home/jdoe/erlang


Creating a new application
==========================

A new application can be created by using the appgen utility in otp/tools/utilities.
This utility will create a basic OTP app framework under the otp/lib directory and
an OTP release under the otp/release directory.

usage: appgen <appname> <prefix>

Appname is the name of the application that you would like to create. The prefix is
usually the first letter of each word in the appname. This prefix is to avoid name
clashes between applications included in a release (Erlang does not have packages).

example usage: appgen my_app ma

which results in

otp/lib/my_app & otp/release/my_app_rel

Running a release
=================

Your release should contain all that you need to run your application. If your application
depends on any applications that are supplied outside of this build tree or OTP itself then
they may be added to the <appname>_rel.rel.src file. If the extra applications are present
in this build tree then they will be found by the make process and included in the final
release.

To run a release there are two options: "local" and installed. The local version can be found
in the otp/release/<appname>_rel/local directory which is added by the make process. This
should be used during development to run your release interactively via an Erlang shell.
To run a release in local mode cd into the "local" directory and run <appname>_rel.sh.

The second way to run a release is to install it and run it as a daemon. This is used for
applications in a production setting. To do this you need to first run make & make install
from the <appname>_rel directory. This will place a complete production ready versioned
release in the /usr/local/lib/ directory under <appname>_rel. To run an installed release
cd to /usr/local/lib/<appname>_rel/release/<rel_vsn> and run <appname>_rel.sh.

In the case where you want to create a production ready release on one machine and then deploy it
on multiple identical machines you may create a production tar archive. To do this run
make & make tar from the otp/release/<appname>_rel/ directory. This will create a tar file conataining
the release name and version number in the file name. This tar can be shipped to its destination and
untarred. Within the untarred directory there is a shell script entitled install.sh. Running this
script will install the release by default in /usr/local/lib/<appname>_rel. An optional argument
can be provided that will direct the installation to a different directory.

Example install.sh /opt/lib

This will install the release in /opt/lib/<appname>_rel




Thrift Erlang Library

README Author: Chris Piro (cpiro@facebook.com)
Last Modified: 2007-Sep-17

Thrift is distributed under the Thrift open source software license.
Please see the included LICENSE file.

Using Thrift with Erlang
========================

The Thrift Erlang binding is built using GNU make. Run `make' in
lib/erl to generate the necessary .beam object files in lib/erl/ebin/.
Although the directories are laid out much like an OTP application,
these bindings (as you will soon discover) are not an OTP application
proper. When starting the Erlang emulator (interpreter) you must use
`-pa /path/to/thrift/lib/erl/ebin' to load the bindings.

Running the Tutorial
====================

It is recommended to pattern your own servers after the tutorial
included in tutorial/. Generate the gen-erl/ directory by running
tutorial.thrift, then cd to tutorial/erl/ and run server.sh. This
script includes the commmands necessary to compile the generated
Erlang source, compile the tutorial server itself, and open the Erlang
emulator. At the emulator prompt, type `server:start()' to begin
listening for connections.

Note that there is no tutorial client; you may use a supplied client
in another language.

Implementation Notes
====================

tExecptions and t*Factorys are straight "new" -- e.g. TF =
tTransportFactory:new() everything else is start_new
(i.e. gen_server:start_link) -- this spawns a process and returns a
pid

tErlProcessor is a shim around the generated code (which is not
actually a gen_server). Of course tErlProcessor isn't a gen_server
either ... thrift_oop_server is a shim to make our "Thrift objects"
gen_servers. Maybe we should remove some layers?

get/set never means process dictionary

Use tErlServer and tErlAcceptor. tSimpleServer and tServerSocket as
are present in the other bindings are incompatible by design ... the
call trace is spastic across the process tree. tErlServer and
tErlAcceptor follow the same model as iserve:

* the top level code spawns a tErlServer, which listens on a socket
* a tErlAcceptor is spawned and calls accept() on the listening
socket
* when accept() finishes, the tErlAcceptor
* tells the tErlServer to spawn a new acceptor
* handles the requests by spawning a processor, a transport, and a
protocol
* (the tricky part) when the socket closes, the protocol exits, so:
* the transport exits because it's the one caller of the protocol
* likewise, the processor exits because it's the caller of the
transport
* the tErlAcceptor traps the protocol's exit and exits with an
acceptor_done
* the tErlServer sees that the acceptor exited and does nothing
since there is already another acceptor accept()ing on the listen
socket

For info about iserve: http://www.trapexit.org/A_fast_web_server_demonstrating_some_undocumented_Erlang_features

Final Thoughts
==============

This binding is a work in progress. It's certainly less thoroughly
tested than the other, older bindings. Despite using parts from
otp_base it is not packaged well, nor is it an OTP application (not to
mention its many smaller transgressions). This implementation
intentionally patterns after the other bindings (which is why there's
oop.erl and thrift_oop_server), but regretfully it departs from
idiomatic Erlang. Please see the included TODO and contribute your
improvements back to the project.
9 changes: 4 additions & 5 deletions lib/erl/lib/thrift/TODO → lib/erl/TODO
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ make thrift a proper OTP application

tutorial client

find TODO(cpiro)s
make all methods effectful, remove the special casing (optionally, implement monads for Erlang)

change objects from {record_tag, ...} to {oop_object, {record_tag, ...}, other_useful_stuff}
Expand All @@ -17,9 +16,11 @@ so 1) we know exactly what's an object (can write is_object/1) e.g.
carry around the class/superclasses so is_a(Object, ClassOrSuperclass) is easy
3) maybe hack up io:format and friends to run objects through oop:inspect automatically

Currently we can't distingish a method exiting in the middle with an undef or function_clause from a method not being defined in a module. Big example: if the generated code can't be called at tErlProcessor.erl:63, it will exit with a missing_method not because tErlProcessor:process/3 is undefined, but because GP:process/3 is undefined, but the error makes it seem like the former happened. The oop code needs to be smarter -- I think it's possible to either a) hook into Erlang's missing function handler or b) do some introspection to determine directly whether a function is defined, rather than trying to infer from the exit.

test suites

move as much as possible out of thrift_logger
move as much (program logic) as possible out of thrift_logger

make thrift_logger 100% robust

Expand All @@ -31,6 +32,4 @@ move away from thrift_oop_server shim to straight-up gen_servers

move away from Factories

move away from ?L0, ?M0, and friends ... make calls in oop
better/worse yet, make an absyn transformer and introduce some slick syntax to make it less painful and more obvious what's going on
ONLY IF our gentle nudging away from oop and thrift_oop_server isn't good enough
move away from ?L0, ?M0, and friends ... make calls in oop or individual modules (like gen_servers should be)
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@

-define(CLASS(Obj), element(1, Obj)).

-define(DEFINE_ATTR(Attr), attr(This, get, Attr, _Value) -> This#?MODULE.Attr;
-define(DEFINE_ATTR(Attr), attr(This, get, Attr, _Value) -> This#?MODULE.Attr;
attr(This, set, Attr, Value) -> This#?MODULE{Attr=Value}
).

%%% static: use only if you're sure This is class ?MODULE and not a super/subclass
-define(ATTR(Attr), This#?MODULE.Attr).

%%% convenience for implementing inspect/1
%%% e.g. -> "foo=5"
-define(FORMAT_ATTR(Attr),
-define(FORMAT_ATTR(Attr),
io_lib:write_atom(Attr) ++ "=" ++ io_lib:print(?ATTR(Attr))
).


-define(ATTR_DUMMY,
attr(dummy, dummy, dummy, dummy) ->
throw(dummy_attr_used)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 0 additions & 10 deletions lib/erl/lib/Makefile

This file was deleted.

6 changes: 0 additions & 6 deletions lib/erl/lib/thrift/HEADER

This file was deleted.

7 changes: 0 additions & 7 deletions lib/erl/lib/thrift/Makefile

This file was deleted.

39 changes: 0 additions & 39 deletions lib/erl/lib/thrift/README

This file was deleted.

11 changes: 0 additions & 11 deletions lib/erl/lib/thrift/server.sh

This file was deleted.

1 change: 0 additions & 1 deletion lib/erl/lib/thrift/tutorial

This file was deleted.

1 change: 0 additions & 1 deletion lib/erl/lib/thrift/user

This file was deleted.

20 changes: 0 additions & 20 deletions lib/erl/licence.txt

This file was deleted.

10 changes: 0 additions & 10 deletions lib/erl/release_DISABLED/Makefile

This file was deleted.

Loading

0 comments on commit c9ef99f

Please sign in to comment.