User Tools

Site Tools


lecture:nrepl:sources

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
lecture:nrepl:sources [2013/03/08 14:41]
psk810 [Bencode]
lecture:nrepl:sources [2013/03/08 15:55]
psk810 [dependencies]
Line 385: Line 385:
  
 Transport는 nREPL의 전송단을 추상화한 인터페이스이다. 외부에는 전송에 관한 내부 구현에는 관계없이 Transport를 이용하여 데이타의 송수신을 할 수 있다. ​ Transport는 nREPL의 전송단을 추상화한 인터페이스이다. 외부에는 전송에 관한 내부 구현에는 관계없이 Transport를 이용하여 데이타의 송수신을 할 수 있다. ​
 +
 +===== Transport 프로토콜 =====
  
 Transpoort는 다음과 같이 프로토콜로 정의되어 있다. Transpoort는 다음과 같이 프로토콜로 정의되어 있다.
Line 396: Line 398:
 recv는 다음 수신된 메세지를 읽어 리턴한다. 메세지가 없으면 대기한다. 대기중 timeout이 지나거나 전송 채널이 종료되면 nil을 리턴한다. recv는 다음 수신된 메세지를 읽어 리턴한다. 메세지가 없으면 대기한다. 대기중 timeout이 지나거나 전송 채널이 종료되면 nil을 리턴한다.
 send는 메시지를 전송 채널에 보내 송신한다. 이것은 Transport 자신을 다시 리턴한다. send는 메시지를 전송 채널에 보내 송신한다. 이것은 Transport 자신을 다시 리턴한다.
 +
 +===== FnTransport 타입 =====
  
 Transport 프로토콜의 구현은 FnTransport와 QueueTransport이 있다. QueueTransport는 파이프 트랜스포트로 사용되지만,​ FnTransport가 실제 bencode를 전송단에서 사용하고 있다. Transport 프로토콜의 구현은 FnTransport와 QueueTransport이 있다. QueueTransport는 파이프 트랜스포트로 사용되지만,​ FnTransport가 실제 bencode를 전송단에서 사용하고 있다.
Line 420: Line 424:
 </​code>​ </​code>​
  
 +===== fn-transport 함수 =====
  
 fn-transport는 실질적으로 Transport 구현을 만들어내는 함수이다. fn-transport는 실질적으로 Transport 구현을 만들어내는 함수이다.
Line 456: Line 461:
  
 __read 함수는 읽어들인 메시지가 예외인 경우 failure 아톰을 nil -> 예외로 변경하고 예외를 던진다. 이후 다른 스레드에서 읽기 시도를 하면 다시 예외를 던지도록 한다.__ __read 함수는 읽어들인 메시지가 예외인 경우 failure 아톰을 nil -> 예외로 변경하고 예외를 던진다. 이후 다른 스레드에서 읽기 시도를 하면 다시 예외를 던지도록 한다.__
 +
 +===== bencode 함수 =====
  
 bencode 함수는 전송단에 실제의 스트림을 연결하여 전송단을 완성한다. bencode 함수는 전송단에 실제의 스트림을 연결하여 전송단을 완성한다.
Line 791: Line 798:
     * handler : 클라이언트 메시지를 처리하기 위한 핸들러. 기본은 ​ defualt-handler.     * handler : 클라이언트 메시지를 처리하기 위한 핸들러. 기본은 ​ defualt-handler.
     * ack-port : 어떤 포트값이 주어진다면,​ 새로 구동되는 서버의 포트를 알려주기 위한 다른 서버 포트. 클로져 도구 구현시에만 유용.     * ack-port : 어떤 포트값이 주어진다면,​ 새로 구동되는 서버의 포트를 알려주기 위한 다른 서버 포트. 클로져 도구 구현시에만 유용.
-  - InetSocketAddress 자바 클래스를 사용하여 bind-address를 만들고 있다. bind가 참일 경우는 해당 ip주소를 사용하고 아닐겨웅에는 localhost가 된다.+  - InetSocketAddress 자바 클래스를 사용하여 bind-address를 만들고 있다. bind가 참일 경우는 해당 ip주소를 사용하고 아닐경우에는 localhost가 된다.
   - ServerSocket 자바 클래스를 서버 소켓을 생성하여 ss로 받는다.   - ServerSocket 자바 클래스를 서버 소켓을 생성하여 ss로 받는다.
   - Server는 server.clj에서 정의된 defrecord이다. Server 레코드 생성후 :ss 슬롯 추가.   - Server는 server.clj에서 정의된 defrecord이다. Server 레코드 생성후 :ss 슬롯 추가.
Line 925: Line 932:
   * add-stdin : "​eval",​ "​stdin"​ op 처리.   * add-stdin : "​eval",​ "​stdin"​ op 처리.
   * session : "​ls-sessions",​ "​close",​ "​clone"​ op 처리.   * session : "​ls-sessions",​ "​close",​ "​clone"​ op 처리.
 +  * pr-values : 메시지의 value 값을 프린트.
  
 linearize-middleware-stack 함수는 middleware.clj에서 정의된 함수로 미들웨어의 의존성에 따라 미들웨어들을 재배열시킨다. linearize-middleware-stack 함수는 middleware.clj에서 정의된 함수로 미들웨어의 의존성에 따라 미들웨어들을 재배열시킨다.
Line 930: Line 938:
 ======= 미들웨어 ======= ======= 미들웨어 =======
  
 +nREPL 서버는 작은 단위의 기능들을 조합해서 서버의 기능을 구성해 낸다. 미들웨어는 이러한 작은 단위의 기능을 구현한다. 하지만 미들웨어가 서로 연결되는 순서가 중요해진다. 예를 들어 세션 미들웨어는 사용자의 세션을 메시지에 추가하는데,​ 이런 후에야 평가 미들웨어가 세션 데이타를 참조할 수 있다. 미들웨어의 순서를 결정하기 위해 각 미들웨어에 미들웨어 설명자를 메타데이타로 정의한다.
 +
 +===== 미들웨어 설명자 =====
 +
 +===== 미들웨어 재배치 =====
 +
 +==== linearize-middleware-stack ====
 +
 +linearize-middleware-stack 함수는 미들웨어 리스트를 입력받아서,​ 각 미들웨어 설명자에 기술된 미들웨어 의존성 정보에 맞추어서 미들웨어의 순서를 정한다.
 +
 +<code clojure>
 +(defn linearize-middleware-stack
 +  [middlewares]
 +  (->> middlewares
 +    extend-deps
 +    (sort-by (comp count (partial apply concat) (juxt :expects :​requires)))
 +    reverse
 +    (reduce #​(conj-sorted % comparator %2) [])
 +    (map :​implemented-by)))
 +</​code>​
 +
 +이 함수는 크게 extend-deps 함수에 의존하고 있다.
 +
 +====  extend-deps ====
 +
 +이 함수는 각 미들웨어 설명자에 기술된 의존성을 확장한다.
 +
 +<code clojure>
 +(defn- extend-deps
 +  [middlewares]
 +  (let [descriptor #(-> % meta ::​descriptor)
 +        middlewares (concat middlewares
 +                            (->> (map descriptor middlewares)
 +                              (mapcat (juxt :expects :requires))
 +                              (mapcat identity)
 +                              (filter var?)))]
 +    (doseq [m (remove descriptor middlewares)]
 +      (binding [*out* *err*]
 +        (printf "​[WARNING] No nREPL middleware descriptor in metadata of %s, see clojure.tools.middleware/​set-descriptor!"​ m)))
 +    (let [middlewares (set (for [m middlewares]
 +                             ​(->​ (descriptor m)
 +                               ; only conj'​ing m here to support direct reference to
 +                               ; middleware dependencies in :expects and :requires,
 +                               ; e.g. interruptable-eval'​s dep on
 +                               ; clojure.tools.nrepl.middleware.pr-values/​pr-values
 +                               ​(update-in [:handles] (comp set #(conj % m) keys))
 +                               ​(assoc :​implemented-by m))))]
 +      (set (for [m middlewares]
 +             ​(reduce
 +               #​(update-in % [%2] into (dependencies middlewares % %2))
 +               m #{:expects :​requires}))))))
 +</​code>​
 +
 +==== dependencies ====
 +
 +<code clojure>
 +(defn- dependencies
 +  [set start dir]
 +  (let [ops (start dir)
 +        deps (set/select
 +               (comp seq (partial set/​intersection ops) :handles)
 +               set)]
 +    (when (deps start)
 +      (throw (IllegalArgumentException.
 +               ​(format "​Middleware %s depends upon itself via %s"
 +                       ​(:​implemented-by start)
 +                       ​dir))))
 +    (concat ops
 +            (mapcat #​(dependencies set % dir) deps))))
 +</​code>​
 +
 +===== comparator =====
 +
 +<code clojure>
 +(defn- comparator
 +  [{a-requires :requires a-expects :expects a-handles :handles}
 +   ​{b-requires :requires b-expects :expects b-handles :handles}]
 +  (or (->> (into {} [[[a-requires b-handles] -1]
 +                     ​[[a-expects b-handles] 1]
 +                     ​[[b-requires a-handles] 1]
 +                     ​[[b-expects a-handles] -1]])
 +        (map (fn [[sets ret]]
 +               (and (seq (apply set/​intersection sets)) ret)))
 +        (some #{-1 1}))
 +      0))
 +</​code>​
 +
 +===== 미들웨어 함수들 =====
 +
 +==== session ====
 +==== add-stdin ====
 +==== wrap-describe ====
 +==== interruptible-eval ====
 +==== wrap-load-file ====
 +==== pr-values ====
  
lecture/nrepl/sources.txt · Last modified: 2019/02/04 14:26 (external edit)