Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Resolved conflicts

  • Loading branch information...
commit ea09c437d5974db908eb87a571ee31615e5f8a5c 2 parents 19c9ea2 + de19f2a
@samluescher samluescher authored
Showing with 5,399 additions and 4,280 deletions.
  1. BIN  .DS_Store
  2. +3 −0  .gitmodules
  3. BIN  Geo.app/Contents/Resources/Scripts/main.scpt
  4. BIN  dump.rdb
  5. +1 −0  g-speak/test-oblessd.html
  6. +10 −0 ios/UIWebViewWebGL/UIWebViewWebGL.xcodeproj/project.pbxproj
  7. +1 −1  ios/UIWebViewWebGL/UIWebViewWebGL/WGLAppDelegate.h
  8. +25 −8 ios/UIWebViewWebGL/UIWebViewWebGL/WGLAppDelegate.m
  9. +0 −3  node_modules/ntwitter/node_modules/cookies/package.json
  10. +1 −1  node_modules/ntwitter/node_modules/keygrip/lib/defaultKeys.json
  11. +0 −3  node_modules/ntwitter/node_modules/keygrip/package.json
  12. +0 −3  node_modules/ntwitter/package.json
  13. +567 −0 node_modules/redis/README.md
  14. +210 −0 node_modules/redis/changelog.md
  15. +5 −0 node_modules/redis/examples/auth.js
  16. +33 −0 node_modules/redis/examples/backpressure_drain.js
  17. +9 −0 node_modules/redis/examples/eval.js
  18. +24 −0 node_modules/redis/examples/extend.js
  19. +32 −0 node_modules/redis/examples/file.js
  20. +5 −0 node_modules/redis/examples/mget.js
  21. +10 −0 node_modules/redis/examples/monitor.js
  22. +46 −0 node_modules/redis/examples/multi.js
  23. +29 −0 node_modules/redis/examples/multi2.js
  24. +33 −0 node_modules/redis/examples/psubscribe.js
  25. +41 −0 node_modules/redis/examples/pub_sub.js
  26. +24 −0 node_modules/redis/examples/simple.js
  27. +17 −0 node_modules/redis/examples/sort.js
  28. +15 −0 node_modules/redis/examples/subqueries.js
  29. +19 −0 node_modules/redis/examples/subquery.js
  30. +29 −0 node_modules/redis/examples/unix_socket.js
  31. +31 −0 node_modules/redis/examples/web_server.js
  32. +39 −0 node_modules/redis/generate_commands.js
  33. +955 −0 node_modules/redis/index.js
  34. +126 −0 node_modules/redis/lib/commands.js
  35. +46 −0 node_modules/redis/lib/parser/hiredis.js
  36. +317 −0 node_modules/redis/lib/parser/javascript.js
  37. +58 −0 node_modules/redis/lib/queue.js
  38. +12 −0 node_modules/redis/lib/to_array.js
  39. +7 −0 node_modules/redis/lib/util.js
  40. +225 −0 node_modules/redis/multi_bench.js
  41. +66 −0 node_modules/redis/package.json
  42. +1,301 −0 node_modules/redis/test.js
  43. +89 −0 node_modules/redis/tests/buffer_bench.js
  44. +38 −0 node_modules/redis/tests/hiredis_parser.js
  45. +29 −0 node_modules/redis/tests/reconnect_test.js
  46. +16 −0 node_modules/redis/tests/stress/codec.js
  47. +38 −0 node_modules/redis/tests/stress/pubsub/pub.js
  48. +10 −0 node_modules/redis/tests/stress/pubsub/run
  49. +23 −0 node_modules/redis/tests/stress/pubsub/server.js
  50. +49 −0 node_modules/redis/tests/stress/rpushblpop/pub.js
  51. +6 −0 node_modules/redis/tests/stress/rpushblpop/run
  52. +30 −0 node_modules/redis/tests/stress/rpushblpop/server.js
  53. +13 −0 node_modules/redis/tests/stress/speed/00
  54. +13 −0 node_modules/redis/tests/stress/speed/plot
  55. BIN  node_modules/redis/tests/stress/speed/size-rate.png
  56. +84 −0 node_modules/redis/tests/stress/speed/speed.js
  57. +18 −0 node_modules/redis/tests/sub_quit_test.js
  58. +0 −2  node_modules/twilio/.npmignore
  59. +0 −145 node_modules/twilio/README.md
  60. +0 −26 node_modules/twilio/examples/dial-list/app.js
  61. +0 −7 node_modules/twilio/examples/dial-list/config.js.sample
  62. +0 −121 node_modules/twilio/examples/quiz-message/app.js
  63. +0 −6 node_modules/twilio/examples/quiz-message/config.js.sample
  64. +0 −27 node_modules/twilio/examples/sms-list/app.js
  65. +0 −7 node_modules/twilio/examples/sms-list/config.js.sample
  66. +0 −1  node_modules/twilio/index.js
  67. +0 −119 node_modules/twilio/lib/auto-uri.js
  68. +0 −3  node_modules/twilio/lib/index.js
  69. +0 −454 node_modules/twilio/lib/rest-client.js
  70. +0 −239 node_modules/twilio/lib/twilio.js
  71. +0 −385 node_modules/twilio/lib/twiml.js
  72. +0 −33 node_modules/twilio/package.json
  73. +0 −7 node_modules/twilio/test/Makefile
  74. +0 −200 node_modules/twilio/test/client-test.js
  75. +0 −7 node_modules/twilio/test/config.js.sample
  76. +0 −11 node_modules/twilio/test/twilio-test.js
  77. +0 −226 node_modules/twilio/test/twiml-test.js
  78. +0 −2  node_modules/twitter/.npmignore
  79. +0 −21 node_modules/twitter/LICENSE
  80. +0 −86 node_modules/twitter/README.md
  81. +0 −1  node_modules/twitter/index.js
  82. +0 −45 node_modules/twitter/lib/parser.js
  83. +0 −1,145 node_modules/twitter/lib/twitter.js
  84. +0 −1  node_modules/twitter/node_modules/cookies/.npmignore
  85. +0 −3  node_modules/twitter/node_modules/cookies/.travis.yml
  86. +0 −20 node_modules/twitter/node_modules/cookies/LICENSE.txt
  87. +0 −115 node_modules/twitter/node_modules/cookies/README.md
  88. +0 −112 node_modules/twitter/node_modules/cookies/lib/cookies.js
  89. +0 −37 node_modules/twitter/node_modules/cookies/package.json
  90. +0 −66 node_modules/twitter/node_modules/cookies/test/express.js
  91. +0 −67 node_modules/twitter/node_modules/cookies/test/http.js
  92. +0 −1  node_modules/twitter/node_modules/keygrip/.npmignore
  93. +0 −3  node_modules/twitter/node_modules/keygrip/.travis.yml
  94. +0 −20 node_modules/twitter/node_modules/keygrip/LICENSE.txt
  95. +0 −99 node_modules/twitter/node_modules/keygrip/README.md
  96. +0 −1  node_modules/twitter/node_modules/keygrip/defaultKeys.json
  97. +0 −48 node_modules/twitter/node_modules/keygrip/index.js
  98. +0 −7 node_modules/twitter/node_modules/keygrip/install.js
  99. +0 −27 node_modules/twitter/node_modules/keygrip/package.json
  100. +0 −41 node_modules/twitter/node_modules/keygrip/test.js
  101. +0 −44 node_modules/twitter/package.json
  102. +0 −38 node_modules/twitter/test/memory.js
  103. +0 −47 node_modules/twitter/test/memory.txt
  104. BIN  public/.DS_Store
  105. +61 −16 public/app.js
  106. +3 −2 public/collections/point-collection.js
  107. +33 −0 public/collections/tweet-collection.js
  108. +2 −4 public/config.js
  109. +4 −0 public/index.html
  110. +16 −3 public/libs/globe.js
  111. +8 −19 public/libs/oblessd-client.js
  112. +37 −0 public/models/tweet.js
  113. +11 −0 public/styles/homepage.css
  114. +1 −0  public/styles/main.css
  115. +1 −1  public/styles/sidebar.css
  116. +1 −1  public/template/add-data.html
  117. +14 −0 public/template/homepage.html
  118. +8 −24 public/template/sidebar.html
  119. +8 −3 public/views/header-view.js
  120. +80 −0 public/views/homepage-view.js
  121. +101 −2 public/views/map-gl-view.js
  122. +1 −1  public/views/map-view.js
  123. +21 −1 public/views/sidebar-view.js
  124. +160 −61 server.js
View
BIN  .DS_Store
Binary file not shown
View
3  .gitmodules
@@ -1,3 +1,6 @@
[submodule "public/libs/threex"]
path = public/libs/threex
url = git://github.com/jeromeetienne/threex.git
+[submodule "public/libs/three"]
+ path = public/libs/three
+ url = git://github.com/mrdoob/three.js.git
View
BIN  Geo.app/Contents/Resources/Scripts/main.scpt
Binary file not shown
View
BIN  dump.rdb
Binary file not shown
View
1  g-speak/test-oblessd.html
@@ -44,6 +44,7 @@
ws.send('watch Object-03')
ws.send('watch Object-04')
ws.send('watch Object-05')
+ ws.send('watch Object-06')
};
var displayFps = function() {
View
10 ios/UIWebViewWebGL/UIWebViewWebGL.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 223E3A28151BE96500770228 /* Palm_Beach.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 223E3A27151BE96500770228 /* Palm_Beach.jpeg */; };
+ 22E2D5361520D58E00991B0E /* CameraViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 22E2D5351520D58E00991B0E /* CameraViewController.m */; };
D89DC61D14592F50000FC7C6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D89DC61C14592F50000FC7C6 /* UIKit.framework */; };
D89DC61F14592F50000FC7C6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D89DC61E14592F50000FC7C6 /* Foundation.framework */; };
D89DC62114592F50000FC7C6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D89DC62014592F50000FC7C6 /* CoreGraphics.framework */; };
@@ -17,6 +19,9 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 223E3A27151BE96500770228 /* Palm_Beach.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = Palm_Beach.jpeg; sourceTree = "<group>"; };
+ 22E2D5341520D58E00991B0E /* CameraViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CameraViewController.h; sourceTree = "<group>"; };
+ 22E2D5351520D58E00991B0E /* CameraViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraViewController.m; sourceTree = "<group>"; };
D89DC61814592F50000FC7C6 /* UIWebViewWebGL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIWebViewWebGL.app; sourceTree = BUILT_PRODUCTS_DIR; };
D89DC61C14592F50000FC7C6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
D89DC61E14592F50000FC7C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -78,6 +83,8 @@
children = (
D89DC62B14592F50000FC7C6 /* WGLAppDelegate.h */,
D89DC62C14592F50000FC7C6 /* WGLAppDelegate.m */,
+ 22E2D5341520D58E00991B0E /* CameraViewController.h */,
+ 22E2D5351520D58E00991B0E /* CameraViewController.m */,
D89DC633145931B3000FC7C6 /* WebGL.html */,
D89DC62314592F50000FC7C6 /* Supporting Files */,
);
@@ -87,6 +94,7 @@
D89DC62314592F50000FC7C6 /* Supporting Files */ = {
isa = PBXGroup;
children = (
+ 223E3A27151BE96500770228 /* Palm_Beach.jpeg */,
D89DC62414592F50000FC7C6 /* UIWebViewWebGL-Info.plist */,
D89DC62514592F50000FC7C6 /* InfoPlist.strings */,
D89DC62814592F50000FC7C6 /* main.m */,
@@ -148,6 +156,7 @@
files = (
D89DC62714592F50000FC7C6 /* InfoPlist.strings in Resources */,
D89DC634145931B3000FC7C6 /* WebGL.html in Resources */,
+ 223E3A28151BE96500770228 /* Palm_Beach.jpeg in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -160,6 +169,7 @@
files = (
D89DC62914592F50000FC7C6 /* main.m in Sources */,
D89DC62D14592F50000FC7C6 /* WGLAppDelegate.m in Sources */,
+ 22E2D5361520D58E00991B0E /* CameraViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
2  ios/UIWebViewWebGL/UIWebViewWebGL/WGLAppDelegate.h
@@ -8,7 +8,7 @@
#import <UIKit/UIKit.h>
-@interface WGLAppDelegate : UIResponder <UIApplicationDelegate>
+@interface WGLAppDelegate : UIResponder <UIApplicationDelegate, UIImagePickerControllerDelegate>
@property (strong, nonatomic) UIWindow *window;
View
33 ios/UIWebViewWebGL/UIWebViewWebGL/WGLAppDelegate.m
@@ -7,6 +7,7 @@
//
#import "WGLAppDelegate.h"
+#import "CameraViewController.h"
@implementation WGLAppDelegate
@@ -14,27 +15,43 @@ @implementation WGLAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
-
-// Class ADWebView = NSClassFromString(@"ADWebView");
-// UIWebView* webView = (UIWebView *)[[[ADWebView alloc] initWithFrame:self.window.bounds] autorelease];
-// [webView setWebGLEnabled:YES];
-
+
UIWebView* webView = [[[UIWebView alloc] initWithFrame:self.window.bounds] autorelease];
+ webView.backgroundColor = [UIColor clearColor];
+ webView.opaque = NO;
id webDocumentView = [webView performSelector:@selector(_browserView)];
id backingWebView = [webDocumentView performSelector:@selector(webView)];
[backingWebView _setWebGLEnabled:YES];
+
- //NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://sam-macbookair.media.mit.edu:8000/globe"]];
- NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://sam-macbookair.media.mit.edu:8124/#globe"]];
+ //NSString *url = @"http://sam-macbookair.media.mit.edu:8124/globe";
+ //NSString *url = @"http://localhost:8124/globe";
+ NSString *url = @"http://18.189.34.8:8124/globe";
+ NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[webView loadRequest:request];
+ CameraViewController *viewController = [[CameraViewController alloc] init];
+
+ /*
UIViewController* viewController = [[[UIViewController alloc] init] autorelease];
- viewController.view = webView;
+ UIView* view = [[UIView alloc] initWithFrame:webView.frame];
+
+ UIImageView* imageView = [[UIImageView alloc] initWithFrame:webView.frame];
+ imageView.image = [UIImage imageNamed:@"Palm_Beach.jpeg"];
+ [view addSubview:imageView];
+ //[view addSubview:webView];
+ viewController.view = view;
+ */
+
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
+ [viewController initCamera];
+ viewController.imagePicker.cameraOverlayView = webView;
+
+
return YES;
}
View
3  node_modules/ntwitter/node_modules/cookies/package.json
@@ -20,8 +20,5 @@
"_npmVersion": "1.1.4",
"_nodeVersion": "v0.6.11",
"_defaultsLoaded": true,
- "dist": {
- "shasum": "9aeb3506c4a3ce662bb2bf8274d3bc4d6413b8b5"
- },
"_from": "cookies@0.1.x"
}
View
2  node_modules/ntwitter/node_modules/keygrip/lib/defaultKeys.json
@@ -1 +1 @@
-["478b6693ccc092bf1cd321eb7f06ca75"]
+["fdef20301a5d286f7e6f989f83063050"]
View
3  node_modules/ntwitter/node_modules/keygrip/package.json
@@ -27,8 +27,5 @@
"_npmVersion": "1.1.4",
"_nodeVersion": "v0.6.11",
"_defaultsLoaded": true,
- "dist": {
- "shasum": "d63375d795fb7bcc7de443b0ee495a5792672037"
- },
"_from": "keygrip@0.1.x"
}
View
3  node_modules/ntwitter/package.json
@@ -35,8 +35,5 @@
"_npmVersion": "1.1.4",
"_nodeVersion": "v0.6.11",
"_defaultsLoaded": true,
- "dist": {
- "shasum": "a80e95fa69d87ee45b13b9779223748db929ffc9"
- },
"_from": "ntwitter@0.2.10"
}
View
567 node_modules/redis/README.md
@@ -0,0 +1,567 @@
+redis - a node.js redis client
+===========================
+
+This is a complete Redis client for node.js. It supports all Redis commands, including many recently added commands like EVAL from
+experimental Redis server branches.
+
+
+Install with:
+
+ npm install redis
+
+Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:
+
+ npm install hiredis redis
+
+If `hiredis` is installed, `node_redis` will use it by default. Otherwise, a pure JavaScript parser will be used.
+
+If you use `hiredis`, be sure to rebuild it whenever you upgrade your version of node. There are mysterious failures that can
+happen between node and native code modules after a node upgrade.
+
+
+## Usage
+
+Simple example, included as `examples/simple.js`:
+
+ var redis = require("redis"),
+ client = redis.createClient();
+
+ client.on("error", function (err) {
+ console.log("Error " + err);
+ });
+
+ client.set("string key", "string val", redis.print);
+ client.hset("hash key", "hashtest 1", "some value", redis.print);
+ client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
+ client.hkeys("hash key", function (err, replies) {
+ console.log(replies.length + " replies:");
+ replies.forEach(function (reply, i) {
+ console.log(" " + i + ": " + reply);
+ });
+ client.quit();
+ });
+
+This will display:
+
+ mjr:~/work/node_redis (master)$ node example.js
+ Reply: OK
+ Reply: 0
+ Reply: 0
+ 2 replies:
+ 0: hashtest 1
+ 1: hashtest 2
+ mjr:~/work/node_redis (master)$
+
+
+## Performance
+
+Here are typical results of `multi_bench.js` which is similar to `redis-benchmark` from the Redis distribution.
+It uses 50 concurrent connections with no pipelining.
+
+JavaScript parser:
+
+ PING: 20000 ops 42283.30 ops/sec 0/5/1.182
+ SET: 20000 ops 32948.93 ops/sec 1/7/1.515
+ GET: 20000 ops 28694.40 ops/sec 0/9/1.740
+ INCR: 20000 ops 39370.08 ops/sec 0/8/1.269
+ LPUSH: 20000 ops 36429.87 ops/sec 0/8/1.370
+ LRANGE (10 elements): 20000 ops 9891.20 ops/sec 1/9/5.048
+ LRANGE (100 elements): 20000 ops 1384.56 ops/sec 10/91/36.072
+
+hiredis parser:
+
+ PING: 20000 ops 46189.38 ops/sec 1/4/1.082
+ SET: 20000 ops 41237.11 ops/sec 0/6/1.210
+ GET: 20000 ops 39682.54 ops/sec 1/7/1.257
+ INCR: 20000 ops 40080.16 ops/sec 0/8/1.242
+ LPUSH: 20000 ops 41152.26 ops/sec 0/3/1.212
+ LRANGE (10 elements): 20000 ops 36563.07 ops/sec 1/8/1.363
+ LRANGE (100 elements): 20000 ops 21834.06 ops/sec 0/9/2.287
+
+The performance of `node_redis` improves dramatically with pipelining, which happens automatically in most normal programs.
+
+
+### Sending Commands
+
+Each Redis command is exposed as a function on the `client` object.
+All functions take either take either an `args` Array plus optional `callback` Function or
+a variable number of individual arguments followed by an optional callback.
+Here is an example of passing an array of arguments and a callback:
+
+ client.mset(["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {});
+
+Here is that same call in the second style:
+
+ client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});
+
+Note that in either form the `callback` is optional:
+
+ client.set("some key", "some val");
+ client.set(["some other key", "some val"]);
+
+For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
+
+The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.
+
+Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,
+integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a
+JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.
+
+# API
+
+## Connection Events
+
+`client` will emit some events about the state of the connection to the Redis server.
+
+### "ready"
+
+`client` will emit `ready` a connection is established to the Redis server and the server reports
+that it is ready to receive commands. Commands issued before the `ready` event are queued,
+then replayed just before this event is emitted.
+
+### "connect"
+
+`client` will emit `connect` at the same time as it emits `ready` unless `client.options.no_ready_check`
+is set. If this options is set, `connect` will be emitted when the stream is connected, and then
+you are free to try to send commands.
+
+### "error"
+
+`client` will emit `error` when encountering an error connecting to the Redis server.
+
+Note that "error" is a special event type in node. If there are no listeners for an
+"error" event, node will exit. This is usually what you want, but it can lead to some
+cryptic error messages like this:
+
+ mjr:~/work/node_redis (master)$ node example.js
+
+ node.js:50
+ throw e;
+ ^
+ Error: ECONNREFUSED, Connection refused
+ at IOWatcher.callback (net:870:22)
+ at node.js:607:9
+
+Not very useful in diagnosing the problem, but if your program isn't ready to handle this,
+it is probably the right thing to just exit.
+
+`client` will also emit `error` if an exception is thrown inside of `node_redis` for whatever reason.
+It would be nice to distinguish these two cases.
+
+### "end"
+
+`client` will emit `end` when an established Redis server connection has closed.
+
+### "drain"
+
+`client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now
+writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,
+you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can
+resume sending when you get `drain`.
+
+### "idle"
+
+`client` will emit `idle` when there are no outstanding commands that are awaiting a response.
+
+## redis.createClient(port, host, options)
+
+Create a new client connection. `port` defaults to `6379` and `host` defaults
+to `127.0.0.1`. If you have `redis-server` running on the same computer as node, then the defaults for
+port and host are probably fine. `options` in an object with the following possible properties:
+
+* `parser`: which Redis protocol reply parser to use. Defaults to `hiredis` if that module is installed.
+This may also be set to `javascript`.
+* `return_buffers`: defaults to false. If set to `true`, then bulk data replies will be returned as node Buffer
+objects instead of JavaScript Strings.
+
+`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.
+
+## client.auth(password, callback)
+
+When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the
+first command after connecting. This can be tricky to coordinate with reconnections, the ready check,
+etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,
+including reconnections. `callback` is invoked only once, after the response to the very first
+`AUTH` command sent.
+
+## client.end()
+
+Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.
+If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.
+
+This example closes the connection to the Redis server before the replies have been read. You probably don't
+want to do this:
+
+ var redis = require("redis"),
+ client = redis.createClient();
+
+ client.set("foo_rand000000000000", "some fantastic value");
+ client.get("foo_rand000000000000", function (err, reply) {
+ console.log(reply.toString());
+ });
+ client.end();
+
+`client.end()` is useful for timeout cases where something is stuck or taking too long and you want
+to start over.
+
+## Friendlier hash commands
+
+Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. When dealing with hash values, there are a couple of useful exceptions to this.
+
+### client.hgetall(hash)
+
+The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact
+with the responses using JavaScript syntax.
+
+Example:
+
+ client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
+ client.hgetall("hosts", function (err, obj) {
+ console.dir(obj);
+ });
+
+Output:
+
+ { mjr: '1', another: '23', home: '1234' }
+
+### client.hmset(hash, obj, [callback])
+
+Multiple values in a hash can be set by supplying an object:
+
+ client.HMSET(key2, {
+ "0123456789": "abcdefghij",
+ "some manner of key": "a type of value"
+ });
+
+The properties and values of this Object will be set as keys and values in the Redis hash.
+
+### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
+
+Multiple values may also be set by supplying a list:
+
+ client.HMSET(key1, "0123456789", "abcdefghij", "some manner of key", "a type of value");
+
+
+## Publish / Subscribe
+
+Here is a simple example of the API for publish / subscribe. This program opens two
+client connections, subscribes to a channel on one of them, and publishes to that
+channel on the other:
+
+ var redis = require("redis"),
+ client1 = redis.createClient(), client2 = redis.createClient(),
+ msg_count = 0;
+
+ client1.on("subscribe", function (channel, count) {
+ client2.publish("a nice channel", "I am sending a message.");
+ client2.publish("a nice channel", "I am sending a second message.");
+ client2.publish("a nice channel", "I am sending my last message.");
+ });
+
+ client1.on("message", function (channel, message) {
+ console.log("client1 channel " + channel + ": " + message);
+ msg_count += 1;
+ if (msg_count === 3) {
+ client1.unsubscribe();
+ client1.end();
+ client2.end();
+ }
+ });
+
+ client1.incr("did a thing");
+ client1.subscribe("a nice channel");
+
+When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode.
+At that point, only commands that modify the subscription set are valid. When the subscription
+set is empty, the connection is put back into regular mode.
+
+If you need to send regular commands to Redis while in pub/sub mode, just open another connection.
+
+## Pub / Sub Events
+
+If a client has subscriptions active, it may emit these events:
+
+### "message" (channel, message)
+
+Client will emit `message` for every message received that matches an active subscription.
+Listeners are passed the channel name as `channel` and the message Buffer as `message`.
+
+### "pmessage" (pattern, channel, message)
+
+Client will emit `pmessage` for every message received that matches an active subscription pattern.
+Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel
+name as `channel`, and the message Buffer as `message`.
+
+### "subscribe" (channel, count)
+
+Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the
+channel name as `channel` and the new count of subscriptions for this client as `count`.
+
+### "psubscribe" (pattern, count)
+
+Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the
+original pattern as `pattern`, and the new count of subscriptions for this client as `count`.
+
+### "unsubscribe" (channel, count)
+
+Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the
+channel name as `channel` and the new count of subscriptions for this client as `count`. When
+`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
+
+### "punsubscribe" (pattern, count)
+
+Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the
+channel name as `channel` and the new count of subscriptions for this client as `count`. When
+`count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
+
+## client.multi([commands])
+
+`MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by
+Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.
+
+ var redis = require("./index"),
+ client = redis.createClient(), set_size = 20;
+
+ client.sadd("bigset", "a member");
+ client.sadd("bigset", "another member");
+
+ while (set_size > 0) {
+ client.sadd("bigset", "member " + set_size);
+ set_size -= 1;
+ }
+
+ // multi chain with an individual callback
+ client.multi()
+ .scard("bigset")
+ .smembers("bigset")
+ .keys("*", function (err, replies) {
+ client.mget(replies, redis.print);
+ })
+ .dbsize()
+ .exec(function (err, replies) {
+ console.log("MULTI got " + replies.length + " replies");
+ replies.forEach(function (reply, index) {
+ console.log("Reply " + index + ": " + reply.toString());
+ });
+ });
+
+`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the
+same command methods as `client` objects do. Commands are queued up inside the `Multi` object
+until `Multi.exec()` is invoked.
+
+You can either chain together `MULTI` commands as in the above example, or you can queue individual
+commands while still sending regular client command as in this example:
+
+ var redis = require("redis"),
+ client = redis.createClient(), multi;
+
+ // start a separate multi command queue
+ multi = client.multi();
+ multi.incr("incr thing", redis.print);
+ multi.incr("incr other thing", redis.print);
+
+ // runs immediately
+ client.mset("incr thing", 100, "incr other thing", 1, redis.print);
+
+ // drains multi queue and runs atomically
+ multi.exec(function (err, replies) {
+ console.log(replies); // 101, 2
+ });
+
+ // you can re-run the same transaction if you like
+ multi.exec(function (err, replies) {
+ console.log(replies); // 102, 3
+ client.quit();
+ });
+
+In addition to adding commands to the `MULTI` queue individually, you can also pass an array
+of commands and arguments to the constructor:
+
+ var redis = require("redis"),
+ client = redis.createClient(), multi;
+
+ client.multi([
+ ["mget", "multifoo", "multibar", redis.print],
+ ["incr", "multifoo"],
+ ["incr", "multibar"]
+ ]).exec(function (err, replies) {
+ console.log(replies);
+ });
+
+
+## Monitor mode
+
+Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server
+across all client connections, including from other client libraries and other computers.
+
+After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`
+will emit a `monitor` event for every new monitor message that comes across. The callback for the
+`monitor` event takes a timestamp from the Redis server and an array of command arguments.
+
+Here is a simple example:
+
+ var client = require("redis").createClient(),
+ util = require("util");
+
+ client.monitor(function (err, res) {
+ console.log("Entering monitoring mode.");
+ });
+
+ client.on("monitor", function (time, args) {
+ console.log(time + ": " + util.inspect(args));
+ });
+
+
+# Extras
+
+Some other things you might like to know about.
+
+## client.server_info
+
+After the ready probe completes, the results from the INFO command are saved in the `client.server_info`
+object.
+
+The `versions` key contains an array of the elements of the version string for easy comparison.
+
+ > client.server_info.redis_version
+ '2.3.0'
+ > client.server_info.versions
+ [ 2, 3, 0 ]
+
+## redis.print()
+
+A handy callback function for displaying return values when testing. Example:
+
+ var redis = require("redis"),
+ client = redis.createClient();
+
+ client.on("connect", function () {
+ client.set("foo_rand000000000000", "some fantastic value", redis.print);
+ client.get("foo_rand000000000000", redis.print);
+ });
+
+This will print:
+
+ Reply: OK
+ Reply: some fantastic value
+
+Note that this program will not exit cleanly because the client is still connected.
+
+## redis.debug_mode
+
+Boolean to enable debug mode and protocol tracing.
+
+ var redis = require("redis"),
+ client = redis.createClient();
+
+ redis.debug_mode = true;
+
+ client.on("connect", function () {
+ client.set("foo_rand000000000000", "some fantastic value");
+ });
+
+This will display:
+
+ mjr:~/work/node_redis (master)$ node ~/example.js
+ send command: *3
+ $3
+ SET
+ $20
+ foo_rand000000000000
+ $20
+ some fantastic value
+
+ on_data: +OK
+
+`send command` is data sent into Redis and `on_data` is data received from Redis.
+
+## client.send_command(command_name, args, callback)
+
+Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis
+Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before
+this library is updated, you can use `send_command()` to send arbitrary commands to Redis.
+
+All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or individual arguments,
+or omitted completely.
+
+## client.connected
+
+Boolean tracking the state of the connection to the Redis server.
+
+## client.command_queue.length
+
+The number of commands that have been sent to the Redis server but not yet replied to. You can use this to
+enforce some kind of maximum queue depth for commands while connected.
+
+Don't mess with `client.command_queue` though unless you really know what you are doing.
+
+## client.offline_queue.length
+
+The number of commands that have been queued up for a future connection. You can use this to enforce
+some kind of maximum queue depth for pre-connection commands.
+
+## client.retry_delay
+
+Current delay in milliseconds before a connection retry will be attempted. This starts at `250`.
+
+## client.retry_backoff
+
+Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries.
+Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.
+
+
+## TODO
+
+Better tests for monitor mode, auth, disconnect/reconnect, and all combinations thereof.
+
+Stream large set/get values into and out of Redis. Otherwise the entire value must be in node's memory.
+
+Performance can be better for very large values.
+
+I think there are more performance improvements left in there for smaller values, especially for large lists of small values.
+
+## Contributors
+
+Some people have have added features and fixed bugs in `node_redis` other than me.
+
+In order of first contribution, they are:
+
+* [Tim Smart](https://github.com/Tim-Smart)
+* [TJ Holowaychuk](https://github.com/visionmedia)
+* [Rick Olson](https://github.com/technoweenie)
+* [Orion Henry](https://github.com/orionz)
+* [Hank Sims](https://github.com/hanksims)
+* [Aivo Paas](https://github.com/aivopaas)
+* [Paul Carey](https://github.com/paulcarey)
+* [Pieter Noordhuis](https://github.com/pietern)
+* [Vladimir Dronnikov](https://github.com/dvv)
+* [Dave Hoover](https://github.com/redsquirrel)
+
+Thanks.
+
+## LICENSE - "MIT License"
+
+Copyright (c) 2010 Matthew Ranney, http://ranney.com/
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+![spacer](http://ranney.com/1px.gif)
View
210 node_modules/redis/changelog.md
@@ -0,0 +1,210 @@
+Changelog
+=========
+
+## v0.7.1 - November 15, 2011
+
+Fix regression in reconnect logic.
+
+Very much need automated tests for reconnection and queue logic.
+
+## v0.7.0 - November 14, 2011
+
+Many contributed fixes. Thanks everybody.
+
+* [GH-127] - properly re-initialize parser on reconnect
+* [GH-136] - handle passing undefined as callback (Ian Babrou)
+* [GH-139] - properly handle exceptions thrown in pub/sub event handlers (Felix Geisendörfer)
+* [GH-141] - detect closing state on stream error (Felix Geisendörfer)
+* [GH-142] - re-select database on reconnection (Jean-Hugues Pinson)
+* [GH-146] - add sort example (Maksim Lin)
+
+Some more goodies:
+
+* Fix bugs with node 0.6
+* Performance improvements
+* New version of `multi_bench.js` that tests more realistic scenarios
+* [GH-140] - support optional callback for subscribe commands
+* Properly flush and error out command queue when connection fails
+* Initial work on reconnection thresholds
+
+## v0.6.7 - July 30, 2011
+
+(accidentally skipped v0.6.6)
+
+Fix and test for [GH-123]
+
+Passing an Array as as the last argument should expand as users
+expect. The old behavior was to coerce the arguments into Strings,
+which did surprising things with Arrays.
+
+## v0.6.5 - July 6, 2011
+
+Contributed changes:
+
+* Support SlowBuffers (Umair Siddique)
+* Add Multi to exports (Louis-Philippe Perron)
+* Fix for drain event calculation (Vladimir Dronnikov)
+
+Thanks!
+
+## v0.6.4 - June 30, 2011
+
+Fix bug with optional callbacks for hmset.
+
+## v0.6.2 - June 30, 2011
+
+Bugs fixed:
+
+* authentication retry while server is loading db (danmaz74) [GH-101]
+* command arguments processing issue with arrays
+
+New features:
+
+* Auto update of new commands from redis.io (Dave Hoover)
+* Performance improvements and backpressure controls.
+* Commands now return the true/false value from the underlying socket write(s).
+* Implement command_queue high water and low water for more better control of queueing.
+
+See `examples/backpressure_drain.js` for more information.
+
+## v0.6.1 - June 29, 2011
+
+Add support and tests for Redis scripting through EXEC command.
+
+Bug fix for monitor mode. (forddg)
+
+Auto update of new commands from redis.io (Dave Hoover)
+
+## v0.6.0 - April 21, 2011
+
+Lots of bugs fixed.
+
+* connection error did not properly trigger reconnection logic [GH-85]
+* client.hmget(key, [val1, val2]) was not expanding properly [GH-66]
+* client.quit() while in pub/sub mode would throw an error [GH-87]
+* client.multi(['hmset', 'key', {foo: 'bar'}]) fails [GH-92]
+* unsubscribe before subscribe would make things very confused [GH-88]
+* Add BRPOPLPUSH [GH-79]
+
+## v0.5.11 - April 7, 2011
+
+Added DISCARD
+
+I originally didn't think DISCARD would do anything here because of the clever MULTI interface, but somebody
+pointed out to me that DISCARD can be used to flush the WATCH set.
+
+## v0.5.10 - April 6, 2011
+
+Added HVALS
+
+## v0.5.9 - March 14, 2011
+
+Fix bug with empty Array arguments - Andy Ray
+
+## v0.5.8 - March 14, 2011
+
+Add `MONITOR` command and special monitor command reply parsing.
+
+## v0.5.7 - February 27, 2011
+
+Add magical auth command.
+
+Authentication is now remembered by the client and will be automatically sent to the server
+on every connection, including any reconnections.
+
+## v0.5.6 - February 22, 2011
+
+Fix bug in ready check with `return_buffers` set to `true`.
+
+Thanks to Dean Mao and Austin Chau.
+
+## v0.5.5 - February 16, 2011
+
+Add probe for server readiness.
+
+When a Redis server starts up, it might take a while to load the dataset into memory.
+During this time, the server will accept connections, but will return errors for all non-INFO
+commands. Now node_redis will send an INFO command whenever it connects to a server.
+If the info command indicates that the server is not ready, the client will keep trying until
+the server is ready. Once it is ready, the client will emit a "ready" event as well as the
+"connect" event. The client will queue up all commands sent before the server is ready, just
+like it did before. When the server is ready, all offline/non-ready commands will be replayed.
+This should be backward compatible with previous versions.
+
+To disable this ready check behavior, set `options.no_ready_check` when creating the client.
+
+As a side effect of this change, the key/val params from the info command are available as
+`client.server_options`. Further, the version string is decomposed into individual elements
+in `client.server_options.versions`.
+
+## v0.5.4 - February 11, 2011
+
+Fix excess memory consumption from Queue backing store.
+
+Thanks to Gustaf Sjöberg.
+
+## v0.5.3 - February 5, 2011
+
+Fix multi/exec error reply callback logic.
+
+Thanks to Stella Laurenzo.
+
+## v0.5.2 - January 18, 2011
+
+Fix bug where unhandled error replies confuse the parser.
+
+## v0.5.1 - January 18, 2011
+
+Fix bug where subscribe commands would not handle redis-server startup error properly.
+
+## v0.5.0 - December 29, 2010
+
+Some bug fixes:
+
+* An important bug fix in reconnection logic. Previously, reply callbacks would be invoked twice after
+ a reconnect.
+* Changed error callback argument to be an actual Error object.
+
+New feature:
+
+* Add friendly syntax for HMSET using an object.
+
+## v0.4.1 - December 8, 2010
+
+Remove warning about missing hiredis. You probably do want it though.
+
+## v0.4.0 - December 5, 2010
+
+Support for multiple response parsers and hiredis C library from Pieter Noordhuis.
+Return Strings instead of Buffers by default.
+Empty nested mb reply bug fix.
+
+## v0.3.9 - November 30, 2010
+
+Fix parser bug on failed EXECs.
+
+## v0.3.8 - November 10, 2010
+
+Fix for null MULTI response when WATCH condition fails.
+
+## v0.3.7 - November 9, 2010
+
+Add "drain" and "idle" events.
+
+## v0.3.6 - November 3, 2010
+
+Add all known Redis commands from Redis master, even ones that are coming in 2.2 and beyond.
+
+Send a friendlier "error" event message on stream errors like connection refused / reset.
+
+## v0.3.5 - October 21, 2010
+
+A few bug fixes.
+
+* Fixed bug with `nil` multi-bulk reply lengths that showed up with `BLPOP` timeouts.
+* Only emit `end` once when connection goes away.
+* Fixed bug in `test.js` where driver finished before all tests completed.
+
+## unversioned wasteland
+
+See the git history for what happened before.
View
5 node_modules/redis/examples/auth.js
@@ -0,0 +1,5 @@
+var redis = require("redis"),
+ client = redis.createClient();
+
+// This command is magical. Client stashes the password and will issue on every connect.
+client.auth("somepass");
View
33 node_modules/redis/examples/backpressure_drain.js
@@ -0,0 +1,33 @@
+var redis = require("../index"),
+ client = redis.createClient(null, null, {
+ command_queue_high_water: 5,
+ command_queue_low_water: 1
+ }),
+ remaining_ops = 100000, paused = false;
+
+function op() {
+ if (remaining_ops <= 0) {
+ console.error("Finished.");
+ process.exit(0);
+ }
+
+ remaining_ops--;
+ if (client.hset("test hash", "val " + remaining_ops, remaining_ops) === false) {
+ console.log("Pausing at " + remaining_ops);
+ paused = true;
+ } else {
+ process.nextTick(op);
+ }
+}
+
+client.on("drain", function () {
+ if (paused) {
+ console.log("Resuming at " + remaining_ops);
+ paused = false;
+ process.nextTick(op);
+ } else {
+ console.log("Got drain while not paused at " + remaining_ops);
+ }
+});
+
+op();
View
9 node_modules/redis/examples/eval.js
@@ -0,0 +1,9 @@
+var redis = require("./index"),
+ client = redis.createClient();
+
+redis.debug_mode = true;
+
+client.eval("return 100.5", 0, function (err, res) {
+ console.dir(err);
+ console.dir(res);
+});
View
24 node_modules/redis/examples/extend.js
@@ -0,0 +1,24 @@
+var redis = require("redis"),
+ client = redis.createClient();
+
+// Extend the RedisClient prototype to add a custom method
+// This one converts the results from "INFO" into a JavaScript Object
+
+redis.RedisClient.prototype.parse_info = function (callback) {
+ this.info(function (err, res) {
+ var lines = res.toString().split("\r\n").sort();
+ var obj = {};
+ lines.forEach(function (line) {
+ var parts = line.split(':');
+ if (parts[1]) {
+ obj[parts[0]] = parts[1];
+ }
+ });
+ callback(obj)
+ });
+};
+
+client.parse_info(function (info) {
+ console.dir(info);
+ client.quit();
+});
View
32 node_modules/redis/examples/file.js
@@ -0,0 +1,32 @@
+// Read a file from disk, store it in Redis, then read it back from Redis.
+
+var redis = require("redis"),
+ client = redis.createClient(),
+ fs = require("fs"),
+ filename = "kids_in_cart.jpg";
+
+// Get the file I use for testing like this:
+// curl http://ranney.com/kids_in_cart.jpg -o kids_in_cart.jpg
+// or just use your own file.
+
+// Read a file from fs, store it in Redis, get it back from Redis, write it back to fs.
+fs.readFile(filename, function (err, data) {
+ if (err) throw err
+ console.log("Read " + data.length + " bytes from filesystem.");
+
+ client.set(filename, data, redis.print); // set entire file
+ client.get(filename, function (err, reply) { // get entire file
+ if (err) {
+ console.log("Get error: " + err);
+ } else {
+ fs.writeFile("duplicate_" + filename, reply, function (err) {
+ if (err) {
+ console.log("Error on write: " + err)
+ } else {
+ console.log("File written.");
+ }
+ client.end();
+ });
+ }
+ });
+});
View
5 node_modules/redis/examples/mget.js
@@ -0,0 +1,5 @@
+var client = require("redis").createClient();
+
+client.mget(["sessions started", "sessions started", "foo"], function (err, res) {
+ console.dir(res);
+});
View
10 node_modules/redis/examples/monitor.js
@@ -0,0 +1,10 @@
+var client = require("../index").createClient(),
+ util = require("util");
+
+client.monitor(function (err, res) {
+ console.log("Entering monitoring mode.");
+});
+
+client.on("monitor", function (time, args) {
+ console.log(time + ": " + util.inspect(args));
+});
View
46 node_modules/redis/examples/multi.js
@@ -0,0 +1,46 @@
+var redis = require("redis"),
+ client = redis.createClient(), set_size = 20;
+
+client.sadd("bigset", "a member");
+client.sadd("bigset", "another member");
+
+while (set_size > 0) {
+ client.sadd("bigset", "member " + set_size);
+ set_size -= 1;
+}
+
+// multi chain with an individual callback
+client.multi()
+ .scard("bigset")
+ .smembers("bigset")
+ .keys("*", function (err, replies) {
+ client.mget(replies, redis.print);
+ })
+ .dbsize()
+ .exec(function (err, replies) {
+ console.log("MULTI got " + replies.length + " replies");
+ replies.forEach(function (reply, index) {
+ console.log("Reply " + index + ": " + reply.toString());
+ });
+ });
+
+client.mset("incr thing", 100, "incr other thing", 1, redis.print);
+
+// start a separate multi command queue
+var multi = client.multi();
+multi.incr("incr thing", redis.print);
+multi.incr("incr other thing", redis.print);
+
+// runs immediately
+client.get("incr thing", redis.print); // 100
+
+// drains multi queue and runs atomically
+multi.exec(function (err, replies) {
+ console.log(replies); // 101, 2
+});
+
+// you can re-run the same transaction if you like
+multi.exec(function (err, replies) {
+ console.log(replies); // 102, 3
+ client.quit();
+});
View
29 node_modules/redis/examples/multi2.js
@@ -0,0 +1,29 @@
+var redis = require("redis"),
+ client = redis.createClient(), multi;
+
+// start a separate command queue for multi
+multi = client.multi();
+multi.incr("incr thing", redis.print);
+multi.incr("incr other thing", redis.print);
+
+// runs immediately
+client.mset("incr thing", 100, "incr other thing", 1, redis.print);
+
+// drains multi queue and runs atomically
+multi.exec(function (err, replies) {
+ console.log(replies); // 101, 2
+});
+
+// you can re-run the same transaction if you like
+multi.exec(function (err, replies) {
+ console.log(replies); // 102, 3
+ client.quit();
+});
+
+client.multi([
+ ["mget", "multifoo", "multibar", redis.print],
+ ["incr", "multifoo"],
+ ["incr", "multibar"]
+]).exec(function (err, replies) {
+ console.log(replies.toString());
+});
View
33 node_modules/redis/examples/psubscribe.js
@@ -0,0 +1,33 @@
+var redis = require("redis"),
+ client1 = redis.createClient(),
+ client2 = redis.createClient(),
+ client3 = redis.createClient(),
+ client4 = redis.createClient(),
+ msg_count = 0;
+
+redis.debug_mode = false;
+
+client1.on("psubscribe", function (pattern, count) {
+ console.log("client1 psubscribed to " + pattern + ", " + count + " total subscriptions");
+ client2.publish("channeltwo", "Me!");
+ client3.publish("channelthree", "Me too!");
+ client4.publish("channelfour", "And me too!");
+});
+
+client1.on("punsubscribe", function (pattern, count) {
+ console.log("client1 punsubscribed from " + pattern + ", " + count + " total subscriptions");
+ client4.end();
+ client3.end();
+ client2.end();
+ client1.end();
+});
+
+client1.on("pmessage", function (pattern, channel, message) {
+ console.log("("+ pattern +")" + " client1 received message on " + channel + ": " + message);
+ msg_count += 1;
+ if (msg_count === 3) {
+ client1.punsubscribe();
+ }
+});
+
+client1.psubscribe("channel*");
View
41 node_modules/redis/examples/pub_sub.js
@@ -0,0 +1,41 @@
+var redis = require("redis"),
+ client1 = redis.createClient(), msg_count = 0,
+ client2 = redis.createClient();
+
+redis.debug_mode = false;
+
+// Most clients probably don't do much on "subscribe". This example uses it to coordinate things within one program.
+client1.on("subscribe", function (channel, count) {
+ console.log("client1 subscribed to " + channel + ", " + count + " total subscriptions");
+ if (count === 2) {
+ client2.publish("a nice channel", "I am sending a message.");
+ client2.publish("another one", "I am sending a second message.");
+ client2.publish("a nice channel", "I am sending my last message.");
+ }
+});
+
+client1.on("unsubscribe", function (channel, count) {
+ console.log("client1 unsubscribed from " + channel + ", " + count + " total subscriptions");
+ if (count === 0) {
+ client2.end();
+ client1.end();
+ }
+});
+
+client1.on("message", function (channel, message) {
+ console.log("client1 channel " + channel + ": " + message);
+ msg_count += 1;
+ if (msg_count === 3) {
+ client1.unsubscribe();
+ }
+});
+
+client1.on("ready", function () {
+ // if you need auth, do it here
+ client1.incr("did a thing");
+ client1.subscribe("a nice channel", "another one");
+});
+
+client2.on("ready", function () {
+ // if you need auth, do it here
+});
View
24 node_modules/redis/examples/simple.js
@@ -0,0 +1,24 @@
+var redis = require("redis"),
+ client = redis.createClient();
+
+client.on("error", function (err) {
+ console.log("error event - " + client.host + ":" + client.port + " - " + err);
+});
+
+client.set("string key", "string val", redis.print);
+client.hset("hash key", "hashtest 1", "some value", redis.print);
+client.hset(["hash key", "hashtest 2", "some other value"], redis.print);
+client.hkeys("hash key", function (err, replies) {
+ if (err) {
+ return console.error("error response - " + err);
+ }
+
+ console.log(replies.length + " replies:");
+ replies.forEach(function (reply, i) {
+ console.log(" " + i + ": " + reply);
+ });
+});
+
+client.quit(function (err, res) {
+ console.log("Exiting from quit command.");
+});
View
17 node_modules/redis/examples/sort.js
@@ -0,0 +1,17 @@
+var redis = require("redis"),
+ client = redis.createClient();
+
+client.sadd("mylist", 1);
+client.sadd("mylist", 2);
+client.sadd("mylist", 3);
+
+client.set("weight_1", 5);
+client.set("weight_2", 500);
+client.set("weight_3", 1);
+
+client.set("object_1", "foo");
+client.set("object_2", "bar");
+client.set("object_3", "qux");
+
+client.sort("mylist", "by", "weight_*", "get", "object_*", redis.print);
+// Prints Reply: qux,foo,bar
View
15 node_modules/redis/examples/subqueries.js
@@ -0,0 +1,15 @@
+// Sending commands in response to other commands.
+// This example runs "type" against every key in the database
+//
+var client = require("redis").createClient();
+
+client.keys("*", function (err, keys) {
+ keys.forEach(function (key, pos) {
+ client.type(key, function (err, keytype) {
+ console.log(key + " is " + keytype);
+ if (pos === (keys.length - 1)) {
+ client.quit();
+ }
+ });
+ });
+});
View
19 node_modules/redis/examples/subquery.js
@@ -0,0 +1,19 @@
+var client = require("redis").createClient();
+
+function print_results(obj) {
+ console.dir(obj);
+}
+
+// build a map of all keys and their types
+client.keys("*", function (err, all_keys) {
+ var key_types = {};
+
+ all_keys.forEach(function (key, pos) { // use second arg of forEach to get pos
+ client.type(key, function (err, type) {
+ key_types[key] = type;
+ if (pos === all_keys.length - 1) { // callbacks all run in order
+ print_results(key_types);
+ }
+ });
+ });
+});
View
29 node_modules/redis/examples/unix_socket.js
@@ -0,0 +1,29 @@
+var redis = require("redis"),
+ client = redis.createClient("/tmp/redis.sock"),
+ profiler = require("v8-profiler");
+
+client.on("connect", function () {
+ console.log("Got Unix socket connection.")
+});
+
+client.on("error", function (err) {
+ console.log(err.message);
+});
+
+client.set("space chars", "space value");
+
+setInterval(function () {
+ client.get("space chars");
+}, 100);
+
+function done() {
+ client.info(function (err, reply) {
+ console.log(reply.toString());
+ client.quit();
+ });
+}
+
+setTimeout(function () {
+ console.log("Taking snapshot.");
+ var snap = profiler.takeSnapshot();
+}, 5000);
View
31 node_modules/redis/examples/web_server.js
@@ -0,0 +1,31 @@
+// A simple web server that generates dyanmic content based on responses from Redis
+
+var http = require("http"), server,
+ redis_client = require("redis").createClient();
+
+server = http.createServer(function (request, response) {
+ response.writeHead(200, {
+ "Content-Type": "text/plain"
+ });
+
+ var redis_info, total_requests;
+
+ redis_client.info(function (err, reply) {
+ redis_info = reply; // stash response in outer scope
+ });
+ redis_client.incr("requests", function (err, reply) {
+ total_requests = reply; // stash response in outer scope
+ });
+ redis_client.hincrby("ip", request.connection.remoteAddress, 1);
+ redis_client.hgetall("ip", function (err, reply) {
+ // This is the last reply, so all of the previous replies must have completed already
+ response.write("This page was generated after talking to redis.\n\n" +
+ "Redis info:\n" + redis_info + "\n" +
+ "Total requests: " + total_requests + "\n\n" +
+ "IP count: \n");
+ Object.keys(reply).forEach(function (ip) {
+ response.write(" " + ip + ": " + reply[ip] + "\n");
+ });
+ response.end();
+ });
+}).listen(80);
View
39 node_modules/redis/generate_commands.js
@@ -0,0 +1,39 @@
+var http = require("http"),
+ fs = require("fs");
+
+function prettyCurrentTime() {
+ var date = new Date();
+ return date.toLocaleString();
+}
+
+function write_file(commands, path) {
+ var file_contents, out_commands;
+
+ console.log("Writing " + Object.keys(commands).length + " commands to " + path);
+
+ file_contents = "// This file was generated by ./generate_commands.js on " + prettyCurrentTime() + "\n";
+
+ out_commands = Object.keys(commands).map(function (key) {
+ return key.toLowerCase();
+ });
+
+ file_contents += "module.exports = " + JSON.stringify(out_commands, null, " ") + ";\n";
+
+ fs.writeFile(path, file_contents);
+}
+
+http.get({host: "redis.io", path: "/commands.json"}, function (res) {
+ var body = "";
+
+ console.log("Response from redis.io/commands.json: " + res.statusCode);
+
+ res.on('data', function (chunk) {
+ body += chunk;
+ });
+
+ res.on('end', function () {
+ write_file(JSON.parse(body), "lib/commands.js");
+ });
+}).on('error', function (e) {
+ console.log("Error fetching command list from redis.io: " + e.message);
+});
View
955 node_modules/redis/index.js
@@ -0,0 +1,955 @@
+/*global Buffer require exports console setTimeout */
+
+var net = require("net"),
+ util = require("./lib/util").util,
+ Queue = require("./lib/queue").Queue,
+ to_array = require("./lib/to_array"),
+ events = require("events"),
+ parsers = [], commands,
+ connection_id = 0,
+ default_port = 6379,
+ default_host = "127.0.0.1";
+
+// can set this to true to enable for all connections
+exports.debug_mode = false;
+
+// hiredis might not be installed
+try {
+ require("./lib/parser/hiredis");
+ parsers.push(require("./lib/parser/hiredis"));
+} catch (err) {
+ if (exports.debug_mode) {
+ console.warn("hiredis parser not installed.");
+ }
+}
+
+parsers.push(require("./lib/parser/javascript"));
+
+function RedisClient(stream, options) {
+ this.stream = stream;
+ this.options = options = options || {};
+
+ this.connection_id = ++connection_id;
+ this.connected = false;
+ this.ready = false;
+ this.connections = 0;
+ this.should_buffer = false;
+ this.command_queue_high_water = this.options.command_queue_high_water || 1000;
+ this.command_queue_low_water = this.options.command_queue_low_water || 0;
+ this.max_attempts = null;
+ if (options.max_attempts && !isNaN(options.max_attempts) && options.max_attempts > 0) {
+ this.max_attempts = +options.max_attempts;
+ }
+ this.command_queue = new Queue(); // holds sent commands to de-pipeline them
+ this.offline_queue = new Queue(); // holds commands issued but not able to be sent
+ this.commands_sent = 0;
+ this.connect_timeout = false;
+ if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) {
+ this.connect_timeout = +options.connect_timeout;
+ }
+ this.initialize_retry_vars();
+ this.subscriptions = false;
+ this.monitoring = false;
+ this.closing = false;
+ this.server_info = {};
+ this.auth_pass = null;
+ this.parser_module = null;
+ this.selected_db = null; // save the selected db here, used when reconnecting
+
+ var self = this;
+
+ this.stream.on("connect", function () {
+ self.on_connect();
+ });
+
+ this.stream.on("data", function (buffer_from_socket) {
+ self.on_data(buffer_from_socket);
+ });
+
+ this.stream.on("error", function (msg) {
+ self.on_error(msg.message);
+ });
+
+ this.stream.on("close", function () {
+ self.connection_gone("close");
+ });
+
+ this.stream.on("end", function () {
+ self.connection_gone("end");
+ });
+
+ this.stream.on("drain", function () {
+ self.should_buffer = false;
+ self.emit("drain");
+ });
+
+ events.EventEmitter.call(this);
+}
+util.inherits(RedisClient, events.EventEmitter);
+exports.RedisClient = RedisClient;
+
+RedisClient.prototype.initialize_retry_vars = function () {
+ this.retry_timer = null;
+ this.retry_totaltime = 0;
+ this.retry_delay = 250;
+ this.retry_backoff = 1.7;
+ this.attempts = 1;
+};
+
+// flush offline_queue and command_queue, erroring any items with a callback first
+RedisClient.prototype.flush_and_error = function (message) {
+ var command_obj;
+ while (this.offline_queue.length > 0) {
+ command_obj = this.offline_queue.shift();
+ if (typeof command_obj.callback === "function") {
+ command_obj.callback(message);
+ }
+ }
+ this.offline_queue = new Queue();
+
+ while (this.command_queue.length > 0) {
+ command_obj = this.command_queue.shift();
+ if (typeof command_obj.callback === "function") {
+ command_obj.callback(message);
+ }
+ }
+ this.command_queue = new Queue();
+};
+
+RedisClient.prototype.on_error = function (msg) {
+ var message = "Redis connection to " + this.host + ":" + this.port + " failed - " + msg,
+ self = this, command_obj;
+
+ if (this.closing) {
+ return;
+ }
+
+ if (exports.debug_mode) {
+ console.warn(message);
+ }
+
+ this.flush_and_error(message);
+
+ this.connected = false;
+ this.ready = false;
+
+ this.emit("error", new Error(message));
+ // "error" events get turned into exceptions if they aren't listened for. If the user handled this error
+ // then we should try to reconnect.
+ this.connection_gone("error");
+};
+
+RedisClient.prototype.do_auth = function () {
+ var self = this;
+
+ if (exports.debug_mode) {
+ console.log("Sending auth to " + self.host + ":" + self.port + " id " + self.connection_id);
+ }
+ self.send_anyway = true;
+ self.send_command("auth", [this.auth_pass], function (err, res) {
+ if (err) {
+ if (err.toString().match("LOADING")) {
+ // if redis is still loading the db, it will not authenticate and everything else will fail
+ console.log("Redis still loading, trying to authenticate later");
+ setTimeout(function () {
+ self.do_auth();
+ }, 2000); // TODO - magic number alert
+ return;
+ } else {
+ return self.emit("error", "Auth error: " + err);
+ }
+ }
+ if (res.toString() !== "OK") {
+ return self.emit("error", "Auth failed: " + res.toString());
+ }
+ if (exports.debug_mode) {
+ console.log("Auth succeeded " + self.host + ":" + self.port + " id " + self.connection_id);
+ }
+ if (self.auth_callback) {
+ self.auth_callback(err, res);
+ self.auth_callback = null;
+ }
+
+ // restore the selected db if needed
+ if (self.selected_db !== null) {
+ self.send_command('select', [self.selected_db]);
+ }
+
+ // now we are really connected
+ self.emit("connect");
+ if (self.options.no_ready_check) {
+ self.ready = true;
+ self.send_offline_queue();
+ } else {
+ self.ready_check();
+ }
+ });
+ self.send_anyway = false;
+};
+
+RedisClient.prototype.on_connect = function () {
+ if (exports.debug_mode) {
+ console.log("Stream connected " + this.host + ":" + this.port + " id " + this.connection_id);
+ }
+ var self = this;
+
+ this.connected = true;
+ this.ready = false;
+ this.attempts = 0;
+ this.connections += 1;
+ this.command_queue = new Queue();
+ this.emitted_end = false;
+ this.initialize_retry_vars();
+ this.stream.setNoDelay();
+ this.stream.setTimeout(0);
+
+ this.init_parser();
+
+ if (this.auth_pass) {
+ this.do_auth();
+ } else {
+ // restore the selected db if needed
+ if (this.selected_db !== null) {
+ this.send_command('select', [this.selected_db]);
+ }
+
+ this.emit("connect");
+
+ if (this.options.no_ready_check) {
+ this.ready = true;
+ this.send_offline_queue();
+ } else {
+ this.ready_check();
+ }
+ }
+};
+
+RedisClient.prototype.init_parser = function () {
+ var self = this;
+
+ if (this.options.parser) {
+ if (! parsers.some(function (parser) {
+ if (parser.name === self.options.parser) {
+ this.parser_module = parser;
+ if (exports.debug_mode) {
+ console.log("Using parser module: " + self.parser_module.name);
+ }
+ return true;
+ }
+ })) {
+ throw new Error("Couldn't find named parser " + self.options.parser + " on this system");
+ }
+ } else {
+ if (exports.debug_mode) {
+ console.log("Using default parser module: " + parsers[0].name);
+ }
+ this.parser_module = parsers[0];
+ }
+
+ this.parser_module.debug_mode = exports.debug_mode;
+
+ this.reply_parser = new this.parser_module.Parser({
+ return_buffers: self.options.return_buffers || false
+ });
+ // "reply error" is an error sent back by Redis
+ this.reply_parser.on("reply error", function (reply) {
+ self.return_error(new Error(reply));
+ });
+ this.reply_parser.on("reply", function (reply) {
+ self.return_reply(reply);
+ });
+ // "error" is bad. Somehow the parser got confused. It'll try to reset and continue.
+ this.reply_parser.on("error", function (err) {
+ self.emit("error", new Error("Redis reply parser error: " + err.stack));
+ });
+};
+
+RedisClient.prototype.on_info_cmd = function (err, res) {
+ var self = this, obj = {}, lines, retry_time;
+
+ if (err) {
+ return self.emit("error", "Ready check failed: " + err);
+ }
+
+ lines = res.toString().split("\r\n");
+
+ lines.forEach(function (line) {
+ var parts = line.split(':');
+ if (parts[1]) {
+ obj[parts[0]] = parts[1];
+ }
+ });
+
+ obj.versions = [];
+ obj.redis_version.split('.').forEach(function (num) {
+ obj.versions.push(+num);
+ });
+
+ // expose info key/vals to users
+ this.server_info = obj;
+
+ if (!obj.loading || (obj.loading && obj.loading === "0")) {
+ if (exports.debug_mode) {
+ console.log("Redis server ready.");
+ }
+ this.ready = true;
+
+ this.send_offline_queue();
+ this.emit("ready");
+ } else {
+ retry_time = obj.loading_eta_seconds * 1000;
+ if (retry_time > 1000) {
+ retry_time = 1000;
+ }
+ if (exports.debug_mode) {
+ console.log("Redis server still loading, trying again in " + retry_time);
+ }
+ setTimeout(function () {
+ self.ready_check();
+ }, retry_time);
+ }
+};
+
+RedisClient.prototype.ready_check = function () {
+ var self = this;
+
+ if (exports.debug_mode) {
+ console.log("checking server ready state...");
+ }
+
+ this.send_anyway = true; // secret flag to send_command to send something even if not "ready"
+ this.info(function (err, res) {
+ self.on_info_cmd(err, res);
+ });
+ this.send_anyway = false;
+};
+
+RedisClient.prototype.send_offline_queue = function () {
+ var command_obj, buffered_writes = 0;
+ while (this.offline_queue.length > 0) {
+ command_obj = this.offline_queue.shift();
+ if (exports.debug_mode) {
+ console.log("Sending offline command: " + command_obj.command);
+ }
+ buffered_writes += !this.send_command(command_obj.command, command_obj.args, command_obj.callback);
+ }
+ this.offline_queue = new Queue();
+ // Even though items were shifted off, Queue backing store still uses memory until next add, so just get a new Queue
+
+ if (!buffered_writes) {
+ this.should_buffer = false;
+ this.emit("drain");
+ }
+};
+
+RedisClient.prototype.connection_gone = function (why) {
+ var self = this, message;
+
+ // If a retry is already in progress, just let that happen
+ if (this.retry_timer) {
+ return;
+ }
+
+ if (exports.debug_mode) {
+ console.warn("Redis connection is gone from " + why + " event.");
+ }
+ this.connected = false;
+ this.ready = false;
+ this.subscriptions = false;
+ this.monitoring = false;
+
+ // since we are collapsing end and close, users don't expect to be called twice
+ if (! this.emitted_end) {
+ this.emit("end");
+ this.emitted_end = true;
+ }
+
+ this.flush_and_error("Redis connection gone from " + why + " event.");
+
+ // If this is a requested shutdown, then don't retry
+ if (this.closing) {
+ this.retry_timer = null;
+ if (exports.debug_mode) {
+ console.warn("connection ended from quit command, not retrying.");
+ }
+ return;
+ }
+
+ this.retry_delay = Math.floor(this.retry_delay * this.retry_backoff);
+
+ if (exports.debug_mode) {
+ console.log("Retry connection in " + this.current_retry_delay + " ms");
+ }
+
+ if (this.max_attempts && this.attempts >= this.max_attempts) {
+ this.retry_timer = null;
+ // TODO - some people need a "Redis is Broken mode" for future commands that errors immediately, and others
+ // want the program to exit. Right now, we just log, which doesn't really help in either case.
+ console.error("node_redis: Couldn't get Redis connection after " + this.max_attempts + " attempts.");
+ return;
+ }
+
+ this.attempts += 1;
+ this.emit("reconnecting", {
+ delay: self.retry_delay,
+ attempt: self.attempts
+ });
+ this.retry_timer = setTimeout(function () {
+ if (exports.debug_mode) {
+ console.log("Retrying connection...");
+ }
+
+ self.retry_totaltime += self.current_retry_delay;
+
+ if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) {
+ self.retry_timer = null;
+ // TODO - engage Redis is Broken mode for future commands, or whatever
+ console.error("node_redis: Couldn't get Redis connection after " + self.retry_totaltime + "ms.");
+ return;
+ }
+
+ self.stream.connect(self.port, self.host);
+ self.retry_timer = null;
+ }, this.retry_delay);
+};
+
+RedisClient.prototype.on_data = function (data) {
+ if (exports.debug_mode) {
+ console.log("net read " + this.host + ":" + this.port + " id " + this.connection_id + ": " + data.toString());
+ }
+
+ try {
+ this.reply_parser.execute(data);
+ } catch (err) {
+ // This is an unexpected parser problem, an exception that came from the parser code itself.
+ // Parser should emit "error" events if it notices things are out of whack.
+ // Callbacks that throw exceptions will land in return_reply(), below.
+ // TODO - it might be nice to have a different "error" event for different types of errors
+ this.emit("error", err);
+ }
+};
+
+RedisClient.prototype.return_error = function (err) {
+ var command_obj = this.command_queue.shift(), queue_len = this.command_queue.getLength();
+
+ if (this.subscriptions === false && queue_len === 0) {
+ this.emit("idle");
+ this.command_queue = new Queue();
+ }
+ if (this.should_buffer && queue_len <= this.command_queue_low_water) {
+ this.emit("drain");
+ this.should_buffer = false;
+ }
+
+ if (command_obj && typeof command_obj.callback === "function") {
+ try {
+ command_obj.callback(err);
+ } catch (callback_err) {
+ // if a callback throws an exception, re-throw it on a new stack so the parser can keep going
+ process.nextTick(function () {
+ throw callback_err;
+ });
+ }
+ } else {
+ console.log("node_redis: no callback to send error: " + err.message);
+ // this will probably not make it anywhere useful, but we might as well throw
+ process.nextTick(function () {
+ throw err;
+ });
+ }
+};
+
+// if a callback throws an exception, re-throw it on a new stack so the parser can keep going.
+// put this try/catch in its own function because V8 doesn't optimize this well yet.
+function try_callback(callback, reply) {
+ try {
+ callback(null, reply);
+ } catch (err) {
+ process.nextTick(function () {
+ throw err;
+ });
+ }
+}
+
+RedisClient.prototype.return_reply = function (reply) {
+ var command_obj, obj, i, len, key, val, type, timestamp, argindex, args, queue_len;
+
+ queue_len = this.command_queue.getLength();
+
+ if (this.subscriptions === false && queue_len === 0) {
+ this.emit("idle");
+ this.command_queue = new Queue(); // explicitly reclaim storage from old Queue
+ }
+ if (this.should_buffer && queue_len <= this.command_queue_low_water) {
+ this.emit("drain");
+ this.should_buffer = false;
+ }
+
+ command_obj = this.command_queue.shift();
+
+ if (command_obj && !command_obj.sub_command) {
+ if (typeof command_obj.callback === "function") {