* Add the specified PGPROC to the shared array. */
| 474 | * Add the specified PGPROC to the shared array. |
| 475 | */ |
| 476 | void |
| 477 | ProcArrayAdd(PGPROC *proc) |
| 478 | { |
| 479 | ProcArrayStruct *arrayP = procArray; |
| 480 | int index; |
| 481 | int movecount; |
| 482 | |
| 483 | /* See ProcGlobal comment explaining why both locks are held */ |
| 484 | LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); |
| 485 | LWLockAcquire(XidGenLock, LW_EXCLUSIVE); |
| 486 | |
| 487 | SIMPLE_FAULT_INJECTOR("procarray_add"); |
| 488 | |
| 489 | if (arrayP->numProcs >= arrayP->maxProcs) |
| 490 | { |
| 491 | /* |
| 492 | * Oops, no room. (This really shouldn't happen, since there is a |
| 493 | * fixed supply of PGPROC structs too, and so we should have failed |
| 494 | * earlier.) |
| 495 | */ |
| 496 | ereport(FATAL, |
| 497 | (errcode(ERRCODE_TOO_MANY_CONNECTIONS), |
| 498 | errmsg("sorry, too many clients already"))); |
| 499 | } |
| 500 | |
| 501 | /* |
| 502 | * Keep the procs array sorted by (PGPROC *) so that we can utilize |
| 503 | * locality of references much better. This is useful while traversing the |
| 504 | * ProcArray because there is an increased likelihood of finding the next |
| 505 | * PGPROC structure in the cache. |
| 506 | * |
| 507 | * Since the occurrence of adding/removing a proc is much lower than the |
| 508 | * access to the ProcArray itself, the overhead should be marginal |
| 509 | */ |
| 510 | for (index = 0; index < arrayP->numProcs; index++) |
| 511 | { |
| 512 | int procno PG_USED_FOR_ASSERTS_ONLY = arrayP->pgprocnos[index]; |
| 513 | |
| 514 | Assert(procno >= 0 && procno < (arrayP->maxProcs + NUM_AUXILIARY_PROCS)); |
| 515 | Assert(allProcs[procno].pgxactoff == index); |
| 516 | |
| 517 | /* If we have found our right position in the array, break */ |
| 518 | if (arrayP->pgprocnos[index] > proc->pgprocno) |
| 519 | break; |
| 520 | } |
| 521 | |
| 522 | movecount = arrayP->numProcs - index; |
| 523 | memmove(&arrayP->pgprocnos[index + 1], |
| 524 | &arrayP->pgprocnos[index], |
| 525 | movecount * sizeof(*arrayP->pgprocnos)); |
| 526 | memmove(&ProcGlobal->xids[index + 1], |
| 527 | &ProcGlobal->xids[index], |
| 528 | movecount * sizeof(*ProcGlobal->xids)); |
| 529 | memmove(&ProcGlobal->subxidStates[index + 1], |
| 530 | &ProcGlobal->subxidStates[index], |
| 531 | movecount * sizeof(*ProcGlobal->subxidStates)); |
| 532 | memmove(&ProcGlobal->statusFlags[index + 1], |
| 533 | &ProcGlobal->statusFlags[index], |
no test coverage detected