Pimki 1.4.092 → 1.5.092
Sign up to get free protection for your applications and to get access to all the features.
- data/README-PIMKI +20 -8
- data/app/controllers/wiki.rb +123 -24
- data/app/models/chunks/engines.rb +6 -2
- data/app/models/chunks/uri.rb +1 -1
- data/app/models/chunks/wiki.rb +15 -14
- data/app/models/page.rb +1 -1
- data/app/models/wiki_content.rb +9 -8
- data/app/models/wiki_service.rb +8 -1
- data/app/views/navigation.rhtml +1 -0
- data/app/views/wiki/adv_search.rhtml +61 -0
- data/app/views/wiki/bliki.rhtml +4 -2
- data/app/views/wiki/bliki_revision.rhtml +1 -1
- data/app/views/wiki/edit.rhtml +4 -3
- data/app/views/wiki/edit_menu.rhtml +1 -1
- data/app/views/wiki/edit_web.rhtml +27 -14
- data/app/views/wiki/page.rhtml +1 -1
- data/app/views/wiki/revision.rhtml +17 -11
- data/app/views/wiki/rollback.rhtml +3 -0
- data/app/views/wiki/search.rhtml +6 -3
- data/favicon.png +0 -0
- data/libraries/action_controller_servlet.rb +9 -4
- data/libraries/madeleine/automatic.rb +1 -1
- data/libraries/madeleine_service.rb +107 -12
- data/libraries/redcloth_2.0.11.rb +894 -0
- data/pimki.rb +85 -70
- metadata +7 -5
@@ -0,0 +1,61 @@
|
|
1
|
+
<% @title = "Advanced Search Options" %>
|
2
|
+
<%= sub_template "top" %>
|
3
|
+
|
4
|
+
<h3>Advanced Search Options:</h3>
|
5
|
+
|
6
|
+
<form action="../search/" method="post">
|
7
|
+
<table>
|
8
|
+
<tr>
|
9
|
+
<td>Search string:</td>
|
10
|
+
<td colspan="3"><input type='text' name='query' id='query' size='60' /></td>
|
11
|
+
</tr>
|
12
|
+
<tr><td> </td></tr>
|
13
|
+
<tr>
|
14
|
+
<td colspan="3"><input type='checkbox' name='case'>Case sensitive</input></td>
|
15
|
+
</tr>
|
16
|
+
<tr>
|
17
|
+
<td>Search string as</td>
|
18
|
+
<td><input type='Radio' name='expression' value='regex' checked>Regular Expression</input></td>
|
19
|
+
<td><input type='Radio' name='expression' value='all'>All words</input></td>
|
20
|
+
<td><input type='Radio' name='expression' value='exact'>Exact phrase</input></td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<td>Search in</td>
|
24
|
+
<td><input type='Radio' name='where' value='all' checked>Pages & Bliki entries</input></td>
|
25
|
+
<td><input type='Radio' name='where' value='pages'>Pages only</input></td>
|
26
|
+
<td><input type='Radio' name='where' value='bliki'>Bliki entries only</input></td>
|
27
|
+
</tr>
|
28
|
+
<tr>
|
29
|
+
<td>Search on</td>
|
30
|
+
<td><input type='Radio' name='fields' value='both' checked>Pages names & contents</input></td>
|
31
|
+
<td><input type='Radio' name='fields' value='names'>Page names only</input></td>
|
32
|
+
<td><input type='Radio' name='fields' value='contents'>Page contents only</input></td>
|
33
|
+
</tr>
|
34
|
+
<tr>
|
35
|
+
<td colspan="2">Limit search to selected categories:</td>
|
36
|
+
<td colspan="2"><select id="category" name="category" size="3" multiple style="width:200">
|
37
|
+
<option value="noselect">------------
|
38
|
+
<% for category in web.categories %>
|
39
|
+
<option value="<%= category %>"><%= category %>
|
40
|
+
<% end %>
|
41
|
+
</select>
|
42
|
+
</td>
|
43
|
+
</tr>
|
44
|
+
<tr>
|
45
|
+
<td colspan="2">Limit search to selected authors:</td>
|
46
|
+
<td colspan="2"><select id="author" name="author" size="3" multiple style="width:200">
|
47
|
+
<option value="noselect">------------
|
48
|
+
<% for author in web.authors %>
|
49
|
+
<option value="<%= author %>"><%= author %>
|
50
|
+
<% end %>
|
51
|
+
</select>
|
52
|
+
</tr>
|
53
|
+
<tr>
|
54
|
+
<td><input type='submit' value='Search'></td>
|
55
|
+
</tr>
|
56
|
+
</table>
|
57
|
+
</form>
|
58
|
+
|
59
|
+
|
60
|
+
<%= sub_template "bottom" %>
|
61
|
+
|
data/app/views/wiki/bliki.rhtml
CHANGED
@@ -79,9 +79,9 @@ function validateSelection() {
|
|
79
79
|
</script>
|
80
80
|
|
81
81
|
<h2>Apply filter:</h2>
|
82
|
+
<form class="navigation" action="bliki" action="post" onSubmit="return validateSelection();">
|
82
83
|
<table><tr>
|
83
84
|
<td>Show only pages authored by:</td>
|
84
|
-
<form class="navigation" action="bliki" action="post" onSubmit="return validateSelection();">
|
85
85
|
<td>
|
86
86
|
<select id="sel_author" name="authorname" size="1">
|
87
87
|
<option value="noselect">------------
|
@@ -94,8 +94,10 @@ function validateSelection() {
|
|
94
94
|
<td>Regexp search on all entries:</td>
|
95
95
|
<td><input type="text" id="search_regex" name="regexp"></td>
|
96
96
|
<td><input type="submit" name="Search" value="Search"></td>
|
97
|
-
|
97
|
+
</tr><tr>
|
98
|
+
<td>Or go to <a href='../adv_search/'>Advanced Search</a></td>
|
98
99
|
</tr></table>
|
100
|
+
</form>
|
99
101
|
|
100
102
|
<%= sub_template "bottom" %>
|
101
103
|
|
@@ -63,7 +63,7 @@
|
|
63
63
|
|
64
64
|
<% if @page.revisions.length > 1 %>
|
65
65
|
<span id="show_changes">
|
66
|
-
| <a href="#" onClick="toggleChanges(); return false;">
|
66
|
+
| <a href="#" onClick="toggleChanges(); return false;">Show changes</a>
|
67
67
|
</span>
|
68
68
|
<span id="hide_changes" style="display: none">
|
69
69
|
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
data/app/views/wiki/edit.rhtml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
<%
|
2
2
|
@title = "Editing #{@page.plain_name}"
|
3
|
-
@content_width =
|
3
|
+
@content_width = 810
|
4
4
|
@hide_navigation = true
|
5
|
-
@style_additions = "#
|
5
|
+
@style_additions = "#Content, #Container {padding-left:100px;}"
|
6
6
|
%>
|
7
7
|
<%= sub_template "top" %>
|
8
8
|
|
@@ -10,6 +10,7 @@
|
|
10
10
|
|
11
11
|
<%= render_markup_help %>
|
12
12
|
|
13
|
+
<div id='main'>
|
13
14
|
<form style="float:right" id="editForm" action="../save/<%= @page.name %>" method="post" onSubmit="cleanAuthorName();">
|
14
15
|
<p>
|
15
16
|
<textarea name="content" style="width: 550px; height: 430px"><%= @page.content %></textarea>
|
@@ -31,7 +32,7 @@
|
|
31
32
|
| <a href="../cancel_edit/<%= @page.name %>">Cancel</a> <small>(unlocks page)</small>
|
32
33
|
</p>
|
33
34
|
</form>
|
34
|
-
|
35
|
+
</div>
|
35
36
|
<script language="JavaScript1.2">
|
36
37
|
function cleanAuthorName() {
|
37
38
|
if (document.getElementById('authorName').value == "") {
|
@@ -24,7 +24,7 @@
|
|
24
24
|
</p>
|
25
25
|
<p>For the above options you can choose if you want to limit the number of results. Enter the number of items you wish, or 0 for all items: <input type="textfield" size="20", name="limit" value="<%= @list_limit %>" /></p>
|
26
26
|
<p><input type="radio" name="type" value="user" <%= 'checked' if @menu_type == 'user' %>>Or just write your own menu contents (as a regular Wiki page):
|
27
|
-
<textarea name="content" style="width: 400px; height: 300px"><%= @menu_content.content %></textarea>
|
27
|
+
<textarea name="content" style="width: 400px; height: 300px"><%= !@menu_content.nil? && Page === @menu_content ? @menu_content.content : @menu_content %></textarea>
|
28
28
|
</p>
|
29
29
|
|
30
30
|
<% if Page === @menu_content && @menu_content.revisions.length > 1
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<% @title = "Edit Web" %>
|
2
2
|
<%= sub_template "top" %>
|
3
3
|
|
4
|
+
<%= "<p style='font-size: 15px; font-variant: italic; color: red;'>#{@message}</span>" if @message %>
|
5
|
+
|
4
6
|
<form action="../update_web" id="setup" method="post" onSubmit="cleanAddress(); return validateSetup()">
|
5
7
|
<h2 style="margin-bottom: 3px">Name and address</h2>
|
6
8
|
<div class="help">
|
@@ -54,6 +56,15 @@
|
|
54
56
|
<textarea id="additionalStyle" style="display: none; margin-top: 10px; margin-bottom: 5px; width: 560px; height: 200px" name="additional_style"><%= @web.additional_style %></textarea>
|
55
57
|
</div>
|
56
58
|
|
59
|
+
<h2 style="margin-bottom: 3px">Persistence Options (all webs)</h2>
|
60
|
+
<div class="help">
|
61
|
+
You can set how often to take snapshots of the web data. (All incremental changes are saved as command_logs; snapshots supercede those with the full data). Recommended values are 1-2 hours if you turn the web on and off often, or 24-48 hours if this is a long running service.<br />
|
62
|
+
Snapshots will not be taken if there are no incremental changes (in the form of command_logs). You can always force a snapshot in the administrative tasks below.
|
63
|
+
</div>
|
64
|
+
<div class="inputBox">
|
65
|
+
<input align='right' type="text" name="snapshots_interval" value='<%= @snapshot_interval %>' /> hour(s).
|
66
|
+
</div>
|
67
|
+
|
57
68
|
<h2 style="margin-bottom: 3px">Password protection for this web (<%= @web.name %>)</h2>
|
58
69
|
<div class="help">
|
59
70
|
This is the password that visitors need to login to view and edit this web. Setting the password to nothing will remove the password protection.
|
@@ -148,27 +159,29 @@
|
|
148
159
|
<input type="password" id="system_password" name="system_password">
|
149
160
|
and
|
150
161
|
<input type="submit" value="Update Web">
|
151
|
-
<br/><br/>
|
152
|
-
...or forget changes and <a href="/new_web/">create a new web</a>
|
153
162
|
</small>
|
154
163
|
</p>
|
155
|
-
|
156
164
|
</form>
|
157
165
|
|
158
166
|
<br/>
|
159
|
-
<
|
160
|
-
|
161
|
-
<
|
167
|
+
<h2>Other administrative tasks</h2>
|
168
|
+
<form action="../administrate" id="administrate" method="post">
|
169
|
+
<p style="font-size: 10px;">
|
170
|
+
Clean up by entering system password
|
171
|
+
<input type="password" id="system_password" name="system_password">
|
172
|
+
and...
|
173
|
+
</p>
|
174
|
+
<p align='right'>
|
175
|
+
<input type="submit" name='action' value="Delete Orphan Pages"><br/>
|
176
|
+
<input type="submit" name='action' value="Clear Render Cache"><br/>
|
177
|
+
<input type="submit" name='action' value="Force Data Snapshot"><br/>
|
178
|
+
<input type="submit" name='action' value="Clean Storage"><br/>
|
179
|
+
</p>
|
180
|
+
</form>
|
162
181
|
|
163
|
-
<p
|
164
|
-
<small>
|
165
|
-
Clean up by entering system password
|
166
|
-
<input type="password" id="system_password" name="system_password">
|
167
|
-
and
|
168
|
-
<input type="submit" value="Delete Orphan Pages">
|
169
|
-
</small>
|
170
|
-
</p>
|
182
|
+
<p style='font-size: 10px;'>...or forget all your changes and <a href="/new_web/">create a new web</a>.</p>
|
171
183
|
|
184
|
+
|
172
185
|
<script>
|
173
186
|
function proposeAddress() {
|
174
187
|
document.getElementById('address').value =
|
data/app/views/wiki/page.rhtml
CHANGED
@@ -36,7 +36,7 @@
|
|
36
36
|
|
37
37
|
<% if @page.revisions.length > 1 %>
|
38
38
|
<span id="show_changes">
|
39
|
-
| <a href="#" onClick="toggleChanges(); return false;">
|
39
|
+
| <a href="#" onClick="toggleChanges(); return false;">Show changes</a>
|
40
40
|
</span>
|
41
41
|
<span id="hide_changes" style="display: none">
|
42
42
|
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
@@ -23,6 +23,15 @@
|
|
23
23
|
|
24
24
|
<div class="navigation">
|
25
25
|
|
26
|
+
<% if @revision.previous_revision %>
|
27
|
+
<a href="../revision/<%= @page.name %>?rev=<%= @revision.previous_revision.number %>" class="navlink">Back in time</a>
|
28
|
+
(<%= @revision.previous_revision.number + 1 %> more)
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% if @revision.next_revision && @revision.previous_revision %>
|
32
|
+
|
|
33
|
+
<% end %>
|
34
|
+
|
26
35
|
<% if @revision.next_revision %>
|
27
36
|
<% if @revision.next_revision.number < (@page.revisions.length - 1) %>
|
28
37
|
<a href="../revision/<%= @page.name %>?rev=<%= @revision.next_revision.number %>" class="navlink">
|
@@ -33,20 +42,11 @@
|
|
33
42
|
(<%= @revision.page.revisions.length - @revision.next_revision.number %> more)
|
34
43
|
<% end %>
|
35
44
|
|
36
|
-
|
37
|
-
|
|
38
|
-
<% end %>
|
39
|
-
|
40
|
-
<% if @revision.previous_revision %>
|
41
|
-
<a href="../revision/<%= @page.name %>?rev=<%= @revision.previous_revision.number %>" class="navlink">Back in time</a>
|
42
|
-
(<%= @revision.previous_revision.number + 1 %> more)
|
43
|
-
<% end %>
|
44
|
-
|
45
|
-
| <a href="../show/<%= @page.name %>" class="navlink">See current</a>
|
45
|
+
| <a href="../show/<%= @page.name %>" class="navlink">Show current</a>
|
46
46
|
|
47
47
|
<% if @revision.previous_revision %>
|
48
48
|
<span id="show_changes">
|
49
|
-
| <a href="#" onClick="toggleChanges(); return false;">
|
49
|
+
| <a href="#" onClick="toggleChanges(); return false;">Show changes</a>
|
50
50
|
</span>
|
51
51
|
<span id="hide_changes" style="display: none">
|
52
52
|
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
@@ -60,6 +60,12 @@
|
|
60
60
|
| Linked from: <%= @page.references.collect { |ref| "<a href='#{ref.name}'>#{ref.name}</a>" }.join(", ") %>
|
61
61
|
</small>
|
62
62
|
<% end %>
|
63
|
+
|
64
|
+
<% if @page.bliki_references.length > 0 %>
|
65
|
+
<small>
|
66
|
+
<br />| Bliki Linked from: <%= @page.bliki_references.collect { |ref| link_to_bliki(ref) }.join(", ") %>
|
67
|
+
</small>
|
68
|
+
<% end %>
|
63
69
|
</div>
|
64
70
|
|
65
71
|
<script language="Javascript">
|
@@ -11,6 +11,9 @@
|
|
11
11
|
<textarea name="content" style="font-size: 12px; width: 450px; height: 500px"><%= @revision.content %></textarea>
|
12
12
|
</p>
|
13
13
|
<p>
|
14
|
+
<% if @web.check_pass_on_edit %>
|
15
|
+
<p>Please enter edit password: <input type="password" name="password" id="password"></p>
|
16
|
+
<% end %>
|
14
17
|
<input type="submit" value="Update"> as
|
15
18
|
<input type="text" name="author" id="authorName" value="<%= @author %>"
|
16
19
|
onClick="this.value == 'AnonymousCoward' ? this.value = '' : true">
|
data/app/views/wiki/search.rhtml
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
<%
|
1
|
+
<% num_results = @results.length + @bliki_results.length
|
2
|
+
@title = num_results > 0 ? "#{num_results} page#{ 's' unless num_results == 1} contain#{ 's' if num_results == 1} \"#{@params["query"]}\"" : "No pages contains \"#{@query}\""
|
3
|
+
%>
|
4
|
+
<%= sub_template "top" %>
|
2
5
|
|
3
6
|
<% if @results.length > 0 %>
|
4
|
-
<h3
|
7
|
+
<h3><%= @results.length %> Matching Page<%= 's' unless @results.length == 1 %>:</h3>
|
5
8
|
<ul>
|
6
9
|
<% for page in @results %>
|
7
10
|
<li><a href="../show/<%= page.name %>"><%= page.plain_name %></a><br />
|
@@ -20,7 +23,7 @@
|
|
20
23
|
</ul>
|
21
24
|
<% end %>
|
22
25
|
<% if @bliki_results.length > 0 %>
|
23
|
-
<h3
|
26
|
+
<h3><%= @bliki_results.length %> Matching Bliki Entr<%= @bliki_results.length == 1 ? 'y' : 'ies' %>:</h3>
|
24
27
|
<ul>
|
25
28
|
<% for entry in @bliki_results %>
|
26
29
|
<li><a href="../bliki_revision/<%= entry.name %>?rev=<%= entry.revisions.size-1 %>"><%= entry.name %></a><br />
|
data/favicon.png
CHANGED
Binary file
|
@@ -6,11 +6,11 @@ include WEBrick
|
|
6
6
|
require 'view_helper'
|
7
7
|
|
8
8
|
class FavIconHandler < HTTPServlet::AbstractServlet
|
9
|
+
LOCAL_PATH = File.join(File.dirname(__FILE__), '../favicon.png')
|
10
|
+
ICO_FILE = File.open(LOCAL_PATH, "rb") { |f| f.read }
|
9
11
|
def do_GET(req, res)
|
10
|
-
ico = File.read(File.join(Dir.pwd, 'favicon.png'))
|
11
12
|
res['content-type'] = 'image/png'
|
12
|
-
res
|
13
|
-
res.body = ico
|
13
|
+
res.body = ICO_FILE
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -171,8 +171,13 @@ class ActionControllerServlet < HTTPServlet::AbstractServlet
|
|
171
171
|
begin
|
172
172
|
ERB.new(IO.readlines(template_path).join).result(binding)
|
173
173
|
rescue Exception => detail
|
174
|
-
@logger.error "
|
174
|
+
@logger.error "Error processing #{template_path}"
|
175
|
+
line = /:(\d+):/.match(detail.backtrace[0]).captures[0].to_i - 172
|
176
|
+
@logger.error "On Line: #{line}"
|
175
177
|
@logger.error detail
|
178
|
+
src = ERB.new(IO.readlines(template_path).join).src
|
179
|
+
lines = src.split("\n")[(line-1)..(line+1)]
|
180
|
+
@logger.error "\n\n" + lines.join("\n\n") + "\n\n"
|
176
181
|
raise
|
177
182
|
end
|
178
183
|
end
|
@@ -8,6 +8,8 @@ class MadeleineService
|
|
8
8
|
include Madeleine::Automatic::Interceptor
|
9
9
|
|
10
10
|
@@storage_path = self.name.downcase + "_storage"
|
11
|
+
automatic_read_only :snapshot_interval_hours, :take_snapshot, :clean_old_snapshots,
|
12
|
+
:restart, :request_stop
|
11
13
|
|
12
14
|
class << self
|
13
15
|
def storage_path
|
@@ -19,25 +21,56 @@ class MadeleineService
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def instance
|
22
|
-
|
24
|
+
if @system.nil?
|
25
|
+
@madeleine_server = MadeleineServer.new(self)
|
26
|
+
@system = @madeleine_server.system
|
27
|
+
end
|
23
28
|
@system
|
24
29
|
end
|
25
30
|
|
26
31
|
def restart
|
27
|
-
MadeleineServer.
|
28
|
-
@system =
|
32
|
+
MadeleineServer.delete_storage(self)
|
33
|
+
@system = nil
|
34
|
+
instance
|
35
|
+
end
|
36
|
+
|
37
|
+
def clean_old_snapshots
|
38
|
+
instance
|
39
|
+
@madeleine_server.clean_storage(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
def take_snapshot
|
43
|
+
instance
|
44
|
+
@madeleine_server.force_snapshot
|
45
|
+
end
|
46
|
+
|
47
|
+
def snapshot_interval_hours
|
48
|
+
instance
|
49
|
+
@madeleine_server.snapshot_interval.div MadeleineServer::ONE_HOUR rescue 1
|
29
50
|
end
|
51
|
+
|
52
|
+
def snapshot_interval_hours= hours
|
53
|
+
instance
|
54
|
+
@madeleine_server.snapshot_interval = hours.to_i * MadeleineServer::ONE_HOUR rescue MadeleineServer::ONE_HOUR
|
55
|
+
end
|
56
|
+
|
57
|
+
def request_stop
|
58
|
+
instance
|
59
|
+
@madeleine_server.request_stop
|
60
|
+
end
|
61
|
+
|
30
62
|
end
|
31
63
|
end
|
32
64
|
|
65
|
+
require 'fileutils'
|
33
66
|
class MadeleineServer
|
34
|
-
|
35
|
-
|
67
|
+
|
68
|
+
attr_reader :storage_path
|
69
|
+
attr_accessor :snapshot_interval
|
36
70
|
|
37
71
|
# Clears all the command_log and snapshot files located in the storage directory, so the
|
38
72
|
# database is essentially dropped and recreated as blank. Used in tests.
|
39
|
-
def self.
|
40
|
-
require 'fileutils'
|
73
|
+
def self.delete_storage(service)
|
41
74
|
if (File.directory?(service.storage_path))
|
42
75
|
FileUtils.rm_rf(Dir[service.storage_path + '/*.command_log'])
|
43
76
|
FileUtils.rm_rf(Dir[service.storage_path + '/*.snapshot'])
|
@@ -45,24 +78,86 @@ class MadeleineServer
|
|
45
78
|
FileUtils.mkdir_p(service.storage_path)
|
46
79
|
end
|
47
80
|
end
|
81
|
+
|
82
|
+
def clean_storage(service)
|
83
|
+
force_snapshot
|
84
|
+
command_logs = Dir[service.storage_path + '/*.command_log']
|
85
|
+
raise 'Error: existing command_logs after snapshot' unless command_logs.empty?
|
86
|
+
|
87
|
+
snapshots = Dir[service.storage_path + '/*.snapshot']
|
88
|
+
FileUtils.rm_rf(snapshots.sort[0..-2])
|
89
|
+
end
|
90
|
+
|
48
91
|
|
49
92
|
def initialize(service)
|
93
|
+
@storage_path = service.storage_path
|
94
|
+
@snapshot_interval = ONE_HOUR
|
50
95
|
marshaller = Madeleine::ZMarshal.new()
|
51
96
|
@server = Madeleine::Automatic::AutomaticSnapshotMadeleine.new(service.storage_path,
|
52
97
|
marshaller) { service.new }
|
53
|
-
start_snapshot_thread
|
98
|
+
start_snapshot_thread
|
54
99
|
end
|
55
100
|
|
56
101
|
def system
|
57
102
|
@server.system
|
58
103
|
end
|
59
104
|
|
105
|
+
def command_log_present?
|
106
|
+
not Dir[storage_path + '/*.command_log'].empty?
|
107
|
+
end
|
108
|
+
|
109
|
+
def force_snapshot
|
110
|
+
begin
|
111
|
+
hours_since_last_snapshot = 0
|
112
|
+
@server.take_snapshot
|
113
|
+
rescue => e
|
114
|
+
sleep(ONE_MINUTE)
|
115
|
+
retry
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
ONE_MINUTE = 60
|
121
|
+
ONE_HOUR = ONE_MINUTE * 60
|
122
|
+
MAX_INTERVAL_HOURS = 24 * 2
|
123
|
+
|
60
124
|
def start_snapshot_thread
|
61
|
-
Thread.new(@server) {
|
62
|
-
|
63
|
-
|
64
|
-
|
125
|
+
@snapshot_thread = Thread.new(@server) {
|
126
|
+
hours_since_last_snapshot = 0
|
127
|
+
while not @request_stop
|
128
|
+
sleep(snapshot_interval)
|
129
|
+
hours_since_last_snapshot += snapshot_interval.div ONE_HOUR
|
130
|
+
begin
|
131
|
+
# Take a snapshot if there is a command log
|
132
|
+
if command_log_present? or hours_since_last_snapshot > MAX_INTERVAL_HOURS
|
133
|
+
# 'Taking a Madeleine snapshot'
|
134
|
+
@server.take_snapshot
|
135
|
+
hours_since_last_snapshot = 0
|
136
|
+
puts "[#{DateTime.now.strftime '%F %T'}] INFO Taking snapshot"
|
137
|
+
else
|
138
|
+
puts "[#{DateTime.now.strftime '%F %T'}] INFO Skipping snapshot (no command logs)"
|
139
|
+
end
|
140
|
+
rescue => e
|
141
|
+
# wait for a minute (not to spoof the log with the same error)
|
142
|
+
# and go back into the loop, to keep trying
|
143
|
+
sleep(ONE_MINUTE)
|
144
|
+
retry
|
145
|
+
end
|
65
146
|
end
|
66
147
|
}
|
67
148
|
end
|
149
|
+
|
150
|
+
def request_stop
|
151
|
+
begin
|
152
|
+
@request_stop = true
|
153
|
+
if @snapshot_thread and @snapshot_thread.alive?
|
154
|
+
@snapshot_thread.wakeup
|
155
|
+
@snapshot_thread.join
|
156
|
+
end
|
157
|
+
@server.take_snapshot if command_log_present?
|
158
|
+
rescue => detail
|
159
|
+
puts detail
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
68
163
|
end
|