rimmed pushed a commit to branch master.

http://git.enlightenment.org/tools/eflete.git/commit/?id=2f689a8c7e1de16798571f3d509b76307b10c8eb

commit 2f689a8c7e1de16798571f3d509b76307b10c8eb
Author: Vyacheslav Reutskiy <v.reuts...@samsung.com>
Date:   Mon Nov 28 08:56:41 2016 +0200

    project manager: rework lock procedure
    
    For adaptate lock to Windows was add file project.lock. This file will
    create on project open and removed on close. File save the pid how lock
    given project.
    
    Change-Id: I955c4a4e543374d56a286e729b3f0fe1232719fa
---
 src/bin/project_manager/project_manager2.c      | 209 ++++++++++++------------
 src/bin/project_manager/project_manager2_data.h |  13 +-
 2 files changed, 109 insertions(+), 113 deletions(-)

diff --git a/src/bin/project_manager/project_manager2.c 
b/src/bin/project_manager/project_manager2.c
index 6e7d139..db00eed 100644
--- a/src/bin/project_manager/project_manager2.c
+++ b/src/bin/project_manager/project_manager2.c
@@ -223,7 +223,6 @@ _project_create(Project_Process_Data *ppd)
         last_error = PM_PROJECT_CREATE_PRO_FAILED;
         goto exit;
      }
-   pro->pro_fd = -1;
    ecore_file_mkdir(pro->develop_path);
    snprintf(buf, sizeof(buf), "%s/images", pro->develop_path);
    ecore_file_mkdir(buf);
@@ -406,100 +405,130 @@ _end_send(void *data)
    func(udata, last_error, project);
 }
 
-#ifndef _WIN32
 static Eina_Bool
-_lock_try(const char *path, Eina_Bool check, int *pro_fd)
+_project_lock(Project *project)
 {
-   struct flock lock, savelock;
+   char path[PATH_MAX];
+   char buf[BUFF_MAX];
+   char *dir;
+   int pid;
 
-   int fd = open(path, O_RDWR);
-   if (fd < 1)
-     {
-        ERR(" %s\n", strerror(errno));
-        return check;
-     }
+   assert(project != NULL);
 
-   lock.l_type    = F_WRLCK;   /* Test for any lock on any part of file. */
-   lock.l_whence  = SEEK_SET;
-   lock.l_start   = 0;
-   lock.l_len     = 0;
-   lock.l_pid     = 0;
-   savelock = lock;
-   if (fcntl(fd, F_GETLK, &lock) == -1)
+   pid = getpid();
+
+   dir = ecore_file_dir_get(project->pro_path);
+   snprintf(path, sizeof(path), "%s/project.lock", dir);
+   free(dir);
+   project->fd_lock = open(path, O_RDWR | O_CREAT, S_IWUSR);
+   if (!project->fd_lock)
      {
-        ERR("Failed get lock status of file [%s] error message [%s].\n", path, 
strerror(errno));
-        close(fd);
+        ERR("%s: %s\n", path, strerror(errno));
         return false;
      }
-   if ((lock.l_pid != 0) && ((lock.l_type == F_WRLCK) || (lock.l_type == 
F_RDLCK)))
+
+#ifndef _WIN32
+   struct flock fl;
+   fl.l_type = F_WRLCK;
+   fl.l_whence = SEEK_SET;
+   fl.l_start = 0;
+   fl.l_len = 0;
+   fl.l_pid = pid;
+   if (fcntl(project->fd_lock, F_SETLK, &fl) == -1)
      {
-        ERR("Process %d has a write lock already!", lock.l_pid);
-        close(fd);
+        ERR("Unable to lock project file '%s'\n", path);
+        close(project->fd_lock);
         return false;
      }
+#endif /* _WIN32 */
 
-   /* if flag check is false not need to lock the file, just close handler */
-   if (!check)
+   snprintf(buf, sizeof(buf), "%d\n", pid);
+   if (!write(project->fd_lock, buf, strlen(buf)))
      {
-        close(fd);
-        return true;
+        close(project->fd_lock);
+        return false;
      }
 
-   if (pro_fd)
-     {
-        savelock.l_pid = getpid();
-        if (fcntl(fd, F_SETLK, &savelock) == -1)
-          {
-             ERR("Failed set lock status of file [%s] error message [%s].\n", 
path, strerror(errno));
-             close(fd);
-             return false;
-          }
-        *pro_fd = fd;
-        return true;
-     }
-   close(fd);
-   return false;
+   return true;
 }
-#else
+
 static Eina_Bool
-_lock_try(const char *path, Eina_Bool check, HANDLE *pro_fd)
+_project_unlock(Project *project)
 {
-   LPCTSTR  lpFileName = path;
-   DWORD dwDesiredAccess = GENERIC_READ|GENERIC_WRITE;
-   DWORD  dwShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
-   LPSECURITY_ATTRIBUTES  lpSecurityAttributes = NULL;
-   DWORD  dwCreationDisposition = OPEN_EXISTING;
-   DWORD  dwFlagsAndAttributes = 0;
-   HANDLE  hTemplateFile = NULL;
-   HANDLE fd = CreateFile(lpFileName,
-                          dwDesiredAccess,
-                          dwShareMode,
-                          lpSecurityAttributes,
-                          dwCreationDisposition,
-                          dwFlagsAndAttributes,
-                          hTemplateFile);
-
-   if (fd == INVALID_HANDLE_VALUE)
+   char path[PATH_MAX];
+   char *dir;
+
+   assert(project != NULL);
+
+
+   dir = ecore_file_dir_get(project->pro_path);
+   snprintf(path, sizeof(path), "%s/project.lock", dir);
+   free(dir);
+
+#ifndef _WIN32
+   struct flock fl;
+   fl.l_type = F_UNLCK;
+   fl.l_whence = SEEK_SET;
+   fl.l_start = 0;
+   fl.l_len = 0;
+   fl.l_pid = getpid();
+   if (fcntl(project->fd_lock, F_SETLK, &fl) == -1)
      {
-        ERR("The file '%s' cannot be opened in mode read-write!", path);
-        return !check;
+        ERR("Unable to unlock file '%s'\n", path);
+        return false;
      }
+#endif /* _WIN32 */
+
+   close(project->fd_lock);
+   if (!ecore_file_unlink(path))
+     ERR("unlink %s: %s\n", path, strerror(errno));
+
+   return true;
+}
+
+static Eina_Bool
+_project_trylock(const char *pro_path)
+{
+   int fd;
+   char *dir;
+   char path[PATH_MAX];
+   Eina_Bool ret = true;
 
-   if (!check)
+   assert(path != NULL);
+
+   dir = ecore_file_dir_get(pro_path);
+   snprintf(path, sizeof(path), "%s/project.lock", dir);
+   free(dir);
+   if (!ecore_file_exists(path))
+     return true;
+
+
+   fd = open(path, O_RDWR);
+   if (fd < 1)
      {
-        CloseHandle(fd);
-        return true;
+        ERR(" %s\n", strerror(errno));
+        return false;
      }
-    if (pro_fd)
+
+#ifndef _WIN32
+   struct flock fl;
+   fl.l_type = F_UNLCK;
+   fl.l_whence = SEEK_SET;
+   fl.l_start = 0;
+   fl.l_len = 0;
+   fl.l_pid = 0;
+   if (fcntl(fd, F_GETLK, &fl) != -1)
      {
-        *pro_fd = fd;
-        return true;
+        if (fl.l_type != F_UNLCK)
+          ret = false;
      }
+   else
+     ret = false;
+#endif /* _WIN32 */
 
-    CloseHandle(fd);
-    return false;
+   close(fd);
+   return ret;
 }
-#endif
 
 static Eina_Bool
 _exe_output_handler(void *data,
@@ -545,6 +574,8 @@ _exporter_finish_handler(void *data,
 static void
 _project_close_internal(Project *project)
 {
+   _project_unlock(project);
+
    if (project->global_object)
      evas_object_del(project->global_object);
 
@@ -572,13 +603,6 @@ _project_close_internal(Project *project)
 
    if (project->ef)
      eet_close(project->ef);
-#ifdef _WIN32
-   if (project->pro_fd != INVALID_HANDLE_VALUE)
-     CloseHandle(project->pro_fd);
-#else
-   if (project->pro_fd != -1)
-     close(project->pro_fd);
-#endif
 }
 
 static PM_Project_Result
@@ -587,12 +611,6 @@ _project_open_internal(Project_Process_Data *ppd)
    char buf[PATH_MAX];
    char *file_dir;
 
-#ifdef _WIN32
-   HANDLE pro_fd = NULL;
-#else
-   int pro_fd = -1;
-#endif
-
    Eet_File *ef;
    char *tmp;
    int tmp_len;
@@ -601,20 +619,6 @@ _project_open_internal(Project_Process_Data *ppd)
    last_error = PM_PROJECT_SUCCESS;
 
    edje_file_cache_flush();
-   if (!_lock_try(ppd->path, true,  &pro_fd))
-     {
-        /* really this case is unlickly, but we need handle it */
-        ERR("Project file already locked by another application");
-#ifdef _WIN32
-        CloseHandle(pro_fd);
-#else
-        if (pro_fd != -1)
-          close(pro_fd);
-#endif
-        last_error = PM_PROJECT_LOCKED;
-        return last_error;
-     }
-
    ef = eet_open(ppd->path, EET_FILE_MODE_READ_WRITE);
    if (!ef)
      {
@@ -635,7 +639,6 @@ _project_open_internal(Project_Process_Data *ppd)
 
    ppd->project->ef = ef;
    ppd->project->pro_path = eina_stringshare_add(ppd->path);
-   ppd->project->pro_fd = pro_fd;
 
    file_dir = ecore_file_dir_get(ppd->path);
    ppd->project->dev = eina_stringshare_printf("%s/%s.dev", file_dir, 
ppd->name);
@@ -649,7 +652,7 @@ _project_open_internal(Project_Process_Data *ppd)
    snprintf(buf, sizeof(buf), "%s/fonts", ppd->project->develop_path);
    ecore_file_mkdir(buf);
 
-
+   _project_lock(ppd->project);
 
    /* updating .dev file path */
    tmp = strdup(ppd->path);
@@ -828,14 +831,6 @@ _project_import_edj(Project_Process_Data *ppd)
    if (!ppd->project)
      return last_error;
 
-   if (!_lock_try(ppd->project->pro_path, true, &ppd->project->pro_fd))
-     {
-        /* really this case is unlickly, but we need handle it */
-        last_error = PM_PROJECT_LOCKED;
-        _end_send(ppd);
-        return last_error;
-     }
-
    groups = edje_file_collection_list(ppd->edj);
    count = eina_list_count(groups);
    edje_edit_string_list_free(groups);
@@ -1458,7 +1453,7 @@ pm_lock_check(const char *path)
 {
    if (ecore_file_exists(path) == false)
      return true;
-   return _lock_try(path, false, NULL);
+   return _project_trylock(path);
 }
 
 const char *
diff --git a/src/bin/project_manager/project_manager2_data.h 
b/src/bin/project_manager/project_manager2_data.h
index c51a975..4545153 100644
--- a/src/bin/project_manager/project_manager2_data.h
+++ b/src/bin/project_manager/project_manager2_data.h
@@ -41,12 +41,6 @@ struct _Project
 {
    /* version of project file */
    int version;
-   /** File descriptor of open "*.pro" file. Needed for keep that file locked*/
-#ifdef _WIN32
-   HANDLE pro_fd;
-#else
-   int pro_fd;
-#endif
    /** The project name */
    Eina_Stringshare *name;
    /** project path */
@@ -62,6 +56,13 @@ struct _Project
    /** this is saved file. */
    Eina_Stringshare *saved_edj;
 
+   /** File descriptor of open "project.lock" file. Needed for keep that file 
locked*/
+#ifdef _WIN32
+   HANDLE fd_lock;
+#else
+   int fd_lock;
+#endif
+
    /** path where will be saved the develop edj file */
    Eina_Stringshare *develop_path;
    /** compile options for release edj file. see edje_cc reference */

-- 


Reply via email to