Index: comment.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/comment.inc,v
retrieving revision 1.99
diff -u -F^f -r1.99 comment.inc
--- comment.inc	4 Oct 2007 17:34:52 -0000	1.99
+++ comment.inc	12 Oct 2007 14:04:42 -0000
@@ -70,8 +70,43 @@ function project_issue_comment(&$arg, $o
       unset($form['page'], $form['issue_details']);
       return $form;
     case 'insert':
-      db_query("INSERT INTO {project_issue_comments} (nid, cid, pid, rid, component, category, priority, assigned, sid, title, timestamp) VALUES (%d, %d, %d, %d, '%s', '%s', %d, %d, %d, '%s', %d)", $arg['nid'], $arg['cid'], $arg['project_info']['pid'], $arg['project_info']['rid'], $arg['project_info']['component'], $arg['category'], $arg['priority'], $arg['assigned'], $arg['sid'], $arg['title'], $arg['timestamp']);
-      project_issue_update_by_comment($arg, 'insert');
+      // Get a lock on the issue in order to generate the next comment ID.
+      $tries = 20;
+      $sleep_increment = 0;
+      while ($tries) {
+        $lock = db_query("UPDATE {project_issues} SET locked = 1 WHERE nid = %d AND locked = 0", $arg['nid']);
+        if (db_affected_rows()) {
+          $id = db_result(db_query("SELECT last_comment_id FROM {project_issues} WHERE nid = %d", $arg['nid'])) + 1;
+          db_query("UPDATE {project_issues} SET last_comment_id = %d WHERE nid = %d", $id, $arg['nid']);
+          db_query("UPDATE {project_issues} SET locked = 0 WHERE nid = %d", $arg['nid']);
+          break;
+        }
+
+        // Wait an increasingly random amount of time before the next lock attempt.
+        $sleep = rand(10000, 1000000) +  $sleep_increment;
+        usleep($sleep);
+        $sleep_increment += 50000;
+        $tries--;
+      }
+
+      if (isset($id)) {
+        db_query("INSERT INTO {project_issue_comments} (nid, cid, pid, rid, component, category, priority, assigned, sid, title, timestamp) VALUES (%d, %d, %d, %d, '%s', '%s', %d, %d, %d, '%s', %d)", $arg['nid'], $arg['cid'], $arg['project_info']['pid'], $arg['project_info']['rid'], $arg['project_info']['component'], $arg['category'], $arg['priority'], $arg['assigned'], $arg['sid'], $arg['title'], $arg['timestamp']);
+        db_query("UPDATE {comments} SET subject = '%s' WHERE cid = %d", "#$id", $arg['nid']);
+        project_issue_update_by_comment($arg, 'insert');
+
+      }
+      else {
+        drupal_set_message(t('There was an error submitting your comment -- please try again. If the problem persists, contact the system administrator.'), 'error');
+        watchdog('project_issue', t('Error obtaining lock for project issue %nid', array('%nid' => $arg['nid'])), WATCHDOG_ERROR, 'node/'. $arg['nid']);
+        // This is a bit extreme, but we have to clean up the failed comment, or it will appear
+        // on the issue.
+        _comment_delete_thread((object) $arg);
+        _comment_update_node_statistics($arg['nid']);
+        cache_clear_all();
+        // The hard redirect prevents any bogus data from being inserted for the failed comment.
+        drupal_goto('node/'. $arg['nid']);
+      }
+
       break;
     case 'update':
       project_issue_update_by_comment($arg, 'update');
Index: issue.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/issue.inc,v
retrieving revision 1.263
diff -u -F^f -r1.263 issue.inc
--- issue.inc	7 Oct 2007 06:45:16 -0000	1.263
+++ issue.inc	12 Oct 2007 14:04:43 -0000
@@ -930,7 +930,7 @@ function project_issue_insert($node) {
     $original_issue_data->$field = $node->$field;
   }
 
-  db_query("INSERT INTO {project_issues} (nid, pid, category, component, priority, rid, assigned, sid, file_path, file_mime, file_size, original_issue_data) VALUES (%d, %d, '%s', '%s', %d, %d, %d, %d, '%s', '%s', %d, '%s')", $node->nid, $node->pid, $node->category, $node->component, $node->priority, $node->rid, $node->assigned, $node->sid, $file->filepath, $file->filemime, $file->filesize, serialize($original_issue_data));
+  db_query("INSERT INTO {project_issues} (nid, pid, category, component, priority, rid, assigned, sid, file_path, file_mime, file_size, original_issue_data, last_comment_id, locked) VALUES (%d, %d, '%s', '%s', %d, %d, %d, %d, '%s', '%s', %d, '%s', %d, %d)", $node->nid, $node->pid, $node->category, $node->component, $node->priority, $node->rid, $node->assigned, $node->sid, $file->filepath, $file->filemime, $file->filesize, serialize($original_issue_data), 0, 0);
   project_mail_notify($node);
 }
 
Index: project_issue.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/project_issue.install,v
retrieving revision 1.24
diff -u -F^f -r1.24 project_issue.install
--- project_issue.install	7 Oct 2007 21:42:53 -0000	1.24
+++ project_issue.install	12 Oct 2007 14:04:43 -0000
@@ -34,6 +34,8 @@ function project_issue_install() {
           file_mime varchar(255) NOT NULL default '',
           file_size int NOT NULL default 0,
           original_issue_data text NOT NULL default '',
+          last_comment_id int NOT NULL default 0,
+          locked tinyint NOT NULL default 0,
           PRIMARY KEY (nid),
           KEY project_issues_pid (pid),
           KEY project_issues_sid (sid),
@@ -100,6 +102,8 @@ function project_issue_install() {
             file_mime varchar(255) default '' NOT NULL,
             file_size int default 0 NOT NULL,
             original_issue_data text NOT NULL default '',
+            last_comment_id int NOT NULL default 0,
+            locked smallint NOT NULL default 0,
             PRIMARY KEY (nid)
           );");
         db_query("CREATE INDEX {project_issues}_pid_idx ON {project_issues}(pid)");
@@ -416,6 +420,8 @@ function project_issue_update_5200() {
           INDEX nid_timestamp (nid, timestamp)
         ) /*!40100 DEFAULT CHARACTER SET utf8 */");
       $ret[] = update_sql("ALTER TABLE {project_issues} ADD COLUMN original_issue_data text NOT NULL DEFAULT ''");
+      $ret[] = update_sql("ALTER TABLE {project_issues} ADD COLUMN last_comment_id int NOT NULL default 0");
+      $ret[] = update_sql("ALTER TABLE {project_issues} ADD COLUMN locked tinyint NOT NULL default 0");
       break;
 
     case 'pgsql':
@@ -437,6 +443,8 @@ function project_issue_update_5200() {
         $ret[] = update_sql('CREATE INDEX {project_issue_comments}_nid_timestamp_idx ON {project_issue_comments} (nid, timestamp)');
       }
       db_add_column(&$ret, 'project_issues', 'original_issue_data', 'text', array('not null' => TRUE, 'default' => "''"));
+      db_add_column(&$ret, 'project_issues', 'last_comment_id', 'int', array('not null' => TRUE, 'default' => 0));
+      db_add_column(&$ret, 'project_issues', 'locked', 'smallint', array('not null' => TRUE, 'default' => 0));
     break;
   }
   $ret[] = update_sql("UPDATE {node} SET comment = ". COMMENT_NODE_READ_WRITE ." WHERE type = 'project_issue';");
@@ -546,6 +554,7 @@ function project_issue_update_5201() {
         db_query("INSERT INTO {comment_upload_files} (fid, nid, cid, filename, filepath, filemime, filesize, description, list) VALUES (%d, %d, %d, '%s', '%s', '%s', %d, '%s', %d)", $fid, $nid, $cid, basename($comment->file_path), $comment->file_path, $comment->file_mime, $comment->file_size, '', 1);
       }
     }
+    db_query("UPDATE {project_issues} SET last_comment_id = %d WHERE nid = %d", $subject, $nid);
     _comment_update_node_statistics($nid);
     $_SESSION['project_issue_update_6000']++;
   }
Index: project_issue.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/project_issue.module,v
retrieving revision 1.56
diff -u -F^f -r1.56 project_issue.module
--- project_issue.module	7 Oct 2007 06:45:16 -0000	1.56
+++ project_issue.module	12 Oct 2007 14:04:44 -0000
@@ -67,7 +67,7 @@ function project_issue_form_alter($form_
       // This is only for show, the number will be generated when the comment
       // is posted.
       else {
-        $next_id = db_result(db_query('SELECT COUNT(cid) FROM {project_issue_comments} WHERE nid = %d', $form['nid']['#value'])) + 1;
+        $next_id = db_result(db_query('SELECT last_comment_id FROM {project_issues} WHERE nid = %d', $form['nid']['#value'])) + 1;
         $subject = "#$next_id";
       }
       $form['subject'] = array(
