i3 - improved tiling WM


Implement shmlog command

Patch status: superseded

Patch by Alexander Berntsen

Long description:

Add shmlog command that takes <size>|toggle|on|off. Separate logbuffer
management into open_logbuffer() and close_logbuffer(). Make
t/187-commands-parser.t expect 'shmlog'.

To apply this patch, use:
curl http://cr.i3wm.org/patch/175/raw.patch | git am

b/include/commands.h

21
@@ -271,4 +271,10 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name);
22
  */
23
 void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id);
24
 
25
+/*
26
+ * Implementation of 'shmlog <size>|toggle|on|off'
27
+ *
28
+ */
29
+void cmd_shmlog(I3_CMD, char *argument);
30
+
31
 #endif

b/include/log.h

36
@@ -39,6 +39,18 @@ extern int shmlog_size;
37
 void init_logging(void);
38
 
39
 /**
40
+ * Opens the logbuffer.
41
+ *
42
+ */
43
+void open_logbuffer(void);
44
+
45
+/**
46
+ * Closes the logbuffer.
47
+ *
48
+ */
49
+void close_logbuffer(void);
50
+
51
+/**
52
  * Set debug logging.
53
  *
54
  */

b/parser-specs/commands.spec

59
@@ -19,6 +19,7 @@ state INITIAL:
60
   'exit' -> call cmd_exit()
61
   'restart' -> call cmd_restart()
62
   'reload' -> call cmd_reload()
63
+  'shmlog' -> SHMLOG
64
   'border' -> BORDER
65
   'layout' -> LAYOUT
66
   'append_layout' -> APPEND_LAYOUT
67
@@ -62,6 +63,12 @@ state EXEC:
68
   command = string
69
       -> call cmd_exec($nosn, $command)
70
 
71
+# shmlog <size>|flip|on|off
72
+state SHMLOG:
73
+  # argument may be a number
74
+  argument = string
75
+    -> call cmd_shmlog($argument)
76
+
77
 # border normal|none|1pixel|toggle|1pixel
78
 state BORDER:
79
   border_style = 'normal', 'pixel'

b/src/commands.c

84
@@ -13,6 +13,7 @@
85
 #include <stdarg.h>
86
 
87
 #include "all.h"
88
+#include "shmlog.h"
89
 
90
 // Macros to make the YAJL API a bit easier to use.
91
 #define y(x, ...) yajl_gen_ ## x (cmd_output->json_gen, ##__VA_ARGS__)
92
@@ -2027,3 +2028,27 @@ void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id) {
93
 
94
     update_barconfig();
95
 }
96
+
97
+/*
98
+ * Implementation of 'shmlog <size>|toggle|on|off'
99
+ *
100
+ */
101
+void cmd_shmlog(I3_CMD, char *argument) {
102
+    if (!strcmp(argument,"toggle"))
103
+        /* Toggle if default is not 0. If it is 0, set to default. */
104
+        shmlog_size = shmlog_size ? -shmlog_size : default_shmlog_size;
105
+    else if (!strcmp(argument, "off"))
106
+        shmlog_size = 0;
107
+    else if (!strcmp(argument, "on"))
108
+        shmlog_size = default_shmlog_size;
109
+    else {
110
+        /* Restart logging with the new size in the argument. */
111
+        shmlog_size = 0;
112
+        LOG("Restarting shm logging...\n");
113
+        init_logging();
114
+        shmlog_size = atoi(argument);
115
+    }
116
+    LOG("%s shm logging\n", shmlog_size > 0 ? "Enabling" : "Disabling");
117
+    init_logging();
118
+    ysuccess(true);
119
+}

b/src/log.c

124
@@ -89,10 +89,21 @@ void init_logging(void) {
125
             }
126
         }
127
     }
128
+    /* Start SHM logging if shmlog_size is > 0. shmlog_size is SHMLOG_SIZE by
129
+     * default on development versions, and 0 on release versions. If it is
130
+     * not > 0, the user has turned it off, so let's close the logbuffer. */
131
+     if (shmlog_size > 0 && logbuffer == NULL)
132
+        open_logbuffer();
133
+     else if (shmlog_size <= 0 && logbuffer)
134
+        close_logbuffer();
135
+     atexit(purge_zerobyte_logfile);
136
+}
137
 
138
-    /* If this is a debug build (not a release version), we will enable SHM
139
-     * logging by default, unless the user turned it off explicitly. */
140
-    if (logbuffer == NULL && shmlog_size > 0) {
141
+/*
142
+ * Opens the logbuffer.
143
+ *
144
+ */
145
+void open_logbuffer(void) {
146
         /* Reserve 1% of the RAM for the logfile, but at max 25 MiB.
147
          * For 512 MiB of RAM this will lead to a 5 MiB log buffer.
148
          * At the moment (2011-12-10), no testcase leads to an i3 log
149
@@ -127,10 +138,8 @@ void init_logging(void) {
150
 
151
         logbuffer = mmap(NULL, logbuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, logbuffer_shm, 0);
152
         if (logbuffer == MAP_FAILED) {
153
-            close(logbuffer_shm);
154
-            shm_unlink(shmlogname);
155
+            close_logbuffer();
156
             fprintf(stderr, "Could not mmap SHM segment for the i3 log: %s\n", strerror(errno));
157
-            logbuffer = NULL;
158
             return;
159
         }
160
 
161
@@ -148,8 +157,16 @@ void init_logging(void) {
162
         logwalk = logbuffer + sizeof(i3_shmlog_header);
163
         loglastwrap = logbuffer + logbuffer_size;
164
         store_log_markers();
165
-    }
166
-    atexit(purge_zerobyte_logfile);
167
+}
168
+
169
+/*
170
+ * Closes the logbuffer.
171
+ *
172
+ */
173
+void close_logbuffer(void) {
174
+    close(logbuffer_shm);
175
+    shm_unlink(shmlogname);
176
+    logbuffer = NULL;
177
 }
178
 
179
 /*

b/testcases/t/187-commands-parser.t

184
@@ -144,7 +144,7 @@ is(parser_calls("\nworkspace test"),
185
 ################################################################################
186
 
187
 is(parser_calls('unknown_literal'),
188
-   "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" .
189
+   "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" .
190
    "ERROR: Your command: unknown_literal\n" .
191
    "ERROR:               ^^^^^^^^^^^^^^^",
192
    'error for unknown literal ok');