Uploaded image for project: 'Crowd Data Center'
  1. Crowd Data Center
  2. CWD-3495

PostgreSQL directory import from internal -> internal causes hang if overwrite is enabled

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Low Low
    • 2.7
    • None
    • None
    • None

      Repro steps (using Crowd 2.6.4 set up on PostgreSQL 8.4.17):

      1. Create an internal directory dirA
      2. Add 2 groups to dirA:
      • users-group
      • admins-group
      1. Add two users to dirA
      • user1 (member of users-group and admins-group)
      • user2 (member of users-group)
      1. Create an internal directory dirB
      2. Import users from dirA to dirB, without overwriting existing
      • 2 users, 2 groups, 3 group-memberships imported
      1. Import users from dirA to dirB, this time overwriting existing
      • Import hangs on org.postgresql.core.v3.QueryExecutorImpl.processResults() (in PostgreSQL JDBC driver)

      Found while investigating CWD-1739.

            [CWD-3495] PostgreSQL directory import from internal -> internal causes hang if overwrite is enabled

            Caspar Krieger (Inactive) added a comment - Added API change notes to https://ecosystem.atlassian.net/wiki/display/EMBCWD/API+Upgrade+Guides

            Okay, I tracked down what's going on.

            Adding groups in batch is done in separate sets of transactions (to avoid impacting db performance), but this means that groups which are removed earlier (because we intend to overwrite them) may not yet be removed in the db because the removal is done in the single transaction for that action, which is still ongoing and uncommitted when existing groups are removed.

            CrowdXWorkTransactionInterceptor is responsible for opening and closing transactions for actions, but does not allow a transaction to be committed before the end of the action, so when groups are being added again then we have a nested transaction with changes in both. Hibernate does not support this, and it causes a hang with postgresql.

            Manually removing groups in their own new transaction and then committing that before adding the to-be-imported ones works, but pollutes DirectoryManagerGeneric with Spring's transaction handling code which probably shouldn't belong there.

            Instead, I opted to remove the groups in a transaction by using the same batch process as is used when adding them. This ensures that the changes of removing the groups will be visible to the transaction which adds the groups back again.

            The same type of thing applies to importing and overwriting users.

            Caspar Krieger (Inactive) added a comment - Okay, I tracked down what's going on. Adding groups in batch is done in separate sets of transactions (to avoid impacting db performance), but this means that groups which are removed earlier (because we intend to overwrite them) may not yet be removed in the db because the removal is done in the single transaction for that action, which is still ongoing and uncommitted when existing groups are removed. CrowdXWorkTransactionInterceptor is responsible for opening and closing transactions for actions, but does not allow a transaction to be committed before the end of the action, so when groups are being added again then we have a nested transaction with changes in both. Hibernate does not support this, and it causes a hang with postgresql. Manually removing groups in their own new transaction and then committing that before adding the to-be-imported ones works, but pollutes DirectoryManagerGeneric with Spring's transaction handling code which probably shouldn't belong there. Instead, I opted to remove the groups in a transaction by using the same batch process as is used when adding them. This ensures that the changes of removing the groups will be visible to the transaction which adds the groups back again. The same type of thing applies to importing and overwriting users.

            This seems to be caused by transactions being handled incorrectly when doing an import & overwriting groups.

            Specifically, the cwd_group table has CONSTRAINT uk_group_name_dir_id UNIQUE (lower_group_name , directory_id ) and this is violated when we do an import overwriting groups because we delete groups in the transaction opened by the "TransactionalInvocation" interceptor, but then we open a new transaction (without committing the previous one) to recreate the groups in the directory.

            This causes a duplicate key constraint error in the postgres logs, but it only appears once Crowd is shutdown, possibly because of some deadlock caused by the 2 to-be-conflicting transactions:

            2013-08-08 16:11:27 EST LOG:  unexpected EOF on client connection
            2013-08-08 16:11:27 EST ERROR:  duplicate key value violates unique constraint "uk_group_name_dir_id"
            2013-08-08 16:11:27 EST STATEMENT:  insert into cwd_group (group_name, lower_group_name, active, is_local, created_date, updated_date, description, group_type, directory_id, id) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
            2013-08-08 16:11:27 EST LOG:  could not send data to client: Broken pipe
            2013-08-08 16:11:27 EST LOG:  unexpected EOF on client connection
            

            Caspar Krieger (Inactive) added a comment - - edited This seems to be caused by transactions being handled incorrectly when doing an import & overwriting groups. Specifically, the cwd_group table has CONSTRAINT uk_group_name_dir_id UNIQUE (lower_group_name , directory_id ) and this is violated when we do an import overwriting groups because we delete groups in the transaction opened by the "TransactionalInvocation" interceptor, but then we open a new transaction (without committing the previous one) to recreate the groups in the directory. This causes a duplicate key constraint error in the postgres logs, but it only appears once Crowd is shutdown, possibly because of some deadlock caused by the 2 to-be-conflicting transactions: 2013-08-08 16:11:27 EST LOG: unexpected EOF on client connection 2013-08-08 16:11:27 EST ERROR: duplicate key value violates unique constraint "uk_group_name_dir_id" 2013-08-08 16:11:27 EST STATEMENT: insert into cwd_group (group_name, lower_group_name, active, is_local, created_date, updated_date, description, group_type, directory_id, id) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) 2013-08-08 16:11:27 EST LOG: could not send data to client: Broken pipe 2013-08-08 16:11:27 EST LOG: unexpected EOF on client connection

              ckrieger Caspar Krieger (Inactive)
              ckrieger Caspar Krieger (Inactive)
              Affected customers:
              0 This affects my team
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: