Xây dựng công cụ phát hiện và cảnh báo bế tắc

Một phần của tài liệu Vấn đề bế tắc (deadlock) trong quy trình được hiện thực bằng BPEL (Trang 43 - 48)

Dựa trên ý tưởng giải pháp ở mục 3.1, chương trình phát hiện và cảnh báo bế tắc thiết kế và xây dựng các module xử lý dựa trên ngôn ngữ Java, bao gồm các phần chính như sau :

 Module tách mã nguồn <flow> và chuyển về đồ thị có hướng với các nút và các cung: trong module này, thực thi các bước từ phân tích file mã nguồn .bpel đầu vào, sử dụng DOM Parser dạng tài liệu XML, thành DOM Tree. Duyệt cây dạng DOM, xác định các nút/ đỉnh, các cung cùng phép điều kiện joinCondition thành đồ thị có hướng với các ràng buộc. Module này phải xây dựng được các lớp đặc trưng cho thao tác chuyển từ các thành phần hoạt động dạng XML về thành các đỉnh của đồ thị có hướng dựa trên đặc trưng của các thành phần hoạt động cơ sở và các thành phần hoạt động có cấu trúc <if>, <sequence>. Các đỉnh là các thành phần hoạt động nằm trong các nhánh của cùng thành phần <if> (các thành phần <source>) nối với một thành phần đích theo các cung (các thành phần <link> cùng thuộc tính

linkName), phải phát hiện được biểu thức điều kiện joinCondition gây bế tắc.

 Module thực hiện: Từ đồ thị trên, module này giải bài toán tìm chu trình trong đồ thị có hướng và bài toán định dạng phát hiện pháp toán joinCondition có phải là phép logic AND của các giá trị cung và các đỉnh đi ra của các cung đó có nằm trong đường đi xuất phát từ một đỉnh if trong đồ thị đã xây dựng. Để dễ dàng giải quyết bài toán trong module này, ở module đầu tiên trên, cần quy chuẩn hoặc đánh dấu các đỉnh, các cung của đồ thị có hướng, phân biệt được, các đỉnh thể hiện thành phần <if>, thành phần <sequence>, các đỉnh thể hiện các activities nằm trong bao đóng của

<sequence>, các cung là thể hiện của các <link>, và phát hiện được điều kiện

joinCondition phép toán AND.

 Module kiểm tra và kiểm thử : Module này, sẽ kiểm định công cụ phát hiện và cảnh báo bế tắc đã xây dựng ở hai module trên. Đầu vào là các tài liệu BPEL thể hiện

bài toán 1, bài toán 2, bài toán 3 trong mục 2.2. Kết quả xử lý, chương trình phải phát hiện được chu trình hay vấn đề bế tắc và thông báo đối với người dùng cuối.

Phần này sẽ đi sâu, mô tả hướng xây dựng và các thuật toán sử dụng trong bài toán. Trong giới hạn luận văn này, sẽ bỏ qua sự phực tạp của bài toán, nghĩa là không xét các trường hợp <scope>, điều khiển lỗi, các thành phần lặp <while>,

<repeatUtil>, <for>… hay là các trường hợp lồng nhau.

 Module tách mã nguồn <flow> và chuyển về đồ thị có hướng với các nút và các cung.

Bước 1: Xây dựng đồ thị có hướng G = (V,E) với V là tập các đỉnh và E là tập các cạnh (cung).

- Bước 1.1: Mã nguồn <flow> đã tách từ <process> phải chuyển thành đồ thị có hướng G định nghĩa trên.

- Bước 1.2: Chuyển activities trong <flow> thành các đỉnh, hay tập V của đồ thị G. Bỏ qua các thuộc tính của các activity, tập đỉnh V chứa các thành phần hoạt động activities được định nghĩa trong BPEL như các <if>, <sequence>, các thành phần cơ sở <assign>, <empty>, <invoke>….

Ví dụ: Mã nguồn biểu diễn cho thành phần <if> như sau:

<bpel:if name="If">

<bpel:condition…></bpel:condition>

<bpel:assign validate="no" name="Assign"> <bpel:copy> <bpel:from> <bpel:query>…</bpel:query> </bpel:from> <bpel:to></bpel:to> </bpel:copy> <bpel:sources> <bpel:source linkName="link1"> </bpel:source> </bpel:sources> </bpel:assign> <bpel:else> <bpel:assign>

<bpel:copy> <bpel:from>…</bpel:from> <bpel:to></bpel:to> </bpel:copy> <bpel:sources> <bpel:source linkName="link2"> </bpel:source> </bpel:sources> </bpel:assign> </bpel:else> <bpel:targets> <bpel:target linkName="link3"> </bpel:target> </bpel:targets> </bpel:if>

Các đỉnh sẽ là If (<bpel:if name="If">), Assign (<bpel:assign validate="no" name="Assign">), Assign1 (<bpel:assign validate="no" name="Assign1">) bỏ qua các thành phần thuộc tính của <if> như <Condition> hay các thuộc tính đi kèm của <assign> là <copy>, <from>, <to>….

 Như vậy ta có, đối với mã nguồn BPEL cho bài toán 1 ở mục 2.2, tập đỉnh sẽ là V = { If, Assign, Assign1, Assign2} với Assign2 (<bpel:assign validate="no" name="Assign2">).

Chuyển <flow> thành các cạnh của đồ thị có hướng G. Nếu <flow> không sử dụng thành phần <link> thì các thành phần hoạt động activities nằm trong bao đóng của

<flow> sẽ thực thi song song (không phải tuần tự mã nguồn) và nếu sử dụng các

thành phần <link> thì sẽ thực thi phụ thuộc giữa thành phần <source> và

<target> của <link> trong <flow>. Trong trường hợp bài toán 1 định nghĩa và

sử dụng các thành phần <link> để điều khiển phụ thuộc, vì thế tập <link> sẽ là các cạnh của đồ thị có hướng G. Thành phần <source> của link được bao đóng bởi thành phần activity nào thì thành phần activity ấy sẽ là một đỉnh đi ra của một cạnh thuộc G. Còn thành phần <target> của link được bao đóng bởi thành phần activity nào thì thành phần activity đó là một đỉnh đi vào của một cạnh thuộc G. Như vậy, từ các link sử dụng ở mã nguồn của bài toán 1 ví dụ, các cạnh được định nghĩa là cung link1 = (Assign, Assign2), cung link2 = (Assign1, Assign2), cung link3 = (Assign2, If). Bên cạnh đó, trong phần đặt vấn đề, giả sử coi như luồng thực thi của thành phần

toán 1, sẽ được các cung định nghĩa là cung if1 = (If, Assign) và cung if2 = (If, Assign1). Bài toán 3, tương tự như bài toán 1.

 Như vậy, tập E các cung bao gồm:

E = {(If, Assign), (If, Assign1), (Assign, Assign2), (Assign1, Assign2), (Assign2, If)}

Biểu diễn đồ thị G = (V, E) được định nghĩa ở trên như hình dưới:

Hình 3.2.1: Đồ thị có hướng cho bài toán 1.

Ứng với cách suy diễn trên, sự liên quan và phối hợp sử dụng thành phần <flow>,

<link> và <if> mô tả cho bài toán 2, chuyển về đồ thị có hướng như hình 3.2.2 bên

Hình 3.2.2: Đồ thị có hướng cho bài toán 2.

 Module thực hiện: tìm chu trình hoặc tìm điều kiện joinCondition gây bế tắc trong <flow>.

Bước 2: Bài toán 1bài toán 3, quy về tìm chu trình trong đồ thị có hướng. Đối với

bài toán 2, từ đồ thị có hướng G = (V, E) xây dựng ở bước 1, xét thuộc tính điều kiện

joinCondition của link. Điều kiện joinCondition là điều kiện đi kèm với các

thành phần đích <target> của <link> hay là điều kiện nối của các thành phần

<link>. Giá trị của joinCondition là biểu thức Boolean, trả về true hoặc

false. Nếu giá trị của joinCondition bằng true, thì thành phần activities tiếp

theo sẽ không được thực thi, ngược lại, luồng thực thi vẫn tiếp tục. Trong trường hợp, xét các điều kiện joinCondition của các link đi ra từ thành phần hoạt động lựa chọn <if>, với giá trị của joinCondition bằng true, thì các thành phần hoạt động tiếp theo sẽ không bao giờ được gọi tới, chương trình chạy ném ra một lỗi sai chuẩn từ thuộc tính bpel:joinFailure hoặc suppressJoinFailure. Các trường hợp này, là lỗi chương trình trong quá trình runtime, nên các công cụ lập trình không phát hiện và cảnh báo. Vì thế, với các link đi ra từ thành phần lựa chọn <if>, xét điều kiện

nối joinCondition, nếu điều kiện là phép toán logic OR, đưa bài toán tìm chu

trình trong đồ thị có hướng G cho bài toán 1bài toán 3 ở bước 2.1, còn lại, điều kiện joinCondition là phép toán logic AND, giải quyết bài toán 2 ở bước 2.2. - Bước 2.1: Tìm chu trình trong đồ thị có hướng G = (V, E)

với V = {If, Assign, Assign1, Assign2} và

E = {(If, Assign), (If, Assign1), (Assign, Assign2), (Assign1, Assign2), (Assign2, If)}. Áp dụng thuật toán tìm kiếm theo chiều sâu DFS (Depth First Search) trong đồ thị, thuật toán có thể trình bay tư tưởng như sau: bắt đầu từ đỉnh s chẳng hạn, mọi đỉnh u

kề với s sẽ đến được s. Với mỗi đỉnh u đó, những đỉnh v kề với u cũng sẽ đến được s…. Khi đó một thủ tục đệ quy DFS(u) mô tả việc duyệt từ đỉnh u bằng cách thăm đỉnh u và tiếp tục quá trình duyệt DFS(v) với v là một đỉnh chưa được thăm kề với u. Tuy nhiên, mục tiêu để xác định đồ thị có chu trình hay không, nên trong đồ thị có hướng, khi v là đỉnh đã được thăm kề với u, thì xác định một chu trình từ đường đi từ s tới v hay không với v là điểm bắt đầu và cũng là điểm kết thúc. Nếu không tồn tại chu trình, duyệt tiếp các đỉnh còn lại dùng đệ quy như trên. Để quá trình duyệt không bỏ sót bất kỳ đỉnh nào, dùng kỹ thuật đánh dấu để phát hiện đỉnh đó đã được thăm hay chưa. Như thế sẽ dễ dàng để tìm chu trình trong đồ thị.

- Bước 2.2: Trong nhiều trường hợp, điều kiện joinCondition được sử dụng cho nhiều <target> của <link> với phép toán logic là AND, chương trình không thực thi được, và ném ra một lỗi chương trình khi runtime, tuy nhiên đó là trường hợp biến dữ liệu làm điều kiện phép AND không thể bằng true, trường hợp đó không xét trong phạm vi luận văn này. Khi nhiều <link> đi ra từ các nhánh của thành phần hành động lựa chọn <if>, điều kiện joinCondition là phép logic AND, thì giá trị

của joinCondition luôn bằng false. Thành phần hoạt động tiếp theo sẽ không

được thực thi, chương trình sẽ ngừng.

 Module Test: Đầu vào chương trình: mã nguồn BPEL chia làm ba kiểu, được xây dựng bằng công cụ Eclipse hoặc Jdeveloper, cấu hình server để chạy kiểm chứng kết quả.

- Kiểu 1: chương trình chạy đúng, cho ra kết quả như ý muốn. Đây là các chương trình đúng logic.

- Kiểu 2: chương trình như mô tả bài toán 1 và bài toán 3, sẽ xuất hiện chu trình. - Kiểu 3: chương trình như mô tả bài toán 2, sẽ gây ra vấn đề bế tắc bởi điều kiện joinCondition bằng AND.

Đầu ra trả về: thông báo dạng cảnh báo, mã nguồn BPEL có khả năng xảy ra chu trình hoặc bế tắc.

Một phần của tài liệu Vấn đề bế tắc (deadlock) trong quy trình được hiện thực bằng BPEL (Trang 43 - 48)

Tải bản đầy đủ (PDF)

(51 trang)