0

このコードはサーバー上で実行され、ファイルへの変更を検出してクライアントに送信します。これは初めて機能し、その後、ファイルを変更して保存してもファイルの長さが更新されません。ここでの理由は、clojureの不変性だと思います。どうすればこれを機能させることができますか?

 (def clients (atom {}))
    (def rfiles (atom {}))
    (def file-pointers (atom {}))

(defn get-rfile [filename]
  (let [rdr ((keyword filename) @rfiles)]
    (if rdr
      rdr
      (let [rfile (RandomAccessFile. filename "rw")]
        (swap! rfiles assoc (keyword filename) rfile)
        rfile))))

(defn send-changes [changes]
  (go (while true
        (let [[op filename] (<! changes)
              rfile (get-rfile filename)
              ignore (println (.. rfile getChannel size))
              prev ((keyword filename) @file-pointers)
              start (if prev prev 0)
              end (.length rfile) // file length is not getting updated even if I changed the file externally
              array (byte-array (- end start))]
          (do
            (println (str "str" start " end" end))
            (.seek rfile start)
            (.readFully rfile array)
            (swap! file-pointers assoc (keyword filename) end)
            (doseq [client @clients]
              (send! (key client) (json/write-str
                                    {:changes  (apply str (map char array))
                                     :fileName filename}))
              false))))))
4

1 に答える 1

0

ここには不変性はありません。rfilesアトムには、変更可能な標準 Java オブジェクトを格納します

このコードは、データがファイルの最後に追加され、サイズが常に増加している場合にのみうまく機能します。

最後以外のファイルに更新/追加 (長さ +N) がある場合、ポインター startendは変更されたデータを指すのではなく、最後の N 文字だけを指し、ダミーのものをクライアントに送信します。 .

長さを減らす削除または変更がある場合は、

array (byte-array (- end start))

見えない (ブロックNegativeArraySizeExceptionに食べられた?)をスローします。常に正または null であるいくつかまたはテストをgo追加して、それを管理し、適切な動作を実行できます: ポインターをリセットしますか?,...(try (...) catch (...))(- end start)

変更をスキャンするファイルは、データを追加することによってのみ変更されますか? そうでない場合は、それに応じてポインターをリセットまたは更新して、このケースを処理する必要があります。

それが役立つことを願っています。


テスト環境を編集します。

以下を定義しました。提供されたコードに変更はありません。

;; define the changes channel
(def notif-chan (chan))

;; define some clients
(def clients (atom {:foo "foo" :bar "bar"}))

;; helper function to post a notif of change in the channel
(defn notify-a-change [op filename]
  (go (>! notif-chan [op filename])))

;; mock of the send! function used in send-changes
(defn send! [client message]
  (println client message))

;; main loop
(defn -main [& args]
  (send-changes notif-chan))

replで、私は走った:

repl> (-main)

シェルで(私もエディタでテストしました):

sh> echo 'hello there' >> ./foo.txt

レプリカで:

repl> (notify-a-change "x" "./foo.txt")
str0 end12
:bar {"changes":"hello there\n","fileName":".\/foo.txt"}
:foo {"changes":"hello there\n","fileName":".\/foo.txt"}

repl> (notify-a-change "x" "./foo.txt")
str12 end12
:bar {"changes":"","fileName":".\/foo.txt"}
:foo {"changes":"","fileName":".\/foo.txt"}

シェルで:

sh> echo 'bye bye' >> ./foo.txt

レプリカで:

repl> (notify-a-change "x" "./foo.txt")
str12 end20
:bar {"changes":"bye bye\n","fileName":".\/foo.txt"}
:foo {"changes":"bye bye\n","fileName":".\/foo.txt"}
于 2015-03-05T12:21:17.273 に答える