00:43:30  <levi>Nice.
01:03:41  * xmingquit (Ping timeout: 248 seconds)
01:04:27  * spionLjoined
01:17:06  <creationix>so did anyone have any comments for https://gist.github.com/2962615
01:17:13  <creationix>levi: ^
01:21:59  * dvvjoined
01:23:12  * TheJHquit (Read error: Operation timed out)
01:24:16  <levi>I have looked at it, but thinking about it sent me off chasing a white rabbit down a very deep hole.
01:24:20  <creationix>hmm, I should use coroutine.wrap
01:24:25  <creationix>better error handling
01:24:34  <creationix>currently any errors in the coroutine have no stack trace
01:26:31  <levi>I was pondering the relationship between evented IO, Enumerator/Iteratee-based IO, actors, and coroutines.
01:26:52  <creationix>what do you mean by "evented" IO
01:26:58  <creationix>just non-blocking
01:27:12  <levi>Node-style, where layers communicate via events.
01:31:37  <levi>In some ways, it's similar to the Enumerator/Iteratee IO.
01:35:29  <creationix>I guess so
01:35:40  <creationix>events are like signals and slots from QT
01:36:02  <creationix>hmm, using coroutine.wrap I still can't get any stack trace lines within the coroutine
01:36:15  <levi>Sure, the event model is easy to understand; it's the Enumerator/Iteratee model that's difficult.
01:36:34  <creationix>I guess I need to xpcall within the coroutine and format the error myself?
01:37:26  <levi>I guess it's probably unwinding the stack too far before it gets handled?
01:38:09  <creationix>it's showing the stack before the coroutine was created
01:38:24  <creationix>the coro has it's own stack
01:39:34  <levi>Interesting.
01:44:03  <creationix>ok, I have to xpcall the block before turning it into a coro (thus xpcalling within the coroutine)
01:45:23  <creationix>oh, or pass in the co to debug.traceback
01:45:36  <creationix>lua sure is interesting
01:54:33  <creationix>hmm, how do I call the callback *in* the main "thread" from the error handler *in* the coroutine
01:54:46  <creationix>maybe xpcall within the coroutine is a bad idea afterall
01:56:40  <levi>Anyway, I've played with the interface a bit, and I think it's a nice fit with the rest of the system, and definitely looks like it will be useful for getting rid of nested callback logic.
01:59:48  <levi>The only kind of awkward bit is that your async calls don't look at all like function calls, but that does make it obvious that they're not normal calls and there's not a straightforward way around it anyway.
02:00:56  <levi>Actually, hmmm... let me try something.
02:05:33  * tim_smart|awaychanged nick to tim_smart
02:07:16  <levi>https://gist.github.com/2981028
02:08:17  <levi>Now the function calls look like function calls, but you still have to explicitly 'wrap' them first.
02:16:30  <creationix>hmm
02:17:03  <creationix>I don't think assert is good here
02:17:12  * aliemquit (Remote host closed the connection)
02:17:21  <creationix>assert requires a truth value on success
02:17:38  <creationix>what about callbacks with no result
02:17:49  <creationix>assert will get nil and throw
02:18:42  <levi>I just left it there because you had it there.
02:19:05  <creationix>I know
02:19:11  <creationix>I'm just thinking
02:19:17  <levi>If you refresh my gist, I made another change in the fiber example that makes the wrapping thing a little clearer.
02:19:58  <creationix>yep, wrapped to look sync
02:20:09  <creationix>question is, is that good
02:20:45  <creationix>well, you have to wrap it within the fiber
02:20:54  <creationix>so I guess it's not bad
02:23:29  <creationix>so maybe just return all args as-is?
02:23:54  <creationix>local err, fd = open("file", …)
02:24:05  <levi>That would be nice.
02:24:11  <creationix>that would be easier
02:24:23  <creationix>I can't call the callback with (err) from the coroutine's thread
02:24:26  <creationix>bad stuff happens
02:25:05  <creationix>so the question is should it return a wrap function or a wait function?
02:25:16  <creationix>s/return/provide/
02:29:30  <levi>Well, I definitely prefer the wrap function. You can get from one to the other fairly easily either way, though.
02:30:12  <creationix>right, but I don't really want to provide both
02:30:25  <creationix>I guess code both and see which feels better
02:30:37  <creationix>I'm still ironing out the error reporting
02:30:52  <creationix>I want thrown errors in the coroutine to go to the callback with a proper stack trace
02:54:11  <creationix>levi: ok, pushed much better error reporting to the gist
02:54:21  <creationix>I decided to assume node-style callbacks
02:54:26  <creationix>and route errors to the fiber's callback
02:54:36  <creationix>so the return value is just the data part of the callback
02:54:55  <creationix>it means you can't handle errors within a fiber's body
02:55:06  <creationix>but I think that's worth the convenience of no error handling
02:55:42  <creationix>though some sort of "finally" mechanism might be nice
02:55:50  <creationix>to close file descriptors and stuff like that in case of error
02:56:35  <levi>That would be good.
02:56:48  <creationix>currently, there is the callback
02:57:06  <creationix>if you store flags in a place the callback can see them, it can check the flags and close things
02:57:31  <creationix>or outside the fiber store an array of cleanup functions
02:57:34  <levi>function curry1(func, arg1) return function(...) return func(arg1, ...) end end
02:57:37  <creationix>and run them all in case of error
02:57:47  <levi>^- turns a wait into a wrap
02:58:19  <creationix>wrap(wait, fn) -> w
02:58:34  <creationix>then I could provide just wait, but it would be easy to wrap
02:59:11  <levi>Yeah.
02:59:13  <creationix>I guess your curry1 == wrap in that case
02:59:20  <levi>Exactly.
02:59:56  * xmingjoined
02:59:56  <creationix>combine wrap with the implicit error handling
03:00:07  <creationix>and it's just as easy as sync programming
03:00:22  <creationix>both uncaught sync errors and errors in the callbacks get routed to the same place saftely
03:00:46  <creationix>only downside is you can't do inline handling of the errors
03:00:57  <creationix>so APIs need to not treat errors as data
03:01:08  <creationix>I'm guilty of that sometims
03:01:21  <creationix>since node errors are objects with the .code property
03:02:05  <creationix>fs.stat("badfile", function (err, stat) { if (err && err.code === "ENOENT") { /* send 404 page */ } })
03:02:26  <creationix>instead it would need to return null as the stat if the file didn't exist
03:02:37  <creationix>since that's often not a real error
03:02:41  <creationix>just a missing file
03:03:28  <creationix>local stat = stat("bad file"); if not stat then --[[ send 404 page ]] end
03:03:46  * ljacksonquit (Quit: Leaving)
03:05:28  <creationix>I don't know
03:05:34  <levi>Sounds good to me.
03:05:51  <creationix>the other option is to make the user use a helper like assert
03:06:33  <creationix>function checker(err, …) if err then error(err) else return … end
03:06:47  <creationix>check(open("bad file"))
03:07:06  <creationix>that's less magical
03:07:21  <creationix>and the wrapper could do that built-in
03:07:39  <creationix>wrap(wait, fn, true) where true means auto-check for errors
03:08:13  <creationix>the problem with baking in auto error handling is there is no way to check the error for the cases where you do want to
03:14:26  * spionLquit (Ping timeout: 246 seconds)
03:24:39  <creationix>hmm, can't do
03:24:49  <creationix>local err, … = fn()
03:24:59  <creationix>how can I grab the rest of the return values?
03:26:37  <creationix>local args = {fn()}
03:26:41  <creationix>local err = args[1]
03:42:52  <creationix>return unpack(args, 2) -- for no error case
03:42:53  <creationix>:)
03:45:29  <rphillips>our agent is using the new http/https library... working great!
03:45:51  <levi>Cool, it looks like you've put a lot of work into it.
03:46:05  <rphillips>thanks
03:46:20  <rphillips>still need to write the http server functionality
03:46:24  <rphillips>unit tests
03:46:31  <rphillips>and unit tests*
03:48:00  <levi>Ahh, unit tests. :)
03:51:17  <levi>creationix: You could make a special object type for wrapped return values that could be used to check for success and failure and get the return values.
03:51:39  <creationix>levi: I think I got it
03:51:44  <creationix>pushing as soon as I tidy the code
03:51:52  <creationix>it's pretty elegant I think
03:57:02  <creationix>levi: what do you think of this https://gist.github.com/2962615
03:57:56  <creationix>levi, we should make a wrap helper that wraps all the functions on a table and returns a new table
03:58:16  <creationix>local fs = wrapTable(wait, fs, true)
03:58:33  <rphillips>+1
03:58:57  <rphillips>could call it wrap and check to see if a table is passed in
03:59:05  <creationix>good idea
03:59:12  <levi>It could just set __index on the metatable of a new table that wraps and calls the original table's entries.
03:59:23  <creationix>levi: nice
03:59:58  <creationix>levi, would it cache the wrapped functions as they are called?
04:00:06  <creationix>or create a new one on every call?
04:00:21  <levi>No reason it couldn't cache them.
04:00:32  <creationix>right, but do we want to?
04:00:46  <creationix>rawest is a great way to cache
04:00:52  <creationix>*rawset
04:02:05  <levi>The only downside would be if you updated the original table's entries at runtime.
04:02:24  <creationix>right
04:02:35  <creationix>how expensive is not caching the wrapping
04:02:39  <creationix>it's just a closure right?
04:02:50  <creationix>compared to the actual async work it should be cheap
04:04:08  <levi>Yeah, should be.
04:05:02  <creationix>ok, let me add that
04:06:03  <levi>If it proves to a performance issue for someone, you can always manually save the wrappers.
04:11:38  <creationix>alright pushed
04:11:40  <creationix>lua is fun
04:15:13  <creationix>I wonder how much of this I can do with generators in JS
04:15:24  <creationix>I need to work on my luvmonkey project for nodeconf too
04:15:57  <creationix>levi: we could add magical self-invalidating cache functions if it proves to be a performance issue
04:16:03  <creationix>or they could cache it manually
04:16:08  <creationix>that's probably best
04:16:13  <creationix>keep things simple
04:17:57  <creationix>ok, I think I'm going to put this code in luvit as fiber.new and fiber.wrap
04:17:59  <creationix>any objections?
04:18:21  <creationix>what we have currently is too painful
04:19:38  <levi>Sounds good to me.
04:20:14  <creationix>hmm, I never use wait in the example
04:20:18  <creationix>just feed it to wrap
04:20:29  <creationix>it would be simpler to have wrap in the parameter like your gist
04:20:42  <creationix>we could pass wait as a second param for people wanting direct access?
04:20:48  <creationix>which do you think will be used more?
04:20:59  <creationix>even for one-off calls, wrap is about the same syntax
04:21:40  <creationix>wrap(fs.open)(…) vs wait(fs.open, …)
04:21:48  <creationix>wrap is more code under the covers
04:22:51  <creationix>and I wonder if I can optimize wrap if it's internal and not based on wait
04:27:12  <creationix>ok, baked wrap into the fiber
04:29:57  <levi>Very nice.
04:32:20  <creationix>I like it
04:32:34  <creationix>and with the callback, it fits nicely inside async code
04:32:47  <creationix>so now, how would I do things in parallel?
04:33:54  <creationix>I was careful to handle multiple results everywhere
04:33:57  <levi>So, it turns out you can set __call on a metatable and invoke a table like a function. You can also set __index on _G's metatable and it can dispatch any functions you call that don't actually exist.
04:34:13  <rphillips>creationix: return a promise
04:34:21  <rphillips>then call promise:wait()
04:34:31  <creationix>rphillips: noooooo!
04:34:34  <rphillips>:)
04:34:48  <creationix>rphillips: you remember those?
04:34:53  <levi>promises are where it's at.
04:34:56  <rphillips>were they in luvit?
04:35:03  <creationix>no, they were in luvit
04:35:06  <creationix>err, node
04:35:25  <creationix>before node had the callback(err, value) pattern, it returned promises
04:35:25  <levi>I hear rumors there's a possibility that promises could make a return to node at some point.
04:36:09  <creationix>levi: maybe, but it's a ways off
04:36:17  <creationix>most the core people love callbacks and hate promises
04:36:33  <creationix>partly due to the fact that node's promises were so terrible
04:36:34  <rphillips>i lean towards callbacks myself
04:37:21  <creationix>rphillips: the problem with promise:wait() is it allow suspending the main thread
04:37:37  <creationix>in this proposal, only fiber blocks can suspend themselves
04:37:46  <rphillips>ah
04:37:48  <creationix>and luvit is very careful to call all callbacks in the main thread
04:38:01  <creationix>so that the callback can tell the coroutine to resume
04:38:18  <creationix>(can't resume from a suspended coroutine, can you)
04:39:06  <creationix>this fiber sugar is still 100% based on node-style callbacks
04:39:18  <creationix>and even exports a node style callback for the fiber itself
04:39:38  <creationix>but within the fiber, it appears quite sync and simple
04:39:59  <rphillips>did you commit it to the repo?
04:40:05  <creationix>if foo() and bar() then baz() else bom() end
04:40:14  <creationix>rphillips: not yet, I can though
04:40:33  <creationix>try doing that conditional logic using all async functions
04:40:34  <rphillips>just trying to find the latest gist
04:40:42  <creationix>https://gist.github.com/2962615
04:40:50  <creationix>the gist should be up to date
04:41:12  <rphillips>coo
04:41:26  <rphillips>this is exactly the style of reconnoiter's lua module
04:41:40  <creationix>really?
04:41:44  <rphillips>async I/O in the background, but a blocking lua plugin system
04:41:53  <rphillips>blocking-like lua plugin system*
04:41:56  <creationix>ahh
04:42:04  <creationix>yeah, for most things, that works fine
04:42:12  <creationix>especially of threads don't share state
04:42:28  <creationix>but even if they do, it's no worse than true multi-threading
04:42:47  <creationix>stuff can only change while waiting for an async function to return
04:42:48  <rphillips>http://labs.omniti.com/labs/reconnoiter/browser/src/modules-lua/noit/module/tcp.lua#L142
04:43:30  <creationix>I see, that is similair
04:43:40  <creationix>looks like assert() friendly return values
04:43:51  <creationix>I couldn't get assert to play nice with node-style functions
04:44:03  <creationix>since it requires a truth value for all successes
04:45:08  <rphillips>really slick... it didn't take too much code
04:48:48  <rphillips>heading to bed. g'night
04:50:36  <creationix>'night
04:57:15  <CIA-113>Tim Caswell coro-sugar * r417f36f / (examples/fs-coroutines.lua lib/luvit/fiber.lua): Make fiber sugar more useful. - http://git.io/LjejJA
04:57:37  <creationix>levi: still around?
04:58:42  <creationix>https://github.com/luvit/luvit/pull/257
04:58:59  * creationixactually used a branch and pull request instead of just pushing to master :)
05:08:53  * tim_smartchanged nick to tim_smart|away
05:18:19  <levi>Cool. :)
05:19:09  <creationix>it appears this can be done in JS as well
05:19:16  <creationix>I'll have to try this with luvmonkey http://tobyho.com/2010/12/10/trampolines-in-javascript-and/
05:28:19  * tokyodanjoined
05:42:01  * ljacksonjoined
05:51:15  <levi>That's not quite the use that I'd typically heard of for trampolines, but it does turn out to be pretty much the same thing.
05:59:53  <levi>I was trying to figure out how you were going to do that in node, but I guess luvmonkey is spidermonkey. :)
06:01:53  <levi>Anyway, I mostly learned about trampolines in the context of C programs implementing language runtimes.
06:32:21  * mmaleckijoined
06:41:32  * tokyodanquit (Quit: tokyodan)
06:52:28  * dvv-androidjoined
07:09:19  * dvv-androidquit (Remote host closed the connection)
07:09:35  * dvv-androidjoined
07:13:57  * `3rdEdenjoined
07:18:38  * dvv-androidquit (Remote host closed the connection)
07:18:54  * dvv-androidjoined
07:41:50  * dvv-androidquit (Remote host closed the connection)
07:42:07  * dvv-androidjoined
08:05:17  * dvv-androidquit (Remote host closed the connection)
08:05:34  * dvv-androidjoined
08:10:35  * xmingquit (Changing host)
08:10:36  * xmingjoined
08:20:31  * `3rdEdenquit (Quit: Leaving...)
08:26:38  * dvv-androidquit (Remote host closed the connection)
08:26:55  * dvv-androidjoined
08:45:55  * dvv-androidquit (Remote host closed the connection)
08:46:11  * dvv-androidjoined
09:01:48  * tim_smart|awaychanged nick to tim_smart
09:03:21  * tokyodanjoined
09:07:14  * dvv-androidquit (Remote host closed the connection)
09:07:31  * dvv-androidjoined
09:19:49  * tokyodanquit (Quit: tokyodan)
09:26:29  * dvv-androidquit (Remote host closed the connection)
09:26:43  * dvv-androidjoined
09:52:02  * dvv-androidquit (Remote host closed the connection)
09:52:19  * dvv-androidjoined
09:53:10  * `3rdEdenjoined
10:19:41  * dvv-androidquit (Remote host closed the connection)
10:19:58  * dvv-androidjoined
10:39:45  * dvv-androidquit (Remote host closed the connection)
10:40:02  * dvv-androidjoined
10:44:54  * `3rdEdenquit (Quit: Linkinus - http://linkinus.com)
10:48:39  * aliemjoined
10:52:14  * AvianFluquit (Ping timeout: 244 seconds)
10:54:13  * tim_smartchanged nick to tim_smart|away
10:55:43  * AvianFlujoined
10:55:45  * dvv-androidquit (Remote host closed the connection)
10:56:01  * dvv-androidjoined
11:01:57  * dvvquit (Ping timeout: 248 seconds)
11:18:01  * dvv-androidquit (Remote host closed the connection)
11:18:17  * dvv-androidjoined
11:31:38  * aliemquit (Remote host closed the connection)
11:33:26  * aliemjoined
11:36:44  * aliemquit (Remote host closed the connection)
11:38:26  * dvv-androidquit (Remote host closed the connection)
11:38:40  * aliemjoined
11:38:42  * dvv-androidjoined
11:39:12  * AvianFluquit (Ping timeout: 244 seconds)
11:45:04  * aliemquit (Remote host closed the connection)
11:49:33  * aliemjoined
11:56:22  * dvv-androidquit (Remote host closed the connection)
11:56:35  * dvv-androidjoined
12:15:32  * dvv-androidquit (Remote host closed the connection)
12:15:49  * dvv-androidjoined
12:36:53  * dvv-androidquit (Remote host closed the connection)
12:37:10  * dvv-androidjoined
12:54:20  * dvv-androidquit (Remote host closed the connection)
12:54:37  * dvv-androidjoined
13:12:08  * dvv-androidquit (Remote host closed the connection)
13:12:24  * dvv-androidjoined
13:21:13  <xming>afternoon, guys
13:22:22  * TheJHjoined
13:22:30  <xming>do we really need build in Openssl support? Does linking to system lib or linking to self build dir enough?
13:24:15  <xming>BTW everything and be optional (except uv and luajit) and everything can be build against system/prebuild libs or built as an external project, except OpenSSL
13:25:40  <xming>I rekon eveyone who wants SSL already has the libs
13:25:46  <xming>except maybe windows people
13:33:14  * dvv-androidquit (Remote host closed the connection)
13:33:31  * dvv-androidjoined
13:39:24  * arek_deepinitjoined
13:39:58  * arek_deepinitquit (Client Quit)
13:40:14  * arek_deepinitjoined
13:52:29  * dvv-androidquit (Remote host closed the connection)
13:52:46  * dvv-androidjoined
14:06:57  * arek_deepinitquit (Quit: Konversation terminated!)
14:18:02  * dvv-androidquit (Remote host closed the connection)
14:18:19  * dvv-androidjoined
14:43:45  * dvv-androidquit (Remote host closed the connection)
14:44:01  * dvv-androidjoined
15:04:56  * dvv-androidquit (Remote host closed the connection)
15:05:13  * dvv-androidjoined
15:24:11  * dvv-androidquit (Remote host closed the connection)
15:24:28  * dvv-androidjoined
15:43:26  * dvv-androidquit (Remote host closed the connection)
15:43:43  * dvv-androidjoined
15:56:23  <rphillips>we will need to include our own openssl
16:00:59  * dvv-androidquit (Remote host closed the connection)
16:01:15  * dvv-androidjoined
16:15:41  * dvv-androidquit (Remote host closed the connection)
16:15:57  * dvv-androidjoined
16:32:47  * dvv-androidquit (Remote host closed the connection)
16:33:04  * dvv-androidjoined
16:50:45  * dvv-androidquit (Remote host closed the connection)
16:51:02  * dvv-androidjoined
17:05:41  * dvv-androidquit (Remote host closed the connection)
17:05:58  * dvv-androidjoined
17:18:05  * dvv-androidquit (Remote host closed the connection)
17:18:22  * dvv-androidjoined
17:30:39  * dvvjoined
17:30:51  * dvv-androidquit (Remote host closed the connection)
17:31:08  * dvv-androidjoined
17:39:31  * mkandrashoffjoined
17:48:02  * dvv-androidquit (Remote host closed the connection)
17:48:19  * dvv-androidjoined
17:52:29  * AvianFlujoined
18:00:59  * dvv-androidquit (Remote host closed the connection)
18:01:16  * dvv-androidjoined
18:03:32  * TheJHquit (Read error: Operation timed out)
18:13:34  * dvv-androidquit (Remote host closed the connection)
18:13:50  * dvv-androidjoined
18:26:32  * dvv-androidquit (Remote host closed the connection)
18:26:49  * dvv-androidjoined
18:45:46  * dvv-androidquit (Remote host closed the connection)
18:46:03  * dvv-androidjoined
19:07:08  * dvv-androidquit (Remote host closed the connection)
19:07:25  * dvv-androidjoined
19:18:35  * AvianFluquit (Ping timeout: 250 seconds)
19:24:17  * dvv-androidquit (Remote host closed the connection)
19:24:34  * dvv-androidjoined
19:39:26  * TheJHjoined
19:40:48  * dvv-androidquit (Remote host closed the connection)
19:41:05  * dvv-androidjoined
19:48:26  <pquerna>xming: openssl tends to be very outdated in many distros -- node.js embeds it too -- we need >1.0 for example to get consistent SNI, SPDY support, and TLS Session tickets.
19:48:26  * dvvquit (Ping timeout: 240 seconds)
19:48:40  * arek_deepinitjoined
19:51:53  * dvvjoined
19:53:03  * AvianFlujoined
19:57:17  * dvv-androidquit (Remote host closed the connection)
19:57:34  * dvv-androidjoined
19:59:47  * dvvquit (Ping timeout: 252 seconds)
20:02:04  <xming>okay understood
20:03:31  * AvianFluquit (Ping timeout: 244 seconds)
20:03:42  <xming>my distro comes with 1.0.0.j :D
20:11:01  * AvianFlujoined
20:11:03  * dvv-androidquit (Remote host closed the connection)
20:11:20  * dvv-androidjoined
20:14:36  * dvvjoined
20:19:26  * AvianFluquit (Ping timeout: 240 seconds)
20:23:33  * dvv-androidquit (Remote host closed the connection)
20:23:49  * dvv-androidjoined
20:26:40  <CIA-113>Ryan Phillips features/improve_http_module * rc7550a7 / examples/http-client.lua : examples: update http-client.lua - http://git.io/Inz0bg
20:41:28  * TheJHquit (Ping timeout: 260 seconds)
20:42:37  * dvv-androidquit (Remote host closed the connection)
20:42:54  * dvv-androidjoined
20:43:52  * AvianFlujoined
20:46:06  * mmaleckiquit (Ping timeout: 245 seconds)
21:01:47  * dvv-androidquit (Remote host closed the connection)
21:02:04  * dvv-androidjoined
21:19:18  * dvv-androidquit (Remote host closed the connection)
21:19:35  * dvv-androidjoined
21:27:52  * mkandrashoffquit (Quit: Leaving.)
21:32:11  * arek_deepinitquit (Quit: Konversation terminated!)
21:36:31  * dvvquit (Ping timeout: 272 seconds)
21:38:25  * dvv-androidquit (Remote host closed the connection)
21:38:41  * dvv-androidjoined
21:46:14  * mmaleckijoined
21:53:23  * dvv-androidquit (Remote host closed the connection)
21:53:40  * dvv-androidjoined
22:12:29  * spionLjoined
22:13:13  * dvv-androidquit (Remote host closed the connection)
22:13:29  * dvv-androidjoined
22:29:36  * dvv-androidquit (Remote host closed the connection)
22:29:52  * dvv-androidjoined
22:48:19  * dvv-androidquit (Remote host closed the connection)
22:48:36  * dvv-androidjoined
22:51:49  * tim_smart|awaychanged nick to tim_smart
22:52:12  * mmaleckiquit (Ping timeout: 265 seconds)
22:55:02  * tokyodanjoined
23:05:54  * dvv-androidquit (Remote host closed the connection)
23:06:10  * dvv-androidjoined
23:20:09  * dvv-androidquit (Remote host closed the connection)
23:20:26  * dvv-androidjoined
23:33:13  * tokyodanquit (Quit: tokyodan)
23:33:13  * dvv-androidquit (Remote host closed the connection)
23:33:27  * dvv-androidjoined
23:52:23  * dvv-androidquit (Remote host closed the connection)
23:52:40  * dvv-androidjoined
23:54:39  * philipsquit (Excess Flood)
23:55:16  * philipsjoined