| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 1 | Thrift Erlang Library | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 2 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 3 | README Author: Chris Piro (cpiro@facebook.com) | 
|  | 4 | Last Modified: 2007-Sep-17 | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 5 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 6 | Thrift is distributed under the Thrift open source software license. | 
|  | 7 | Please see the included LICENSE file. | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 8 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 9 | Using Thrift with Erlang | 
|  | 10 | ======================== | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 11 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 12 | The Thrift Erlang binding is built using GNU make.  Run `make' in | 
|  | 13 | lib/erl to generate the necessary .beam object files in lib/erl/ebin/. | 
|  | 14 | Although the directories are laid out much like an OTP application, | 
|  | 15 | these bindings (as you will soon discover) are not an OTP application | 
|  | 16 | proper.  When starting the Erlang emulator (interpreter) you must use | 
|  | 17 | `-pa /path/to/thrift/lib/erl/ebin' to load the bindings. | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 18 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 19 | Running the Tutorial | 
|  | 20 | ==================== | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 21 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 22 | It is recommended to pattern your own servers after the tutorial | 
|  | 23 | included in tutorial/.  Generate the gen-erl/ directory by running | 
|  | 24 | tutorial.thrift, then cd to tutorial/erl/ and run server.sh.  This | 
|  | 25 | script includes the commmands necessary to compile the generated | 
|  | 26 | Erlang source, compile the tutorial server itself, and open the Erlang | 
|  | 27 | emulator.  At the emulator prompt, type `server:start()' to begin | 
|  | 28 | listening for connections. | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 29 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 30 | Note that there is no tutorial client; you may use a supplied client | 
|  | 31 | in another language. | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 32 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 33 | Implementation Notes | 
|  | 34 | ==================== | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 35 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 36 | tExecptions and t*Factorys are straight "new" -- e.g. TF = | 
|  | 37 | tTransportFactory:new() everything else is start_new | 
|  | 38 | (i.e. gen_server:start_link) -- this spawns a process and returns a | 
|  | 39 | pid | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 40 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 41 | tErlProcessor is a shim around the generated code (which is not | 
|  | 42 | actually a gen_server).  Of course tErlProcessor isn't a gen_server | 
|  | 43 | either ... thrift_oop_server is a shim to make our "Thrift objects" | 
|  | 44 | gen_servers.  Maybe we should remove some layers? | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 45 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 46 | get/set never means process dictionary | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 47 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 48 | Use tErlServer and tErlAcceptor.  tSimpleServer and tServerSocket as | 
|  | 49 | are present in the other bindings are incompatible by design ... the | 
|  | 50 | call trace is spastic across the process tree.  tErlServer and | 
|  | 51 | tErlAcceptor follow the same model as iserve: | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 52 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 53 | * the top level code spawns a tErlServer, which listens on a socket | 
|  | 54 | * a tErlAcceptor is spawned and calls accept() on the listening | 
|  | 55 | socket | 
|  | 56 | * when accept() finishes, the tErlAcceptor | 
|  | 57 | * tells the tErlServer to spawn a new acceptor | 
|  | 58 | * handles the requests by spawning a processor, a transport, and a | 
|  | 59 | protocol | 
|  | 60 | * (the tricky part) when the socket closes, the protocol exits, so: | 
|  | 61 | * the transport exits because it's the one caller of the protocol | 
|  | 62 | * likewise, the processor exits because it's the caller of the | 
|  | 63 | transport | 
|  | 64 | * the tErlAcceptor traps the protocol's exit and exits with an | 
|  | 65 | acceptor_done | 
|  | 66 | * the tErlServer sees that the acceptor exited and does nothing | 
|  | 67 | since there is already another acceptor accept()ing on the listen | 
|  | 68 | socket | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 69 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 70 | For info about iserve: http://www.trapexit.org/A_fast_web_server_demonstrating_some_undocumented_Erlang_features | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 71 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 72 | Final Thoughts | 
|  | 73 | ============== | 
| Christopher Piro | 094823a | 2007-07-18 00:26:12 +0000 | [diff] [blame] | 74 |  | 
| Christopher Piro | 93a0664 | 2007-09-18 06:23:33 +0000 | [diff] [blame] | 75 | This binding is a work in progress.  It's certainly less thoroughly | 
|  | 76 | tested than the other, older bindings.  Despite using parts from | 
|  | 77 | otp_base it is not packaged well, nor is it an OTP application (not to | 
|  | 78 | mention its many smaller transgressions).  This implementation | 
|  | 79 | intentionally patterns after the other bindings (which is why there's | 
|  | 80 | oop.erl and thrift_oop_server), but regretfully it departs from | 
|  | 81 | idiomatic Erlang.  Please see the included TODO and contribute your | 
|  | 82 | improvements back to the project. |