diff --git a/wcfs/client/wcfs.cpp b/wcfs/client/wcfs.cpp index cf96a990e95f10035af68db9867431cdee6fc44a..b052d788d478ccdde59704647ce0dd2c8b7bacbf 100644 --- a/wcfs/client/wcfs.cpp +++ b/wcfs/client/wcfs.cpp @@ -583,17 +583,21 @@ error _Conn::resync(zodb::Tid at) { atMuWLocked = false; // send watch updates to wcfs. - // the pinner is now running and will be able to serve pin requests triggered by out watch. + // the pinner is now running and will be able to serve pin requests triggered by our watch. + // + // update only fileh in "opened" state - for fileh in "opening" and + // "closing" states, watch setup is currently in-progress and performed by + // Conn.open and FileH.close correspondingly. for (auto fit : wconn._filehTab) { zodb::Oid foid = fit.first; - //FileH f = fit.second; + FileH f = fit.second; + + // XXX locking ok? (protected by wconn._mu ?) + if (f->_state != _FileHOpened) + continue; - // XXX need to lock f.mu because wconn.atMu is only R now. - // XXX need to coordinate with e.g. FileH.close -> "if f.state != CLOSING" ? - // XXX need to coordinate with e.g. Conn.open -> "if f.state != OPENING" ? + // XXX need to lock f.mu because wconn.atMu is only R now. (???) string ack; - // XXX f._watchMu.lock() + unlock() - // XXX + recheck status before sending the watch? tie(ack, err) = wconn._wlink->sendReq(context::background(), fmt::sprintf("watch %s @%s", v(foid), v(at))); if (err != nil) return E(err); @@ -687,7 +691,7 @@ retry: wconn._filehTab.erase(foid); wconn._mu.Unlock(); } - f->_state = _FileHOpened; + f->_state = _FileHOpened; // XXX move under wconn._mu ? f->_openReady.close(); }); wconn._mu.Unlock(); @@ -764,7 +768,8 @@ error _FileH::close() { }); // fileh.close can be called several times. just return nil for second close. - if (fileh._closed) +// if (fileh._closed) + if (fileh._state >= _FileHClosing) return nil; // decref open count; do real close only when last open goes away. @@ -777,6 +782,9 @@ error _FileH::close() { // last open went away - real close. xerr::Contextf E("%s: close f<%s>", v(wconn), v(fileh.foid)); + ASSERT(fileh._state == _FileHOpened); // there can be no open-in-progress, because + fileh._state = _FileHClosing; // .close() can be called only on "opened" fileh + error err, eret; auto reterr1 = [&eret](error err) { if (eret == nil && err != nil) @@ -785,6 +793,9 @@ error _FileH::close() { // XXX change all fileh.mmaps to cause EFAULT on any access after fileh.close + // XXX unlock wconn.mu + // XXX unlock f.mu + // stop watching f XXX ok under f.mu ? string ack; // XXX f._watchMu.lock() + unlock diff --git a/wcfs/client/wcfs.h b/wcfs/client/wcfs.h index 5282af08feed1304c076aef062988eeb1e557819..7af3127f987405b986d2ad023a74ebd962fbea0e 100644 --- a/wcfs/client/wcfs.h +++ b/wcfs/client/wcfs.h @@ -252,7 +252,7 @@ struct _FileH : object { bool _closed; // y after .close() // "watch <.foid> ..." requests we send to wcfs are serialized via FileH._watchMu - // XXX sync::Mutex _watchMu; + // XXX sync::Mutex _watchMu; XXX kill // don't new - create via Conn.open private: