// Generated by IcedCoffeeScript 1.7.1-c
(function() {
  var Lockfile, a_json_parse, athrow, fs, get_id, iced, make_esc, prng, read_all, __iced_k, __iced_k_noop, _all, _ref;

  iced = require('iced-runtime').iced;
  __iced_k = __iced_k_noop = function() {};

  fs = require('fs');

  prng = require('crypto').prng;

  a_json_parse = require('./util').a_json_parse;

  _ref = require('iced-error'), athrow = _ref.athrow, make_esc = _ref.make_esc;

  _all = [];

  get_id = function() {
    return prng(16).toString('hex');
  };

  read_all = function(fd, cb) {
    var b, bufs, eof, err, l, nbytes, ___iced_passed_deferral, __iced_deferrals, __iced_k;
    __iced_k = __iced_k_noop;
    ___iced_passed_deferral = iced.findDeferral(arguments);
    err = null;
    eof = false;
    bufs = [];
    l = 0x1000;
    (function(_this) {
      return (function(__iced_k) {
        var _results, _while;
        _results = [];
        _while = function(__iced_k) {
          var _break, _continue, _next;
          _break = function() {
            return __iced_k(_results);
          };
          _continue = function() {
            return iced.trampoline(function() {
              return _while(__iced_k);
            });
          };
          _next = function(__iced_next_arg) {
            _results.push(__iced_next_arg);
            return _continue();
          };
          if (!!((err != null) || eof)) {
            return _break();
          } else {
            b = new Buffer(l);
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced"
              });
              fs.read(fd, b, 0, l, null, __iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    err = arguments[0];
                    return nbytes = arguments[1];
                  };
                })(),
                lineno: 23
              }));
              __iced_deferrals._fulfill();
            })(function() {
              return _next(err != null ? void 0 : nbytes === 0 ? eof = true : (b = b.slice(0, nbytes), bufs.push(b)));
            });
          }
        };
        _while(__iced_k);
      });
    })(this)((function(_this) {
      return function() {
        return cb(err, Buffer.concat(bufs));
      };
    })(this));
  };

  Lockfile = (function() {
    function Lockfile(_arg) {
      var mode, poke_interval, poke_timeout, reclaim_timeout, retry_interval, wait_limit;
      this.filename = _arg.filename, wait_limit = _arg.wait_limit, poke_timeout = _arg.poke_timeout, reclaim_timeout = _arg.reclaim_timeout, poke_interval = _arg.poke_interval, retry_interval = _arg.retry_interval, mode = _arg.mode, this.log = _arg.log;
      this.retry_interval = retry_interval || 100;
      this.poke_interval = poke_interval || 100;
      this.poke_timeout = poke_timeout || (this.poke_interval * 20);
      this.reclaim_timeout = reclaim_timeout || (this.poke_interval * 5);
      this.wait_limit = 10 * 1000;
      this.mode = mode || 0x1a4;
      this.id = get_id();
      this._locked = false;
      this._maintain_cb = null;
      this._release_cb = null;
    }

    Lockfile.prototype._log = function(level, s) {
      if (this.log != null) {
        s = "" + this.filename + ": " + s;
        return this.log[level](s);
      }
    };

    Lockfile.prototype.warn = function(s) {
      return this._log('warn', s);
    };

    Lockfile.prototype.info = function(s) {
      return this._log('info', s);
    };

    Lockfile.prototype._acquire_1 = function(cb) {
      var err, res, unlinked, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      res = false;
      unlinked = false;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
            funcname: "Lockfile._acquire_1"
          });
          fs.open(_this.filename, 'wx', _this.mode, __iced_deferrals.defer({
            assign_fn: (function(__slot_1) {
              return function() {
                err = arguments[0];
                return __slot_1.fd = arguments[1];
              };
            })(_this),
            lineno: 66
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            if (typeof err === "undefined" || err === null) {
              return __iced_k(res = true);
            } else {
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                  funcname: "Lockfile._acquire_1"
                });
                _this._acquire_1_fallback(__iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      err = arguments[0];
                      return unlinked = arguments[1];
                    };
                  })(),
                  lineno: 69
                }));
                __iced_deferrals._fulfill();
              })(function() {
                return __iced_k(typeof err !== "undefined" && err !== null ? _this.warn(err.message) : void 0);
              });
            }
          })(function() {
            return cb(res, unlinked);
          });
        };
      })(this));
    };

    Lockfile.prototype._lock_dat = function() {
      var s;
      s = JSON.stringify([Date.now(), this.id, process.pid]);
      return new Buffer(s, 'utf8');
    };

    Lockfile.prototype._acquire_1_fallback = function(cb) {
      var buf, err, esc, jso, now, obj, rfd, unlinked, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      unlinked = false;
      esc = make_esc(cb, "_acquire_1_fallback");
      err = null;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
            funcname: "Lockfile._acquire_1_fallback"
          });
          fs.open(_this.filename, 'r', esc(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return rfd = arguments[0];
              };
            })(),
            lineno: 93
          })));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            __iced_deferrals = new iced.Deferrals(__iced_k, {
              parent: ___iced_passed_deferral,
              filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
              funcname: "Lockfile._acquire_1_fallback"
            });
            read_all(rfd, esc(__iced_deferrals.defer({
              assign_fn: (function() {
                return function() {
                  return buf = arguments[0];
                };
              })(),
              lineno: 94
            })));
            __iced_deferrals._fulfill();
          })(function() {
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                funcname: "Lockfile._acquire_1_fallback"
              });
              a_json_parse(buf, esc(__iced_deferrals.defer({
                assign_fn: (function() {
                  return function() {
                    return jso = arguments[0];
                  };
                })(),
                lineno: 95
              })));
              __iced_deferrals._fulfill();
            })(function() {
              now = Date.now();
              (function(__iced_k) {
                if (!Array.isArray(jso) || jso.length < 2) {
                  return __iced_k(err = new Error("Bad lock file; expected an array with 2 values"));
                } else {
                  (function(__iced_k) {
                    if ((jso[1] === _this.id) && (now - jso[0] > _this.reclaim_timeout)) {
                      (function(__iced_k) {
                        __iced_deferrals = new iced.Deferrals(__iced_k, {
                          parent: ___iced_passed_deferral,
                          filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                          funcname: "Lockfile._acquire_1_fallback"
                        });
                        fs.unlink(_this.filename, esc(__iced_deferrals.defer({
                          lineno: 100
                        })));
                        __iced_deferrals._fulfill();
                      })(function() {
                        return __iced_k(unlinked = true);
                      });
                    } else {
                      (function(__iced_k) {
                        if ((jso[1] !== _this.id) && (now - jso[0] > _this.poke_timeout)) {
                          obj = _this._lock_dat();
                          (function(__iced_k) {
                            __iced_deferrals = new iced.Deferrals(__iced_k, {
                              parent: ___iced_passed_deferral,
                              filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                              funcname: "Lockfile._acquire_1_fallback"
                            });
                            fs.writeFile(_this.filename, obj, {
                              encoding: 'utf8',
                              mode: _this.mode
                            }, esc(__iced_deferrals.defer({
                              lineno: 104
                            })));
                            __iced_deferrals._fulfill();
                          })(__iced_k);
                        } else {
                          return __iced_k();
                        }
                      })(__iced_k);
                    }
                  })(__iced_k);
                }
              })(function() {
                return cb(null, unlinked);
              });
            });
          });
        };
      })(this));
    };

    Lockfile.prototype.acquire = function(cb) {
      var acquired, err, start, unlinked, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      acquired = false;
      start = Date.now();
      err = null;
      (function(_this) {
        return (function(__iced_k) {
          var _results, _while;
          _results = [];
          _while = function(__iced_k) {
            var _break, _continue, _next;
            _break = function() {
              return __iced_k(_results);
            };
            _continue = function() {
              return iced.trampoline(function() {
                return _while(__iced_k);
              });
            };
            _next = function(__iced_next_arg) {
              _results.push(__iced_next_arg);
              return _continue();
            };
            if (!true) {
              return _break();
            } else {
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                  funcname: "Lockfile.acquire"
                });
                _this._acquire_1(__iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      acquired = arguments[0];
                      return unlinked = arguments[1];
                    };
                  })(),
                  lineno: 114
                }));
                __iced_deferrals._fulfill();
              })(function() {
                (function(__iced_k) {
                  if (acquired) {
                    (function(__iced_k) {
_break()
                    })(__iced_k);
                  } else {
                    return __iced_k();
                  }
                })(function() {
                  (function(__iced_k) {
                    if (_this.wait_limit && (Date.now() - start) > _this.wait_limit) {
                      (function(__iced_k) {
_break()
                      })(__iced_k);
                    } else {
                      return __iced_k();
                    }
                  })(function() {
                    (function(__iced_k) {
                      if (!unlinked) {
                        (function(__iced_k) {
                          __iced_deferrals = new iced.Deferrals(__iced_k, {
                            parent: ___iced_passed_deferral,
                            filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                            funcname: "Lockfile.acquire"
                          });
                          setTimeout(__iced_deferrals.defer({
                            lineno: 117
                          }), _this.retry_interval);
                          __iced_deferrals._fulfill();
                        })(__iced_k);
                      } else {
                        return __iced_k();
                      }
                    })(_next);
                  });
                });
              });
            }
          };
          _while(__iced_k);
        });
      })(this)((function(_this) {
        return function() {
          if (acquired) {
            _this.maintain_lock_loop();
          }
          if (!acquired) {
            err = new Error("failed to acquire lock");
          }
          return cb(err);
        };
      })(this));
    };

    Lockfile.prototype.release = function(cb) {
      if (this._locked) {
        this._release_cb = cb;
        this._locked = false;
        return typeof this._maintain_cb === "function" ? this._maintain_cb() : void 0;
      } else if (cb != null) {
        return cb(new Error("tried to unlock file that wasn't locked"));
      }
    };

    Lockfile.prototype.maintain_wait = function(cb) {
      var rv, which, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      rv = new iced.Rendezvous();
      this._maintain_cb = rv.id(true).defer({
        lineno: 138,
        context: __iced_deferrals
      });
      setTimeout(rv.id(false).defer({
        lineno: 139,
        context: __iced_deferrals
      }), this.poke_interval);
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
            funcname: "Lockfile.maintain_wait"
          });
          rv.wait(__iced_deferrals.defer({
            assign_fn: (function() {
              return function() {
                return which = arguments[0];
              };
            })(),
            lineno: 140
          }));
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb();
        };
      })(this));
    };

    Lockfile.prototype.maintain_lock_loop = function() {
      var b, err, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      this._locked = true;
      (function(_this) {
        return (function(__iced_k) {
          var _results, _while;
          _results = [];
          _while = function(__iced_k) {
            var _break, _continue, _next;
            _break = function() {
              return __iced_k(_results);
            };
            _continue = function() {
              return iced.trampoline(function() {
                return _while(__iced_k);
              });
            };
            _next = function(__iced_next_arg) {
              _results.push(__iced_next_arg);
              return _continue();
            };
            if (!_this._locked) {
              return _break();
            } else {
              b = _this._lock_dat();
              (function(__iced_k) {
                __iced_deferrals = new iced.Deferrals(__iced_k, {
                  parent: ___iced_passed_deferral,
                  filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                  funcname: "Lockfile.maintain_lock_loop"
                });
                fs.write(_this.fd, b, 0, b.length, 0, __iced_deferrals.defer({
                  assign_fn: (function() {
                    return function() {
                      return err = arguments[0];
                    };
                  })(),
                  lineno: 149
                }));
                __iced_deferrals._fulfill();
              })(function() {
                if (err != null) {
                  _this.warn("error in maintain_lock_loop: " + err);
                }
                (function(__iced_k) {
                  if (_this._locked) {
                    (function(__iced_k) {
                      __iced_deferrals = new iced.Deferrals(__iced_k, {
                        parent: ___iced_passed_deferral,
                        filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
                        funcname: "Lockfile.maintain_lock_loop"
                      });
                      _this.maintain_wait(__iced_deferrals.defer({
                        lineno: 153
                      }));
                      __iced_deferrals._fulfill();
                    })(__iced_k);
                  } else {
                    return __iced_k();
                  }
                })(_next);
              });
            }
          };
          _while(__iced_k);
        });
      })(this)((function(_this) {
        return function() {
          (function(__iced_k) {
            __iced_deferrals = new iced.Deferrals(__iced_k, {
              parent: ___iced_passed_deferral,
              filename: "/Users/max/src/iced/iced-utils/src/lockfile.iced",
              funcname: "Lockfile.maintain_lock_loop"
            });
            fs.unlink(_this.filename, __iced_deferrals.defer({
              assign_fn: (function() {
                return function() {
                  return err = arguments[0];
                };
              })(),
              lineno: 154
            }));
            __iced_deferrals._fulfill();
          })(function() {
            if (typeof err !== "undefined" && err !== null) {
              _this.warn("error deleting lock file: " + err);
            }
            return typeof _this._release_cb === "function" ? _this._release_cb(err) : void 0;
          });
        };
      })(this));
    };

    return Lockfile;

  })();

  exports.Lockfile = Lockfile;

}).call(this);
