memory.watch = fs.watch(source, { persistent: false }, function (event) { // TODO: what if the file was deleted? if (event !== 'change') return; var step = memory.stream.modified || 1; // refresh memoryStream memory.stream = flower.memoryStream(); memory.stream.modified = step + 1; // since there is no link between memory.relay().resume and source.resume // we will source.resume as soon as something has been piped to memory memory.stream.once('pipe', function (source) { source.resume(); }); compileSource(self, filename, source, cache, memory.stream); });
Leaflet.prototype.read = function (filename) { var self = this, output, pipelink; if (this.ready === false) { return new Error('leaflet object is not ready'); } // absolute paths will be relative to read dir filename = trimPath(filename); // resolve read and write filepath var source = path.resolve(this.options.source, filename); var cache = path.resolve(this.options.cache, filename); // check ignorefiles list if (this.ignorefiles.filepath.indexOf( filename ) !== -1 || this.ignorefiles.filename.indexOf( path.basename(filename) ) !== -1) { return streamError("ENOENT, open '" + source + "'", { errno: 34, code: 'ENOENT', path: source, ignored: true }); } // Get stores properties var cacheStat = this.state[filename]; var memory = getMemory(this, filename); // Increase request counter memory.request += 1; // Read from memory if (memory.stream && this.cacheSize) { output = this.cache[filename].stream.relay(); output.pause(); // Add stat emit to query or emit now if ready emitStat(self, filename, output, new Date(cacheStat.mtime)); return output; } // in case this file isn't cached but should be cached var memorizeFile = (!!cacheStat && resolveCache(this, memory)); if (memorizeFile) { pipelink = memory.stream = flower.memoryStream(); // since there is no link between memory.relay().resume and source.resume // we will source.resume as soon as something has been piped to memory pipelink.once('pipe', function (source) { source.resume(); }); // cleanup cache memory pipelink.once('close', function () { resolveCache(self, memory); }); // Live refresh memoryStream when source file is updated if (this.watching) { memory.watch = fs.watch(source, { persistent: false }, function (event) { // TODO: what if the file was deleted? if (event !== 'change') return; var step = memory.stream.modified || 1; // refresh memoryStream memory.stream = flower.memoryStream(); memory.stream.modified = step + 1; // since there is no link between memory.relay().resume and source.resume // we will source.resume as soon as something has been piped to memory memory.stream.once('pipe', function (source) { source.resume(); }); compileSource(self, filename, source, cache, memory.stream); }); } output = pipelink.relay(); output.pause(); } // just read from cache if (cacheStat && this.watching === false) { if (memorizeFile) { fs.createReadStream(cache, { bufferSize: chunkSize }).pipe(pipelink); } else { output = fs.createReadStream(cache, { bufferSize: chunkSize }); output.pause(); } // emit stat event to output emitStat(self, filename, output, new Date(cacheStat.mtime)); return output; } // create a relay stream since async handling will be needed if (!memorizeFile) { pipelink = output = flower.relayReadStream(); output.pause(); } // at this point some async opration will be required before the streams can be linked // set memory.inProgress flag, so mtime requests will be pushed to query if (memorizeFile) { memory.inProgress = true; emitStat(self, filename, output); } // has never read from source before or dont need to validate source if (!cacheStat || this.watching === false) { compileSource(self, filename, source, cache, pipelink); return output; } // check source file for modification fs.stat(source, function (error, stat) { if (error) { updateStat(self, filename); return pipelink.emit('error', error); } // source has been modified, read from source if (!cacheStat || stat.mtime.getTime() > cacheStat.mtime || stat.size !== cacheStat.size) { return compileSource(self, filename, source, cache, pipelink); } // stat has not changed execute query // note: this could be moved up however since compileSource can be called by // two reasons this is the simplest solution memory.inProgress = false; emitStat(self, filename, output, stat.mtime); // source has not been modified, read from cache var cacheStream = fs.createReadStream(cache, { bufferSize: chunkSize }); cacheStream.pause(); cacheStream.pipe(pipelink); }); // return relay stream, content will be relayed to this shortly return output; };