PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 2ms app.codeStats 0ms

/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/gridfs/chunk.js

https://bitbucket.org/xinghuo/caiwu
JavaScript | 209 lines | 103 code | 17 blank | 89 comment | 33 complexity | 49d46c874ce42db71b5cde271fe17674 MD5 | raw file
Possible License(s): MIT
  1. var Binary = require('bson').Binary,
  2. ObjectID = require('bson').ObjectID;
  3. /**
  4. * Class for representing a single chunk in GridFS.
  5. *
  6. * @class
  7. *
  8. * @param file {GridStore} The {@link GridStore} object holding this chunk.
  9. * @param mongoObject {object} The mongo object representation of this chunk.
  10. *
  11. * @throws Error when the type of data field for {@link mongoObject} is not
  12. * supported. Currently supported types for data field are instances of
  13. * {@link String}, {@link Array}, {@link Binary} and {@link Binary}
  14. * from the bson module
  15. *
  16. * @see Chunk#buildMongoObject
  17. */
  18. var Chunk = exports.Chunk = function(file, mongoObject) {
  19. if(!(this instanceof Chunk)) return new Chunk(file, mongoObject);
  20. this.file = file;
  21. var self = this;
  22. var mongoObjectFinal = mongoObject == null ? {} : mongoObject;
  23. this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id;
  24. this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n;
  25. this.data = new Binary();
  26. if(mongoObjectFinal.data == null) {
  27. } else if(typeof mongoObjectFinal.data == "string") {
  28. var buffer = new Buffer(mongoObjectFinal.data.length);
  29. buffer.write(mongoObjectFinal.data, 'binary', 0);
  30. this.data = new Binary(buffer);
  31. } else if(Array.isArray(mongoObjectFinal.data)) {
  32. var buffer = new Buffer(mongoObjectFinal.data.length);
  33. buffer.write(mongoObjectFinal.data.join(''), 'binary', 0);
  34. this.data = new Binary(buffer);
  35. } else if(mongoObjectFinal.data instanceof Binary || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") {
  36. this.data = mongoObjectFinal.data;
  37. } else if(Buffer.isBuffer(mongoObjectFinal.data)) {
  38. } else {
  39. throw Error("Illegal chunk format");
  40. }
  41. // Update position
  42. this.internalPosition = 0;
  43. };
  44. /**
  45. * Writes a data to this object and advance the read/write head.
  46. *
  47. * @param data {string} the data to write
  48. * @param callback {function(*, GridStore)} This will be called after executing
  49. * this method. The first parameter will contain null and the second one
  50. * will contain a reference to this object.
  51. */
  52. Chunk.prototype.write = function(data, callback) {
  53. this.data.write(data, this.internalPosition);
  54. this.internalPosition = this.data.length();
  55. if(callback != null) return callback(null, this);
  56. return this;
  57. };
  58. /**
  59. * Reads data and advances the read/write head.
  60. *
  61. * @param length {number} The length of data to read.
  62. *
  63. * @return {string} The data read if the given length will not exceed the end of
  64. * the chunk. Returns an empty String otherwise.
  65. */
  66. Chunk.prototype.read = function(length) {
  67. // Default to full read if no index defined
  68. length = length == null || length == 0 ? this.length() : length;
  69. if(this.length() - this.internalPosition + 1 >= length) {
  70. var data = this.data.read(this.internalPosition, length);
  71. this.internalPosition = this.internalPosition + length;
  72. return data;
  73. } else {
  74. return '';
  75. }
  76. };
  77. Chunk.prototype.readSlice = function(length) {
  78. if ((this.length() - this.internalPosition + 1) >= length) {
  79. var data = null;
  80. if (this.data.buffer != null) { //Pure BSON
  81. data = this.data.buffer.slice(this.internalPosition, this.internalPosition + length);
  82. } else { //Native BSON
  83. data = new Buffer(length);
  84. length = this.data.readInto(data, this.internalPosition);
  85. }
  86. this.internalPosition = this.internalPosition + length;
  87. return data;
  88. } else {
  89. return null;
  90. }
  91. };
  92. /**
  93. * Checks if the read/write head is at the end.
  94. *
  95. * @return {boolean} Whether the read/write head has reached the end of this
  96. * chunk.
  97. */
  98. Chunk.prototype.eof = function() {
  99. return this.internalPosition == this.length() ? true : false;
  100. };
  101. /**
  102. * Reads one character from the data of this chunk and advances the read/write
  103. * head.
  104. *
  105. * @return {string} a single character data read if the the read/write head is
  106. * not at the end of the chunk. Returns an empty String otherwise.
  107. */
  108. Chunk.prototype.getc = function() {
  109. return this.read(1);
  110. };
  111. /**
  112. * Clears the contents of the data in this chunk and resets the read/write head
  113. * to the initial position.
  114. */
  115. Chunk.prototype.rewind = function() {
  116. this.internalPosition = 0;
  117. this.data = new Binary();
  118. };
  119. /**
  120. * Saves this chunk to the database. Also overwrites existing entries having the
  121. * same id as this chunk.
  122. *
  123. * @param callback {function(*, GridStore)} This will be called after executing
  124. * this method. The first parameter will contain null and the second one
  125. * will contain a reference to this object.
  126. */
  127. Chunk.prototype.save = function(callback) {
  128. var self = this;
  129. self.file.chunkCollection(function(err, collection) {
  130. collection.remove({'_id':self.objectId}, {safe:true}, function(err, result) {
  131. if(self.data.length() > 0) {
  132. self.buildMongoObject(function(mongoObject) {
  133. collection.insert(mongoObject, {safe:true}, function(err, collection) {
  134. callback(null, self);
  135. });
  136. });
  137. } else {
  138. callback(null, self);
  139. }
  140. });
  141. });
  142. };
  143. /**
  144. * Creates a mongoDB object representation of this chunk.
  145. *
  146. * @param callback {function(Object)} This will be called after executing this
  147. * method. The object will be passed to the first parameter and will have
  148. * the structure:
  149. *
  150. * <pre><code>
  151. * {
  152. * '_id' : , // {number} id for this chunk
  153. * 'files_id' : , // {number} foreign key to the file collection
  154. * 'n' : , // {number} chunk number
  155. * 'data' : , // {bson#Binary} the chunk data itself
  156. * }
  157. * </code></pre>
  158. *
  159. * @see <a href="http://www.mongodb.org/display/DOCS/GridFS+Specification#GridFSSpecification-{{chunks}}">MongoDB GridFS Chunk Object Structure</a>
  160. */
  161. Chunk.prototype.buildMongoObject = function(callback) {
  162. var mongoObject = {'_id': this.objectId,
  163. 'files_id': this.file.fileId,
  164. 'n': this.chunkNumber,
  165. 'data': this.data};
  166. callback(mongoObject);
  167. };
  168. /**
  169. * @return {number} the length of the data
  170. */
  171. Chunk.prototype.length = function() {
  172. return this.data.length();
  173. };
  174. /**
  175. * The position of the read/write head
  176. * @name position
  177. * @lends Chunk#
  178. * @field
  179. */
  180. Object.defineProperty(Chunk.prototype, "position", { enumerable: true
  181. , get: function () {
  182. return this.internalPosition;
  183. }
  184. , set: function(value) {
  185. this.internalPosition = value;
  186. }
  187. });
  188. /**
  189. * The default chunk size
  190. * @constant
  191. */
  192. Chunk.DEFAULT_CHUNK_SIZE = 1024 * 256;