From 0073ec1eed94b00de29129aca9ac08e8d17120c9 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Thu, 25 Jun 2015 21:00:19 -0400 Subject: Implement basic locking --- lock.ur | 27 +++++++++++ lock.urs | 16 +++++++ main.ur | 156 +++++++++++++++++++++++++++---------------------------------- urwiki.urp | 2 + 4 files changed, 115 insertions(+), 86 deletions(-) create mode 100644 lock.ur create mode 100644 lock.urs diff --git a/lock.ur b/lock.ur new file mode 100644 index 0000000..9accf81 --- /dev/null +++ b/lock.ur @@ -0,0 +1,27 @@ +(* Copyright 2015 the Massachusetts Institute of Technology + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. *) + +table lock : { Title : string, + Holder : client } + PRIMARY KEY Title + +fun take page_title = + new_holder <- self; + result <- tryDml (INSERT INTO lock (Title, Holder) + VALUES ({[page_title]}, {[new_holder]})); + return (Option.isNone result) + +fun release page_title = + requestor <- self; + dml (DELETE FROM lock + WHERE Holder = {[requestor]}) diff --git a/lock.urs b/lock.urs new file mode 100644 index 0000000..f7282cc --- /dev/null +++ b/lock.urs @@ -0,0 +1,16 @@ +(* Copyright 2015 the Massachusetts Institute of Technology + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. *) + +val take : string -> transaction bool + +val release : string -> transaction unit diff --git a/main.ur b/main.ur index 4110c96..6478dd1 100644 --- a/main.ur +++ b/main.ur @@ -20,16 +20,11 @@ type id = int table commit : { Id : id, Created : time, + Title : string, Content : string } PRIMARY KEY Id sequence commit_id_next -table article : { Title : string, - Head : id } - PRIMARY KEY Title, - CONSTRAINT Head - FOREIGN KEY Head REFERENCES commit(Id) - datatype mode = View | Edit val eq_mode = mkEq (fn x y => @@ -44,90 +39,79 @@ fun only_in mode_source target_mode = then null else Style.invisible) -fun commit_article title text : transaction unit = +fun current_revision title = + commits <- queryL1 (SELECT commit.Created, commit.Title, commit.Content + FROM commit + WHERE commit.Title = {[title]} + ORDER BY commit.Created ASC); + return (case commits of + Nil => {Title = title, Body = "Not found."} + | art :: _ => {Title = art.Title, + Body = show art.Content}) + +fun create_commit title text : transaction unit = id <- nextval commit_id_next; creation_time <- now; - dml (INSERT INTO commit (Id, Created, Content) - VALUES ({[id]}, {[creation_time]}, {[text]})); - (* TODO(bbaren): This is ugly. Use CAS instead? *) - sql_error <- tryDml (INSERT INTO article (Title, Head) - VALUES ({[title]}, {[id]})); - case sql_error of - None => - (* We created a new article. *) - return () - | Some _ => - (* The article already exists. *) - dml (UPDATE article - SET Head = {[id]} - WHERE Title = {[title]}) + dml (INSERT INTO commit (Id, Created, Title, Content) + VALUES ({[id]}, {[creation_time]}, {[title]}, {[text]})) fun wiki requested_article_title = (* Look up the article. *) - extant_articles <- - queryL (SELECT article.Title, commit.Content - FROM article LEFT JOIN commit ON article.Head = commit.Id - WHERE article.Title = {[requested_article_title]}); - let - val article = - case extant_articles of - Nil => {Title = requested_article_title, Body = "Not found."} - | art :: Nil => {Title = art.Article.Title, - Body = show art.Commit.Content} - | _ :: _ :: _ => error - - Multiple articles with title - ‘{[requested_article_title]}’ - - in - (* Stuff the article text in a source so we can live-update it as the user - edits. *) - article_body_source <- source article.Body; - (* Initially, we're in View mode, and we can switch to Edit mode on user - request. *) - page_mode <- source View; - return - - - - {[if article.Title = Configuration.main_page_name - then Configuration.wiki_title - else article.Title ^ " – " ^ Configuration.wiki_title]} - - - - - (* Page headings *) -
-

{[Configuration.wiki_title]}

- + article <- current_revision requested_article_title; + (* Stuff the article text in a source so we can live-update it as the user + edits. *) + article_body_source <- source article.Body; + (* Initially, we're in View mode, and we can switch to Edit mode on user + request. *) + page_mode <- source View; + return + + + + {[if article.Title = Configuration.main_page_name + then Configuration.wiki_title + else article.Title ^ " – " ^ Configuration.wiki_title]} + + + + + (* Page headings *) +
+

{[Configuration.wiki_title]}

+ +
+ (* Article *) + {[text]}
} />
+ (* Editing panel *) +
+ (* Controls for View mode *) +
+
- (* Article *) - {[text]}} />
- (* Editing panel *) -
- (* Controls for View mode *) -
-
- (* Controls for Edit mode *) -
-
-
+ (* Controls for Edit mode *) +
+
+
- - - end +
+ + diff --git a/urwiki.urp b/urwiki.urp index 48ffebb..066918c 100644 --- a/urwiki.urp +++ b/urwiki.urp @@ -1,5 +1,7 @@ allow url /urwiki.css file /urwiki.css urwiki.css +$/option style +lock main -- cgit v1.2.3