[PATCH] Cache xkbcomp output

Keith Packard keithp at keithp.com
Thu Jul 12 15:07:48 PDT 2012


Construct a unique filename based on the display name and the RMLVO
values. If that file contains valid contents, use it. Otherwise,
compile the keymap to that file and don't unlink it so that it will be
re-used the next time the server runs.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 include/xkbsrv.h |    8 +--
 xkb/ddxLoad.c    |  182 ++++++++++++++++++++++++++++++++----------------------
 xkb/xkb.c        |    5 +-
 3 files changed, 111 insertions(+), 84 deletions(-)

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index d584785..7b17282 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -857,12 +857,8 @@ extern _X_EXPORT unsigned int XkbDDXLoadKeymapByNames(DeviceIntPtr /* keybd */ ,
                                                       /* names */ ,
                                                       unsigned int /* want */ ,
                                                       unsigned int /* need */ ,
-                                                      XkbDescPtr *
-                                                      /* finfoRtrn */ ,
-                                                      char *
-                                                      /* keymapNameRtrn */ ,
-                                                      int       /* keymapNameRtrnLen */
-    );
+                                                      XkbDescPtr *xkbRtrn,
+                                                      char *path_name);
 
 extern _X_EXPORT Bool XkbDDXNamesFromRules(DeviceIntPtr /* keybd */ ,
                                            char * /* rules */ ,
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index cb2dfc3..62da8a4 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -169,10 +169,10 @@ static Bool
 XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
                            XkbComponentNamesPtr names,
                            unsigned want,
-                           unsigned need, char *nameRtrn, int nameRtrnLen)
+                           unsigned need, char *file_name)
 {
     FILE *out;
-    char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
+    char *buf = NULL;
 
     const char *emptystring = "";
     char *xkbbasedirflag = NULL;
@@ -188,10 +188,6 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
     const char *xkmfile = "-";
 #endif
 
-    snprintf(keymap, sizeof(keymap), "server-%s", display);
-
-    OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
-
 #ifdef WIN32
     strcpy(tmpname, Win32TempDir());
     strcat(tmpname, "\\xkb_XXXXXX");
@@ -216,13 +212,13 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
 
     if (asprintf(&buf,
                  "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
-                 "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
+                 "-em1 %s -emp %s -eml %s \"%s\"",
                  xkbbindir, xkbbindirsep,
                  ((xkbDebugFlags < 2) ? 1 :
                   ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)),
                  xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
                  PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
-                 xkm_output_dir, keymap) == -1)
+                 file_name) == -1)
         buf = NULL;
 
     free(xkbbasedirflag);
@@ -255,9 +251,6 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
         {
             if (xkbDebugFlags)
                 DebugF("[xkb] xkb executes: %s\n", buf);
-            if (nameRtrn) {
-                strlcpy(nameRtrn, keymap, nameRtrnLen);
-            }
             free(buf);
 #ifdef WIN32
             unlink(tmpname);
@@ -265,7 +258,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
             return TRUE;
         }
         else
-            LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
+            LogMessage(X_ERROR, "Error compiling keymap (%s)\n", file_name);
 #ifdef WIN32
         /* remove the temporary file */
         unlink(tmpname);
@@ -278,46 +271,58 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
         LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
 #endif
     }
-    if (nameRtrn)
-        nameRtrn[0] = '\0';
     free(buf);
     return FALSE;
 }
 
-static FILE *
-XkbDDXOpenConfigFile(char *mapName, char *fileNameRtrn, int fileNameRtrnLen)
+static char *
+xkb_config_pathname(char *filename)
 {
-    char buf[PATH_MAX], xkm_output_dir[PATH_MAX];
-    FILE *file;
+    char        xkm_output_dir[PATH_MAX];
+    char        *pathname;
 
-    buf[0] = '\0';
-    if (mapName != NULL) {
-        OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
-        if ((XkbBaseDirectory != NULL) && (xkm_output_dir[0] != '/')
+    OutputDirectory(xkm_output_dir, sizeof (xkm_output_dir));
+
+    if ((XkbBaseDirectory != NULL) && (xkm_output_dir[0] != '/')
 #ifdef WIN32
-            && (!isalpha(xkm_output_dir[0]) || xkm_output_dir[1] != ':')
+        && (!isalpha(xkm_output_dir[0]) || xkm_output_dir[1] != ':')
 #endif
-            ) {
-            if (snprintf(buf, PATH_MAX, "%s/%s%s.xkm", XkbBaseDirectory,
-                         xkm_output_dir, mapName) >= PATH_MAX)
-                buf[0] = '\0';
-        }
-        else {
-            if (snprintf(buf, PATH_MAX, "%s%s.xkm", xkm_output_dir, mapName)
-                >= PATH_MAX)
-                buf[0] = '\0';
-        }
-        if (buf[0] != '\0')
-            file = fopen(buf, "rb");
-        else
-            file = NULL;
+        ) {
+        if (asprintf (&pathname, "%s%s%s", XkbBaseDirectory,
+                      xkm_output_dir, filename) <= 0)
+            pathname = NULL;
     }
-    else
-        file = NULL;
-    if ((fileNameRtrn != NULL) && (fileNameRtrnLen > 0)) {
-        strlcpy(fileNameRtrn, buf, fileNameRtrnLen);
+    else {
+        if (asprintf (&pathname, "%s%s", xkm_output_dir, filename) <= 0)
+            pathname = NULL;
+    }
+    return pathname;
+}
+
+static unsigned
+xkb_load_keymap_file(char *file_name, unsigned want, unsigned need, XkbDescPtr *xkbRtrn)
+{
+    FILE *file;
+    unsigned missing;
+
+    file = fopen(file_name, "r");
+    if (file == NULL) {
+        LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
+                   file_name);
+        return 0;
+    }
+    missing = XkmReadFile(file, need, want, xkbRtrn);
+    if (*xkbRtrn == NULL) {
+        LogMessage(X_ERROR, "Error loading keymap %s\n", file_name);
+        fclose(file);
+        return 0;
+    }
+    else {
+        DebugF("Loaded XKB keymap %s, defined=0x%x\n", file_name,
+               (*xkbRtrn)->defined);
     }
-    return file;
+    fclose(file);
+    return (need | want) & (~missing);
 }
 
 unsigned
@@ -325,12 +330,21 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
                         XkbComponentNamesPtr names,
                         unsigned want,
                         unsigned need,
-                        XkbDescPtr *xkbRtrn, char *nameRtrn, int nameRtrnLen)
+                        XkbDescPtr *xkbRtrn, char *file_name)
 {
     XkbDescPtr xkb;
-    FILE *file;
-    char fileName[PATH_MAX];
-    unsigned missing;
+    unsigned provided;
+    char *local_file_name = file_name;
+
+    if (!file_name) {
+        char    local_name[PATH_MAX];
+
+        if (snprintf(local_name, sizeof (local_name), "server-%s.xkm", display) >= sizeof (local_name))
+            return 0;
+        local_file_name = xkb_config_pathname (local_name);
+        if (local_file_name == NULL)
+            return 0;
+    }
 
     *xkbRtrn = NULL;
     if ((keybd == NULL) || (keybd->key == NULL) ||
@@ -343,33 +357,31 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
         (names->geometry == NULL)) {
         LogMessage(X_ERROR, "XKB: No components provided for device %s\n",
                    keybd->name ? keybd->name : "(unnamed keyboard)");
+        if (local_file_name != file_name)
+            free(local_file_name);
         return 0;
     }
     else if (!XkbDDXCompileKeymapByNames(xkb, names, want, need,
-                                         nameRtrn, nameRtrnLen)) {
+                                         file_name)) {
         LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
+        if (local_file_name != file_name)
+            free(local_file_name);
         return 0;
     }
-    file = XkbDDXOpenConfigFile(nameRtrn, fileName, PATH_MAX);
-    if (file == NULL) {
-        LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
-                   fileName);
-        return 0;
-    }
-    missing = XkmReadFile(file, need, want, xkbRtrn);
-    if (*xkbRtrn == NULL) {
-        LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
-        fclose(file);
-        (void) unlink(fileName);
+
+    provided = xkb_load_keymap_file(file_name, want, need, xkbRtrn);
+
+    if (!xkbRtrn) {
+        unlink(local_file_name);
+        if (local_file_name != file_name)
+            free(local_file_name);
         return 0;
     }
-    else {
-        DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
-               (*xkbRtrn)->defined);
+    if (local_file_name != file_name) {
+        unlink(local_file_name);
+        free(local_file_name);
     }
-    fclose(file);
-    (void) unlink(fileName);
-    return (need | want) & (~missing);
+    return provided;
 }
 
 Bool
@@ -447,20 +459,42 @@ XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, int need)
     XkbDescPtr xkb = NULL;
     unsigned int provided;
     XkbComponentNamesRec kccgst = { 0 };
-    char name[PATH_MAX];
-
-    if (XkbRMLVOtoKcCGST(dev, rmlvo, &kccgst)) {
-        provided =
-            XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask, need, &xkb,
-                                    name, PATH_MAX);
-        if ((need & provided) != need) {
-            if (xkb) {
-                XkbFreeKeyboard(xkb, 0, TRUE);
-                xkb = NULL;
+    char *filename, *pathname;
+
+    if (asprintf(&filename, "server-%s-%s-%s-%s-%s-%s.xkm",
+                 display,
+                 rmlvo->rules,
+                 rmlvo->model,
+                 rmlvo->layout,
+                 rmlvo->variant,
+                 rmlvo->options) <= 0)
+        return NULL;
+
+    pathname = xkb_config_pathname(filename);
+    if (pathname == NULL)
+        return NULL;
+
+    provided = xkb_load_keymap_file(pathname, XkmAllIndicesMask, need, &xkb);
+
+    if ((need & provided) != need) {
+        (void) unlink(pathname);
+        if (xkb)
+            XkbFreeKeyboard(xkb, 0, TRUE);
+        if (XkbRMLVOtoKcCGST(dev, rmlvo, &kccgst)) {
+            provided = XkbDDXLoadKeymapByNames(dev, &kccgst, XkmAllIndicesMask,
+                                               need, &xkb, pathname);
+            if ((need & provided) != need) {
+                if (xkb) {
+                    (void) unlink(pathname);
+                    XkbFreeKeyboard(xkb, 0, TRUE);
+                    xkb = NULL;
+                }
             }
         }
     }
 
+    free (pathname);
+
     XkbFreeComponentNames(&kccgst, FALSE);
     return xkb;
 }
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 4440a98..8b2684b 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5704,7 +5704,6 @@ ProcXkbGetKbdByName(ClientPtr client)
     XkbComponentNamesRec names = { 0 };
     XkbDescPtr xkb, new;
     unsigned char *str;
-    char mapFile[PATH_MAX];
     unsigned len;
     unsigned fwant, fneed, reported;
     int status;
@@ -5762,7 +5761,6 @@ ProcXkbGetKbdByName(ClientPtr client)
         geom_changed = FALSE;
     }
 
-    memset(mapFile, 0, PATH_MAX);
     rep.type = X_Reply;
     rep.deviceID = dev->id;
     rep.sequenceNumber = client->sequence;
@@ -5784,8 +5782,7 @@ ProcXkbGetKbdByName(ClientPtr client)
     }
 
     /* We pass dev in here so we can get the old names out if needed. */
-    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
-                                        mapFile, PATH_MAX);
+    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new, NULL);
     rep.newKeyboard = FALSE;
     rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
 
-- 
1.7.10.4



More information about the xorg-devel mailing list