Use a sorted list of files in desc_gentool to avoid unnecessary rebuilds. 06/86006/1
authorJunghyun Kim <jh0822.kim@samsung.com>
Tue, 30 Aug 2016 06:23:36 +0000 (15:23 +0900)
committerJunghyun Kim <jh0822.kim@samsung.com>
Tue, 30 Aug 2016 06:23:36 +0000 (15:23 +0900)
- PROBLEM
We use OBS to build packages in Tizen.
There is a mechanism not to rebuild when the result binary is the same.
For example, there is a dependency graph: A->B->C.
If A is modified, B would be built.
If the result RPM of B is not changed, OBS does not trigger a build of C.
To effectively use this mechanism, each packages make sure that
the result binary should be the same if the input source is the same.

There is a reason we found is that the file list given by
python(os.walk(), os.listdir()), widely used executable(find),
and system call(readdir()) is unordered.
In this case, different OBS workers can make different results
because of the file list in different order.

The same thing happens in webapi-plugins.
desc_gentool uses readdir_r() which returns an unordered list of files.

- SOLUTION
Use scandir() instead of readdir_r().
We can obtain a sorted list of files when using scandir().

Change-Id: I2faf53d816ce40744444e0815eab35cd6c9adad0
Signed-off-by: Junghyun Kim <jh0822.kim@samsung.com>
src/tool/desc_gentool.cc

index c93f5db9e44096155e6ce4078bd053c6c3103558..0583aa7b3b7502c983ec23d512b5cd0e12ac0974 100644 (file)
@@ -7,6 +7,8 @@
 #include <dlfcn.h>
 #include <dirent.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
 
 #include <common/extension.h>
 
@@ -163,12 +165,11 @@ int main(int argc, char* argv[]) {
     return -1;
   }
 
-  DIR * dir;
-  struct dirent ent = {0};
-  struct dirent* result = nullptr;
-  if ((dir = opendir(tec_path.c_str())) != NULL) {
-    while ((0 == (readdir_r(dir, &ent, &result))) && result) {
-      std::string fname = ent.d_name;
+  struct dirent** namelist;
+  int num_entries = scandir(tec_path.c_str(), &namelist, NULL, alphasort);
+  if( num_entries >= 0 ) {
+    for( int i = 0; i < num_entries; ++i ) {
+      std::string fname = namelist[i]->d_name;
 
       if (fname.size() >= prefix_.size() + postfix_.size() &&
           !fname.compare(0, prefix_.size(), prefix_) &&
@@ -206,12 +207,14 @@ int main(int argc, char* argv[]) {
         //
         // dlclose(handle);
       }
+      free(namelist[i]);
     }
-    closedir(dir);
-
+    free(namelist);
     print_json();
   } else {
-    std::cerr << "path not exist : " << tec_path << std::endl;
+    perror("scandir");
+    if( errno == ENOENT )
+      std::cerr << "path not exist : " << tec_path << std::endl;
     return -1;
   }