]>
jfr.im git - irc/quakenet/snircd.git/blob - libs/dbprim/st_add.c
2 ** Copyright (C) 2002 by Kevin L. Mitchell <klmitch@mit.edu>
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Library General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2 of the License, or (at your option) any later version.
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Library General Public License for more details.
14 ** You should have received a copy of the GNU Library General Public
15 ** License along with this library; if not, write to the Free
16 ** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 ** @(#)$Id: st_add.c,v 1.1 2003/03/07 02:36:11 klmitch Exp $
24 #include "dbprim_int.h"
26 RCSTAG("@(#)$Id: st_add.c,v 1.1 2003/03/07 02:36:11 klmitch Exp $");
28 /** \ingroup dbprim_smat
29 * \brief Add an entry to a sparse matrix.
31 * This function adds an entry to a sparse matrix. The entry is
32 * referenced in three different places, thus the complex set of
33 * arguments. This function will allocate a #smat_entry_t and return
34 * it through the \c entry_p result parameter.
36 * \param table A pointer to a #smat_table_t.
38 * A pointer to a pointer to a #smat_entry_t. This is a
39 * result parameter. If \c NULL is passed, the addition
40 * will be performed and an appropriate error code
42 * \param head1 A pointer to a #smat_head_t representing a
43 * #SMAT_LOC_FIRST sparse matrix list.
44 * \param loc1 A #link_loc_t indicating where the entry should be
46 * \param ent1 A pointer to a #smat_entry_t describing another
47 * element in the list represented by \c head1 if \p loc1
48 * is #LINK_LOC_BEFORE or #LINK_LOC_AFTER.
49 * \param head2 A pointer to a #smat_head_t representing a
50 * #SMAT_LOC_SECOND sparse matrix list.
51 * \param loc2 A #link_loc_t indicating where the entry should be
53 * \param ent2 A pointer to a #smat_entry_t describing another
54 * element in the list represented by \c head2 if \p loc2
55 * is #LINK_LOC_BEFORE or #LINK_LOC_AFTER.
57 * \retval DB_ERR_BADARGS An argument was invalid.
58 * \retval DB_ERR_BUSY One of the arguments is already in the
60 * \retval DB_ERR_FROZEN The table is currently frozen.
61 * \retval DB_ERR_NOTABLE The bucket table has not been
62 * allocated and automatic growth is not
64 * \retval DB_ERR_WRONGTABLE One of the arguments was not in the
65 * proper table or list.
66 * \retval DB_ERR_UNUSED One of the \c ent arguments is not
67 * presently in a list.
68 * \retval DB_ERR_UNRECOVERABLE An unrecoverable error occurred while
70 * \retval ENOMEM No memory could be allocated for the
71 * #smat_entry_t structure.
74 st_add(smat_table_t
*table
, smat_entry_t
**entry_p
,
75 smat_head_t
*head1
, link_loc_t loc1
, smat_entry_t
*ent1
,
76 smat_head_t
*head2
, link_loc_t loc2
, smat_entry_t
*ent2
)
79 unsigned long retval
= 0;
80 unsigned int freeflags
= 0;
83 initialize_dbpr_error_table(); /* initialize error table */
85 /* Verify arguments--like ll_add(), but has to account for two seperate
88 if (!st_verify(table
) || !sh_verify(head1
) || !sh_verify(head2
) ||
89 head1
->sh_elem
!= SMAT_LOC_FIRST
|| head2
->sh_elem
!= SMAT_LOC_SECOND
||
90 (ent1
&& !se_verify(ent1
)) || (ent2
&& !se_verify(ent2
)) ||
91 ((loc1
== LINK_LOC_BEFORE
|| loc1
== LINK_LOC_AFTER
) && !ent1
) ||
92 ((loc2
== LINK_LOC_BEFORE
|| loc2
== LINK_LOC_AFTER
) && !ent2
))
93 return DB_ERR_BADARGS
;
95 /* verify that everything's in the right tables... */
96 if ((head1
->sh_table
&& head1
->sh_table
!= table
) ||
97 (head2
->sh_table
&& head2
->sh_table
!= table
) ||
98 (ent1
&& ent1
->se_table
!= table
) ||
99 (ent2
&& ent2
->se_table
!= table
))
100 return DB_ERR_WRONGTABLE
;
102 if (!(se
= _smat_alloc())) /* get an entry object */
105 freeflags
|= ST_REM_FREE
; /* entry has been allocated */
107 se
->se_object
[SMAT_LOC_FIRST
] = sh_object(head1
); /* set up the hash key */
108 se
->se_object
[SMAT_LOC_SECOND
] = sh_object(head2
);
109 dk_key(&key
) = &se
->se_object
;
112 /* add the element to the hash table first */
113 if ((retval
= ht_add(&table
->st_table
, &se
->se_hash
, &key
)))
116 freeflags
|= ST_REM_HASH
; /* entry must be removed from hash table */
118 /* add the element to the first linked list */
119 if ((retval
= ll_add(&head1
->sh_head
, &se
->se_link
[SMAT_LOC_FIRST
], loc1
,
120 ent1
? &ent1
->se_link
[SMAT_LOC_FIRST
] : 0)))
123 freeflags
|= ST_REM_FIRST
; /* entry must be removed from linked list 1 */
125 /* add the element to the second linked list */
126 if ((retval
= ll_add(&head2
->sh_head
, &se
->se_link
[SMAT_LOC_SECOND
], loc2
,
127 ent2
? &ent2
->se_link
[SMAT_LOC_SECOND
] : 0)))
130 head1
->sh_table
= head2
->sh_table
= table
; /* remember our table */
131 se
->se_table
= table
;
133 if (!entry_p
) /* user wants to know which entry it is */
136 return 0; /* all done! */
139 /* unlink entry from linked list 1 */
140 if ((freeflags
& ST_REM_FIRST
) &&
141 ll_remove(&head1
->sh_head
, &se
->se_link
[SMAT_LOC_FIRST
]))
142 return DB_ERR_UNRECOVERABLE
;
144 /* remove element from hash table */
145 if ((freeflags
& ST_REM_HASH
) && ht_remove(&table
->st_table
, &se
->se_hash
))
146 return DB_ERR_UNRECOVERABLE
;
148 /* return element to free pool */
149 if (freeflags
& ST_REM_FREE
)
152 return retval
; /* return error */