1 /* objmgr.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: objmgr.c
27 *
28 * Author: James Ostell
29 *
30 * Version Creation Date: 9/94
31 *
32 * $Revision: 6.90 $
33 *
34 * File Description: Manager for Bioseqs and BioseqSets
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 *
39 * ==========================================================================
40 */
41
42 /** for ErrPostEx() ****/
43
44 static char *this_module = "ncbiapi";
45 #define THIS_MODULE this_module
46 static char *this_file = __FILE__;
47 #define THIS_FILE this_file
48
49 /**********************/
50
51 #include <objmgr.h> /* the interface */
52 #include <objsset.h> /* temporary for caching functions */
53 #include <ncbithr.h> /* for thread safe functions */
54 #include <sequtil.h>
55 #include <explore.h> /* for SeqMgrClearFeatureIndexes */
56
57 /***
58 #define DEBUG_OBJMGR
59 ***/
60
61 #define OBJMGR_MAX UINT4_MAX
62
63
64 /*****************************************************************************
65 *
66 * Data Object local functions
67 *
68 *****************************************************************************/
69 static Uint4 NEAR ObjMgrTouchCnt PROTO((void));
70 static Boolean NEAR ObjMgrExtend PROTO((ObjMgrPtr omp));
71 static ObjMgrDataPtr NEAR ObjMgrFindByEntityID PROTO((ObjMgrPtr omp, Uint2 entityID, ObjMgrDataPtr PNTR prev));
72 static Boolean NEAR ObjMgrFreeClipBoardFunc PROTO((ObjMgrPtr omp));
73 static Boolean NEAR ObjMgrFreeCacheFunc PROTO((ObjMgrPtr omp, Uint2 type, Uint2Ptr rettype, VoidPtr PNTR retval));
74 static Boolean NEAR ObjMgrAddFunc PROTO((ObjMgrPtr omp, Uint2 type, Pointer data));
75 static Boolean NEAR ObjMgrFreeUserDataFunc PROTO((ObjMgrPtr omp, Uint2 entityID,
76 Uint2 procid, Uint2 proctype, Uint2 userkey));
77 static Int4 NEAR ObjMgrLockFunc (ObjMgrPtr omp, Uint2 type, Pointer data, Boolean lockit);
78 /*****************************************************************************
79 *
80 * Procedure Management local Functions
81 *
82 *****************************************************************************/
83 static Boolean NEAR ObjMgrProcExtend PROTO((ObjMgrPtr omp));
84
85 /*****************************************************************************
86 *
87 * Type Management Local functions
88 *
89 *****************************************************************************/
90 static Boolean NEAR ObjMgrTypeExtend PROTO((ObjMgrPtr omp));
91
92 /*****************************************************************************
93 *
94 * Messaging/Selection local functions
95 *
96 *****************************************************************************/
97 static Boolean NEAR ObjMgrSendMsgFunc PROTO((ObjMgrPtr omp, ObjMgrDataPtr omdp,
98 Int2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype, Uint2 rowID,
99 Uint2 fromProcID, Uint2 toProcID, Pointer procmsgdata));
100 static Boolean NEAR ObjMgrSendStructMsgFunc PROTO((ObjMgrPtr omp, ObjMgrDataPtr omdp,
101 OMMsgStructPtr ommsp));
102 static SelStructPtr NEAR ObjMgrAddSelStruct PROTO((ObjMgrPtr omp,
103 Uint2 entityID, Uint4 itemID, Uint2 itemtype, Uint1 regiontype, Pointer region));
104 static Boolean NEAR ObjMgrSelectFunc PROTO((ObjMgrPtr omp, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
105 Uint1 regiontype, Pointer region));
106 static Boolean NEAR ObjMgrDeSelectFunc PROTO((ObjMgrPtr omp, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
107 Uint1 regiontype, Pointer region));
108 /* static Boolean NEAR ObjMgrDeSelectStrucFunc PROTO((ObjMgrPtr omp, SelStructPtr ssp)); */
109 static Boolean NEAR ObjMgrDeSelectAllFunc PROTO((ObjMgrPtr omp));
110 static Boolean NEAR ObjMgrRegionMatch PROTO((Uint1 regiontype1, Pointer region1,
111 Uint1 regiontype2, Pointer region2));
112 /* static Pointer NEAR ObjMgrRegionCopy PROTO((ObjMgrPtr omp, Uint1 regiontype, Pointer region)); */
113 static Pointer NEAR ObjMgrRegionFree PROTO((ObjMgrPtr omp, Uint1 regiontype, Pointer region));
114 static Pointer NEAR ObjMgrMemCopyFunc PROTO((ObjMgrPtr omp, Uint2 type, Pointer ptr, Boolean unlock));
115 static Pointer NEAR ObjMgrFreeFunc PROTO((ObjMgrPtr omp, Uint2 type, Pointer ptr, Boolean unlock));
116
117 /*****************************************************************************
118 *
119 * ObjMgr Functions
120 *
121 *****************************************************************************/
122 static TNlmMutex omctr_mutex = NULL;
ObjMgrTouchCnt(void)123 static Uint4 NEAR ObjMgrTouchCnt (void)
124 {
125 static Uint4 ObjMgrTouchCtr = 1; /* start at 1 to avoid rollover signal */
126 Int4 ret, imax, i;
127 ObjMgrPtr omp;
128 ObjMgrDataPtr PNTR omdpp;
129 Uint4 tmpctr;
130
131 if (! ObjMgrTouchCtr) /* rolled over */
132 {
133 ret = NlmMutexLockEx(&omctr_mutex); /* protect this section */
134 if (ret) /* error */
135 {
136 ErrPostEx(SEV_FATAL,0,0,"ObjMgrTouchCnt failed [%ld]", (long)ret);
137 return ObjMgrTouchCtr;
138 }
139
140 /**** reset the touch values *****/
141 /** all calls to this function should already have ObjMgrWriteLock **/
142
143 if (! ObjMgrTouchCtr) /* check that this was not a stalled thread */
144 {
145 tmpctr = 0;
146 omp = ObjMgrGet();
147 imax = omp->currobj;
148 omdpp = omp->datalist;
149 for (i = 0; i < imax; i++)
150 {
151 if (omdpp[i]->parentptr == NULL)
152 omdpp[i]->touch = ++tmpctr;
153 }
154 ObjMgrTouchCtr = tmpctr;
155 }
156 NlmMutexUnlock(omctr_mutex);
157 }
158
159 return ++ObjMgrTouchCtr;
160
161 }
162
ObjMgrGetData(Uint2 entityID)163 NLM_EXTERN ObjMgrDataPtr LIBCALL ObjMgrGetData (Uint2 entityID)
164 {
165 ObjMgrDataPtr prev, retval=NULL;
166 ObjMgrPtr omp;
167
168 omp = ObjMgrReadLock();
169 retval = ObjMgrFindByEntityID (omp, entityID, &prev);
170 ObjMgrUnlock();
171 return retval;
172 }
173
ObjMgrGetDataStruct(ObjMgrPtr omp,Uint2 entityID)174 NLM_EXTERN ObjMgrDataPtr LIBCALL ObjMgrGetDataStruct (ObjMgrPtr omp, Uint2 entityID)
175 {
176 ObjMgrDataPtr prev;
177
178 return ObjMgrFindByEntityID (omp, entityID, &prev);
179 }
180
181 /* cache to avoid linear search of all objects in ObjMgrFindByEntityID */
182
183 #define TOP_ID_STACK_SIZE 100
184
185 static Uint2 topEntityIDs [TOP_ID_STACK_SIZE];
186 static ObjMgrDataPtr topOMDPs [TOP_ID_STACK_SIZE];
187 static Int2 topIDStackPt = 0;
188
189 extern void ObjMgrRecordOmdpByEntityID (Uint2 entityID, ObjMgrDataPtr omdp);
ObjMgrRecordOmdpByEntityID(Uint2 entityID,ObjMgrDataPtr omdp)190 extern void ObjMgrRecordOmdpByEntityID (Uint2 entityID, ObjMgrDataPtr omdp)
191
192 {
193 Int2 i;
194
195 if (entityID < 1) return;
196
197 /* check for preexisting entry, update */
198
199 for (i = 0; i < topIDStackPt; i++) {
200 if (entityID == topEntityIDs [i]) {
201 topOMDPs [i] = omdp; /* record in stack */
202 if (omdp == NULL) { /* remove if null */
203 if (topIDStackPt > i + 1) {
204 topIDStackPt--;
205 topEntityIDs [i] = topEntityIDs [topIDStackPt];
206 topOMDPs [i] = topOMDPs [topIDStackPt];
207 } else {
208 topIDStackPt--;
209 }
210 }
211 return;
212 }
213 }
214
215 /* add if not found */
216
217 if (omdp == NULL) return;
218 if (topIDStackPt < TOP_ID_STACK_SIZE) {
219 topEntityIDs [topIDStackPt] = entityID;
220 topOMDPs [topIDStackPt] = omdp;
221 topIDStackPt++;
222 }
223 ObjMgrAddIndexOnEntityID(NULL,entityID,omdp);
224 }
225
ObjMgrFindByEntityID(ObjMgrPtr omp,Uint2 entityID,ObjMgrDataPtr PNTR prev)226 static ObjMgrDataPtr NEAR ObjMgrFindByEntityID (ObjMgrPtr omp, Uint2 entityID, ObjMgrDataPtr PNTR prev)
227 {
228 ObjMgrDataPtr omdp, prevptr=NULL;
229 ObjMgrDataPtr PNTR omdpp;
230 Int4 i, imax;
231
232 /* check cache first to avoid linear search through all objects */
233 if((omdp=ObjMgrLookupIndexOnEntityID(omp,entityID)) != NULL) return omdp;
234
235 for (i = 0; i < topIDStackPt; i++) {
236 if (entityID == topEntityIDs [i]) {
237 omdp = topOMDPs [i];
238 if (omdp != NULL && omdp->parentptr == NULL && omdp->EntityID == entityID) {
239 if (prev != NULL)
240 *prev = prevptr;
241 return omdp;
242 }
243 }
244 }
245
246 imax = omp->currobj;
247 omdpp = omp->datalist;
248 for (i = 0; i < imax; i++)
249 {
250 omdp = omdpp[i]; /* emptys always at end */
251 if (omdp->parentptr == NULL)
252 {
253 if (omdp->EntityID == entityID)
254 {
255 if (prev != NULL)
256 *prev = prevptr;
257 return omdp;
258 }
259 }
260 }
261 return NULL;
262 }
263
ObjMgrFindByData(ObjMgrPtr omp,Pointer ptr)264 NLM_EXTERN ObjMgrDataPtr LIBCALL ObjMgrFindByData (ObjMgrPtr omp, Pointer ptr)
265 {
266 ObjMgrDataPtr omdp;
267 ObjMgrDataPtr PNTR omdpp;
268 Int4 i, imax;
269
270 if (ptr == NULL) return NULL;
271
272 imax = omp->currobj;
273 omdpp = omp->datalist;
274
275 i = ObjMgrLookup(omp, ptr); /* find by binary search on dataptr? */
276 if (i >= 0)
277 return omdpp[i]; /* found it */
278
279 for (i = 0; i < imax; i++)
280 {
281 omdp = omdpp[i]; /* emptys always at end */
282 if ((Pointer)(omdp->choice) == ptr)
283 {
284 return omdp;
285 }
286 }
287 return NULL;
288 }
289
290 static TNlmMutex entityid_array_mutex = NULL;
291
292 static Uint4 assignedIDsArray [2050];
293 static Int2 assignedIDStackPt = 0;
294 static Boolean assignedIDsInited = FALSE;
295
296 static Uint4 assignedIDsBitIdx [32];
297
ObjMgrInitAssignedIDArray(void)298 static void ObjMgrInitAssignedIDArray (void)
299
300 {
301 Uint4 bit;
302 Int2 jdx;
303
304 if (! assignedIDsInited) {
305 ObjMgrWriteLock ();
306
307 MemSet ((Pointer) &assignedIDsArray, 0, sizeof assignedIDsArray);
308 MemSet ((Pointer) &assignedIDsBitIdx, 0, sizeof (assignedIDsBitIdx));
309
310 /* initialize bit index array */
311
312 bit = 1;
313 for (jdx = 0; jdx < 32; jdx++) {
314 assignedIDsBitIdx [jdx] = bit;
315 bit = bit << 1;
316 }
317
318 /* entityID 0 is not available for use */
319
320 assignedIDsArray [0] = assignedIDsBitIdx [0];
321
322 assignedIDStackPt = 0;
323 assignedIDsInited = TRUE;
324
325 ObjMgrUnlock ();
326 }
327 }
328
329
ObjMgrNextAvailEntityIDInt(ObjMgrPtr omp)330 static Uint2 ObjMgrNextAvailEntityIDInt (ObjMgrPtr omp)
331
332 {
333 Uint2 entityID;
334 Int2 idx, jdx;
335 Uint4 val;
336
337 if (! assignedIDsInited) {
338 ObjMgrInitAssignedIDArray ();
339 }
340
341 /* find first 32 bit word with an available entityID */
342
343 idx = assignedIDStackPt;
344 while (idx < 2048 && assignedIDsArray [idx] == 0xFFFFFFFF) {
345 idx++;
346 }
347 if (idx >= 2048) {
348 ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrNextAvailEntityID failed with idx %d", (int) idx);
349 return 0;
350 }
351
352 /* reset starting point, everything below should be in use */
353
354 assignedIDStackPt = idx;
355
356 /* find first empty bit in array element */
357
358 val = assignedIDsArray [idx];
359 jdx = 0;
360 while (jdx < 32 && (val & assignedIDsBitIdx [jdx]) != 0) {
361 jdx++;
362 }
363 if (jdx >= 32) {
364 ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrNextAvailEntityID failed with jdx %d", (int) jdx);
365 return 0;
366 }
367
368 /* set bit to mark new entityID as in use */
369
370 assignedIDsArray [idx] |= assignedIDsBitIdx [jdx];
371
372 /* calculate entityID */
373
374 entityID = (Uint2) (((Int4) idx) * 32L + (Int4) jdx);
375
376 if (omp != NULL && omp->HighestEntityID < entityID) {
377 omp->HighestEntityID = entityID;
378 }
379
380 return entityID;
381 }
382
ObjMgrNextAvailEntityID(ObjMgrPtr omp)383 static Uint2 ObjMgrNextAvailEntityID (ObjMgrPtr omp)
384
385 {
386 Uint2 entityID;
387
388 NlmMutexLockEx (&entityid_array_mutex);
389 ObjMgrWriteLock ();
390
391 entityID = ObjMgrNextAvailEntityIDInt (omp);
392
393 ObjMgrUnlock ();
394 NlmMutexUnlock (entityid_array_mutex);
395
396 return entityID;
397 }
398
ObjMgrRecycleEntityIDInt(Uint2 entityID,ObjMgrPtr omp)399 static void ObjMgrRecycleEntityIDInt (Uint2 entityID, ObjMgrPtr omp)
400
401 {
402 Int2 idx, jdx;
403
404 if (! assignedIDsInited) {
405 ObjMgrInitAssignedIDArray ();
406 }
407
408 if (entityID < 1) return;
409
410 idx = (Int2) ((Uint4) entityID / 32L);
411 jdx = (Int2) ((Uint4) entityID % 32L);
412
413 if (idx >= 2048 || idx < 0) {
414 ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrRecycleEntityID %d failed with idx %d", (int) entityID, (int) idx);
415 return;
416 }
417 if (jdx >= 32 || jdx < 0) {
418 ErrPostEx (SEV_ERROR, 0, 0, "ObjMgrRecycleEntityID %d failed with jdx %d", (int) entityID, (int) jdx);
419 return;
420 }
421
422 /* clear bit to mark old entityID as available */
423
424 assignedIDsArray [idx] ^= assignedIDsBitIdx [jdx];
425
426 /* reset starting point, everything below should be in use */
427
428 if (idx < assignedIDStackPt) {
429 assignedIDStackPt = idx;
430 }
431 }
432
ObjMgrRecycleEntityID(Uint2 entityID,ObjMgrPtr omp)433 static void ObjMgrRecycleEntityID (Uint2 entityID, ObjMgrPtr omp)
434
435 {
436 NlmMutexLockEx (&entityid_array_mutex);
437 ObjMgrWriteLock ();
438
439 ObjMgrRecycleEntityIDInt (entityID, omp);
440
441 ObjMgrUnlock ();
442 NlmMutexUnlock (entityid_array_mutex);
443 }
444
ObjMgrRemoveEntityIDFromRecycleInt(Uint2 entityID,ObjMgrPtr omp)445 static void ObjMgrRemoveEntityIDFromRecycleInt (Uint2 entityID, ObjMgrPtr omp)
446
447 {
448 Int2 idx, jdx;
449
450 if (! assignedIDsInited) {
451 ObjMgrInitAssignedIDArray ();
452 }
453
454 if (entityID < 1) return;
455
456 idx = (Int2) ((Uint4) entityID / 32L);
457 jdx = (Int2) ((Uint4) entityID % 32L);
458
459 if (idx >= 2048 || idx < 0) return;
460 if (jdx >= 32 || jdx < 0) return;
461
462 /* set bit to restore old entityID status to in use */
463
464 assignedIDsArray [idx] |= assignedIDsBitIdx [jdx];
465 }
466
467 extern void ObjMgrRemoveEntityIDFromRecycle (Uint2 entityID, ObjMgrPtr omp);
ObjMgrRemoveEntityIDFromRecycle(Uint2 entityID,ObjMgrPtr omp)468 extern void ObjMgrRemoveEntityIDFromRecycle (Uint2 entityID, ObjMgrPtr omp)
469
470 {
471 NlmMutexLockEx (&entityid_array_mutex);
472 ObjMgrWriteLock ();
473
474 ObjMgrRemoveEntityIDFromRecycleInt (entityID, omp);
475
476 ObjMgrUnlock ();
477 NlmMutexUnlock (entityid_array_mutex);
478 }
479
ObjMgrAddEntityID(ObjMgrPtr omp,ObjMgrDataPtr omdp)480 NLM_EXTERN Uint2 LIBCALL ObjMgrAddEntityID (ObjMgrPtr omp, ObjMgrDataPtr omdp)
481 {
482 if (omdp == NULL) return 0;
483
484 if (omdp->EntityID)
485 return omdp->EntityID;
486
487 /* omdp->EntityID = ++(omp->HighestEntityID); */
488 omdp->EntityID = ObjMgrNextAvailEntityID (omp);
489 ObjMgrRecordOmdpByEntityID (omdp->EntityID, omdp);
490
491 #ifdef DEBUG_OBJMGR
492 ObjMgrDump(NULL, "ObjMgrAddEntityID-A");
493 #endif
494
495 ObjMgrSendMsgFunc(omp, omdp, OM_MSG_CREATE, omdp->EntityID, 0, 0, 0, 0, 0, NULL);
496
497 #ifdef DEBUG_OBJMGR
498 ObjMgrDump(NULL, "ObjMgrAddEntityID-B");
499 #endif
500
501 return omdp->EntityID;
502 }
ObjMgrSendMsgFunc(ObjMgrPtr omp,ObjMgrDataPtr omdp,Int2 msg,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint2 rowID,Uint2 fromProcID,Uint2 toProcID,Pointer procmsgdata)503 static Boolean NEAR ObjMgrSendMsgFunc (ObjMgrPtr omp, ObjMgrDataPtr omdp,
504 Int2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype, Uint2 rowID,
505 Uint2 fromProcID, Uint2 toProcID, Pointer procmsgdata)
506 {
507 OMMsgStruct omms;
508
509 MemSet((Pointer)(&omms), 0, sizeof(OMMsgStruct));
510
511 omms.message = msg;
512 omms.entityID = entityID;
513 omms.itemID = itemID;
514 omms.itemtype = itemtype;
515 omms.fromProcID = fromProcID;
516 omms.toProcID = toProcID;
517 omms.procmsgdata = procmsgdata;
518 omms.rowID = rowID;
519
520 return ObjMgrSendStructMsgFunc (omp, omdp, &omms);
521 }
522
523 /*********************************************************************
524 *
525 * ObjMgrSendStructMsgFunc()
526 * This function actually sends the messages to registered proceedures.
527 * It has to unlock the objmgr so the proceedures can read or write the
528 * objmgr. This is risky, but I am not sure how to do this safer. It does
529 * keep an array of messages to send before it unlocks anything, in case
530 * the message list changes from a callback. This imposes a fixed limit to
531 * the number of messages that can be sent at once to MAXMSG. This may become
532 * a problem.
533 *
534 *********************************************************************/
ObjMgrSendStructMsgFunc(ObjMgrPtr omp,ObjMgrDataPtr omdp,OMMsgStructPtr ommsp)535 static Boolean NEAR ObjMgrSendStructMsgFunc (ObjMgrPtr omp, ObjMgrDataPtr omdp,
536 OMMsgStructPtr ommsp)
537 {
538 #define MAXMSG 250 /* max number of messages to save */
539 OMUserDataPtr prev=NULL, curr, next, PNTR root, msgs[MAXMSG], omudp;
540 Int2 retval;
541 Int2 ctr, nummsg, i;
542 Boolean is_write_locked, too_many, done;
543
544 is_write_locked = omp->is_write_locked; /* remember state */
545 nummsg = 0; /* no messages known yet */
546
547 /*****************************************
548 * First find all messages to send while locked
549 *****************************************/
550 curr = omp->userdata;
551 root = &(omp->userdata);
552 ctr = 2;
553 too_many = FALSE;
554 while ((ctr) && (! too_many))
555 {
556 prev = NULL;
557 while ((curr != NULL) && (! too_many))
558 {
559 next = curr->next;
560 if (curr->messagefunc != NULL)
561 {
562 if (ommsp->toProcID == 0 || ommsp->toProcID == curr->procid) {
563 if (nummsg < MAXMSG)
564 {
565 msgs[nummsg] = curr;
566 nummsg++;
567 }
568 else
569 too_many = TRUE;
570 }
571 }
572 curr = next;
573 }
574
575 if (omdp == NULL)
576 ctr -= 2;
577 else if (ctr == 2)
578 {
579 ctr--;
580 curr = omdp->userdata;
581 root = &(omdp->userdata);
582 }
583 else
584 ctr--;
585 }
586
587 if (too_many)
588 {
589 ErrPostEx(SEV_ERROR,0,0,"ObjMgrSendMessage: more than %d messages",
590 (int)nummsg);
591 }
592
593
594
595 /*****************************************
596 * now send the messages confirming that each
597 * still exists
598 *****************************************/
599
600 for (i = 0; i < nummsg; i++)
601 {
602 omudp = msgs[i];
603 done = FALSE;
604 curr = omp->userdata;
605 root = &(omp->userdata);
606 ctr = 2;
607 while ((ctr) && (! done))
608 {
609 prev = NULL;
610 while ((curr != NULL) && (! done))
611 {
612 next = curr->next;
613 if (curr == omudp)
614 {
615 done = TRUE; /* found this one */
616 if (curr->messagefunc != NULL)
617 {
618 ommsp->omuserdata = (Pointer)curr;
619
620 ObjMgrUnlock(); /* have to allow message to react */
621 retval = (* (curr->messagefunc))(ommsp);
622 if (is_write_locked)
623 ObjMgrWriteLock();
624 else
625 ObjMgrReadLock();
626
627 if (retval == OM_MSG_RET_ERROR)
628 ErrShow();
629 else if (retval == OM_MSG_RET_DEL)
630 {
631 if (prev == NULL)
632 *root = next;
633 else
634 prev->next = next;
635 if (curr->freefunc != NULL)
636 (* (curr->freefunc))(curr->userdata.ptrvalue);
637 MemFree(curr);
638 }
639 }
640 }
641 curr = next;
642 }
643
644 if (omdp == NULL)
645 ctr -= 2;
646 else if (ctr == 2)
647 {
648 ctr--;
649 curr = omdp->userdata;
650 root = &(omdp->userdata);
651 }
652 else
653 ctr--;
654 }
655 }
656 return TRUE;
657
658 }
659 /*****************************************************************************
660 *
661 * Return the current ObjMgr
662 * ObjMgrGet is obsolete
663 * ObjMgrReadLock, ReadUnlock, WriteLock, WriteUnlock are thread safe
664 *
665 *****************************************************************************/
666 static TNlmMutex omp_mutex = NULL;
667 static ObjMgrPtr global_omp = NULL;
668 static TNlmRWlock omp_RWlock = NULL;
669
670 /*****************************************************************************
671 *
672 * Return the current ObjMgr
673 * Initialize if not done already
674 * This function will become obsolete
675 *
676 *****************************************************************************/
ObjMgrGet(void)677 NLM_EXTERN ObjMgrPtr LIBCALL ObjMgrGet (void)
678 {
679 Int4 ret;
680 ObjMgrPtr omp;
681
682 if (global_omp != NULL)
683 return global_omp;
684
685 ret = NlmMutexLockEx(&omp_mutex); /* protect this section */
686 if (ret) /* error */
687 {
688 ErrPostEx(SEV_FATAL,0,0,"ObjMgrGet failed [%ld]", (long)ret);
689 return NULL;
690 }
691
692 if (global_omp == NULL) /* check again after mutex */
693 {
694 /*** have to initialize it **/
695 omp = (ObjMgrPtr) MemNew (sizeof(ObjMgr));
696 omp->maxtemp = DEFAULT_MAXTEMP;
697 omp->maxobj = DEFAULT_MAXOBJ;
698 omp_RWlock = NlmRWinit(); /* initialize RW lock */
699 global_omp = omp; /* do this last for mutex safety */
700 }
701
702 NlmMutexUnlock(omp_mutex);
703
704 return global_omp;
705 }
706
707 /*****************************************************************************
708 *
709 * ObjMgrReadLock()
710 * Initialize if not done already
711 * A thread can have only one read or write lock at a time
712 * Many threads can have read locks
713 * Only one thread can have a write lock
714 * No other threads may have read locks if a write lock is granted
715 * If another thread holds a write lock, this call blocks until write
716 * is unlocked.
717 *
718 *****************************************************************************/
ObjMgrReadLock(void)719 NLM_EXTERN ObjMgrPtr LIBCALL ObjMgrReadLock (void)
720 {
721 ObjMgrPtr omp;
722 Int4 ret;
723
724 omp = ObjMgrGet(); /* ensure initialization */
725
726 ret = NlmRWrdlock(omp_RWlock);
727 /* ret = NlmRWwrlock(omp_RWlock); */
728
729 if (ret != 0)
730 {
731 ErrPostEx(SEV_ERROR,0,0,"ObjMgrReadLock: RWrdlock error [%ld]",
732 (long)ret);
733 return NULL;
734 }
735
736 omp->is_write_locked = TRUE;
737
738 return omp;
739 }
740
741 /*****************************************************************************
742 *
743 * ObjMgrWriteLock
744 * Initialize if not done already
745 * A thread can have only one read or write lock at a time
746 * Many threads can have read locks
747 * Only one thread can have a write lock
748 * No other threads may have read locks if a write lock is granted
749 * If another thread holds a read or write lock, this call blocks until write
750 * is unlocked.
751 *
752 *****************************************************************************/
ObjMgrWriteLock(void)753 NLM_EXTERN ObjMgrPtr LIBCALL ObjMgrWriteLock (void)
754 {
755 ObjMgrPtr omp;
756 Int4 ret;
757
758 omp = ObjMgrGet(); /* ensure initialization */
759
760 ret = NlmRWwrlock(omp_RWlock);
761 if (ret != 0)
762 {
763 ErrPostEx(SEV_ERROR,0,0,"ObjMgrWriteLock: RWwrlock error [%ld]",
764 (long)ret);
765 return NULL;
766 }
767 omp->is_write_locked = TRUE;
768 return omp;
769 }
770
771
772 /*****************************************************************************
773 *
774 * ObjMgrUnlock()
775 *
776 *****************************************************************************/
ObjMgrUnlock(void)777 NLM_EXTERN Boolean LIBCALL ObjMgrUnlock (void)
778 {
779 ObjMgrPtr omp;
780 Int4 ret;
781
782 omp = ObjMgrGet(); /* ensure initialization */
783
784 ret = NlmRWunlock(omp_RWlock);
785 if (ret != 0)
786 {
787 ErrPostEx(SEV_ERROR,0,0,"ObjMgrUnlock: RWunlock error [%ld]",
788 (long)ret);
789 return FALSE;
790 }
791 omp->is_write_locked = FALSE; /* can't be write locked */
792 return TRUE;
793 }
794
795
796
797
798 /*****************************************************************************
799 *
800 * ObjMgrSetOptions(Uint2 option, Uint2 entityID)
801 * Sets options on the ObjMgr. All Options are 1 bit flags set with
802 * defines. Several Options may be ORed together.
803 * returns current options.
804 *
805 *****************************************************************************/
ObjMgrSetOptions(Uint2 option,Uint2 entityID)806 NLM_EXTERN Uint2 LIBCALL ObjMgrSetOptions (Uint2 option, Uint2 entityID)
807 {
808 ObjMgrPtr omp;
809 Uint2Ptr optionptr;
810 ObjMgrDataPtr omdp, prev;
811
812 omp = ObjMgrGet();
813 if (entityID == 0)
814 optionptr = &(omp->options);
815 else
816 {
817 omdp = ObjMgrFindByEntityID(omp, entityID, &prev);
818 if (omdp == NULL)
819 return 0;
820 optionptr = &(omdp->options);
821 }
822 *optionptr |= (option & 0xFFFF);
823 return *optionptr;
824 }
825
826 /*****************************************************************************
827 *
828 * ObjMgrClearOptions(Uint2 option, Uint2 entityID)
829 * Clears options on the ObjMgr. All Options are 1 bit flags set with
830 * defines. Several Options may be ORed together.
831 * returns current options.
832 *
833 *****************************************************************************/
ObjMgrClearOptions(Uint2 option,Uint2 entityID)834 NLM_EXTERN Uint2 LIBCALL ObjMgrClearOptions (Uint2 option, Uint2 entityID)
835 {
836 ObjMgrPtr omp;
837 Uint2Ptr optionptr;
838 ObjMgrDataPtr omdp, prev;
839
840
841 omp = ObjMgrGet();
842 if (entityID == 0)
843 optionptr = &(omp->options);
844 else
845 {
846 omdp = ObjMgrFindByEntityID(omp, entityID, &prev);
847 if (omdp == NULL)
848 return 0;
849 optionptr = &(omdp->options);
850 }
851 *optionptr &= ~(option & 0xFFFF);
852 return *optionptr;
853 }
854
855 /*****************************************************************************
856 *
857 * ObjMgrGetOptions(entityID)
858 * Returns options on the ObjMgr. All Options are 1 bit flags set with
859 * defines. Several Options may be ORed together.
860 *
861 *****************************************************************************/
ObjMgrGetOptions(Uint2 entityID)862 NLM_EXTERN Uint2 LIBCALL ObjMgrGetOptions (Uint2 entityID)
863 {
864 ObjMgrPtr omp;
865 ObjMgrDataPtr omdp, prev;
866 Uint2 retval = 0;
867
868 omp = ObjMgrReadLock();
869 if (entityID == 0)
870 retval = omp->options;
871 else
872 {
873 omdp = ObjMgrFindByEntityID(omp, entityID, &prev);
874 if (omdp != NULL)
875 retval = omdp->options;
876 }
877 ObjMgrUnlock();
878 return retval;
879 }
880
881 /*****************************************************************************
882 *
883 * ObjMgrTestOptions(Uint2 option)
884 * Tests options on the ObjMgr. All Options are 1 bit flags set with
885 * defines. Several Options may be ORed together.
886 * returns TRUE if ANY flags in "option" are set in the ObjMgr.
887 * Normally one would supply only 1 option to test. If many were to
888 * be tested, use ObjMgrGetOptions()
889 *
890 *****************************************************************************/
ObjMgrTestOptions(Uint2 option,Uint2 entityID)891 NLM_EXTERN Boolean LIBCALL ObjMgrTestOptions (Uint2 option, Uint2 entityID)
892 {
893 ObjMgrPtr omp;
894 Uint2Ptr optionptr;
895 ObjMgrDataPtr omdp, prev;
896 Boolean retval = FALSE;
897
898 omp = ObjMgrReadLock();
899 if (entityID == 0)
900 optionptr = &(omp->options);
901 else
902 {
903 omdp = ObjMgrFindByEntityID(omp, entityID, &prev);
904 if (omdp == NULL)
905 goto erret;
906 optionptr = &(omdp->options);
907 }
908
909 if (*optionptr & (option & 0xFFFF))
910 retval = TRUE;
911 erret:
912
913 ObjMgrUnlock();
914
915 return retval;
916 }
917
918 /*****************************************************************************
919 *
920 * ObjMgrSetHold()
921 * Increments hold count in ObjMgr
922 * returns current hold count
923 * if hold != 0, then no tempload records are cached out of memory
924 * This is useful if you are doing a complex task involving repeated
925 * access to many records and you want them to stay in memory while
926 * the task is performed, even though they are loaded temporarily by
927 * BioseqLock..
928 * Be sure to call ObjMgrClearHold() when you are done so they can be
929 * cached out.
930 *
931 *****************************************************************************/
ObjMgrSetHold(void)932 NLM_EXTERN Uint2 LIBCALL ObjMgrSetHold (void)
933 {
934 ObjMgrPtr omp;
935
936 omp = ObjMgrWriteLock();
937
938 if (omp->hold < OBJMGR_MAX)
939 omp->hold++;
940 else
941 ErrPostEx(SEV_ERROR,0,0, "ObjMgrSetHold: hold > OBJMGR_MAX");
942 ObjMgrUnlock();
943 return omp->hold;
944 }
945
946 /*****************************************************************************
947 *
948 * ObjMgrClearHold()
949 * Decrements hold count in ObjMgr
950 * returns current hold count
951 * will never decrement below 0
952 * if hold == 0, then tempload records will be cached out of memory
953 *
954 *****************************************************************************/
ObjMgrClearHold(void)955 NLM_EXTERN Uint2 LIBCALL ObjMgrClearHold (void)
956 {
957 ObjMgrPtr omp;
958
959 omp = ObjMgrWriteLock();
960
961 if (omp->hold)
962 {
963 omp->hold--;
964 if (! (omp->hold)) /* down to 0 */
965 ObjMgrReap(omp);
966 }
967 else
968 ErrPostEx(SEV_ERROR,0,0, "ObjMgrClearHold: hold = 0");
969 ObjMgrUnlock();
970 return omp->hold;
971 }
972
973 /*****************************************************************************
974 *
975 * ObjMgrCheckHold()
976 * returns current hold count
977 * if hold == 0, then tempload records will be cached out of memory
978 *
979 *****************************************************************************/
ObjMgrCheckHold(void)980 NLM_EXTERN Uint2 LIBCALL ObjMgrCheckHold (void)
981 {
982 ObjMgrPtr omp;
983
984 omp = ObjMgrReadLock();
985 ObjMgrUnlock();
986 return omp->hold;
987 }
988
989
990
991 /*****************************************************************************
992 *
993 * Data Management Functions
994 *
995 *****************************************************************************/
996
997
998 /*****************************************************************************
999 *
1000 * ObjMgrExtend(omp)
1001 *
1002 *****************************************************************************/
ObjMgrExtend(ObjMgrPtr omp)1003 static Boolean NEAR ObjMgrExtend (ObjMgrPtr omp)
1004 {
1005 Boolean result = FALSE;
1006 OMDataPtr omdp, prev=NULL;
1007 ObjMgrDataPtr PNTR tmp;
1008 Int4 i, j;
1009
1010 for (omdp = omp->ncbidata; omdp != NULL; omdp = omdp->next)
1011 prev = omdp;
1012
1013 omdp = (OMDataPtr)MemNew(sizeof(OMData));
1014 if (omdp == NULL) return result;
1015 tmp = (ObjMgrDataPtr PNTR)MemNew((size_t)(sizeof(ObjMgrDataPtr) * (omp->totobj + NUM_OMD)));
1016 if (tmp == NULL)
1017 {
1018 MemFree(omdp);
1019 return result;
1020 }
1021
1022 if (prev != NULL)
1023 {
1024 prev->next = omdp;
1025 MemMove(tmp, omp->datalist, (size_t)(sizeof(ObjMgrDataPtr) * omp->totobj));
1026 MemFree(omp->datalist);
1027 }
1028 else
1029 omp->ncbidata = omdp;
1030
1031 j = omp->totobj;
1032
1033 for (i = 0; i < NUM_OMD; i++, j++)
1034 tmp[j] = &(omdp->data[i]);
1035
1036 if (omp->totobj < OBJMGR_MAX - NUM_OMD)
1037 omp->totobj += NUM_OMD;
1038 else
1039 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrExtend: incrementing totobj above OBJMGR_MAX");
1040 omp->datalist = tmp;
1041
1042 result = TRUE;
1043 return result;
1044 }
1045 /*****************************************************************************
1046 *
1047 * ObjMgrAdd(type, data)
1048 * adds a pointer (data) of type (type) to the sequence manager
1049 *
1050 *****************************************************************************/
ObjMgrAdd(Uint2 type,Pointer data)1051 NLM_EXTERN Boolean LIBCALL ObjMgrAdd (Uint2 type, Pointer data)
1052 {
1053 ObjMgrPtr omp;
1054 Boolean retval = FALSE;
1055
1056 omp = ObjMgrWriteLock();
1057 retval = ObjMgrAddFunc(omp, type, data);
1058 ObjMgrUnlock();
1059 return retval;
1060 }
1061
1062
1063 /*****************************************************************************
1064 *
1065 * ObjMgrAddFunc(omp, type, data)
1066 * adds a pointer (data) of type (type) to the sequence manager
1067 *
1068 *****************************************************************************/
ObjMgrAddFunc(ObjMgrPtr omp,Uint2 type,Pointer data)1069 static Boolean NEAR ObjMgrAddFunc (ObjMgrPtr omp, Uint2 type, Pointer data)
1070 {
1071 ObjMgrDataPtr omdp;
1072 ObjMgrDataPtr PNTR omdpp;
1073 Int4 i, imin, imax;
1074 Boolean retval = FALSE;
1075 unsigned long tmp, datai;
1076 BioseqPtr bsp;
1077 #ifdef DEBUG_OBJMGR
1078 FILE * fp;
1079
1080 fp = FileOpen("ObjMgr.log", "a");
1081 #endif
1082
1083 /* if autoclean is set and above maxobj, remove least recently accessed objects */
1084 if (omp->autoclean && omp->currobj >= omp->maxobj) {
1085 ObjMgrReapOne (omp);
1086 ObjMgrFreeCache (OBJ_MAX); /* only frees unlocked objects */
1087 }
1088
1089 if (omp->currobj >= omp->totobj)
1090 {
1091 if (! ObjMgrExtend(omp))
1092 goto erret;
1093 }
1094
1095 i = omp->currobj;
1096 omdpp = omp->datalist;
1097 omdp = omdpp[i]; /* emptys always at end */
1098 omdp->options = omp->options; /* set default options */
1099
1100 imin = 0; /* find where it goes */
1101 imax = omp->currobj-1;
1102
1103 datai = (unsigned long)data;
1104
1105 if ((i) && (datai < (unsigned long)(omdpp[imax]->dataptr)))
1106 {
1107 i = (imax + imin) / 2;
1108 while (imax > imin)
1109 {
1110 tmp = (unsigned long)(omdpp[i]->dataptr);
1111 #ifdef DEBUG_OBJMGR
1112 fprintf(fp, "Sort: i=%d tmp=%ld data=%ld imax=%d imin=%d\n",
1113 (int)i, (long)tmp, (long)data, (int)imax, (int)imin);
1114 #endif
1115 if (tmp > datai)
1116 imax = i - 1;
1117 else if (tmp < datai)
1118 imin = i + 1;
1119 else
1120 break;
1121 i = (imax + imin)/2;
1122 }
1123
1124 #ifdef DEBUG_OBJMGR
1125 fprintf(fp, "End: i=%d tmp=%ld data=%ld imax=%d imin=%d\n",
1126 (int)i, (long)tmp, (long)data, (int)imax, (int)imin);
1127 #endif
1128 if (datai > (unsigned long)(omdpp[i]->dataptr)) /* check for off by 1 */
1129 {
1130 i++;
1131 #ifdef DEBUG_OBJMGR
1132 fprintf(fp, "Adjust: i=%d\n", (int)i);
1133 #endif
1134 }
1135
1136
1137 imax = omp->currobj - 1; /* open the array */
1138 while (imax >= i)
1139 {
1140 omdpp[imax+1] = omdpp[imax];
1141 imax--;
1142 }
1143 }
1144
1145 omdpp[i] = omdp; /* put in the pointer in order */
1146 if (omp->currobj < OBJMGR_MAX)
1147 omp->currobj++; /* got one more */
1148 else
1149 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrAddFunc: incrementing currobj above OBJMGR_MAX");
1150
1151 omdp->dataptr = data; /* fill in the values */
1152 omdp->datatype = type;
1153 omdp->touch = ObjMgrTouchCnt(); /* stamp with time */
1154
1155 if (type == OBJ_BIOSEQ) {
1156 bsp = (BioseqPtr) data;
1157 if (bsp != NULL) {
1158 /* used for feature indexing, rapid delete from SeqID index */
1159 /* may not be thread safe */
1160 /* bsp->omdp = (Pointer) omdp; */
1161 }
1162 }
1163
1164 #ifdef DEBUG_OBJMGR
1165 FileClose(fp);
1166 ObjMgrDump(NULL, "ObjMgrAdd");
1167 #endif
1168 retval = TRUE;
1169 erret:
1170 return retval;
1171 }
1172
1173 /*****************************************************************************
1174 *
1175 * ObjMgrRegister (datatype, data)
1176 * datatype is the datatype of data to register
1177 * if data is already registered in ObjMgr, returns entityID
1178 * if not, is added to the ObjMgr, returns entityID
1179 *
1180 * if (datatype is a choice type, uses data as a ValNodePtr)
1181 *
1182 * on failure returns 0
1183 *
1184 *****************************************************************************/
ObjMgrRegister(Uint2 datatype,Pointer data)1185 NLM_EXTERN Uint2 LIBCALL ObjMgrRegister (Uint2 datatype, Pointer data)
1186 {
1187 Uint2 dtype, retval = 0;
1188 ObjMgrPtr omp;
1189 ObjMgrDataPtr omdp;
1190 ObjMgrTypePtr omtp;
1191 Pointer ptr;
1192
1193
1194 if (data == NULL) return retval;
1195
1196 dtype = datatype; /* sets the default state */
1197 ptr = data;
1198
1199 omp = ObjMgrWriteLock();
1200
1201 omdp = ObjMgrFindByData(omp, data); /* already have it? */
1202 if (omdp != NULL)
1203 {
1204 if (! omdp->EntityID)
1205 {
1206 if (omdp->parentptr != NULL)
1207 ErrPostEx(SEV_ERROR,0,0, "ObjMgrRegister: parent != NULL");
1208
1209 ObjMgrAddEntityID(omp, omdp);
1210 }
1211
1212 retval = omdp->EntityID;
1213 goto erret;
1214 }
1215 /* have to add it to ObjMgr */
1216 omtp = ObjMgrTypeFind(omp, datatype, NULL, NULL);
1217 if (omtp == NULL)
1218 {
1219 ErrPostEx(SEV_ERROR,0,0, "ObjMgrRegister: invalid data type [%d]", (int)datatype);
1220 goto erret;
1221 }
1222
1223 /*** this was to register things like SeqEntry.. currently we register data.ptrvalue directly **
1224
1225 if (omtp->fromchoicefunc == NULL)
1226 {
1227 dtype = datatype;
1228 ptr = data;
1229 }
1230 else
1231 {
1232 vnp = (ValNodePtr)data;
1233 dtype = (*(omtp->fromchoicefunc))(vnp);
1234 ptr = vnp->data.ptrvalue;
1235 }
1236
1237 ***********************************************************************************************/
1238
1239 ObjMgrAddFunc(omp, dtype, ptr);
1240 omdp = ObjMgrFindByData(omp, ptr);
1241 if (omdp == NULL) goto erret;
1242
1243 ObjMgrAddEntityID(omp, omdp);
1244 retval = omdp->EntityID;
1245 erret:
1246 ObjMgrUnlock();
1247
1248 return retval;
1249 }
1250
1251
1252 /*****************************************************************************
1253 *
1254 * ObjMgrAddUserData(entityID, procid, proctype, userkey)
1255 * creates a new OMUserData struct attached to entityID
1256 * if entityID = 0, attaches to the desktop (all objects)
1257 * Caller must fill in returned structure
1258 * returns NULL on failure
1259 *
1260 *****************************************************************************/
ObjMgrAddUserData(Uint2 entityID,Uint2 procid,Uint2 proctype,Uint2 userkey)1261 NLM_EXTERN OMUserDataPtr LIBCALL ObjMgrAddUserData (Uint2 entityID, Uint2 procid, Uint2 proctype, Uint2 userkey)
1262 {
1263 OMUserDataPtr omudp=NULL, tmp;
1264 ObjMgrPtr omp;
1265 ObjMgrDataPtr omdp;
1266
1267 omp = ObjMgrWriteLock();
1268
1269 omudp = MemNew(sizeof(OMUserData));
1270 omudp->procid = procid;
1271 omudp->proctype = proctype;
1272 omudp->userkey = userkey;
1273
1274 if (entityID == 0)
1275 {
1276 if (omp->userdata == NULL)
1277 omp->userdata = omudp;
1278 else
1279 {
1280 for (tmp = omp->userdata; tmp->next != NULL; tmp = tmp->next)
1281 continue;
1282 tmp->next = omudp;
1283 }
1284 }
1285 else
1286 {
1287 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
1288 if (omdp == NULL)
1289 omudp = MemFree(omudp);
1290 else
1291 {
1292 if (omdp->userdata == NULL)
1293 omdp->userdata = omudp;
1294 else
1295 {
1296 for (tmp = omdp->userdata; tmp->next != NULL; tmp = tmp->next)
1297 continue;
1298 tmp->next = omudp;
1299
1300 }
1301 }
1302 }
1303
1304 ObjMgrUnlock();
1305 return omudp;
1306 }
1307
1308 /*****************************************************************************
1309 *
1310 * ObjMgrGetUserData(entityID, procid, proctype, userkey)
1311 * Finds an OMUserData struct attached to entityID
1312 * if entityID = 0, gets from the desktop
1313 * returns NULL on failure
1314 *
1315 *****************************************************************************/
ObjMgrGetUserData(Uint2 entityID,Uint2 procid,Uint2 proctype,Uint2 userkey)1316 NLM_EXTERN OMUserDataPtr LIBCALL ObjMgrGetUserData (Uint2 entityID, Uint2 procid, Uint2 proctype, Uint2 userkey)
1317 {
1318 OMUserDataPtr omudp=NULL;
1319 ObjMgrPtr omp;
1320 ObjMgrDataPtr omdp;
1321
1322 omp = ObjMgrReadLock();
1323
1324 if (entityID == 0)
1325 {
1326 omudp = omp->userdata;
1327 }
1328 else
1329 {
1330 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
1331 if (omdp != NULL)
1332 omudp = omdp->userdata;
1333 }
1334
1335 while (omudp != NULL)
1336 {
1337 if ((omudp->procid == procid) || (! procid))
1338 {
1339 if ((omudp->proctype == proctype) || (! proctype))
1340 {
1341 if ((omudp->userkey == userkey) || (! userkey))
1342 break;
1343 }
1344 }
1345 omudp = omudp->next;
1346 }
1347
1348 ObjMgrUnlock();
1349 return omudp;
1350 }
1351 /*****************************************************************************
1352 *
1353 * ObjMgrFreeUserData(entityID, procid, proctype, userkey)
1354 * frees OMUserData attached to entityID by procid
1355 * if procid ==0, frees all OMUserData of proctype
1356 * if proctype ==0, matches any proctype
1357 * if userkey == matches any userkey
1358 * returns TRUE if any freed
1359 *
1360 *****************************************************************************/
ObjMgrFreeUserData(Uint2 entityID,Uint2 procid,Uint2 proctype,Uint2 userkey)1361 NLM_EXTERN Boolean LIBCALL ObjMgrFreeUserData (Uint2 entityID, Uint2 procid, Uint2 proctype, Uint2 userkey)
1362 {
1363 ObjMgrPtr omp;
1364 Boolean retval = FALSE;
1365
1366 omp = ObjMgrWriteLock();
1367 retval = ObjMgrFreeUserDataFunc(omp, entityID, procid, proctype, userkey);
1368 ObjMgrUnlock();
1369 return retval;
1370 }
1371
1372 /*****************************************************************************
1373 *
1374 * ObjMgrFreeUserDataFunc(omp, entityID, procid, proctype, userkey)
1375 * frees OMUserData attached to entityID by procid
1376 * if procid ==0, frees all OMUserData of proctype
1377 * if proctype ==0, matches any proctype
1378 * if userkey == matches any userkey
1379 * returns TRUE if any freed
1380 *
1381 *****************************************************************************/
ObjMgrFreeUserDataFunc(ObjMgrPtr omp,Uint2 entityID,Uint2 procid,Uint2 proctype,Uint2 userkey)1382 static Boolean NEAR ObjMgrFreeUserDataFunc (ObjMgrPtr omp, Uint2 entityID,
1383 Uint2 procid, Uint2 proctype, Uint2 userkey)
1384 {
1385 OMUserDataPtr omudp=NULL, prev, next;
1386 ObjMgrDataPtr omdp = NULL;
1387 Boolean got_one = FALSE, view_left;
1388 ObjMgrTypePtr omtp = NULL;
1389 Uint2 type, options;
1390 Pointer ptr;
1391 Boolean is_write_locked;
1392
1393 options = omp->options;
1394
1395 if (entityID == 0)
1396 {
1397 omudp = omp->userdata;
1398 }
1399 else
1400 {
1401 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
1402 if (omdp != NULL)
1403 {
1404 omudp = omdp->userdata;
1405 options = omdp->options;
1406 }
1407 }
1408
1409 prev = NULL;
1410 view_left = FALSE; /* assume nothing left to receive messages */
1411 while (omudp != NULL)
1412 {
1413 next = omudp->next;
1414 if ((omudp->procid == procid) || (! procid))
1415 {
1416 if ((omudp->proctype == proctype) || (! proctype))
1417 {
1418 if ((omudp->userkey == userkey) || (! userkey))
1419 {
1420 got_one = TRUE;
1421 if (prev == NULL)
1422 {
1423 if (entityID == 0)
1424 omp->userdata = next;
1425 else
1426 omdp->userdata = next;
1427 }
1428 else
1429 prev->next = next;
1430 if (omudp->freefunc != NULL)
1431 (* (omudp->freefunc))(omudp->userdata.ptrvalue);
1432 omudp = MemFree(omudp);
1433 }
1434 }
1435 }
1436 if (omudp != NULL)
1437 {
1438 prev = omudp;
1439 if (omudp->messagefunc != NULL) /* gets messages */
1440 view_left = TRUE;
1441 }
1442 omudp = next;
1443 }
1444
1445 if (options & OM_OPT_FREE_IF_NO_VIEW) /* free data if no more views */
1446 {
1447 if ((got_one) && (! view_left) && (omdp != NULL)) /* no more views */
1448 {
1449 if (! omdp->being_freed) /* being freed by ObjMgrDelete */
1450 {
1451 if (omdp->choice != NULL)
1452 {
1453 type = omdp->choicetype;
1454 ptr = omdp->choice;
1455 }
1456 else
1457 {
1458 type = omdp->datatype;
1459 ptr = omdp->dataptr;
1460 }
1461
1462 omtp = ObjMgrTypeFind(omp, type, NULL, NULL);
1463 if (omtp != NULL)
1464 {
1465 omdp->being_freed = TRUE; /* flag not to call this func */
1466 /* get rid of extra user data */
1467 ObjMgrFreeUserDataFunc(omp, entityID, 0, 0, 0);
1468 is_write_locked = omp->is_write_locked;
1469 ObjMgrUnlock();
1470 (*(omtp->freefunc))(ptr);
1471 if (is_write_locked)
1472 ObjMgrWriteLock();
1473 else
1474 ObjMgrReadLock();
1475 }
1476 }
1477 }
1478 }
1479 return got_one;
1480 }
1481
1482
1483
1484 /*****************************************************************************
1485 *
1486 * ObjMgrLookup(omp, data)
1487 * Binary lookup of data in omp->datalist
1488 * returns index (>=0) if found
1489 * returns -1 if not found
1490 *
1491 *****************************************************************************/
ObjMgrLookup(ObjMgrPtr omp,Pointer data)1492 NLM_EXTERN Int4 LIBCALL ObjMgrLookup(ObjMgrPtr omp, Pointer data)
1493 {
1494 Int4 imin, imax, i;
1495 ObjMgrDataPtr PNTR omdpp;
1496 unsigned long tmp, datai;
1497
1498 imin = 0;
1499 imax = omp->currobj - 1;
1500 omdpp = omp->datalist;
1501
1502 datai = (unsigned long)data;
1503
1504 while (imax >= imin)
1505 {
1506 i = (imax + imin)/2;
1507 tmp = (unsigned long)(omdpp[i]->dataptr);
1508 if (tmp > datai)
1509 imax = i - 1;
1510 else if (tmp < datai)
1511 imin = i + 1;
1512 else
1513 return i;
1514 }
1515
1516 return (Int4)(-1);
1517 }
1518
1519 /*****************************************************************************
1520 *
1521 * ObjMgrDelete(type, data)
1522 * deletes a pointer (data) of type (type) to the sequence manager
1523 *
1524 *****************************************************************************/
ObjMgrDelete(Uint2 type,Pointer data)1525 NLM_EXTERN Boolean LIBCALL ObjMgrDelete (Uint2 type, Pointer data)
1526 {
1527 ObjMgrPtr omp;
1528 ObjMgrDataPtr omdp;
1529 ObjMgrDataPtr PNTR omdpp, PNTR to, PNTR from;
1530 Int4 i, j;
1531 Boolean retval = FALSE;
1532
1533 omp = ObjMgrWriteLock(); /* really remove the entity */
1534 i = ObjMgrLookup(omp, data); /* make sure it is still current */
1535 if (i < 0) /* not found */
1536 {
1537 /*** may not be registered with objmgr ***
1538 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrDelete: pointer [%ld] type [%d] not found",
1539 (long)data, (int)type);
1540 ***/
1541 goto erret;
1542 }
1543
1544 omdpp = omp->datalist;
1545 omdp = omdpp[i]; /* emptys always at end */
1546
1547 if (omdp == NULL) goto erret;
1548
1549 if (omdp->EntityID != 0)
1550 {
1551 ObjMgrSendMsgFunc(omp, omdp, OM_MSG_DEL, omdp->EntityID, 0, 0, 0, 0, 0, NULL);
1552 ObjMgrDeSelectFunc(omp, omdp->EntityID,0,0,0,NULL);
1553 if (! omdp->being_freed) /* ObjMgrFreeUserData can call delete */
1554 {
1555 omdp->being_freed = TRUE; /* break cycle */
1556 ObjMgrFreeUserDataFunc(omp, omdp->EntityID, 0, 0, 0);
1557 }
1558 }
1559
1560 if (omdp->clipboard) /* update the clipboard */
1561 omp->clipboard = NULL;
1562
1563 if (omdp->lockcnt)
1564 ErrPostEx(SEV_ERROR, 0,0,"ObjMgrDelete: deleting locked element");
1565 else if (omdp->tempload == TL_LOADED)
1566 {
1567 if (omp->tempcnt)
1568 omp->tempcnt--;
1569 else
1570 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrDelete: reducing tempcnt below 0");
1571 }
1572
1573 /* if (omdp->EntityID != 0 && omdp->EntityID == omp->HighestEntityID)
1574 omp->HighestEntityID--; */
1575 if (omdp->EntityID != 0)
1576 ObjMgrRecycleEntityID (omdp->EntityID, omp);
1577
1578 ObjMgrDeleteIndexOnEntityID(omp,omdp->EntityID);
1579
1580 if (omdp->extradata != NULL && omdp->freeextra != NULL) {
1581 omdp->freeextra ((Pointer) omdp);
1582 }
1583
1584 if (omdp->bulkIndexFree) {
1585 ObjMgrUnlock(); /* if bulk free, delete at end of BioseqFree or BioseqSetFree */
1586 return TRUE;
1587 }
1588
1589 MemSet((Pointer)omdp, 0, sizeof(ObjMgrData));
1590 if (omp->currobj)
1591 omp->currobj--;
1592 else
1593 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrDelete: reducing currobj below 0");
1594 j = omp->currobj - i;
1595 if (j)
1596 {
1597 to = omdpp + i;
1598 from = to + 1;
1599 MemMove(to, from, (size_t)(sizeof(ObjMgrDataPtr) * j));
1600 }
1601 omdpp[omp->currobj] = omdp; /* put in pointer to empty data space */
1602
1603 #ifdef DEBUG_OBJMGR
1604 ObjMgrDump(NULL, "ObjMgrDelete");
1605 #endif
1606
1607 retval = TRUE;
1608 erret:
1609 ObjMgrUnlock();
1610 return retval;
1611 }
1612
1613 /*****************************************************************************
1614 *
1615 * ObjMgrDeleteAllInRecord()
1616 * deletes all omdp entries in a record
1617 *
1618 *****************************************************************************/
ObjMgrDeleteAllInRecord(void)1619 NLM_EXTERN Boolean LIBCALL ObjMgrDeleteAllInRecord (
1620 void
1621 )
1622
1623 {
1624 Int4 i, j, k, num;
1625 ObjMgrDataPtr omdp;
1626 ObjMgrDataPtr PNTR omdpp;
1627 ObjMgrPtr omp;
1628 ObjMgrDataPtr PNTR tmp;
1629
1630 omp = ObjMgrWriteLock ();
1631
1632 if (omp != NULL) {
1633 omdpp = omp->datalist;
1634 if (omdpp != NULL) {
1635
1636 num = omp->currobj;
1637 tmp = (ObjMgrDataPtr PNTR) MemNew (sizeof (ObjMgrDataPtr) * (size_t) (num + 1));
1638 if (tmp != NULL) {
1639
1640 for (i = 0, j = 0, k = 0; i < num; i++) {
1641 omdp = omdpp [i];
1642 if (omdp != NULL && omdp->bulkIndexFree) {
1643 MemSet ((Pointer) omdp, 0, sizeof (ObjMgrData));
1644 tmp [k] = omdp;
1645 k++;
1646 } else {
1647 omdpp [j] = omdpp [i];
1648 j++;
1649 }
1650 }
1651 omp->currobj = j;
1652 MemMove (omdpp + j, tmp, sizeof (ObjMgrDataPtr) * (size_t) k);
1653 }
1654
1655 MemFree (tmp);
1656 }
1657 }
1658
1659 ObjMgrUnlock ();
1660
1661 return TRUE;
1662 }
1663
1664 /*****************************************************************************
1665 *
1666 * ObjMgrGetClipBoard()
1667 * returns ObjMgrDataPtr to current clipboard object or NULL if none
1668 *
1669 *****************************************************************************/
ObjMgrGetClipBoard(void)1670 NLM_EXTERN ObjMgrDataPtr LIBCALL ObjMgrGetClipBoard (void)
1671 {
1672 ObjMgrPtr omp;
1673
1674 omp = ObjMgrReadLock();
1675 ObjMgrUnlock();
1676 return omp->clipboard;
1677 }
1678
1679 /*****************************************************************************
1680 *
1681 * ObjMgrAddToClipBoard(entityID, ptr)
1682 * if entityID > 0, then uses it.
1683 * else, looks up entityID using ptr
1684 * adds entityID if needed
1685 * sends OM_MSG_TO_CLIPBOARD
1686 *
1687 * Anything in the clipboard is deleted
1688 *
1689 *****************************************************************************/
ObjMgrAddToClipBoard(Uint2 entityID,Pointer ptr)1690 NLM_EXTERN Boolean LIBCALL ObjMgrAddToClipBoard (Uint2 entityID, Pointer ptr)
1691 {
1692 ObjMgrPtr omp;
1693 ObjMgrDataPtr omdp;
1694 Boolean retval = FALSE;
1695
1696 omp = ObjMgrWriteLock();
1697 if (! entityID)
1698 {
1699 omdp = ObjMgrFindByData(omp, ptr);
1700 if (omdp != NULL)
1701 {
1702 if (omdp->parentptr != NULL)
1703 {
1704 ErrPostEx(SEV_ERROR,0,0,"AddToClipBoard: ParentPtr != NULL");
1705 goto erret;
1706 }
1707 /* if (omdp->EntityID == 0)
1708 omdp->EntityID = ++(omp->HighestEntityID); */
1709 if (omdp->EntityID == 0) {
1710 omdp->EntityID = ObjMgrNextAvailEntityID (omp);
1711 ObjMgrRecordOmdpByEntityID (omdp->EntityID, omdp);
1712 }
1713 }
1714 }
1715 else
1716 {
1717 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
1718 }
1719
1720 if (omdp == NULL)
1721 {
1722 ErrPostEx(SEV_ERROR,0,0,"AddToClipBoard: data not found");
1723 goto erret;
1724 }
1725
1726 ObjMgrFreeClipBoardFunc(omp);
1727
1728 omdp->clipboard = TRUE;
1729 omp->clipboard = omdp;
1730
1731 ObjMgrSendMsgFunc(omp, omdp, OM_MSG_TO_CLIPBOARD, omdp->EntityID, 0, 0, 0, 0, 0, NULL);
1732
1733 retval = TRUE;
1734 erret:
1735 ObjMgrUnlock();
1736
1737 return retval;
1738 }
1739
1740 /*****************************************************************************
1741 *
1742 * ObjMgrFreeClipBoard()
1743 * clears any data from the clipboard
1744 *
1745 *****************************************************************************/
ObjMgrFreeClipBoard(void)1746 NLM_EXTERN Boolean LIBCALL ObjMgrFreeClipBoard (void)
1747 {
1748 ObjMgrPtr omp;
1749 Boolean retval;
1750
1751 omp = ObjMgrWriteLock();
1752 retval = ObjMgrFreeClipBoardFunc(omp);
1753 ObjMgrUnlock();
1754 return retval;
1755 }
1756
1757 /*****************************************************************************
1758 *
1759 * ObjMgrFreeClipBoardFunc()
1760 * clears any data from the clipboard
1761 *
1762 *****************************************************************************/
ObjMgrFreeClipBoardFunc(ObjMgrPtr omp)1763 static Boolean NEAR ObjMgrFreeClipBoardFunc (ObjMgrPtr omp)
1764 {
1765 ObjMgrTypePtr omtp;
1766 ObjMgrDataPtr omdp;
1767 Uint2 type;
1768 Pointer ptr;
1769
1770 omdp = omp->clipboard;
1771 if (omdp == NULL) return TRUE;
1772
1773 if (omdp->choice != NULL)
1774 {
1775 type = omdp->choicetype;
1776 ptr = omdp->choice;
1777 }
1778 else
1779 {
1780 type = omdp->datatype;
1781 ptr = omdp->dataptr;
1782 }
1783
1784 omtp = ObjMgrTypeFind(omp, type, NULL, NULL);
1785 if (omtp == NULL)
1786 {
1787 ErrPostEx(SEV_ERROR,0,0,"ObjMgrFreeClipBoard: cant find type [%d]", (int)type);
1788 return FALSE;
1789 }
1790 else
1791 (*(omtp->freefunc))(ptr);
1792 ObjMgrDelete(omdp->datatype, omdp->dataptr);
1793 omp->clipboard = NULL;
1794 return TRUE;
1795 }
1796 /*****************************************************************************
1797 *
1798 * ObjMgrConnect (type, data, parenttype, parentdata)
1799 * Adds parent info to element
1800 * Updates EntityID
1801 * if both are 0, assigns it by incrementing HighestEntityID
1802 * if one is 0, assigns it the other
1803 * if neither is 0 and not the same ID
1804 * assigns parent to child (and cascades to its children)
1805 *
1806 *****************************************************************************/
ObjMgrConnect(Uint2 type,Pointer data,Uint2 parenttype,Pointer parentdata)1807 NLM_EXTERN Boolean LIBCALL ObjMgrConnect (Uint2 type, Pointer data, Uint2 parenttype, Pointer parentdata)
1808 {
1809 ObjMgrPtr omp;
1810 Boolean retval = FALSE;
1811
1812 omp = ObjMgrWriteLock();
1813 retval = ObjMgrConnectFunc(omp, type, data, parenttype, parentdata);
1814 ObjMgrUnlock();
1815 return retval;
1816 }
1817
1818 /*****************************************************************************
1819 *
1820 * ObjMgrConnectFunc (type, data, parenttype, parentdata)
1821 * Adds parent info to element
1822 * Updates EntityID
1823 * if both are 0, assigns it by incrementing HighestEntityID
1824 * if one is 0, assigns it the other
1825 * if neither is 0 and not the same ID
1826 * assigns parent to child (and cascades to its children)
1827 *
1828 *****************************************************************************/
ObjMgrConnectFunc(ObjMgrPtr omp,Uint2 type,Pointer data,Uint2 parenttype,Pointer parentdata)1829 NLM_EXTERN Boolean LIBCALL ObjMgrConnectFunc (ObjMgrPtr omp, Uint2 type, Pointer data, Uint2 parenttype, Pointer parentdata)
1830 {
1831 Int4 i;
1832 ObjMgrDataPtr omdp;
1833 Boolean retval = FALSE;
1834
1835 i = ObjMgrLookup(omp, data);
1836 if (i < 0) /* not found */
1837 {
1838 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrConnect: pointer [%ld] type [%d] not found",
1839 (long)data, (int)type);
1840 goto erret;
1841 }
1842
1843 omdp = omp->datalist[i];
1844
1845 if ((omdp->EntityID != 0) && (parentdata != NULL))
1846 { /* registered type, inform any attached procs */
1847
1848 ObjMgrSendMsgFunc(omp, omdp, OM_MSG_CONNECT, omdp->EntityID, 0, 0, 0, 0, 0, NULL);
1849 ObjMgrDeSelectFunc(omp, omdp->EntityID,0,0,0,NULL);
1850 ObjMgrFreeUserDataFunc(omp, omdp->EntityID, 0, 0, 0);
1851
1852 /* if (omp->HighestEntityID == omdp->EntityID) {
1853 (omp->HighestEntityID)--;
1854 } */
1855 ObjMgrRecycleEntityID (omdp->EntityID, omp);
1856 ObjMgrDeleteIndexOnEntityID (omp, omdp->EntityID);
1857 omdp->EntityID = 0; /* reset.. now has a parent */
1858 }
1859 omdp->parenttype = parenttype;
1860 omdp->parentptr = parentdata;
1861
1862 if (parentdata != NULL)
1863 {
1864 i = ObjMgrLookup(omp, parentdata);
1865 if (i < 0) /* not found */
1866 {
1867 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrConnect: parent pointer [%ld] type [%d] not found",
1868 (long)parentdata, (int)parenttype);
1869 goto erret;
1870 }
1871
1872
1873 }
1874
1875 #ifdef DEBUG_OBJMGR
1876 ObjMgrDump(NULL, "ObjMgrConnect");
1877 #endif
1878 retval = TRUE;
1879 erret:
1880 return retval;
1881 }
1882 /*****************************************************************************
1883 *
1884 * ObjMgrDetach (type, data)
1885 * Removes parent info from element
1886 * Adds to objmgr if necessary
1887 * Does NOT register entity
1888 *
1889 *****************************************************************************/
ObjMgrDetach(Uint2 type,Pointer data)1890 NLM_EXTERN Boolean LIBCALL ObjMgrDetach (Uint2 type, Pointer data)
1891 {
1892 ObjMgrPtr omp;
1893 Boolean retval = FALSE;
1894
1895 omp = ObjMgrWriteLock();
1896 retval = ObjMgrDetachFunc(omp, type, data);
1897 ObjMgrUnlock();
1898 return retval;
1899 }
1900
1901 /*****************************************************************************
1902 *
1903 * ObjMgrDetach (type, data)
1904 * Removes parent info from element
1905 * Adds to objmgr if necessary
1906 * Does NOT register entity
1907 *
1908 *****************************************************************************/
ObjMgrDetachFunc(ObjMgrPtr omp,Uint2 type,Pointer data)1909 NLM_EXTERN Boolean LIBCALL ObjMgrDetachFunc (ObjMgrPtr omp, Uint2 type, Pointer data)
1910 {
1911 Int4 i;
1912 ObjMgrDataPtr omdp;
1913 Boolean retval = FALSE;
1914
1915 i = ObjMgrLookup(omp, data);
1916 if (i < 0) /* not found */
1917 {
1918 retval = ObjMgrAddFunc(omp, type, data);
1919 goto erret;
1920 }
1921
1922 omdp = omp->datalist[i];
1923 if (omdp->parentptr == NULL) /* not connected anyway */
1924 return TRUE;
1925
1926 omdp->parenttype = 0;
1927 omdp->parentptr = NULL;
1928 ObjMgrDeleteIndexOnEntityID (omp, omdp->EntityID);
1929 omdp->EntityID = 0; /* reset.. now has a parent */
1930
1931 retval = TRUE;
1932 erret:
1933 return retval;
1934 }
1935
1936 /*****************************************************************************
1937 *
1938 * ObjMgrSetDirtyFlag (entityID, the_flag)
1939 * record that an entity has been changed but not yet saved.
1940 * the_flag sets or unsets this state
1941 *
1942 *****************************************************************************/
ObjMgrSetDirtyFlag(Uint2 entityID,Boolean the_flag)1943 NLM_EXTERN Boolean LIBCALL ObjMgrSetDirtyFlag (Uint2 entityID, Boolean the_flag)
1944 {
1945 ObjMgrPtr omp;
1946 ObjMgrDataPtr omdp;
1947 Boolean retval = FALSE;
1948
1949 if (entityID <= 0) return FALSE;
1950
1951 omp = ObjMgrWriteLock();
1952 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
1953 if (omdp != NULL)
1954 {
1955 omdp->dirty = the_flag;
1956 retval = TRUE;
1957 }
1958 ObjMgrUnlock();
1959 return retval;
1960 }
1961
1962 /*****************************************************************************
1963 *
1964 * ObjMgrGetDirtyFlag (entityID)
1965 * returns the state of the dirty flag for entityID
1966 *
1967 *****************************************************************************/
ObjMgrGetDirtyFlag(Uint2 entityID)1968 NLM_EXTERN Boolean LIBCALL ObjMgrGetDirtyFlag (Uint2 entityID)
1969 {
1970 ObjMgrPtr omp;
1971 ObjMgrDataPtr omdp;
1972 Boolean retval = FALSE;
1973
1974 if (entityID <= 0) return retval;
1975
1976 omp = ObjMgrReadLock();
1977 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
1978 if (omdp != NULL)
1979 retval = omdp->dirty;
1980 ObjMgrUnlock();
1981 return retval;
1982 }
1983
1984 /*****************************************************************************
1985 *
1986 * ObjMgrSetChoice(type, choice, data)
1987 * Adds the ValNodePtr pointing directly to this Bioseq or BioseqSet
1988 *
1989 *****************************************************************************/
ObjMgrSetChoice(Uint2 type,ValNodePtr choice,Pointer data)1990 NLM_EXTERN Boolean LIBCALL ObjMgrSetChoice (Uint2 type, ValNodePtr choice, Pointer data)
1991 {
1992 ObjMgrPtr omp;
1993 Int4 i;
1994 ObjMgrDataPtr omdp;
1995 Boolean retval = FALSE;
1996
1997 omp = ObjMgrWriteLock();
1998
1999 i = ObjMgrLookup(omp, data);
2000 if (i < 0) /* not found */
2001 {
2002 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrChoice: pointer [%ld] type [%d] not found",
2003 (long)data, (int)type);
2004 goto erret;
2005 }
2006
2007 omdp = omp->datalist[i];
2008 omdp->choicetype = type;
2009 omdp->choice = choice;
2010 retval = TRUE;
2011 erret:
2012 ObjMgrUnlock();
2013
2014 #ifdef DEBUG_OBJMGR
2015 ObjMgrDump(NULL, "ObjMgrChoice");
2016 #endif
2017
2018 return retval;
2019 }
2020
2021 /*****************************************************************************
2022 *
2023 * ObjMgrFindTop(omp, omdp)
2024 * finds the highest parent of omdp
2025 * returns a ObjMgrDataPtr to the top
2026 *
2027 *****************************************************************************/
ObjMgrFindTop(ObjMgrPtr omp,ObjMgrDataPtr omdp)2028 NLM_EXTERN ObjMgrDataPtr LIBCALL ObjMgrFindTop (ObjMgrPtr omp, ObjMgrDataPtr omdp)
2029 {
2030 Int4 i;
2031
2032 if ((omp == NULL) || (omdp == NULL)) return NULL;
2033
2034 while (omdp->parentptr != NULL)
2035 {
2036 i = ObjMgrLookup(omp, omdp->parentptr);
2037 if (i < 0) /* not found */
2038 {
2039 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrFindTop: parentptr [%ld] not found",
2040 (long)(omdp->parentptr));
2041 return NULL;
2042 }
2043 omdp = omp->datalist[i];
2044 }
2045
2046 return omdp;
2047 }
2048
2049 /*****************************************************************************
2050 *
2051 * ObjMgrWholeEntity(omdp, itemID, itemtype)
2052 * returns TRUE if itemID, itemtype identify a complete entity omdp
2053 * returns FALSE if these are an internal part of the entity
2054 *
2055 *****************************************************************************/
ObjMgrWholeEntity(ObjMgrDataPtr omdp,Uint4 itemID,Uint2 itemtype)2056 NLM_EXTERN Boolean LIBCALL ObjMgrWholeEntity (ObjMgrDataPtr omdp, Uint4 itemID, Uint2 itemtype)
2057 {
2058 if (omdp == NULL)
2059 return FALSE;
2060
2061 if ((itemID == 0) && (itemtype == 0))
2062 return TRUE;
2063
2064 if ((itemID == 1) && (itemtype == omdp->datatype))
2065 return TRUE;
2066
2067 return FALSE;
2068
2069 }
2070
2071 /*****************************************************************************
2072 *
2073 * ObjMgrFreeCache(type)
2074 * Frees all cached objects of type and subtypes of type
2075 * based on ObjMgrMatch()
2076 * if type == 0, frees all cached objects
2077 * returns TRUE if no errors occurred
2078 *
2079 *****************************************************************************/
ObjMgrFreeCache(Uint2 type)2080 NLM_EXTERN Boolean LIBCALL ObjMgrFreeCache (Uint2 type)
2081 {
2082 ObjMgrPtr omp;
2083 Boolean more_to_go = TRUE;
2084 Uint2 rettype = 0;
2085 VoidPtr retval = NULL;
2086
2087 while (more_to_go)
2088 {
2089 omp = ObjMgrWriteLock();
2090 /*
2091 omp = ObjMgrReadLock ();
2092 */
2093 more_to_go = ObjMgrFreeCacheFunc(omp, type, &rettype, &retval);
2094 if (more_to_go)
2095 {
2096 switch (rettype)
2097 {
2098 case OBJ_SEQENTRY:
2099 SeqEntryFree((SeqEntryPtr)retval);
2100 break;
2101 case OBJ_BIOSEQ:
2102 BioseqFree((BioseqPtr)retval);
2103 break;
2104 case OBJ_BIOSEQSET:
2105 BioseqSetFree((BioseqSetPtr)retval);
2106 break;
2107 default:
2108 break;
2109 }
2110 }
2111 ObjMgrUnlock();
2112 }
2113
2114 /* if(type == 0)
2115 omp->HighestEntityID = 0; */
2116
2117 return TRUE;
2118 }
2119
2120 /*****************************************************************************
2121 *
2122 * ObjMgrFreeCacheFunc(type)
2123 * Finds next cached objects of type and subtypes of type
2124 * based on ObjMgrMatch()
2125 * if type == 0, frees all cached objects
2126 * if type == OBJ_MAX, frees unlocked cached objects
2127 * returns TRUE if no more found
2128 *
2129 *****************************************************************************/
ObjMgrFreeCacheFunc(ObjMgrPtr omp,Uint2 type,Uint2Ptr rettype,VoidPtr PNTR retval)2130 static Boolean NEAR ObjMgrFreeCacheFunc (ObjMgrPtr omp, Uint2 type, Uint2Ptr rettype, VoidPtr PNTR retval)
2131 {
2132 Int4 i, num;
2133 ObjMgrDataPtr PNTR omdpp, omdp;
2134
2135 if (omp->hold) /* things are being held */
2136 return FALSE; /* nothing to do, but send a warning */
2137
2138 omdpp = omp->datalist;
2139 num = omp->currobj;
2140 for (i = 0; i < num; i++)
2141 {
2142 omdp = omdpp[i];
2143 if ((omdp->parentptr == NULL) && /* top level */
2144 (omdp->tempload == TL_CACHED || /* cached or */
2145 (type == 0 && omdp->tempload == TL_LOADED) || /* temp loaded but not cached out */
2146 (type == OBJ_MAX && omdp->tempload == TL_LOADED && omdp->lockcnt == 0))) /* unlocked but not cached out */
2147 {
2148 if (type == 0 || type == OBJ_MAX ||
2149 (ObjMgrMatch(type, omdp->datatype)) ||
2150 (ObjMgrMatch(type, omdp->choicetype)))
2151 {
2152 /** here is where the freefunc should be called **/
2153
2154 if (omdp->choice != NULL)
2155 {
2156 switch (omdp->choicetype)
2157 {
2158 case OBJ_SEQENTRY:
2159 *rettype = omdp->choicetype;
2160 *retval = omdp->choice;
2161 return TRUE;
2162 default:
2163 ErrPostEx(SEV_ERROR,0,0, "ObjMgrFreeCache: unsupported choicetype[%d]",
2164 (int)(omdp->choicetype));
2165 break;
2166 }
2167 }
2168 else
2169 {
2170 switch(omdp->datatype)
2171 {
2172 case OBJ_BIOSEQ:
2173 case OBJ_BIOSEQSET:
2174 *rettype = omdp->datatype;
2175 *retval = omdp->dataptr;
2176 return TRUE;
2177 default:
2178 ErrPostEx(SEV_ERROR,0,0,"ObjMgrFreeCache: usupported datatype [%d]",
2179 (int)(omdp->datatype));
2180 break;
2181 }
2182 }
2183 }
2184 }
2185 }
2186 return FALSE;
2187
2188 }
2189
2190
2191 /*****************************************************************************
2192 *
2193 * ObjMgrMatch(type1, type2)
2194 * returns 0 if no match
2195 * 1 if identical
2196 * 2 if 2 is a subset of 1 (e.g. 1=OBJ_SEQENTRY, 2=BIOSEQ)
2197 * current type1 that can have subtypes are:
2198 * OBJ_SEQENTRY
2199 * OBJ_PUB
2200 * OBJ_SEQANNOT
2201 * OBJ_SEQCODE_SET
2202 * OBJ_GENETIC_CODE_SET
2203 *
2204 *****************************************************************************/
ObjMgrMatch(Uint2 type1,Uint2 type2)2205 NLM_EXTERN Int2 LIBCALL ObjMgrMatch (Uint2 type1, Uint2 type2)
2206 {
2207 if (type1 == type2)
2208 return 1;
2209
2210 switch (type1)
2211 {
2212 case OBJ_SEQENTRY:
2213 switch (type2)
2214 {
2215 case OBJ_BIOSEQ:
2216 case OBJ_BIOSEQSET:
2217 return 2;
2218 }
2219 break;
2220 case OBJ_SEQANNOT:
2221 switch (type2)
2222 {
2223 case OBJ_SEQFEAT:
2224 case OBJ_SEQALIGN:
2225 case OBJ_SEQGRAPH:
2226 return 2;
2227 }
2228 break;
2229 case OBJ_SEQCODE_SET:
2230 switch (type2)
2231 {
2232 case OBJ_SEQCODE:
2233 return 2;
2234 }
2235 break;
2236 case OBJ_GENETIC_CODE_SET:
2237 switch (type2)
2238 {
2239 case OBJ_GENETIC_CODE:
2240 return 2;
2241 }
2242 break;
2243 default:
2244 break;
2245 }
2246
2247 return 0;
2248 }
2249
2250
2251 /*****************************************************************************
2252 *
2253 * ObjMgrGetChoiceForData(data)
2254 * returns ValNodePtr for a BioseqPtr or BioseqSetPtr
2255 * choice must have been put in ObjMgr using ObjMgrChoice
2256 * the Bioseq/BioseqSets it is a part of must also be in ObjMgr
2257 * returns NULL on failure.
2258 *
2259 *****************************************************************************/
ObjMgrGetChoiceForData(Pointer data)2260 NLM_EXTERN ValNodePtr LIBCALL ObjMgrGetChoiceForData (Pointer data)
2261 {
2262 ObjMgrPtr omp;
2263 Int4 i;
2264 ValNodePtr choice = NULL;
2265
2266 if (data == NULL) return choice;
2267 omp = ObjMgrReadLock();
2268 i = ObjMgrLookup(omp, data);
2269 if (i < 0)
2270 {
2271 ErrPostEx(SEV_ERROR, 0,0, "ChoiceGetChoiceForData: data not in ObjMgr");
2272 }
2273 else
2274 {
2275 choice = omp->datalist[i]->choice;
2276 }
2277 ObjMgrUnlock();
2278
2279 return choice;
2280 }
2281
2282 /*****************************************************************************
2283 *
2284 * ObjMgrGetEntityIDForChoice(choice)
2285 * returns the EntityID for a ValNodePtr
2286 * choice must have been put in ObjMgr using ObjMgrChoice
2287 * the Bioseq/BioseqSets it is a part of must also be in ObjMgr
2288 * This function will move up to the top of the Choice tree it may be
2289 * in. If top level EntityID is 0, one is assigned at this point.
2290 * If an element is moved under a different hierarchy, its EntityID will
2291 * change.
2292 * returns 0 on failure.
2293 *
2294 *****************************************************************************/
ObjMgrGetEntityIDForChoice(ValNodePtr choice)2295 NLM_EXTERN Uint2 LIBCALL ObjMgrGetEntityIDForChoice (ValNodePtr choice)
2296 {
2297 Pointer data;
2298
2299 if (choice == NULL) return 0;
2300 data = choice->data.ptrvalue;
2301 if (data == NULL) return 0;
2302
2303 return ObjMgrGetEntityIDForPointer (data);
2304 }
2305
2306 /*****************************************************************************
2307 *
2308 * ObjMgrGetEntityIDForPointer(data)
2309 * returns the EntityID for any pointer, Choice or Data
2310 * This function will move up to the top of the tree it may be
2311 * in. If top level EntityID is 0, one is assigned at this point.
2312 * If an element is moved under a different hierarchy, its EntityID will
2313 * change.
2314 *
2315 * Either ObjMgrGetEntityIDForPointer() or ObjMgrGetEntityIDForChoice()
2316 * MUST be called to have an OM_MSG_CREATE message sent to any
2317 * registered proceedures
2318 *
2319 * returns 0 on failure.
2320 *
2321 *****************************************************************************/
ObjMgrGetEntityIDForPointer(Pointer ptr)2322 NLM_EXTERN Uint2 LIBCALL ObjMgrGetEntityIDForPointer (Pointer ptr)
2323 {
2324 ObjMgrPtr omp;
2325 ObjMgrDataPtr omdp;
2326 Uint2 retval = 0;
2327
2328 if (ptr == NULL)
2329 return retval;
2330
2331 omp = ObjMgrWriteLock(); /* (EY) */
2332 omdp = ObjMgrFindByData(omp, ptr);
2333
2334 if (omdp == NULL) goto erret;
2335
2336 omdp = ObjMgrFindTop(omp, omdp);
2337 if (omdp == NULL) goto erret;
2338
2339 if (omdp->EntityID == 0) /* need to assign it */
2340 ObjMgrAddEntityID(omp, omdp);
2341
2342 retval = omdp->EntityID;
2343 erret:
2344 ObjMgrUnlock();
2345
2346 return retval;
2347 }
2348
2349 /*****************************************************************************
2350 *
2351 * ObjMgrGetChoiceForEntityID (id)
2352 *
2353 *****************************************************************************/
ObjMgrGetChoiceForEntityID(Uint2 id)2354 NLM_EXTERN ValNodePtr LIBCALL ObjMgrGetChoiceForEntityID (Uint2 id)
2355 {
2356 ObjMgrPtr omp;
2357 ObjMgrDataPtr omdp;
2358 ValNodePtr retval = NULL;
2359
2360 if (id <= 0) return retval;
2361
2362 omp = ObjMgrReadLock();
2363 omdp = ObjMgrFindByEntityID(omp, id, NULL);
2364 if (omdp != NULL)
2365 retval = omdp->choice;
2366 ObjMgrUnlock();
2367 return retval;
2368 }
2369
2370 /*****************************************************************************
2371 *
2372 * ObjMgrLock(type, data, lockit)
2373 * if lockit=TRUE, locks the element
2374 * else unlocks it
2375 * returns the current lock count or -1 on failure
2376 *
2377 *****************************************************************************/
ObjMgrLock(Uint2 type,Pointer data,Boolean lockit)2378 NLM_EXTERN Int4 LIBCALL ObjMgrLock (Uint2 type, Pointer data, Boolean lockit)
2379 {
2380 ObjMgrPtr omp;
2381 Int4 retval = -1;
2382
2383 omp = ObjMgrWriteLock();
2384 if (omp != NULL)
2385 retval = ObjMgrLockFunc(omp, type, data, lockit);
2386 ObjMgrUnlock();
2387 return retval;
2388 }
2389
ObjMgrLockFunc(ObjMgrPtr omp,Uint2 type,Pointer data,Boolean lockit)2390 static Int4 NEAR ObjMgrLockFunc (ObjMgrPtr omp, Uint2 type, Pointer data, Boolean lockit)
2391 {
2392 Int4 i, lockcnt = -1;
2393 ObjMgrDataPtr omdp;
2394
2395 #ifdef DEBUG_OBJMGR
2396 Char buf[80];
2397 #endif
2398
2399 i = ObjMgrLookup(omp, data);
2400 if (i < 0) /* not found */
2401 {
2402 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrLock: pointer [%ld] type [%d] not found",
2403 (long)data, (int)type);
2404 return lockcnt;
2405 }
2406
2407 omdp = ObjMgrFindTop(omp, omp->datalist[i]);
2408 if (omdp == NULL) {
2409 return lockcnt;
2410 }
2411
2412 if (lockit) {
2413 omdp->lockcnt++;
2414
2415 /******** desktop can do this *******
2416 if (omdp->tempload == TL_CACHED)
2417 {
2418 ErrPostEx(SEV_ERROR, 0,0,"ObjMgrLock: locking a cached entity");
2419 }
2420 *************************************/
2421 }
2422 else
2423 {
2424 if (omdp->lockcnt) {
2425 omdp->lockcnt--;
2426 }
2427 else
2428 {
2429 ErrPostEx(SEV_ERROR, 0,0,"ObjMgrLock: unlocking 0 lockcnt");
2430 return lockcnt;
2431 }
2432 }
2433
2434 lockcnt = omdp->lockcnt;
2435
2436 if (! lockit) /* check for automatic delete */
2437 {
2438 if ((omdp->tempload != TL_NOT_TEMP) && (! omdp->lockcnt))
2439 {
2440 omdp->touch = ObjMgrTouchCnt(); /* stamp with time */
2441 /*
2442 omp->tempcnt++;
2443 */
2444 ObjMgrReap(omp);
2445 }
2446 }
2447
2448
2449 #ifdef DEBUG_OBJMGR
2450 if (lockit)
2451 sprintf(buf, "ObjMgrLock Lock [%d]", (int)i);
2452 else
2453 sprintf(buf, "ObjMgrLock Unlock [%d]", (int)i);
2454 ObjMgrDump(NULL, buf);
2455 #endif
2456
2457 return lockcnt;
2458 }
2459
2460 /*****************************************************************************
2461 *
2462 * Boolean ObjMgrSetTempLoad (ObjMgrPtr omp, Pointer ptr)
2463 * Sets a Loaded element to "temporary"
2464 *
2465 *****************************************************************************/
ObjMgrSetTempLoad(ObjMgrPtr omp,Pointer ptr)2466 NLM_EXTERN Boolean LIBCALL ObjMgrSetTempLoad (ObjMgrPtr omp, Pointer ptr)
2467 {
2468 Int4 index;
2469 ObjMgrDataPtr omdp;
2470
2471 index = ObjMgrLookup(omp, ptr);
2472 if (index < 0) return FALSE;
2473
2474 omdp = ObjMgrFindTop(omp, omp->datalist[index]);
2475 if (omdp == NULL) return FALSE;
2476
2477 if (omdp->tempload == TL_NOT_TEMP)
2478 {
2479 omdp->tempload = TL_LOADED;
2480 omp->tempcnt++;
2481 }
2482 omdp->touch = ObjMgrTouchCnt();
2483
2484 omdp->lockcnt++; /* protect against reaping this one */
2485 ObjMgrReap (omp); /* check to see if we need to reap */
2486 omdp->lockcnt--; /* reset to previous state */
2487
2488 return TRUE;
2489 }
2490
2491 /*****************************************************************************
2492 *
2493 * ObjMgrReap(omp)
2494 * Checks to see if memory needs to be cleared, and does it
2495 *
2496 *****************************************************************************/
SortDitchArrayByTouchTime(VoidPtr vp1,VoidPtr vp2)2497 static int LIBCALLBACK SortDitchArrayByTouchTime (
2498 VoidPtr vp1,
2499 VoidPtr vp2
2500 )
2501
2502 {
2503 ObjMgrDataPtr omdpp1, omdpp2;
2504
2505 if (vp1 == NULL || vp2 == NULL) return 0;
2506 omdpp1 = *((ObjMgrDataPtr PNTR) vp1);
2507 omdpp2 = *((ObjMgrDataPtr PNTR) vp2);
2508 if (omdpp1 == NULL || omdpp2 == NULL) return 0;
2509
2510 if (omdpp1->touch > omdpp2->touch) return 1;
2511 if (omdpp1->touch < omdpp2->touch) return -1;
2512
2513 return 0;
2514 }
2515
ObjMgrReap(ObjMgrPtr omp)2516 NLM_EXTERN Boolean LIBCALL ObjMgrReap (ObjMgrPtr omp)
2517 {
2518 Uint4 lowest;
2519 Int4 num, j;
2520 Uint2 tempcnt, i, k;
2521 ObjMgrDataPtr tmp, ditch, PNTR omdpp, PNTR ditcharray;
2522 Boolean is_write_locked, did_one = FALSE;
2523
2524 if (omp->hold) /* keep all tempload records around while hold is on */
2525 return FALSE;
2526
2527 if (omp->reaping) /* protect against recursion caused by ObjMgrSendMsg */
2528 return FALSE;
2529
2530 tempcnt = 0;
2531 num = omp->currobj;
2532 omdpp = omp->datalist;
2533 for (j = 0; j < num; j++, omdpp++)
2534 {
2535 tmp = *omdpp;
2536 if ((tmp->tempload == TL_LOADED) && (! tmp->lockcnt))
2537 {
2538 tempcnt++;
2539 }
2540 }
2541
2542 if (tempcnt <= omp->maxtemp) return TRUE;
2543
2544 /* faster version */
2545
2546 ditcharray = (ObjMgrDataPtr PNTR) MemNew (sizeof (ObjMgrDataPtr) * (tempcnt + 1));
2547 if (ditcharray != NULL) {
2548
2549 tempcnt = 0;
2550 num = omp->currobj;
2551 omdpp = omp->datalist;
2552 for (j = 0; j < num; j++, omdpp++) {
2553 tmp = *omdpp;
2554 if ((tmp->tempload == TL_LOADED) && (! tmp->lockcnt)) {
2555 ditcharray [(int) tempcnt] = tmp;
2556 tempcnt++;
2557 }
2558 }
2559
2560 StableMergeSort (ditcharray, (size_t) tempcnt, sizeof (ObjMgrDataPtr), SortDitchArrayByTouchTime);
2561
2562 for (i = 0, k = tempcnt; i < tempcnt && k > omp->maxtemp; i++, k--) {
2563 ditch = ditcharray [(int) i];
2564 if (ditch == NULL) continue;
2565
2566 omp->reaping = TRUE;
2567 ditch->tempload = TL_CACHED;
2568 ObjMgrSendMsgFunc(omp, ditch, OM_MSG_CACHED, ditch->EntityID, 0, 0, 0, 0, 0, NULL);
2569 omp->tempcnt--;
2570 is_write_locked = omp->is_write_locked;
2571
2572 /* null out feature pointers in seqmgr feature indices via reap function */
2573
2574 if (ditch->extradata != NULL && ditch->reapextra != NULL) {
2575 ditch->reapextra ((Pointer) ditch);
2576 }
2577
2578 if (ditch->choice != NULL) {
2579 switch (ditch->choicetype) {
2580 case OBJ_SEQENTRY:
2581 did_one = TRUE;
2582 ObjMgrUnlock();
2583 SeqEntryFreeComponents(ditch->choice);
2584 break;
2585 default:
2586 ErrPostEx(SEV_ERROR,0,0,"ObjMgrReap: ditching unknown type");
2587 break;
2588 }
2589 } else {
2590 switch (ditch->datatype) {
2591 case OBJ_BIOSEQ:
2592 did_one = TRUE;
2593 ObjMgrUnlock();
2594 BioseqFreeComponents((BioseqPtr)(ditch->dataptr));
2595 break;
2596 case OBJ_BIOSEQSET:
2597 did_one = TRUE;
2598 ObjMgrUnlock();
2599 BioseqSetFreeComponents((BioseqSetPtr)(ditch->dataptr), FALSE);
2600 break;
2601 default:
2602 ErrPostEx(SEV_ERROR,0,0,"ObjMgrReap: ditching unknown type");
2603 break;
2604 }
2605 }
2606
2607 if (did_one) {
2608 if (is_write_locked) {
2609 omp = ObjMgrWriteLock();
2610 } else {
2611 omp = ObjMgrReadLock();
2612 }
2613 }
2614
2615 omp->reaping = FALSE;
2616 }
2617
2618 MemFree (ditcharray);
2619 return TRUE;
2620 }
2621
2622 /* otherwise fall through to old less efficient code */
2623
2624 while (/* omp-> */ tempcnt > omp->maxtemp) /* time to reap */
2625 {
2626 lowest = UINT4_MAX;
2627
2628 tempcnt = 0;
2629 num = omp->currobj;
2630 omdpp = omp->datalist;
2631 ditch = NULL;
2632 for (j = 0; j < num; j++, omdpp++)
2633 {
2634 tmp = *omdpp;
2635 if ((tmp->tempload == TL_LOADED) && (! tmp->lockcnt))
2636 {
2637 tempcnt++;
2638 if (lowest > tmp->touch)
2639 {
2640 lowest = tmp->touch;
2641 ditch = tmp;
2642 }
2643 }
2644 }
2645 if (ditch == NULL) /* nothing to free */
2646 return FALSE;
2647
2648 omp->reaping = TRUE;
2649 ditch->tempload = TL_CACHED;
2650 ObjMgrSendMsgFunc(omp, ditch, OM_MSG_CACHED, ditch->EntityID, 0, 0, 0, 0, 0, NULL);
2651 omp->tempcnt--;
2652 tempcnt--;
2653 is_write_locked = omp->is_write_locked;
2654
2655 /* null out feature pointers in seqmgr feature indices via reap function */
2656
2657 if (ditch->extradata != NULL && ditch->reapextra != NULL) {
2658 ditch->reapextra ((Pointer) ditch);
2659 }
2660
2661 if (ditch->choice != NULL)
2662 {
2663 switch (ditch->choicetype)
2664 {
2665 case OBJ_SEQENTRY:
2666 did_one = TRUE;
2667 ObjMgrUnlock();
2668 SeqEntryFreeComponents(ditch->choice);
2669 break;
2670 }
2671 }
2672 else
2673 {
2674 switch (ditch->datatype)
2675 {
2676 case OBJ_BIOSEQ:
2677 did_one = TRUE;
2678 ObjMgrUnlock();
2679 BioseqFreeComponents((BioseqPtr)(ditch->dataptr));
2680 break;
2681 case OBJ_BIOSEQSET:
2682 did_one = TRUE;
2683 ObjMgrUnlock();
2684 BioseqSetFreeComponents((BioseqSetPtr)(ditch->dataptr), FALSE);
2685 break;
2686 default:
2687 ErrPostEx(SEV_ERROR,0,0,"ObjMgrUnlock: ditching unknown type");
2688 break;
2689 }
2690 }
2691
2692 if (did_one)
2693 {
2694 if (is_write_locked)
2695 omp = ObjMgrWriteLock();
2696 else
2697 omp = ObjMgrReadLock();
2698 }
2699
2700 omp->reaping = FALSE;
2701
2702 #ifdef DEBUG_OBJMGR
2703 ObjMgrDump(NULL, "ObjMgrReap");
2704 #endif
2705
2706 }
2707
2708 return TRUE;
2709 }
2710
2711 /*****************************************************************************
2712 *
2713 * ObjMgrReapOne(omp)
2714 * Reaps the single least recently accessed entity
2715 *
2716 *****************************************************************************/
ObjMgrReapOne(ObjMgrPtr omp)2717 NLM_EXTERN Boolean LIBCALL ObjMgrReapOne (ObjMgrPtr omp)
2718 {
2719 Uint4 lowest;
2720 Int4 num, j;
2721 ObjMgrDataPtr tmp, ditch, PNTR omdpp;
2722 Boolean is_write_locked, did_one = FALSE;
2723
2724 if (omp->hold) /* keep all tempload records around while hold is on */
2725 return FALSE;
2726
2727 if (omp->reaping) /* protect against recursion caused by ObjMgrSendMsg */
2728 return FALSE;
2729
2730 lowest = UINT4_MAX;
2731
2732 num = omp->currobj;
2733 omdpp = omp->datalist;
2734 ditch = NULL;
2735 for (j = 0; j < num; j++, omdpp++)
2736 {
2737 tmp = *omdpp;
2738 if ((tmp->tempload == TL_LOADED) && (! tmp->lockcnt))
2739 {
2740 if (lowest > tmp->touch)
2741 {
2742 lowest = tmp->touch;
2743 ditch = tmp;
2744 }
2745 }
2746 }
2747 if (ditch == NULL) /* nothing to free */
2748 return FALSE;
2749
2750 omp->reaping = TRUE;
2751 ditch->tempload = TL_CACHED;
2752 ObjMgrSendMsgFunc(omp, ditch, OM_MSG_CACHED, ditch->EntityID, 0, 0, 0, 0, 0, NULL);
2753 omp->tempcnt--;
2754 is_write_locked = omp->is_write_locked;
2755
2756 /* null out feature pointers in seqmgr feature indices via reap function */
2757
2758 if (ditch->extradata != NULL && ditch->reapextra != NULL) {
2759 ditch->reapextra ((Pointer) ditch);
2760 }
2761
2762 if (ditch->choice != NULL)
2763 {
2764 switch (ditch->choicetype)
2765 {
2766 case OBJ_SEQENTRY:
2767 did_one = TRUE;
2768 ObjMgrUnlock();
2769 SeqEntryFreeComponents(ditch->choice);
2770 break;
2771 }
2772 }
2773 else
2774 {
2775 switch (ditch->datatype)
2776 {
2777 case OBJ_BIOSEQ:
2778 did_one = TRUE;
2779 ObjMgrUnlock();
2780 BioseqFreeComponents((BioseqPtr)(ditch->dataptr));
2781 break;
2782 case OBJ_BIOSEQSET:
2783 did_one = TRUE;
2784 ObjMgrUnlock();
2785 BioseqSetFreeComponents((BioseqSetPtr)(ditch->dataptr), FALSE);
2786 break;
2787 default:
2788 ErrPostEx(SEV_ERROR,0,0,"ObjMgrUnlock: ditching unknown type");
2789 break;
2790 }
2791 }
2792
2793 if (did_one)
2794 {
2795 if (is_write_locked)
2796 omp = ObjMgrWriteLock();
2797 else
2798 omp = ObjMgrReadLock();
2799 }
2800
2801 omp->reaping = FALSE;
2802
2803 #ifdef DEBUG_OBJMGR
2804 ObjMgrDump(NULL, "ObjMgrReapOne");
2805 #endif
2806
2807 return TRUE;
2808 }
2809
2810 /*****************************************************************************
2811 *
2812 * Boolean ObjMgrIsTemp(data)
2813 * returns TRUE if data is a temporarily loaded item
2814 * data must be BioseqPtr or BioseqSetPtr
2815 *
2816 *****************************************************************************/
ObjMgrIsTemp(Pointer data)2817 NLM_EXTERN Boolean LIBCALL ObjMgrIsTemp (Pointer data)
2818 {
2819 ObjMgrPtr omp;
2820 Int4 i;
2821 ObjMgrDataPtr omdp;
2822 Boolean retval = FALSE;
2823
2824 omp = ObjMgrReadLock();
2825
2826 i = ObjMgrLookup(omp, data);
2827 if (i < 0) /* not found */
2828 {
2829 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrIsTemp: pointer [%ld] not found",
2830 (long)data);
2831 goto erret;
2832 }
2833
2834 omdp = ObjMgrFindTop(omp, omp->datalist[i]);
2835 if (omdp == NULL) goto erret;
2836
2837 if (omdp->tempload != TL_NOT_TEMP)
2838 retval = TRUE;
2839 erret:
2840 ObjMgrUnlock();
2841 return retval;
2842 }
2843
2844 /*****************************************************************************
2845 *
2846 * Boolean ObjMgrIsParent(parent, child)
2847 * returns TRUE if child is a child of parent
2848 * if parent = NULL, returns TRUE if child has no parent
2849 * child must never be NULL
2850 * returns TRUE if they are the equal
2851 * data must be BioseqPtr or BioseqSetPtr
2852 *
2853 *****************************************************************************/
ObjMgrIsChild(Pointer parent,Pointer child)2854 NLM_EXTERN Boolean LIBCALL ObjMgrIsChild (Pointer parent, Pointer child)
2855 {
2856 ObjMgrPtr omp;
2857 Int4 i;
2858 ObjMgrDataPtr omdp, PNTR omdpp;
2859 Boolean retval = FALSE;
2860
2861 if (child == NULL) return FALSE;
2862 if (parent == child) return TRUE;
2863
2864 omp = ObjMgrReadLock();
2865 omdpp = omp->datalist;
2866
2867 i = ObjMgrLookup(omp, child);
2868 if (i < 0) /* not found */
2869 {
2870 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrIsChild: pointer [%ld] not found",
2871 (long)child);
2872 goto erret;
2873 }
2874
2875 omdp = omdpp[i];
2876 if (parent == NULL)
2877 {
2878 if (omdp->parentptr == NULL)
2879 retval = TRUE;
2880 goto erret;
2881 }
2882
2883 while (omdp->parentptr != NULL)
2884 {
2885 if (omdp->parentptr == parent)
2886 {
2887 retval = TRUE;
2888 goto erret;
2889 }
2890 i = ObjMgrLookup(omp, omdp->parentptr);
2891 if (i < 0)
2892 goto erret;
2893 omdp = omdpp[i];
2894 }
2895 erret:
2896 ObjMgrUnlock();
2897 return retval;
2898 }
2899
2900 /*****************************************************************************
2901 *
2902 * ObjMgrDump(fp)
2903 *
2904 *****************************************************************************/
2905
ObjMgrDump(FILE * fp,CharPtr title)2906 NLM_EXTERN void LIBCALL ObjMgrDump (FILE * fp, CharPtr title)
2907 {
2908 ObjMgrPtr omp;
2909 ObjMgrDataPtr omdp;
2910 Uint4 i;
2911 Char buf[128];
2912 BioseqPtr bsp;
2913 Boolean close_it = FALSE;
2914
2915 if (fp == NULL)
2916 {
2917 fp = FileOpen("ObjMgr.log", "a");
2918 close_it = TRUE;
2919 }
2920
2921 omp = ObjMgrGet();
2922 fprintf(fp, "\n%s currobj=%d tempcnt=%d\n", title, (int)(omp->currobj),
2923 (int)(omp->tempcnt));
2924 for (i = 0; i < omp->currobj; i++)
2925 {
2926 omdp = omp->datalist[i];
2927 fprintf(fp, "[%d] [%d %d %ld] [%d %ld] %ld (%d) %ud\n", (int)i,
2928 (int)omdp->EntityID, (int)(omdp->datatype),
2929 (long)(omdp->dataptr), (int)(omdp->parenttype),
2930 (long)(omdp->parentptr), (long)(omdp->choice), (int)(omdp->lockcnt),
2931 (omdp->touch));
2932 if ((omdp->datatype == OBJ_BIOSEQ) && (omdp->dataptr != NULL))
2933 {
2934 bsp = (BioseqPtr)(omdp->dataptr);
2935 SeqIdWrite(bsp->id, buf, PRINTID_FASTA_LONG, sizeof (buf));
2936 fprintf(fp, "[%s %ld]\n", buf, (long)(bsp));
2937 }
2938 }
2939
2940 if (close_it)
2941 FileClose(fp);
2942 return;
2943 }
2944
2945 /*****************************************************************************
2946 *
2947 * Procedure Management Functions
2948 *
2949 *****************************************************************************/
2950
2951
2952 /*****************************************************************************
2953 *
2954 * ObjMgrProcExtend(omp)
2955 *
2956 *****************************************************************************/
ObjMgrProcExtend(ObjMgrPtr omp)2957 static Boolean NEAR ObjMgrProcExtend (ObjMgrPtr omp)
2958 {
2959 Boolean result = FALSE;
2960 OMProcPtr omdp, prev=NULL;
2961 ObjMgrProcPtr PNTR tmp;
2962 Int4 i, j;
2963
2964 for (omdp = omp->ncbiproc; omdp != NULL; omdp = omdp->next)
2965 prev = omdp;
2966
2967 omdp = (OMProcPtr)MemNew(sizeof(OMProc));
2968 if (omdp == NULL) return result;
2969 tmp = (ObjMgrProcPtr PNTR)MemNew((size_t)(sizeof(ObjMgrProcPtr) * (omp->totproc + NUM_OMD)));
2970 if (tmp == NULL)
2971 {
2972 MemFree(omdp);
2973 return result;
2974 }
2975
2976 if (prev != NULL)
2977 {
2978 prev->next = omdp;
2979 MemMove(tmp, omp->proclist, (size_t)(sizeof(ObjMgrProcPtr) *omp->totproc));
2980 MemFree(omp->proclist);
2981 }
2982 else
2983 omp->ncbiproc = omdp;
2984
2985 j = omp->totproc;
2986
2987 for (i = 0; i < NUM_OMD; i++, j++)
2988 tmp[j] = &(omdp->data[i]);
2989
2990 omp->totproc += NUM_OMD;
2991 omp->proclist = tmp;
2992
2993 result = TRUE;
2994 return result;
2995 }
2996
2997 /*****************************************************************************
2998 *
2999 * ObjMgrProcAdd(data, priority)
3000 * adds an ObjMgrProc at given priority
3001 * priority must be > 0
3002 * highest priority function is called first.
3003 * if priority == 0 (default)
3004 * gets the next highest priority over previous procs of same type
3005 * if priority == PROC_PRIORITY_HIGHEST
3006 * is always the highest priority (first one wins)
3007 * if priority == PROC_PRIORITY_LOWEST
3008 * is always the lowest priority
3009 *
3010 *****************************************************************************/
ObjMgrProcAdd(ObjMgrProcPtr data,Int2 priority)3011 NLM_EXTERN Uint2 LIBCALL ObjMgrProcAdd (ObjMgrProcPtr data, Int2 priority)
3012 {
3013 ObjMgrPtr omp;
3014 ObjMgrProcPtr omdp;
3015 ObjMgrProcPtr PNTR omdpp;
3016 Int4 i;
3017 Uint2 procID;
3018 Uint2 retval = 0;
3019
3020 omp = ObjMgrWriteLock();
3021
3022 if (priority == 0) /* set to next highest */
3023 {
3024 omdp = ObjMgrProcFindNext(omp, data->proctype, data->inputtype,
3025 data->outputtype, NULL);
3026 if (omdp != NULL)
3027 priority = omdp->priority + 10;
3028 }
3029
3030
3031 if (omp->currproc >= omp->totproc)
3032 {
3033 if (! ObjMgrProcExtend(omp))
3034 goto erret;
3035 }
3036
3037 i = omp->currproc;
3038 omdpp = omp->proclist;
3039 omdp = omdpp[i]; /* emptys always at end */
3040
3041 omp->currproc++; /* got one more */
3042 procID = ++(omp->HighestProcID);
3043
3044 MemMove(omdp, data, sizeof(ObjMgrProc));
3045 omdp->priority = priority;
3046 omdp->procid = procID; /* fill in the values */
3047 omdp->proclabel = StringSave(data->proclabel);
3048 omdp->procname = StringSave(data->procname);
3049 omdp->submenu = StringSave(data->submenu);
3050 retval = procID;
3051 erret:
3052 ObjMgrUnlock();
3053
3054 return retval;
3055 }
3056
3057 /*****************************************************************************
3058 *
3059 * ObjMgrProcLoadEx(proctype, procname, proclabel, inputtype, subinputtype,
3060 * outputtype, suboutputtype,
3061 * data, func, priority, submenu)
3062 * adds a new proceedure with these parameters
3063 * returns the procid
3064 * if a procedure of the same name and type are already loaded
3065 * returns the procid of the loaded proc.. does not reload
3066 *
3067 *****************************************************************************/
ObjMgrProcLoadEx(Uint2 proctype,CharPtr procname,CharPtr proclabel,Uint2 inputtype,Uint2 subinputtype,Uint2 outputtype,Uint2 suboutputtype,Pointer userdata,ObjMgrGenFunc func,Int2 priority,CharPtr submenu)3068 NLM_EXTERN Uint2 ObjMgrProcLoadEx (Uint2 proctype, CharPtr procname, CharPtr proclabel,
3069 Uint2 inputtype, Uint2 subinputtype,
3070 Uint2 outputtype, Uint2 suboutputtype, Pointer userdata,
3071 ObjMgrGenFunc func, Int2 priority, CharPtr submenu)
3072 {
3073 ObjMgrPtr omp;
3074 ObjMgrProcPtr ompp;
3075 ObjMgrProc ompd;
3076
3077 omp = ObjMgrWriteLock();
3078 ompp = ObjMgrProcFind(omp, 0, procname, proctype);
3079 ObjMgrUnlock();
3080 if (ompp != NULL) /* already enabled */
3081 {
3082 return ompp->procid;
3083 }
3084
3085 ompp = &ompd;
3086 MemSet((Pointer)ompp, 0, sizeof(ObjMgrProc));
3087
3088 ompp->proctype = proctype;
3089 ompp->procname = procname;
3090 ompp->proclabel = proclabel;
3091 ompp->inputtype = inputtype;
3092 ompp->subinputtype = subinputtype;
3093 ompp->outputtype = outputtype;
3094 ompp->suboutputtype = suboutputtype;
3095 ompp->procdata = userdata;
3096 ompp->func = func;
3097 ompp->submenu = submenu;
3098
3099 return ObjMgrProcAdd(ompp, priority); /* order determines priority */
3100
3101 }
3102
3103 /*****************************************************************************
3104 *
3105 * ObjMgrProcLoad(proctype, procname, proclabel, inputtype, subinputtype,
3106 * outputtype, suboutputtype,
3107 * data, func, priority)
3108 * adds a new proceedure with these parameters
3109 * returns the procid
3110 * if a procedure of the same name and type are already loaded
3111 * returns the procid of the loaded proc.. does not reload
3112 *
3113 *****************************************************************************/
ObjMgrProcLoad(Uint2 proctype,CharPtr procname,CharPtr proclabel,Uint2 inputtype,Uint2 subinputtype,Uint2 outputtype,Uint2 suboutputtype,Pointer userdata,ObjMgrGenFunc func,Int2 priority)3114 NLM_EXTERN Uint2 ObjMgrProcLoad (Uint2 proctype, CharPtr procname, CharPtr proclabel,
3115 Uint2 inputtype, Uint2 subinputtype,
3116 Uint2 outputtype, Uint2 suboutputtype, Pointer userdata,
3117 ObjMgrGenFunc func, Int2 priority)
3118
3119 {
3120 return ObjMgrProcLoadEx (proctype, procname, proclabel, inputtype, subinputtype,
3121 outputtype, suboutputtype, userdata, func, priority, NULL);
3122 }
3123
3124 /*****************************************************************************
3125 *
3126 * ObjMgrProcLookup(omp, procid)
3127 * these are currently just stored in order
3128 * returns index (>=0) if found
3129 * returns -1 if not found
3130 *
3131 *****************************************************************************/
ObjMgrProcLookup(ObjMgrPtr omp,Uint2 procid)3132 NLM_EXTERN Int4 LIBCALL ObjMgrProcLookup(ObjMgrPtr omp, Uint2 procid)
3133 {
3134 if (omp == NULL)
3135 return (Int4)(-1);
3136
3137 if (procid)
3138 return (Int4)(procid - 1);
3139 else
3140 return (Int4)(-1);
3141 }
3142
3143 /*****************************************************************************
3144 *
3145 * ObjMgrProcFind(omp, procid, procname, proctype)
3146 * if procid != NULL looks for it
3147 * else matches on procname and proctype
3148 * proctype = 0, matches all proctypes
3149 *
3150 *****************************************************************************/
ObjMgrProcFind(ObjMgrPtr omp,Uint2 procid,CharPtr procname,Uint2 proctype)3151 NLM_EXTERN ObjMgrProcPtr LIBCALL ObjMgrProcFind(ObjMgrPtr omp, Uint2 procid,
3152 CharPtr procname, Uint2 proctype)
3153 {
3154 ObjMgrProcPtr ompp=NULL, PNTR omppp, tmp;
3155 Int4 i, imax;
3156
3157 omppp = omp->proclist;
3158 imax = omp->currproc;
3159
3160 if (procid) /* procid lookup is different */
3161 {
3162 i = ObjMgrProcLookup(omp, procid);
3163 if (i >= 0)
3164 ompp = omppp[i];
3165 return ompp;
3166 }
3167
3168 for (i = 0; i < imax; i++)
3169 {
3170 tmp = omppp[i];
3171 if ((! proctype) || (proctype == tmp->proctype))
3172 {
3173 if (! StringCmp(procname, tmp->procname))
3174 return tmp;
3175 }
3176 }
3177 return ompp;
3178 }
3179
3180 /*****************************************************************************
3181 *
3182 * ObjMgrGetProcID(omp, procname, proctype)
3183 * returns procid given procname and proctype
3184 *
3185 *****************************************************************************/
ObjMgrGetProcID(ObjMgrPtr omp,CharPtr procname,Uint2 proctype)3186 NLM_EXTERN Uint2 LIBCALL ObjMgrGetProcID (ObjMgrPtr omp, CharPtr procname, Uint2 proctype)
3187
3188 {
3189 ObjMgrProcPtr ompp;
3190
3191 ompp = ObjMgrProcFind (omp, 0, procname, proctype);
3192 if (ompp == NULL) return 0;
3193 return ompp->procid;
3194 }
3195
3196 /*****************************************************************************
3197 *
3198 * ObjMgrProcFindNext(omp, proctype, inputtype, outputtype, last)
3199 * looks for proctype of highest priority that
3200 * matches inputtype and outputtype
3201 * 0 on proctype or inputtype or outputtype matches any
3202 * if last != NULL, then gets next after last
3203 * if omp == NULL, will ObjMgrReadLock() and Unlock() within the function
3204 *
3205 *****************************************************************************/
ObjMgrProcFindNext(ObjMgrPtr tomp,Uint2 proctype,Uint2 inputtype,Uint2 outputtype,ObjMgrProcPtr last)3206 NLM_EXTERN ObjMgrProcPtr LIBCALL ObjMgrProcFindNext (ObjMgrPtr tomp, Uint2 proctype,
3207 Uint2 inputtype, Uint2 outputtype, ObjMgrProcPtr last)
3208 {
3209 ObjMgrPtr omp;
3210 ObjMgrProcPtr best = NULL, tmp, retval = NULL;
3211 Int4 i, bestpriority=-32766, imax, maxpriority=32767;
3212 ObjMgrProcPtr PNTR omppp;
3213 Boolean unlock = FALSE;
3214
3215 if (tomp == NULL)
3216 {
3217 omp = ObjMgrReadLock();
3218 unlock = TRUE;
3219 }
3220 else
3221 omp = tomp;
3222
3223 omppp = omp->proclist;
3224 imax = omp->currproc;
3225
3226 if (last != NULL)
3227 {
3228 maxpriority = last->priority;
3229 i = ObjMgrProcLookup(omp, last->procid);
3230 i++;
3231 while (i < imax) /* find next of equal priority */
3232 {
3233 tmp = omppp[i];
3234 if ((! proctype) || (tmp->proctype == proctype))
3235 {
3236 if ((! inputtype) || (tmp->inputtype == inputtype))
3237 {
3238 if ((! outputtype) || (tmp->outputtype == outputtype))
3239 {
3240 if (tmp->priority == maxpriority)
3241 {
3242 retval = tmp;
3243 goto erret;
3244 }
3245 }
3246 }
3247 }
3248 i++;
3249 }
3250 }
3251
3252 for (i = 0; i < imax; i++) /* find the highest priority less than any previous */
3253 {
3254 tmp = omppp[i];
3255 if ((! proctype) || (tmp->proctype == proctype))
3256 {
3257 if ((! inputtype) || (tmp->inputtype == inputtype))
3258 {
3259 if ((! outputtype) || (tmp->outputtype == outputtype))
3260 {
3261 if ((tmp->priority > bestpriority) &&
3262 (tmp->priority < maxpriority))
3263 {
3264 best = tmp;
3265 bestpriority = tmp->priority;
3266 }
3267 }
3268 }
3269 }
3270
3271 }
3272
3273 retval = best;
3274 erret:
3275 if (unlock)
3276 ObjMgrUnlock();
3277 return retval;
3278 }
3279
ObjMgrProcOpen(ObjMgrPtr omp,Uint2 outputtype)3280 NLM_EXTERN Int2 LIBCALL ObjMgrProcOpen (ObjMgrPtr omp, Uint2 outputtype)
3281 {
3282 ObjMgrProcPtr currp=NULL;
3283 Int2 retval = OM_MSG_RET_ERROR;
3284 Boolean did_one = FALSE;
3285 OMProcControl ompc;
3286
3287 MemSet((Pointer)(&ompc), 0, sizeof(OMProcControl));
3288 ompc.output_itemtype = outputtype;
3289
3290 while ((currp = ObjMgrProcFindNext(omp, OMPROC_OPEN, 0, outputtype, currp)) != NULL)
3291 {
3292 ompc.proc = currp;
3293 retval = (*(currp->func)) (&ompc);
3294 did_one = TRUE;
3295 if (retval == OM_MSG_RET_DONE)
3296 break;
3297 }
3298
3299 if (! did_one)
3300 {
3301 ErrPostEx(SEV_ERROR,0,0, "No OPEN function found");
3302 retval = OM_MSG_RET_ERROR;
3303 }
3304 return retval;
3305 }
3306
OMGetNextUserKey(void)3307 NLM_EXTERN Uint2 LIBCALL OMGetNextUserKey (void)
3308
3309 {
3310 ObjMgrPtr omp;
3311 Uint2 retval = 0;
3312
3313 omp = ObjMgrWriteLock ();
3314 if (omp == NULL) return retval;
3315 (omp->HighestUserKey)++;
3316 if (omp->HighestUserKey == 0) {
3317 (omp->HighestUserKey)++;
3318 }
3319 retval = omp->HighestUserKey;
3320 ObjMgrUnlock();
3321 return retval;
3322 }
3323
3324 /*****************************************************************************
3325 *
3326 * Data Type Functions
3327 *
3328 *****************************************************************************/
3329
ObjMgrDefaultLabelFunc(Pointer data,CharPtr buffer,Int2 buflen,Uint1 content)3330 static Int2 LIBCALLBACK ObjMgrDefaultLabelFunc ( Pointer data, CharPtr buffer, Int2 buflen, Uint1 content)
3331 {
3332 ObjMgrPtr omp;
3333 ObjMgrDataPtr omdp;
3334 ObjMgrTypePtr omtp;
3335 CharPtr label=NULL;
3336 static CharPtr defaultlabel="NoLabel";
3337 Int2 retval = 0;
3338
3339 label = defaultlabel;
3340 omp = ObjMgrReadLock();
3341 omdp = ObjMgrFindByData(omp, data);
3342 if (omdp != NULL)
3343 {
3344 omtp = ObjMgrTypeFind(omp, omdp->datatype, NULL, NULL);
3345 if (omtp != NULL)
3346 {
3347 if (omtp->label != NULL)
3348 label = omtp->label;
3349 else if (omtp->name != NULL)
3350 label = omtp->name;
3351 else
3352 label = omtp->asnname;
3353 }
3354 }
3355
3356 retval = LabelCopy(buffer, label, buflen);
3357 ObjMgrUnlock();
3358 return retval;
3359 }
3360
ObjMgrDefaultSubTypeFunc(Pointer ptr)3361 static Uint2 LIBCALLBACK ObjMgrDefaultSubTypeFunc (Pointer ptr)
3362 {
3363 return 0;
3364 }
3365
3366 /*****************************************************************************
3367 *
3368 * ObjMgrTypeExtend(omp)
3369 *
3370 *****************************************************************************/
ObjMgrTypeExtend(ObjMgrPtr omp)3371 static Boolean NEAR ObjMgrTypeExtend (ObjMgrPtr omp)
3372 {
3373 Boolean result = FALSE;
3374 OMTypePtr omdp, prev=NULL;
3375 ObjMgrTypePtr PNTR tmp;
3376 Int4 i, j;
3377
3378 for (omdp = omp->ncbitype; omdp != NULL; omdp = omdp->next)
3379 prev = omdp;
3380
3381 omdp = (OMTypePtr)MemNew(sizeof(OMType));
3382 if (omdp == NULL) return result;
3383 tmp = (ObjMgrTypePtr PNTR)MemNew((size_t)(sizeof(ObjMgrTypePtr) * (omp->tottype + NUM_OMD)));
3384 if (tmp == NULL)
3385 {
3386 MemFree(omdp);
3387 return result;
3388 }
3389
3390 if (prev != NULL)
3391 {
3392 prev->next = omdp;
3393 MemMove(tmp, omp->typelist, (size_t)(sizeof(ObjMgrTypePtr) * omp->tottype));
3394 MemFree(omp->typelist);
3395 }
3396 else
3397 omp->ncbitype = omdp;
3398
3399 j = omp->tottype;
3400
3401 for (i = 0; i < NUM_OMD; i++, j++)
3402 tmp[j] = &(omdp->data[i]);
3403
3404 omp->tottype += NUM_OMD;
3405 omp->typelist = tmp;
3406
3407 result = TRUE;
3408 return result;
3409 }
3410
3411 /*****************************************************************************
3412 *
3413 * ObjMgrTypeAddFunc(omp, type, data)
3414 * adds a pointer (data) of type (type) to the sequence manager
3415 * Currently this MUST be predefined and < OBJ_MAX
3416 *
3417 *****************************************************************************/
ObjMgrTypeAdd(ObjMgrTypePtr data)3418 NLM_EXTERN Uint2 LIBCALL ObjMgrTypeAdd (ObjMgrTypePtr data)
3419 {
3420 ObjMgrPtr omp;
3421 ObjMgrTypePtr omdp;
3422 ObjMgrTypePtr PNTR omdpp;
3423 Int4 i, imin, imax;
3424 Uint2 tmp, type,retval = 0;
3425
3426 if (data == NULL) return retval;
3427
3428 omp = ObjMgrWriteLock();
3429
3430 type = data->datatype;
3431 if ((! type) || (type >= OBJ_MAX))
3432 {
3433 /***
3434 type = ++(omp->HighestObjMgrType);
3435 ***/
3436
3437 ErrPostEx(SEV_ERROR, 0,0, "ObjMgrTypeAdd: Can't register new object types yet");
3438 goto erret;
3439 }
3440
3441 if (omp->currtype >= omp->tottype)
3442 {
3443 if (! ObjMgrTypeExtend(omp))
3444 goto erret;
3445 }
3446
3447 i = omp->currtype;
3448 omdpp = omp->typelist;
3449 omdp = omdpp[i]; /* emptys always at end */
3450
3451 imin = 0; /* find where it goes */
3452 imax = omp->currtype-1;
3453
3454 if ((i) && (type < omdpp[imax]->datatype))
3455 {
3456 i = (imax + imin) / 2;
3457 while (imax > imin)
3458 {
3459 tmp = omdpp[i]->datatype;
3460 if (tmp > type)
3461 imax = i - 1;
3462 else if (tmp < type)
3463 imin = i + 1;
3464 else
3465 break;
3466 i = (imax + imin)/2;
3467 }
3468
3469 if (type > omdpp[i]->datatype) /* check for off by 1 */
3470 i++;
3471
3472 imax = omp->currtype - 1; /* open the array */
3473 while (imax >= i)
3474 {
3475 omdpp[imax+1] = omdpp[imax];
3476 imax--;
3477 }
3478 }
3479
3480 omdpp[i] = omdp; /* put in the pointer in order */
3481 omp->currtype++; /* got one more */
3482
3483 MemMove(omdp, data, sizeof(ObjMgrType));
3484 omdp->datatype = type; /* fill in the values */
3485 omdp->asnname = StringSave(data->asnname);
3486 omdp->label = StringSave(data->label);
3487 omdp->name = StringSave(data->name);
3488 if (omdp->labelfunc == NULL)
3489 omdp->labelfunc = ObjMgrDefaultLabelFunc;
3490 if (omdp->subtypefunc == NULL)
3491 omdp->subtypefunc = ObjMgrDefaultSubTypeFunc;
3492 retval = type;
3493 erret:
3494 ObjMgrUnlock();
3495 return retval;
3496 }
3497
3498 /*****************************************************************************
3499 *
3500 * ObjMgrTypeLoad(args)
3501 *
3502 *****************************************************************************/
ObjMgrTypeLoad(Uint2 type,CharPtr asnname,CharPtr label,CharPtr name,AsnTypePtr atp,OMNewFunc newfunc,AsnReadFunc asnread,AsnWriteFunc asnwrite,OMFreeFunc freefunc,OMLabelFunc labelfunc,OMSubTypeFunc subtypefunc)3503 NLM_EXTERN Uint2 LIBCALL ObjMgrTypeLoad ( Uint2 type, CharPtr asnname,
3504 CharPtr label, CharPtr name, AsnTypePtr atp, OMNewFunc newfunc,
3505 AsnReadFunc asnread, AsnWriteFunc asnwrite, OMFreeFunc freefunc,
3506 OMLabelFunc labelfunc, OMSubTypeFunc subtypefunc)
3507 {
3508 ObjMgrType omt;
3509 Uint2 newtype;
3510
3511 MemSet((Pointer)(&omt), 0, sizeof(ObjMgrType));
3512 omt.datatype = type;
3513 omt.asnname = asnname;
3514 omt.label = label;
3515 omt.name = name;
3516 omt.atp = atp;
3517 omt.newfunc = newfunc;
3518 omt.asnread = asnread;
3519 omt.asnwrite = asnwrite;
3520 omt.freefunc = freefunc;
3521 omt.labelfunc = labelfunc;
3522 omt.subtypefunc = subtypefunc;
3523
3524 newtype = ObjMgrTypeAdd(&omt);
3525
3526 return newtype;
3527 }
3528
3529 /*****************************************************************************
3530 *
3531 * ObjMgrTypeLookup(omp, data)
3532 * Binary lookup of data in omp->typelist
3533 * returns index (>=0) if found
3534 * returns -1 if not found
3535 *
3536 *****************************************************************************/
ObjMgrTypeLookup(ObjMgrPtr omp,Uint2 data)3537 NLM_EXTERN Int4 LIBCALL ObjMgrTypeLookup(ObjMgrPtr omp, Uint2 data)
3538 {
3539 Int4 imin, imax, i;
3540 ObjMgrTypePtr PNTR omdpp;
3541 Uint2 tmp;
3542
3543 imin = 0;
3544 imax = omp->currtype - 1;
3545 omdpp = omp->typelist;
3546
3547 while (imax >= imin)
3548 {
3549 i = (imax + imin)/2;
3550 tmp = omdpp[i]->datatype;
3551 if (tmp > data)
3552 imax = i - 1;
3553 else if (tmp < data)
3554 imin = i + 1;
3555 else
3556 return i;
3557 }
3558
3559 return (Int4)(-1);
3560 }
3561
3562 /*****************************************************************************
3563 *
3564 * ObjMgrTypeFind(omp, type, asnname, name)
3565 * returns the objmgrptr by looking for
3566 * type: if type != 0
3567 * asnname: if asnname != NULL
3568 * name: if name != NULL
3569 * in that order of preference.
3570 * if omp == NULL, then does temporary read lock in this function
3571 * returns NULL if can't match on highest priority key
3572 *
3573 *****************************************************************************/
ObjMgrTypeFind(ObjMgrPtr tomp,Uint2 type,CharPtr asnname,CharPtr name)3574 NLM_EXTERN ObjMgrTypePtr LIBCALL ObjMgrTypeFind (ObjMgrPtr tomp, Uint2 type, CharPtr asnname, CharPtr name)
3575 {
3576 ObjMgrTypePtr omtp = NULL;
3577 ObjMgrTypePtr PNTR omdpp;
3578 Int4 i, imax, result;
3579 ObjMgrPtr omp;
3580 Boolean unlock = FALSE;
3581
3582 if (tomp == NULL)
3583 {
3584 omp = ObjMgrReadLock();
3585 unlock = TRUE;
3586 }
3587 else
3588 omp = tomp;
3589
3590 omdpp = omp->typelist;
3591 imax = omp->currtype;
3592 if (type)
3593 {
3594 i = ObjMgrTypeLookup(omp, type);
3595 if (i >= 0)
3596 omtp = omdpp[i];
3597 }
3598 else
3599 {
3600 for (i = 0; i < imax; i++)
3601 {
3602 if (asnname != NULL)
3603 result = StringCmp(omdpp[i]->asnname, asnname);
3604 else
3605 result = StringCmp(omdpp[i]->name, name);
3606 if (! result)
3607 {
3608 omtp = omdpp[i];
3609 break;
3610 }
3611 }
3612 }
3613
3614 if (unlock)
3615 ObjMgrUnlock();
3616
3617 return omtp;
3618 }
3619
3620 /*****************************************************************************
3621 *
3622 * ObjMgrTypeSetLabelFunc(type, labelfunc)
3623 * replaces the labelfunc for type with a new one
3624 * can also set it for the first time
3625 *
3626 *****************************************************************************/
ObjMgrTypeSetLabelFunc(Uint2 type,OMLabelFunc labelfunc)3627 NLM_EXTERN Boolean LIBCALL ObjMgrTypeSetLabelFunc(Uint2 type, OMLabelFunc labelfunc)
3628 {
3629 ObjMgrPtr omp;
3630 ObjMgrTypePtr omtp;
3631 Boolean retval = FALSE;
3632
3633 omp = ObjMgrWriteLock();
3634 omtp = ObjMgrTypeFind(omp, type, NULL, NULL);
3635 if (omtp != NULL)
3636 {
3637 omtp->labelfunc = labelfunc;
3638 retval = TRUE;
3639 }
3640 ObjMgrUnlock();
3641 return retval;
3642 }
3643
3644 /**************************************************************************
3645 *
3646 * ObjMgrTypeFindNext(omp, omtp)
3647 * returns next ObjMgrType after omtp
3648 * Exhaustively traverses registered types if omtp starts as NULL
3649 *
3650 ***************************************************************************/
ObjMgrTypeFindNext(ObjMgrPtr omp,ObjMgrTypePtr last)3651 NLM_EXTERN ObjMgrTypePtr LIBCALL ObjMgrTypeFindNext (ObjMgrPtr omp, ObjMgrTypePtr last)
3652 {
3653 ObjMgrTypePtr PNTR omdpp;
3654 Int4 i, imax;
3655 Boolean got_it = FALSE;
3656
3657 omdpp = omp->typelist;
3658 imax = omp->currtype;
3659 if (last == NULL) /* take the first one */
3660 got_it = TRUE;
3661 for (i = 0; i < imax; i++)
3662 {
3663 if (got_it)
3664 return omdpp[i];
3665
3666 if (omdpp[i] == last)
3667 got_it = TRUE;
3668 }
3669
3670 return NULL;
3671 }
3672
3673 /*****************************************************************************
3674 *
3675 * Selection Functions for data objects
3676 *
3677 *****************************************************************************/
ObjMgrSendSelMsg(ObjMgrPtr omp,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)3678 static Boolean NEAR ObjMgrSendSelMsg (ObjMgrPtr omp, Uint2 entityID,
3679 Uint4 itemID, Uint2 itemtype, Uint1 regiontype, Pointer region)
3680 {
3681 ObjMgrDataPtr omdp;
3682 OMMsgStruct ommds;
3683
3684 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
3685 if (omdp == NULL)
3686 return FALSE;
3687
3688 MemSet((Pointer)(&ommds), 0, sizeof(OMMsgStruct));
3689 ommds.message = OM_MSG_SELECT;
3690 ommds.entityID = entityID;
3691 ommds.itemtype = itemtype;
3692 ommds.itemID = itemID;
3693 ommds.regiontype = regiontype;
3694 ommds.region = region;
3695
3696 ObjMgrSendStructMsgFunc(omp, omdp, &ommds);
3697 return TRUE;
3698 }
3699
ObjMgrSendDeSelMsg(ObjMgrPtr omp,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)3700 static Boolean NEAR ObjMgrSendDeSelMsg (ObjMgrPtr omp, Uint2 entityID,
3701 Uint4 itemID, Uint2 itemtype, Uint1 regiontype, Pointer region)
3702 {
3703 ObjMgrDataPtr omdp;
3704 OMMsgStruct ommds;
3705
3706 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
3707 if (omdp == NULL)
3708 return FALSE;
3709
3710 MemSet((Pointer)(&ommds), 0, sizeof(OMMsgStruct));
3711 ommds.message = OM_MSG_DESELECT;
3712 ommds.entityID = entityID;
3713 ommds.itemtype = itemtype;
3714 ommds.itemID = itemID;
3715 ommds.regiontype = regiontype;
3716 ommds.region = region;
3717
3718 ObjMgrSendStructMsgFunc(omp, omdp, &ommds);
3719 return TRUE;
3720 }
3721
ObjMgrAddSelStruct(ObjMgrPtr omp,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)3722 static SelStructPtr NEAR ObjMgrAddSelStruct (ObjMgrPtr omp, Uint2 entityID,
3723 Uint4 itemID, Uint2 itemtype, Uint1 regiontype, Pointer region)
3724 {
3725 SelStructPtr ssp, tmp;
3726
3727 tmp = omp->sel;
3728
3729 if (tmp != NULL)
3730 {
3731 while (tmp->next != NULL)
3732 tmp = tmp->next;
3733 }
3734
3735 ssp = MemNew(sizeof(SelStruct));
3736 if (tmp != NULL)
3737 {
3738 tmp->next = ssp;
3739 ssp->prev = tmp;
3740 }
3741 else
3742 omp->sel = ssp;
3743
3744 ssp->entityID = entityID;
3745 ssp->itemID = itemID;
3746 ssp->itemtype = itemtype;
3747 ssp->regiontype = regiontype;
3748 ssp->region = region;
3749
3750 return ssp;
3751 }
3752
3753
ObjMgrDeSelectStructFunc(ObjMgrPtr omp,SelStructPtr ssp)3754 static Boolean NEAR ObjMgrDeSelectStructFunc (ObjMgrPtr omp, SelStructPtr ssp)
3755 {
3756 SelStructPtr next, prev;
3757
3758 if (ssp == NULL)
3759 return FALSE;
3760
3761 next = ssp->next;
3762 prev = ssp->prev;
3763 if (prev != NULL)
3764 prev->next = next;
3765 else
3766 omp->sel = next;
3767 if (next != NULL)
3768 next->prev = prev;
3769
3770 ObjMgrSendDeSelMsg (omp, ssp->entityID, ssp->itemID, ssp->itemtype, ssp->regiontype, ssp->region);
3771
3772 ObjMgrRegionFree(omp, ssp->regiontype, ssp->region); /* free any region */
3773
3774 MemFree(ssp);
3775
3776 return TRUE;
3777 }
3778
ObjMgrDeSelectAllFunc(ObjMgrPtr omp)3779 static Boolean NEAR ObjMgrDeSelectAllFunc (ObjMgrPtr omp)
3780 {
3781 SelStructPtr tmp, prev;
3782
3783 tmp = omp->sel;
3784 if (tmp == NULL)
3785 return TRUE;
3786
3787 prev = NULL;
3788
3789 while (tmp->next != NULL)
3790 {
3791 prev = tmp;
3792 tmp = tmp->next;
3793 }
3794
3795 while (tmp != NULL)
3796 {
3797 ObjMgrDeSelectStructFunc(omp, tmp);
3798 tmp = prev;
3799 if (tmp != NULL)
3800 prev = tmp->prev;
3801 }
3802
3803 return TRUE;
3804 }
3805
ObjMgrRegionMatch(Uint1 regiontype1,Pointer region1,Uint1 regiontype2,Pointer region2)3806 static Boolean NEAR ObjMgrRegionMatch (Uint1 regiontype1, Pointer region1,
3807 Uint1 regiontype2, Pointer region2)
3808 {
3809 SeqLocPtr slp;
3810 SeqIntPtr sip1, sip2;
3811
3812 if (regiontype1 != regiontype2) return FALSE;
3813 if (! regiontype1) return FALSE;
3814 if ((region1 == NULL) || (region2 == NULL)) return FALSE;
3815
3816 switch (regiontype1)
3817 {
3818 case OM_REGION_SEQLOC: /* SeqLocs of type SeqInt */
3819 slp = (SeqLocPtr)region1;
3820 sip1 = (SeqIntPtr)(slp->data.ptrvalue);
3821 slp = (SeqLocPtr)(region2);
3822 sip2 = (SeqIntPtr)(slp->data.ptrvalue);
3823 if (sip1 == NULL || sip2 == NULL) return FALSE;
3824 if ( ((sip1->from == sip2->from) &&
3825 (sip1->to == sip2->to)))
3826 /* get rid of (sip1->strand == sip2->strand) */
3827 return TRUE;
3828 break;
3829 default:
3830 break;
3831 }
3832 return FALSE;
3833 }
3834
3835 /*
3836 static Pointer NEAR ObjMgrRegionCopy (ObjMgrPtr omp, Uint1 regiontype, Pointer region)
3837 {
3838 Pointer newregion = NULL;
3839
3840 if (region != NULL)
3841 {
3842 switch (regiontype)
3843 {
3844 case OM_REGION_SEQLOC:
3845 newregion = ObjMgrMemCopyFunc(omp, OBJ_SEQLOC, region, FALSE);
3846 break;
3847 default:
3848 break;
3849 }
3850 }
3851 return newregion;
3852 }
3853 */
3854
ObjMgrRegionFree(ObjMgrPtr omp,Uint1 regiontype,Pointer region)3855 static Pointer NEAR ObjMgrRegionFree (ObjMgrPtr omp, Uint1 regiontype, Pointer region)
3856 {
3857 if (region != NULL)
3858 {
3859 switch (regiontype)
3860 {
3861 case OM_REGION_SEQLOC:
3862 ObjMgrFreeFunc(omp, OBJ_SEQLOC, region, FALSE);
3863 break;
3864 default:
3865 break;
3866 }
3867 }
3868
3869 return NULL;
3870 }
3871
3872 /*****************************************************************************
3873 *
3874 * ObjMgrSelect(entityID, itemID, itemtype)
3875 * if entityID == 0, just deselects everything
3876 * if entityID,itemID, itemtype already selected, deselects everything else
3877 * if something else selected, deselects it first, then selects requested
3878 * item
3879 * returns TRUE if item is now currently selected, FALSE if not
3880 *
3881 *****************************************************************************/
ObjMgrSelect(Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)3882 NLM_EXTERN Boolean LIBCALL ObjMgrSelect (Uint2 entityID, Uint4 itemID, Uint2 itemtype,
3883 Uint1 regiontype, Pointer region)
3884 {
3885 ObjMgrPtr omp;
3886 Boolean retval = FALSE;
3887
3888 omp = ObjMgrWriteLock();
3889 retval = ObjMgrSelectFunc(omp, entityID, itemID, itemtype,
3890 regiontype, region);
3891 ObjMgrUnlock();
3892 return retval;
3893 }
3894
3895
3896 /*****************************************************************************
3897 *
3898 * ObjMgrSelect(entityID, itemID, itemtype)
3899 * if entityID == 0, just deselects everything
3900 * if entityID,itemID, itemtype already selected, deselects everything else
3901 * if something else selected, deselects it first, then selects requested
3902 * item
3903 * returns TRUE if item is now currently selected, FALSE if not
3904 *
3905 *****************************************************************************/
ObjMgrSelectFunc(ObjMgrPtr omp,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)3906 static Boolean NEAR ObjMgrSelectFunc (ObjMgrPtr omp, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
3907 Uint1 regiontype, Pointer region)
3908 {
3909 SelStructPtr ssp, next;
3910 Boolean was_selected = FALSE, is_selected, remove_this, retval = TRUE;
3911
3912
3913 if (entityID == 0) /* desktop */
3914 {
3915 ObjMgrDeSelectAllFunc(omp);
3916 goto erret;
3917 }
3918 else
3919 {
3920 ssp = omp->sel;
3921 while (ssp != NULL)
3922 {
3923 remove_this = TRUE;
3924 next = ssp->next;
3925 if (ssp->entityID == entityID)
3926 {
3927 if ((ssp->itemID == itemID) || (! itemID))
3928 {
3929 if ((ssp->itemtype == itemtype) || (! itemtype))
3930 {
3931 if ((ssp->regiontype == regiontype) || (! regiontype))
3932 {
3933 is_selected = TRUE;
3934 if (regiontype)
3935 is_selected = ObjMgrRegionMatch(ssp->regiontype,
3936 ssp->region, regiontype, region);
3937 if (is_selected)
3938 {
3939 remove_this = FALSE;
3940 was_selected = TRUE;
3941 }
3942 }
3943 }
3944 }
3945 }
3946 if (remove_this)
3947 ObjMgrDeSelectStructFunc(omp, ssp);
3948
3949 ssp = next;
3950 }
3951 }
3952
3953 if (was_selected) /* no more action needed */
3954 {
3955 retval = TRUE;
3956 }
3957 else
3958 {
3959 ssp = ObjMgrAddSelStruct(omp, entityID, itemID, itemtype, regiontype, region);
3960
3961 if (ssp != NULL)
3962 retval = ObjMgrSendSelMsg(omp, entityID, itemID, itemtype, regiontype, region);;
3963 }
3964
3965 erret:
3966 return retval;
3967
3968 }
3969
SeqLocChangeIntervalle(SeqLocPtr slp,Int4 start,Int4 stop)3970 static SeqLocPtr SeqLocChangeIntervalle (SeqLocPtr slp, Int4 start, Int4 stop)
3971 {
3972 SeqIntPtr sip;
3973
3974 sip = (SeqIntPtr)(slp->data.ptrvalue);
3975 if (start > -1)
3976 sip->from = start;
3977 if (stop > -1)
3978 sip->to = stop;
3979 return slp;
3980 }
3981
ObjMgrRegionComp(Pointer region1,Pointer region2,Boolean direction2_plus)3982 static Int2 NEAR ObjMgrRegionComp (Pointer region1,Pointer region2, Boolean direction2_plus)
3983 {
3984 SeqLocPtr slp1, slp2;
3985 Int2 res;
3986
3987 if ((region1 == NULL) || (region2 == NULL))
3988 return FALSE;
3989
3990 slp1 = (SeqLocPtr)region1;
3991 slp2 = (SeqLocPtr)region2;
3992 res = SeqLocCompare (slp1,slp2);
3993 if (res == SLC_NO_MATCH)
3994 {
3995 if (SeqLocStop(slp1) == SeqLocStart(slp2)-1)
3996 return 2;
3997 if (SeqLocStart(slp1) == SeqLocStop(slp2)+1)
3998 return 3;
3999 return 0;
4000 }
4001 if (res == SLC_A_EQ_B)
4002 return 1;
4003 if (res == SLC_B_IN_A)
4004 {
4005 if (SeqLocStart(slp1)==SeqLocStart(slp2))
4006 return 5;
4007 if (SeqLocStop(slp1)==SeqLocStop(slp2))
4008 return 6;
4009 if (direction2_plus)
4010 return 5;
4011 else
4012 return 6;
4013 }
4014 if (res == SLC_A_IN_B)
4015 return 4;
4016 if (res == SLC_A_OVERLAP_B)
4017 {
4018 if (SeqLocStart(slp1) < SeqLocStart(slp2))
4019 return 2;
4020 if (SeqLocStart(slp1) > SeqLocStart(slp2))
4021 return 3;
4022 }
4023 return 0;
4024 }
4025
4026
ObjMgrSelectFunc2(ObjMgrPtr omp,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)4027 static Boolean NEAR ObjMgrSelectFunc2
4028 (ObjMgrPtr omp, Uint2 entityID, Uint4 itemID, Uint2 itemtype, Uint1 regiontype, Pointer region)
4029 {
4030 SelStructPtr ssp, next;
4031 Boolean retval = FALSE;
4032 SeqLocPtr tmp = NULL,
4033 tmp2 = NULL;
4034 Int2 res=0;
4035 Boolean direction_plus = TRUE;
4036
4037 if (entityID == 0) /* desktop */
4038 {
4039 ObjMgrDeSelectAllFunc(omp);
4040 goto erret;
4041 }
4042 else if (region)
4043 {
4044 /***** Colombe Patrick ****/
4045 /** send Seq_strand_minus seqloc of selection when the cursor moves to the left **/
4046 /** the Seq_strand_minus is now change to Seq_strand_plus for ever **/
4047
4048 if (SeqLocStrand(region)==Seq_strand_minus)
4049 {
4050 SeqIntPtr sit;
4051 SeqLocPtr slp;
4052 slp = (SeqLocPtr)region;
4053 sit = (SeqIntPtr)(slp->data.ptrvalue);
4054 sit->strand = Seq_strand_plus;
4055 direction_plus=FALSE;
4056 }
4057 /***** Colombe Patrick ****/
4058 ssp = omp->sel;
4059 while (ssp != NULL && res == 0)
4060 {
4061 next = ssp->next;
4062 if (ssp->entityID == entityID)
4063 {
4064 if ((ssp->itemID == itemID) || (! itemID))
4065 {
4066 if ((ssp->itemtype == itemtype) || (! itemtype))
4067 {
4068 if (ssp->regiontype && regiontype)
4069 {
4070 res = ObjMgrRegionComp (ssp->region, region, direction_plus);
4071 if (res>0)
4072 break;
4073 }
4074 }
4075 }
4076 }
4077 ssp = next;
4078 }
4079 }
4080 if (res==2) /* extend ssp->region to right */
4081 {
4082 SeqLocChangeIntervalle ((SeqLocPtr)ssp->region, -1, SeqLocStop(region));
4083 retval=ObjMgrSendSelMsg (omp, entityID, itemID, itemtype, ssp->regiontype, ssp->region);
4084 }
4085 else if (res==3) /* extend ssp->region to left */
4086 {
4087 SeqLocChangeIntervalle ((SeqLocPtr)ssp->region, SeqLocStart(region), -1);
4088 retval=ObjMgrSendSelMsg (omp, entityID, itemID, itemtype, ssp->regiontype, ssp->region);
4089 }
4090 else if (res==4) /* extend ssp->regiontype both sides */
4091 {
4092 SeqLocChangeIntervalle ((SeqLocPtr)ssp->region, SeqLocStart(region), SeqLocStop(region));
4093 retval=ObjMgrSendSelMsg (omp, entityID, itemID, itemtype, ssp->regiontype, ssp->region);
4094 }
4095 else if (res==5) /* shrink ssp->region from right */
4096 {
4097 tmp = SeqLocIntNew (SeqLocStart((SeqLocPtr)ssp->region), SeqLocStop((SeqLocPtr)region), 0, SeqLocId(region));
4098 tmp2 = SeqLocIntNew (SeqLocStop((SeqLocPtr)region)+1, SeqLocStop((SeqLocPtr)ssp->region), 0, SeqLocId(region));
4099 SeqLocChangeIntervalle ((SeqLocPtr)ssp->region, -1, (Int4)(SeqLocStop(region)));
4100 ValNodeFree (tmp);
4101 retval=ObjMgrSendDeSelMsg (omp, entityID, itemID, itemtype, OM_REGION_SEQLOC, tmp2);
4102
4103 ValNodeFree (tmp2);
4104 }
4105 else if (res==6) /* shrink ssp->region from left */
4106 {
4107 tmp = SeqLocIntNew (SeqLocStart((SeqLocPtr)region), SeqLocStop((SeqLocPtr)ssp->region), 0, SeqLocId(region));
4108 tmp2 = SeqLocIntNew (SeqLocStart((SeqLocPtr)ssp->region), SeqLocStart((SeqLocPtr)region)-1, 0, SeqLocId(region));
4109 SeqLocChangeIntervalle ((SeqLocPtr)ssp->region, (Int4)(SeqLocStart(region)), -1);
4110 ValNodeFree (tmp);
4111 retval=ObjMgrSendDeSelMsg (omp, entityID, itemID, itemtype, OM_REGION_SEQLOC, tmp2);
4112 ValNodeFree (tmp2);
4113 }
4114 else if (res==0)
4115 {
4116 ssp = ObjMgrAddSelStruct(omp, entityID, itemID, itemtype, regiontype, region);
4117 if (ssp != NULL)
4118 retval=ObjMgrSendSelMsg (omp, entityID, itemID, itemtype, regiontype, region);
4119 }
4120
4121 erret:
4122 return (Boolean)(res>0);
4123
4124 }
4125
CheckRedondantSelect(ObjMgrPtr omp)4126 static Boolean NEAR CheckRedondantSelect (ObjMgrPtr omp)
4127 {
4128 SelStructPtr ssp1 = NULL,
4129 ssp2 = NULL,
4130 next1,
4131 next2 = NULL, pre2 = NULL;
4132 SeqLocPtr tmp;
4133 Boolean retval = FALSE;
4134 Int2 res=0;
4135
4136 if (omp!=NULL)
4137 {
4138 ssp1 = omp->sel;
4139 while (ssp1 != NULL && res==0)
4140 {
4141 next1 = ssp1->next;
4142 ssp2=next1;
4143 pre2=ssp1;
4144 while (ssp2!=NULL && res==0)
4145 {
4146 next2 = ssp2->next;
4147 if (ssp1->entityID == ssp2->entityID)
4148 {
4149 if (ssp1->itemID == ssp2->itemID)
4150 {
4151 if (ssp1->itemtype == ssp2->itemtype)
4152 {
4153 if (ssp1->regiontype && ssp2->regiontype)
4154 {
4155 res = ObjMgrRegionComp (ssp1->region, ssp2->region, TRUE);
4156 if (res>0)
4157 break;
4158 }
4159 }
4160 }
4161 }
4162 ssp2 = next2;
4163 }
4164 if (res==0)
4165 ssp1 = next1;
4166 }
4167 }
4168 if (res==1)
4169 {
4170 pre2->next=next2;
4171 ssp2=MemFree(ssp2);
4172 ObjMgrSendSelMsg (omp, ssp1->entityID, ssp1->itemID, ssp1->itemtype, 0, 0);
4173 retval=TRUE;
4174 }
4175 else if (res==2) /* extend ssp->regiontype to right */
4176 {
4177 SeqLocChangeIntervalle ((SeqLocPtr)ssp1->region, -1, SeqLocStop(ssp2->region));
4178 pre2->next=next2;
4179 ssp2=MemFree(ssp2);
4180 ObjMgrSendSelMsg (omp, ssp1->entityID, ssp1->itemID, ssp1->itemtype, 0, 0);
4181 retval=TRUE;
4182 }
4183 else if (res==3) /* extend ssp->regiontype to left */
4184 {
4185 SeqLocChangeIntervalle ((SeqLocPtr)ssp1->region, SeqLocStart(ssp2->region), -1);
4186 pre2->next=next2;
4187 ssp2=MemFree(ssp2);
4188 ObjMgrSendSelMsg (omp, ssp1->entityID, ssp1->itemID, ssp1->itemtype, 0, 0);
4189 retval=TRUE;
4190 }
4191 else if (res==4) /* extend ssp->regiontype both sides */
4192 {
4193 SeqLocChangeIntervalle ((SeqLocPtr)ssp1->region, SeqLocStart(ssp2->region), SeqLocStop(ssp2->region));
4194 pre2->next=next2;
4195 ssp2=MemFree(ssp2);
4196 ObjMgrSendSelMsg (omp, ssp1->entityID, ssp1->itemID, ssp1->itemtype, 0, 0);
4197 retval=TRUE;
4198 }
4199 else if (res==5) /* shrink ssp->region from right */
4200 {
4201 tmp = SeqLocIntNew (SeqLocStart((SeqLocPtr)ssp1->region), SeqLocStop(ssp2->region), 0, SeqLocId(ssp2->region));
4202 SeqLocChangeIntervalle ((SeqLocPtr)ssp1->region, -1, SeqLocStop(ssp2->region));
4203 pre2->next=next2;
4204 ssp2=MemFree(ssp2);
4205 ObjMgrSendDeSelMsg (omp, ssp1->entityID, ssp1->itemID, ssp1->itemtype, 0, 0);
4206 ValNodeFree (tmp);
4207 retval=TRUE;
4208 }
4209 else if (res==6) /* shrink ssp->region from left */
4210 {
4211 tmp = SeqLocIntNew (SeqLocStart(ssp2->region), SeqLocStop((SeqLocPtr)ssp1->region), 0, SeqLocId(ssp2->region));
4212 SeqLocChangeIntervalle ((SeqLocPtr)ssp1->region, SeqLocStart(ssp2->region), -1);
4213 pre2->next=next2;
4214 ssp2=MemFree(ssp2);
4215 ObjMgrSendDeSelMsg (omp, ssp1->entityID, ssp1->itemID, ssp1->itemtype, 0, 0);
4216 ValNodeFree (tmp);
4217 retval=TRUE;
4218 }
4219 return retval;
4220 }
4221
4222
4223
4224 /*****************************************************************************
4225 *
4226 * ObjMgrSetColor(entityID, itemID, itemtype, regiontype, region, rgb);
4227 * Sets color of object in displays
4228 * if regiontype != 0, and restricts to region
4229 * rgb is a pointer to a Uint1[3] array containing an RGB value.
4230 *
4231 *****************************************************************************/
ObjMgrSetColor(Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region,Uint1Ptr rgb)4232 NLM_EXTERN Boolean LIBCALL ObjMgrSetColor (Uint2 entityID, Uint4 itemID,
4233 Uint2 itemtype, Uint1 regiontype,
4234 Pointer region, Uint1Ptr rgb)
4235 {
4236 ObjMgrPtr omp;
4237 ObjMgrDataPtr omdp;
4238 OMMsgStruct ommds;
4239 Boolean retval = FALSE;
4240
4241 omp = ObjMgrReadLock();
4242
4243 if (rgb == NULL) goto erret;
4244
4245 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
4246 if (omdp == NULL) goto erret;
4247
4248 MemSet((Pointer)(&ommds), 0, sizeof(OMMsgStruct));
4249 ommds.message = OM_MSG_SETCOLOR;
4250 ommds.entityID = entityID;
4251 ommds.itemtype = itemtype;
4252 ommds.itemID = itemID;
4253 ommds.regiontype = regiontype;
4254 ommds.region = region;
4255 ommds.rgb[0] = rgb[0];
4256 ommds.rgb[1] = rgb[1];
4257 ommds.rgb[2] = rgb[2];
4258
4259 /* send the message */
4260 ObjMgrSendStructMsgFunc(omp, omdp, &ommds);
4261 /* free the region */
4262 retval = TRUE;
4263 erret:
4264 ObjMgrUnlock();
4265
4266 return retval;
4267 }
4268 /*****************************************************************************
4269 *
4270 * ObjMgrDeSelect(entityID, itemID, itemtype)
4271 * if this item was selected, then deselects and returns TRUE
4272 * else returns FALSE
4273 *
4274 *****************************************************************************/
4275
ObjMgrDeSelect(Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)4276 NLM_EXTERN Boolean LIBCALL ObjMgrDeSelect (Uint2 entityID, Uint4 itemID, Uint2 itemtype,
4277 Uint1 regiontype, Pointer region)
4278 {
4279 ObjMgrPtr omp;
4280 Boolean retval=FALSE;
4281
4282 omp = ObjMgrWriteLock();
4283 retval = ObjMgrDeSelectFunc (omp, entityID, itemID, itemtype,
4284 regiontype, region);
4285 ObjMgrUnlock();
4286 return retval;
4287 }
4288
4289
4290 /*****************************************************************************
4291 *
4292 * ObjMgrDeSelect(entityID, itemID, itemtype)
4293 * if this item was selected, then deselects and returns TRUE
4294 * else returns FALSE
4295 *
4296 *****************************************************************************/
4297
ObjMgrDeSelectFunc(ObjMgrPtr omp,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)4298 static Boolean NEAR ObjMgrDeSelectFunc (ObjMgrPtr omp, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
4299 Uint1 regiontype, Pointer region)
4300 {
4301 SelStructPtr tmp, next;
4302 Boolean retval=FALSE, tret, do_it;
4303 SeqLocPtr slp;
4304
4305 if (entityID == 0)
4306 {
4307 retval = ObjMgrDeSelectAllFunc(omp);
4308 goto erret;
4309 }
4310
4311 tmp = omp->sel;
4312 while (tmp != NULL)
4313 {
4314 next = tmp->next;
4315 do_it = FALSE;
4316 if (tmp->entityID == entityID)
4317 {
4318 if ((! itemtype) || (itemtype == tmp->itemtype))
4319 {
4320 if ((! itemID) || (itemID == tmp->itemID))
4321 {
4322 if ((tmp->regiontype == regiontype) || (! regiontype))
4323 {
4324 do_it = TRUE;
4325 if (regiontype)
4326 do_it = ObjMgrRegionMatch(tmp->regiontype,
4327 tmp->region, regiontype, region);
4328 if (do_it)
4329 {
4330 tret = ObjMgrDeSelectStructFunc(omp, tmp);
4331 if (tret)
4332 retval = TRUE;
4333 }
4334 else if (SeqLocCompare(tmp->region, region)==SLC_B_IN_A)
4335 {
4336 if (SeqLocStart(tmp->region)==SeqLocStart(region))
4337 {
4338 SeqLocChangeIntervalle ((SeqLocPtr)tmp->region, (Int4)(SeqLocStop(region)+1), -1);
4339 retval=ObjMgrSendDeSelMsg (omp, entityID, itemID, itemtype, OM_REGION_SEQLOC, region);
4340 }
4341 else if (SeqLocStop(tmp->region)==SeqLocStop(region))
4342 {
4343 SeqLocChangeIntervalle ((SeqLocPtr)tmp->region, -1, (Int4)(SeqLocStart(region)-1));
4344 retval=ObjMgrSendDeSelMsg (omp, entityID, itemID, itemtype, OM_REGION_SEQLOC, region);
4345 }
4346 else {
4347 slp=SeqLocIntNew(SeqLocStop(region)+1, SeqLocStop((SeqLocPtr)tmp->region), 0, SeqLocId(tmp->region));
4348 SeqLocChangeIntervalle ((SeqLocPtr)tmp->region, -1, (Int4)(SeqLocStart(region)-1));
4349 ObjMgrAddSelStruct(omp, entityID, itemID, itemtype, regiontype, slp);
4350 retval=ObjMgrSendDeSelMsg (omp, entityID, itemID, itemtype, OM_REGION_SEQLOC, region);
4351
4352 }
4353 }
4354 }
4355 }
4356 }
4357 }
4358 tmp = next;
4359 }
4360
4361 erret:
4362 return retval;
4363 }
4364
ObjMgrAlsoSelect(Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint1 regiontype,Pointer region)4365 NLM_EXTERN Boolean LIBCALL ObjMgrAlsoSelect (Uint2 entityID, Uint4 itemID,
4366 Uint2 itemtype, Uint1 regiontype, Pointer region)
4367 {
4368 ObjMgrPtr omp;
4369 Boolean retval;
4370 /* if already selected, just deselect */
4371 /**
4372 if (ObjMgrDeSelect(entityID, itemID, itemtype, regiontype, region))
4373 return FALSE;
4374 **/
4375 omp = ObjMgrWriteLock();
4376
4377 retval = ObjMgrSelectFunc2 (omp, entityID, itemID, itemtype, regiontype, region);
4378 if (retval) {
4379 while (retval)
4380 retval=CheckRedondantSelect (omp);
4381 }
4382 ObjMgrUnlock();
4383
4384 return retval;
4385
4386 }
4387
ObjMgrDeSelectAll(void)4388 NLM_EXTERN Boolean LIBCALL ObjMgrDeSelectAll (void)
4389 {
4390 ObjMgrPtr omp;
4391 Boolean retval = FALSE;
4392
4393 omp = ObjMgrWriteLock();
4394 retval = ObjMgrDeSelectAllFunc(omp);
4395 ObjMgrUnlock();
4396 return retval;
4397 }
4398
ObjMgrGetSelected(void)4399 NLM_EXTERN SelStructPtr LIBCALL ObjMgrGetSelected (void)
4400 {
4401 ObjMgrPtr omp;
4402 SelStructPtr sel;
4403
4404 omp = ObjMgrReadLock();
4405 sel = omp->sel;
4406 ObjMgrUnlock();
4407 return sel;
4408 }
4409
4410 /*****************************************************************************
4411 *
4412 * ObjMgrSendMsg(msg, entityID, itemID, itemtype)
4413 * Directly invokes the objmgr messaging system
4414 * should be used cautiously
4415 *
4416 *****************************************************************************/
ObjMgrSendMsg(Uint2 msg,Uint2 entityID,Uint4 itemID,Uint2 itemtype)4417 NLM_EXTERN Boolean LIBCALL ObjMgrSendMsg(Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype)
4418 {
4419 ObjMgrPtr omp;
4420 ObjMgrDataPtr omdp;
4421 Boolean retval = FALSE;
4422
4423 if (msg == OM_MSG_UPDATE) {
4424 SeqMgrClearFeatureIndexes (entityID, NULL);
4425 } else if (msg == OM_MSG_DEL) {
4426 SeqMgrClearFeatureIndexes (entityID, NULL);
4427 ObjMgrDeSelect (entityID, itemID, itemtype, 0, NULL);
4428 }
4429 omp = ObjMgrReadLock();
4430 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
4431 if (omdp != NULL)
4432 {
4433 ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, 0, 0, 0, NULL);
4434 retval = TRUE;
4435 }
4436 ObjMgrUnlock();
4437 return retval;
4438 }
4439
4440
ObjMgrSendMsgOnlyFeatLabelChange(Uint2 msg,Uint2 entityID,Uint4 itemID,Uint2 itemtype)4441 NLM_EXTERN Boolean LIBCALL ObjMgrSendMsgOnlyFeatLabelChange (Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype)
4442 {
4443 ObjMgrPtr omp;
4444 ObjMgrDataPtr omdp;
4445 Boolean retval = FALSE;
4446
4447 if (msg == OM_MSG_UPDATE) {
4448 SeqMgrRedoFeatByLabelIndexes (entityID, NULL);
4449 } else if (msg == OM_MSG_DEL) {
4450 SeqMgrRedoFeatByLabelIndexes (entityID, NULL);
4451 ObjMgrDeSelect (entityID, itemID, itemtype, 0, NULL);
4452 }
4453 omp = ObjMgrReadLock();
4454 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
4455 if (omdp != NULL)
4456 {
4457 ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, 0, 0, 0, NULL);
4458 retval = TRUE;
4459 }
4460 ObjMgrUnlock();
4461 return retval;
4462 }
4463
4464
4465
ObjMgrSendMsgNoFeatureChange(Uint2 msg,Uint2 entityID,Uint4 itemID,Uint2 itemtype)4466 NLM_EXTERN Boolean LIBCALL ObjMgrSendMsgNoFeatureChange(Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype)
4467 {
4468 ObjMgrPtr omp;
4469 ObjMgrDataPtr omdp;
4470 Boolean retval = FALSE;
4471
4472 if (msg == OM_MSG_UPDATE) {
4473 SeqMgrRedoDescriptorIndexes (entityID, NULL);
4474 } else if (msg == OM_MSG_DEL) {
4475 SeqMgrRedoDescriptorIndexes (entityID, NULL);
4476 ObjMgrDeSelect (entityID, itemID, itemtype, 0, NULL);
4477 }
4478
4479 omp = ObjMgrReadLock();
4480 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
4481 if (omdp != NULL)
4482 {
4483 ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, 0, 0, 0, NULL);
4484 retval = TRUE;
4485 }
4486 ObjMgrUnlock();
4487 return retval;
4488 }
4489
4490
ObjMgrSendProcMsg(Uint2 msg,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint2 fromProcID,Uint2 toProcID,Pointer procmsgdata)4491 NLM_EXTERN Boolean LIBCALL ObjMgrSendProcMsg(Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
4492 Uint2 fromProcID, Uint2 toProcID, Pointer procmsgdata)
4493 {
4494 ObjMgrPtr omp;
4495 ObjMgrDataPtr omdp;
4496 Boolean retval = FALSE;
4497
4498 omp = ObjMgrReadLock();
4499 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
4500 if (omdp != NULL)
4501 {
4502 ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, 0, fromProcID, toProcID, procmsgdata);
4503 retval = TRUE;
4504 }
4505 ObjMgrUnlock();
4506 return retval;
4507 }
4508
ObjMgrSendRowMsg(Uint2 msg,Uint2 entityID,Uint4 itemID,Uint2 itemtype,Uint2 rowID)4509 NLM_EXTERN Boolean LIBCALL ObjMgrSendRowMsg(Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype, Uint2 rowID)
4510 {
4511 ObjMgrPtr omp;
4512 ObjMgrDataPtr omdp;
4513 Boolean retval = FALSE;
4514
4515 omp = ObjMgrReadLock();
4516 omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
4517 if (omdp != NULL)
4518 {
4519 ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, rowID, 0, 0, NULL);
4520 retval = TRUE;
4521 }
4522 ObjMgrUnlock();
4523 return retval;
4524 }
4525
4526 /*****************************************************************************
4527 *
4528 * ObjMgrGenericAsnTextFileRead(filename, datatypeptr, entityIDptr)
4529 * reads an asn1 text file for any datatype registered with the ObjMgr.
4530 * filename may contain a path
4531 * scans the start of the file to figure out the type.
4532 *
4533 * if it fails, it returns NULL
4534 * if it succeeds, it returns a Pointer to the loaded data object
4535 * if datatypeptr is not NULL, fills it in with the proper OBJ_...
4536 * if entityIDptr is not NULL,
4537 * it registers the data with the object manager
4538 * it fills in entityIDptr with the entityID of the loaded object
4539 *
4540 *****************************************************************************/
ObjMgrGenericAsnTextFileRead(CharPtr filename,Uint2Ptr datatypeptr,Uint2Ptr entityIDptr)4541 NLM_EXTERN Pointer LIBCALL ObjMgrGenericAsnTextFileRead (CharPtr filename,
4542 Uint2Ptr datatypeptr, Uint2Ptr entityIDptr)
4543 {
4544 Char line[255];
4545 FILE * fp;
4546 AsnIoPtr aip;
4547 Pointer ptr = NULL;
4548 Int2 ct, i;
4549 ObjMgrPtr omp;
4550 ObjMgrTypePtr omtp = NULL;
4551
4552 if (filename == NULL)
4553 return ptr;
4554
4555 if (datatypeptr != NULL) *datatypeptr = 0;
4556 if (entityIDptr != NULL) *entityIDptr = 0;
4557
4558 fp = FileOpen(filename, "r");
4559 ct = FileRead(line, 1, 255, fp);
4560 for (i = 0; i < ct; i++)
4561 {
4562 if (line[i] == ':')
4563 {
4564 if ((line[i+1] == ':') && (line[i+2] == '='))
4565 {
4566 line[i] = '\0';
4567 i--;
4568 while ((i >= 0) && (IS_WHITESP(line[i])))
4569 {
4570 line[i] = '\0';
4571 i--;
4572 }
4573 while ((i >= 0) && (! IS_WHITESP(line[i])))
4574 i--;
4575 omp = ObjMgrReadLock();
4576 omtp = ObjMgrTypeFind(omp, 0, &(line[i+1]), NULL);
4577 ObjMgrUnlock();
4578 if (omtp == NULL)
4579 {
4580 FileClose(fp);
4581 ErrPostEx(SEV_ERROR, 0,0, "Can't read ASN.1 type [%s]",
4582 &(line[i+1]));
4583 return ptr;
4584 }
4585 break;
4586 }
4587 }
4588 }
4589
4590 if (omtp == NULL)
4591 {
4592 FileClose(fp);
4593 ErrPostEx(SEV_ERROR,0,0,"Don't know how to read file [%s]", filename);
4594 return ptr;
4595 }
4596
4597 fseek(fp, (long)(i+1), SEEK_SET);
4598 aip = AsnIoNew(ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
4599 if (aip != NULL)
4600 aip->fname = StringSave(filename);
4601 ptr = (*(omtp->asnread))(aip, NULL);
4602 AsnIoClose(aip);
4603 if (ptr == NULL)
4604 {
4605 ErrPostEx(SEV_ERROR,0,0,"Couldn't read [%s], type [%s]", filename, omtp->asnname);
4606 }
4607 else
4608 {
4609 if (datatypeptr != NULL)
4610 *datatypeptr = omtp->datatype;
4611 if (entityIDptr != NULL)
4612 *entityIDptr = ObjMgrRegister(omtp->datatype, ptr);
4613 }
4614
4615 return ptr;
4616 }
4617
4618 /***********************************************************************************
4619 *
4620 * ObjMgrMemCopy(type, ptr)
4621 * Uses AsnIoMemCopy to make a copy of any ObjMgr supported type
4622 * ObjMgrType for "type" must have been previously loaded
4623 *
4624 ***********************************************************************************/
ObjMgrMemCopy(Uint2 type,Pointer ptr)4625 NLM_EXTERN Pointer LIBCALL ObjMgrMemCopy (Uint2 type, Pointer ptr)
4626 {
4627 Pointer newptr = NULL;
4628 ObjMgrPtr omp;
4629
4630 if (ptr == NULL) return newptr;
4631
4632 omp = ObjMgrReadLock();
4633 newptr = ObjMgrMemCopyFunc(omp, type, ptr, TRUE);
4634
4635 return newptr;
4636 }
4637
ObjMgrMemCopyFunc(ObjMgrPtr omp,Uint2 type,Pointer ptr,Boolean unlock)4638 static Pointer NEAR ObjMgrMemCopyFunc (ObjMgrPtr omp, Uint2 type, Pointer ptr, Boolean unlock)
4639 {
4640 Pointer newptr = NULL;
4641 ObjMgrTypePtr omtp;
4642
4643 if (ptr == NULL) {
4644
4645 if (unlock)
4646 ObjMgrUnlock();
4647
4648 return newptr;
4649 }
4650
4651 omtp = ObjMgrTypeFind(omp, type, NULL, NULL);
4652 if (unlock)
4653 ObjMgrUnlock();
4654 if (omtp == NULL) return newptr;
4655
4656 newptr = AsnIoMemCopy(ptr, omtp->asnread, omtp->asnwrite);
4657
4658 return newptr;
4659 }
4660
4661 /***********************************************************************************
4662 *
4663 * ObjMgrFree(type, ptr)
4664 * ObjMgrType for "type" must have been previously loaded
4665 *
4666 ***********************************************************************************/
ObjMgrFree(Uint2 type,Pointer ptr)4667 NLM_EXTERN Pointer LIBCALL ObjMgrFree (Uint2 type, Pointer ptr)
4668 {
4669 Pointer newptr = NULL;
4670 ObjMgrPtr omp;
4671
4672 if (ptr == NULL) return newptr;
4673
4674 omp = ObjMgrReadLock();
4675 newptr = ObjMgrFreeFunc(omp, type, ptr, TRUE);
4676
4677 return newptr;
4678 }
4679
ObjMgrFreeByEntityID(Uint2 entityID)4680 NLM_EXTERN Pointer LIBCALL ObjMgrFreeByEntityID (Uint2 entityID)
4681 {
4682 ObjMgrDataPtr omdp;
4683 Uint2 type;
4684 Pointer ptr;
4685
4686 if (entityID < 1) return NULL;
4687 omdp = ObjMgrGetData (entityID);
4688 if (omdp == NULL) return NULL;
4689
4690 if (omdp->choice != NULL) {
4691 type = omdp->choicetype;
4692 ptr = omdp->choice;
4693 } else {
4694 type = omdp->datatype;
4695 ptr = omdp->dataptr;
4696 }
4697
4698 return ObjMgrFree (type, ptr);
4699 }
4700
ObjMgrFreeFunc(ObjMgrPtr omp,Uint2 type,Pointer ptr,Boolean unlock)4701 static Pointer NEAR ObjMgrFreeFunc (ObjMgrPtr omp, Uint2 type, Pointer ptr, Boolean unlock)
4702 {
4703 Pointer newptr = NULL;
4704 ObjMgrTypePtr omtp;
4705
4706 if (ptr == NULL) {
4707 if (unlock)
4708 ObjMgrUnlock();
4709 return newptr;
4710 }
4711
4712 omtp = ObjMgrTypeFind(omp, type, NULL, NULL);
4713
4714 if (unlock)
4715 ObjMgrUnlock();
4716 if (omtp == NULL) return newptr;
4717 (*(omtp->freefunc))(ptr);
4718
4719 return newptr;
4720 }
4721
ObjMgrResetAll(void)4722 NLM_EXTERN void LIBCALL ObjMgrResetAll (void)
4723 {
4724 Int4 ret;
4725
4726 if (global_omp == NULL)
4727 return;
4728
4729 ret = NlmMutexLockEx(&omp_mutex); /* protect this section */
4730 if (ret) { /* error */
4731 ErrPostEx(SEV_FATAL,0,0,"ObjMgrResetAll failed [%ld]", (long)ret);
4732 return;
4733 }
4734
4735 global_omp = (ObjMgrPtr) MemFree(global_omp);
4736 NlmRWdestroy(omp_RWlock);
4737 omp_RWlock = NULL;
4738
4739 NlmMutexUnlock(omp_mutex);
4740
4741 return;
4742 }
4743
4744 static CharPtr objmgrtypestrs [] = {
4745 "OBJ_ALL", "OBJ_SEQENTRY", "OBJ_BIOSEQ", "OBJ_BIOSEQSET", "OBJ_SEQDESC",
4746 "OBJ_SEQANNOT", "OBJ_ANNOTDESC", "OBJ_SEQFEAT", "OBJ_SEQALIGN", "OBJ_SEQGRAPH",
4747 "OBJ_SEQSUB", "OBJ_SUBMIT_BLOCK", "OBJ_SEQSUB_CONTACT", "13", "OBJ_BIOSEQ_MAPFEAT",
4748 "OBJ_BIOSEQ_SEG", "OBJ_SEQHIST", "OBJ_SEQHIST_ALIGN", "OBJ_BIOSEQ_DELTA", "19",
4749 "OBJ_PUB", "OBJ_SEQFEAT_CIT", "OBJ_SEQSUB_CIT", "OBJ_MEDLINE_ENTRY", "OBJ_PUB_SET",
4750 "OBJ_SEQLOC", "OBJ_SEQID", "OBJ_SEQCODE", "OBJ_SEQCODE_SET", "OBJ_GENETIC_CODE",
4751 "OBJ_GENETIC_CODE_SET", "OBJ_TEXT_REPORT", "OBJ_FASTA", "OBJ_VIBRANT_PICTURE", "OBJ_PROJECT"
4752 };
4753
4754 static CharPtr temploadstrs [] = {
4755 "TL_NOT_TEMP", "TL_LOADED", "TL_CACHED"
4756 };
4757
4758 static CharPtr proctypestrs [] = {
4759 "0", "OMPROC_OPEN", "OMPROC_DELETE", "OMPROC_VIEW", "OMPROC_EDIT",
4760 "OMPROC_SAVE", "OMPROC_CUT", "OMPROC_COPY", "OMPROC_PASTE", "OMPROC_ANALYZE",
4761 "OMPROC_FIND", "OMPROC_REPLACE", "OMPROC_FILTER", "OMPROC_FETCH",
4762 };
4763
PrintABool(FILE * fp,CharPtr str,Boolean val)4764 static void PrintABool (FILE *fp, CharPtr str, Boolean val)
4765
4766 {
4767 if (val) {
4768 fprintf (fp, "%s TRUE\n", str);
4769 } else {
4770 fprintf (fp, "%s FALSE\n", str);
4771 }
4772 }
4773
ReportOnEntity(ObjMgrDataPtr omdp,ObjMgrPtr omp,Boolean selected,Uint4 itemID,Uint2 itemtype,Int2 index,FILE * fp)4774 static void ReportOnEntity (ObjMgrDataPtr omdp, ObjMgrPtr omp, Boolean selected,
4775 Uint4 itemID, Uint2 itemtype, Int2 index, FILE *fp)
4776
4777 {
4778 BioseqPtr bsp;
4779 BioseqSetPtr bssp;
4780 Char buf [50];
4781 OMUserDataPtr omudp;
4782
4783 if (omdp == NULL || fp == NULL) return;
4784 if (selected) {
4785 fprintf (fp, "Data Element\n\n");
4786 fprintf (fp, " EntityID %d selected\n", (int) omdp->EntityID);
4787 fprintf (fp, " ItemID %d, Itemtype %d\n", (int) itemID, (int) itemtype);
4788 } else if (omdp->parentptr == NULL) {
4789 fprintf (fp, "Top Data Element %d\n\n", (int) index);
4790 fprintf (fp, " EntityID %d\n", (int) omdp->EntityID);
4791 } else {
4792 fprintf (fp, "Inner Data Element %d\n\n", (int) index);
4793 fprintf (fp, " EntityID %d\n", (int) omdp->EntityID);
4794 }
4795 if (omdp->datatype < OBJ_MAX) {
4796 fprintf (fp, " Datatype %s", objmgrtypestrs [omdp->datatype]);
4797 if (omdp->datatype == OBJ_BIOSEQ) {
4798 bsp = (BioseqPtr) omdp->dataptr;
4799 if (bsp != NULL) {
4800 SeqIdWrite (bsp->id, buf, PRINTID_FASTA_LONG, sizeof (buf) - 1);
4801 fprintf (fp, " %s, length %ld", buf, (long) bsp->length);
4802 }
4803 } else if (omdp->datatype == OBJ_BIOSEQSET) {
4804 bssp = (BioseqSetPtr) omdp->dataptr;
4805 if (bssp != NULL) {
4806 fprintf (fp, " class %d", (int) bssp->_class);
4807 }
4808 }
4809 fprintf (fp, "\n");
4810 } else {
4811 fprintf (fp, " Unregistered datatype %d\n", (int) omdp->datatype);
4812 }
4813 fprintf (fp, " Lockcnt %d\n", (int) omdp->lockcnt);
4814 if (omdp->tempload < 3) {
4815 fprintf (fp, " Tempload %s\n", temploadstrs [omdp->tempload]);
4816 } else {
4817 fprintf (fp, " Unrecognized tempload %d\n", (int) omdp->tempload);
4818 }
4819 PrintABool (fp, " Clipboard", omdp->clipboard);
4820 PrintABool (fp, " Dirty", omdp->dirty);
4821 PrintABool (fp, " Being_freed", omdp->being_freed);
4822 PrintABool (fp, " Free", omdp->free);
4823 fprintf (fp, "\n");
4824 for (omudp = omdp->userdata; omudp != NULL; omudp = omudp->next) {
4825 if (omudp->proctype <= OMPROC_MAX) {
4826 fprintf (fp, " Proctype %s\n", proctypestrs [omudp->proctype]);
4827 } else {
4828 fprintf (fp, " Unrecognized proctype %d\n", (int) omudp->proctype);
4829 }
4830 fprintf (fp, " Procid %d\n", (int) omudp->procid);
4831 fprintf (fp, " Userkey %d\n", (int) omudp->userkey);
4832 fprintf (fp, "\n");
4833 }
4834 }
4835
4836
ObjMgrReportProc(FILE * fp)4837 NLM_EXTERN void LIBCALL ObjMgrReportProc (FILE *fp)
4838
4839 {
4840 Uint4 j;
4841 Uint4 num;
4842 ObjMgrPtr omp;
4843 ObjMgrDataPtr omdp;
4844 ObjMgrDataPtr PNTR omdpp;
4845
4846 if (fp == NULL) return;
4847 omp = ObjMgrGet ();
4848 if (omp == NULL) return;
4849 fprintf (fp, "Object Manager\n\n");
4850 fprintf (fp, " HighestEntityID %d\n", (int) omp->HighestEntityID);
4851 fprintf (fp, " Totobj %d\n", (int) omp->totobj);
4852 fprintf (fp, " Currobj %d\n", (int) omp->currobj);
4853 fprintf (fp, " Maxtemp %d\n", (int) omp->maxtemp);
4854 fprintf (fp, " Tempcnt %d\n", (int) omp->tempcnt);
4855 fprintf (fp, " Hold %d\n", (int) omp->hold);
4856 PrintABool (fp, " Reaping", omp->reaping);
4857 PrintABool (fp, " Is_write_locked", omp->is_write_locked);
4858 fprintf (fp, "\n");
4859 num = omp->currobj;
4860 for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
4861 omdp = *omdpp;
4862 if (omdp->parentptr == NULL) {
4863 ReportOnEntity (omdp, omp, FALSE, 0, 0, j + 1, fp);
4864 }
4865 }
4866 for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
4867 omdp = *omdpp;
4868 if (omdp->parentptr != NULL) {
4869 ReportOnEntity (omdp, omp, FALSE, 0, 0, j + 1, fp);
4870 }
4871 }
4872 }
4873
4874
ObjMgrReportFunc(CharPtr filename)4875 NLM_EXTERN void LIBCALL ObjMgrReportFunc (CharPtr filename)
4876
4877 {
4878 FILE *fp;
4879 Uint4 j;
4880 Uint4 num;
4881 ObjMgrPtr omp;
4882 ObjMgrDataPtr omdp;
4883 ObjMgrDataPtr PNTR omdpp;
4884
4885 omp = ObjMgrGet ();
4886 if (omp == NULL) return;
4887 fp = FileOpen (filename, "w");
4888 fprintf (fp, "Object Manager\n\n");
4889 fprintf (fp, " HighestEntityID %d\n", (int) omp->HighestEntityID);
4890 fprintf (fp, " Totobj %d\n", (int) omp->totobj);
4891 fprintf (fp, " Currobj %d\n", (int) omp->currobj);
4892 fprintf (fp, " Maxtemp %d\n", (int) omp->maxtemp);
4893 fprintf (fp, " Tempcnt %d\n", (int) omp->tempcnt);
4894 fprintf (fp, " Hold %d\n", (int) omp->hold);
4895 PrintABool (fp, " Reaping", omp->reaping);
4896 PrintABool (fp, " Is_write_locked", omp->is_write_locked);
4897 fprintf (fp, "\n");
4898 num = omp->currobj;
4899 for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
4900 omdp = *omdpp;
4901 if (omdp->parentptr == NULL) {
4902 ReportOnEntity (omdp, omp, FALSE, 0, 0, j + 1, fp);
4903 }
4904 }
4905 for (j = 0, omdpp = omp->datalist; j < num && omdpp != NULL; j++, omdpp++) {
4906 omdp = *omdpp;
4907 if (omdp->parentptr != NULL) {
4908 ReportOnEntity (omdp, omp, FALSE, 0, 0, j + 1, fp);
4909 }
4910 }
4911 FileClose (fp);
4912 }
4913
4914
ObjMgrCountAssignedEntityIDs(void)4915 static Uint4 LIBCALL ObjMgrCountAssignedEntityIDs (void)
4916
4917 {
4918 Uint4 count = 0, val;
4919 Int2 idx, jdx;
4920
4921 NlmMutexLockEx (&entityid_array_mutex);
4922 ObjMgrWriteLock ();
4923
4924 if (! assignedIDsInited) {
4925 ObjMgrInitAssignedIDArray ();
4926 }
4927
4928 for (idx = 0; idx < 2048; idx++) {
4929 val = assignedIDsArray [idx];
4930 if (val == 0xFFFFFFFF) {
4931 count += 32;
4932 } else if (val > 0) {
4933 for (jdx = 0; jdx < 32; jdx++) {
4934 if ((val & assignedIDsBitIdx [jdx]) != 0) {
4935 count++;
4936 }
4937 }
4938 }
4939 }
4940
4941 ObjMgrUnlock ();
4942 NlmMutexUnlock (entityid_array_mutex);
4943
4944 return count;
4945 }
4946
ObjMgrStatusString(CharPtr str,size_t len)4947 NLM_EXTERN Boolean LIBCALL ObjMgrStatusString (CharPtr str, size_t len)
4948
4949 {
4950 Char buf [256];
4951 ObjMgrPtr omp;
4952
4953 if (str == NULL || len < 1) return FALSE;
4954 *str = '\0';
4955 buf [0] = '\0';
4956 omp = ObjMgrGet ();
4957 if (omp == NULL) return FALSE;
4958
4959 sprintf (buf, "HighID %5d NumIDs %5d TotObj %5d TempObj %5d",
4960 (int) omp->HighestEntityID,
4961 (int) ObjMgrCountAssignedEntityIDs (),
4962 (int) omp->totobj, (int) omp->tempcnt);
4963
4964 StringNCpy_0 (str, buf, len);
4965 return TRUE;
4966 }
4967
4968 NLM_EXTERN void LIBCALL
ObjMgrAddIndexOnEntityID(ObjMgrPtr omp,Uint2 entityID,ObjMgrDataPtr omdp)4969 ObjMgrAddIndexOnEntityID(ObjMgrPtr omp,Uint2 entityID,ObjMgrDataPtr omdp)
4970 {
4971 Uint1 h,l;
4972
4973 h=entityID >> 8;
4974 l=entityID & 0xff;
4975 if(omp==NULL) omp=ObjMgrGet();
4976 if(omp){
4977 if(!omp->entityID_index){
4978 omp->entityID_index=MemNew(256*sizeof(*omp->entityID_index));
4979 }
4980 if(!omp->entityID_index[h]){
4981 omp->entityID_index[h]=MemNew(256*sizeof(**omp->entityID_index));
4982 }
4983 omp->entityID_index[h][l]=omdp;
4984 }
4985 }
4986
4987
4988 NLM_EXTERN void LIBCALL
ObjMgrDeleteIndexOnEntityID(ObjMgrPtr omp,Uint2 entityID)4989 ObjMgrDeleteIndexOnEntityID(ObjMgrPtr omp,Uint2 entityID)
4990 {
4991 Uint1 h,l;
4992
4993 h=entityID >> 8;
4994 l=entityID & 0xff;
4995 if(omp==NULL) omp=ObjMgrGet();
4996 if(omp && omp->entityID_index && omp->entityID_index[h]){
4997 omp->entityID_index[h][l]=NULL;
4998 }
4999 }
5000
5001
5002 NLM_EXTERN ObjMgrDataPtr LIBCALL
ObjMgrLookupIndexOnEntityID(ObjMgrPtr omp,Uint2 entityID)5003 ObjMgrLookupIndexOnEntityID(ObjMgrPtr omp,Uint2 entityID)
5004 {
5005 Uint1 h,l;
5006
5007 h=entityID >> 8;
5008 l=entityID & 0xff;
5009 if(omp==NULL) omp=ObjMgrGet();
5010 if(omp && omp->entityID_index && omp->entityID_index[h]){
5011 return omp->entityID_index[h][l];
5012 } else {
5013 return NULL;
5014 }
5015 }
5016
DeleteRemainingViews(Uint2 entityID)5017 NLM_EXTERN Boolean DeleteRemainingViews (Uint2 entityID)
5018 {
5019 OMUserDataPtr omudp;
5020 Boolean found_desktop = FALSE, has_other = FALSE, removed_one;
5021 Uint2 procid;
5022 Uint4 i, num;
5023 ObjMgrDataPtr omdp;
5024 ObjMgrDataPtr PNTR omdpp;
5025 ObjMgrPtr omp;
5026
5027 if (entityID == 0) return FALSE;
5028 omp = ObjMgrWriteLock();
5029 if (omp == NULL)
5030 {
5031 return FALSE;
5032 }
5033
5034 procid = ObjMgrGetProcID(omp, "NCBI DeskTop", OMPROC_EDIT);
5035
5036 omdpp = omp->datalist;
5037 if (omdpp != NULL) {
5038 for (i = 0; i < omp->currobj && !has_other; i++) {
5039 if (omdpp[i] != NULL && omdpp[i]->EntityID == entityID && !omdpp[i]->being_freed) {
5040 omudp = omdpp[i]->userdata;
5041 while (omudp != NULL && !has_other) {
5042 if (omudp->procid != procid) {
5043 has_other = TRUE;
5044 }
5045 omudp = omudp->next;
5046 }
5047 }
5048 }
5049 if (!has_other) {
5050 removed_one = TRUE;
5051 while (removed_one && omp->currobj > 0) {
5052 removed_one = FALSE;
5053 num = omp->currobj;
5054 omdpp = omp->datalist;
5055 for (i = 0; i < num && ! removed_one; i++) {
5056 omdp = omdpp [i];
5057 if (omdp != NULL && omdp->EntityID == entityID) {
5058 omudp = omdp->userdata;
5059 if (omudp != NULL) {
5060 ObjMgrFreeUserDataFunc (omp, entityID, omudp->procid, omudp->proctype, omudp->userkey);
5061 removed_one = TRUE;
5062 }
5063 }
5064 }
5065 }
5066 }
5067 }
5068
5069 ObjMgrUnlock ();
5070 return found_desktop;
5071 }
5072