paho.mqtt.c icon indicating copy to clipboard operation
paho.mqtt.c copied to clipboard

Persistence: `containskeyUnix` could be much faster

Open dismirlian opened this issue 2 years ago • 1 comments

containskeyUnix currently loops over the whole directory. It can be simplified significantly. With this change, persistence loads much faster (for a very large persistence "database", the speedup can be 20' -> 1').

diff --git a/src/MQTTPersistenceDefault.c b/src/MQTTPersistenceDefault.c
index 48aa34e..46fd64f 100644
--- a/src/MQTTPersistenceDefault.c
+++ b/src/MQTTPersistenceDefault.c
@@ -484,55 +484,20 @@ exit:
 int containskeyUnix(char *dirname, char *key)
 {
 	int notFound = MQTTCLIENT_PERSISTENCE_ERROR;
-	char *filekey, *ptraux;
-	DIR *dp = NULL;
-	struct dirent *dir_entry;
 	struct stat stat_info;
 
-	FUNC_ENTRY;
-	if((dp = opendir(dirname)) != NULL)
-	{
-		while((dir_entry = readdir(dp)) != NULL && notFound)
-		{
-			const size_t allocsize = strlen(dirname) + strlen(dir_entry->d_name) + 2;
-			char* filename = malloc(allocsize);
-
-			if (!filename)
-			{
-				notFound = PAHO_MEMORY_ERROR;
-				goto exit;
-			}
-			if (snprintf(filename, allocsize, "%s/%s", dirname, dir_entry->d_name) >= allocsize)
-			{
-				free(filename);
-				notFound = MQTTCLIENT_PERSISTENCE_ERROR;
-				goto exit;
-			}
-			lstat(filename, &stat_info);
-			free(filename);
-			if(S_ISREG(stat_info.st_mode))
-			{
-				if ((filekey = malloc(strlen(dir_entry->d_name) + 1)) == NULL)
-				{
-					notFound = PAHO_MEMORY_ERROR;
-					goto exit;
-				}
-				strcpy(filekey, dir_entry->d_name);
-				ptraux = strstr(filekey, MESSAGE_FILENAME_EXTENSION);
-				if ( ptraux != NULL )
-					*ptraux = '\0' ;
-				if(strcmp(filekey, key) == 0)
-					notFound = 0;
-				free(filekey);
-			}
-		}
-	}
-
-exit:
-	if (dp)
-		closedir(dp);
-	FUNC_EXIT_RC(notFound);
-	return notFound;
+    FUNC_ENTRY;
+    const size_t allocsize = strlen(dirname) + 1 + strlen(key) + strlen(MESSAGE_FILENAME_EXTENSION) + 1;
+    char* filename = malloc(allocsize);
+    snprintf(filename, allocsize, "%s/%s" MESSAGE_FILENAME_EXTENSION, dirname, key);
+    lstat(filename, &stat_info);
+    free(filename);
+    if(S_ISREG(stat_info.st_mode))
+    {
+        notFound = 0;
+    }
+    FUNC_EXIT_RC(notFound);
+    return notFound;
 }
 #endif

dismirlian avatar Mar 28 '22 17:03 dismirlian

Would you like to make a PR?

icraggs avatar Mar 29 '22 12:03 icraggs