Changeset bff8619 in mainline for uspace/lib/sif/src/sif.c
- Timestamp:
- 2024-08-20T22:07:31Z (2 months ago)
- Branches:
- master
- Children:
- ac9b4f2
- Parents:
- a3ba37d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/sif/src/sif.c
ra3ba37d rbff8619 1 1 /* 2 * Copyright (c) 202 3Jiri Svoboda2 * Copyright (c) 2024 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 33 33 * 34 34 * Structured Information Format (SIF) is an API that allows an application 35 * to maintain data in a persistent repository in a format that 36 * 37 * - is structured (and hence extensible) 38 * - allows atomic (transactional) updates 39 * - allows efficient updates 35 * to maintain data in a persistent repository in a format that is 36 * structured (and hence extensible). 40 37 * 41 38 * SIF is meant to be used as the basis for the storage backend used to … … 44 41 * similar to an XML document that contains just tags with attributes 45 42 * (but no text). 46 *47 * SIF can thus naturally express ordered lists (unlike a relational database).48 * When contrasted to a (relational) database, SIF is much more primitive.49 *50 * In particular, SIF51 *52 * - does not run on a separate server53 * - des not handle concurrency54 * - does not have a notion of types or data validation55 * - does not understand relations56 * - does not implement any kind of search/queries57 * - does not deal with data sets large enough not to fit in primary memory58 *59 * any kind of structure data validation is left up to the application.60 43 */ 61 44 … … 172 155 } 173 156 174 /** Create and open a SIF repository. 175 * 176 * @param fname File name 177 * @param rsess Place to store pointer to new session. 157 /** Create SIF document. 158 * 159 * @param rdoc Place to store pointer to new document. 178 160 * 179 161 * @return EOK on success or error code 180 162 */ 181 errno_t sif_ create(const char *fname, sif_sess_t **rsess)182 { 183 sif_ sess_t *sess;163 errno_t sif_new(sif_doc_t **rdoc) 164 { 165 sif_doc_t *doc; 184 166 sif_node_t *root = NULL; 185 sif_trans_t *trans = NULL;186 167 errno_t rc; 187 FILE *f; 188 189 sess = calloc(1, sizeof(sif_sess_t)); 190 if (sess == NULL) 191 return ENOMEM; 192 193 sess->fname = str_dup(fname); 194 if (sess->fname == NULL) { 195 rc = ENOMEM; 196 goto error; 197 } 168 169 doc = calloc(1, sizeof(sif_doc_t)); 170 if (doc == NULL) 171 return ENOMEM; 198 172 199 173 root = sif_node_new(NULL); … … 209 183 } 210 184 211 f = fopen(fname, "wx"); 212 if (f == NULL) { 213 rc = EIO; 214 goto error; 215 } 216 217 sess->f = f; 218 sess->root = root; 219 220 /* Run a dummy trasaction to marshall initial repo state to file */ 221 rc = sif_trans_begin(sess, &trans); 222 if (rc != EOK) 223 goto error; 224 225 rc = sif_trans_end(trans); 226 if (rc != EOK) 227 goto error; 228 229 *rsess = sess; 185 doc->root = root; 186 187 *rdoc = doc; 230 188 return EOK; 231 189 error: 232 if (trans != NULL)233 sif_trans_abort(trans);234 190 sif_node_delete(root); 235 if (sess->fname != NULL) 236 free(sess->fname); 237 free(sess); 191 free(doc); 238 192 return rc; 239 193 } 240 194 241 /** Open an existing SIF repository.195 /** Load SIF document. 242 196 * 243 197 * @param fname File name 244 * @param r sess Place to store pointer to new session.198 * @param rdoc Place to store pointer to new document. 245 199 * 246 200 * @return EOK on success or error code 247 201 */ 248 errno_t sif_ open(const char *fname, sif_sess_t **rsess)249 { 250 sif_ sess_t *sess;202 errno_t sif_load(const char *fname, sif_doc_t **rdoc) 203 { 204 sif_doc_t *doc; 251 205 sif_node_t *root = NULL; 252 206 errno_t rc; 253 207 FILE *f; 254 208 255 sess = calloc(1, sizeof(sif_sess_t));256 if ( sess== NULL)257 return ENOMEM; 258 259 sess->fname = str_dup(fname);260 if ( sess->fname == NULL) {209 doc = calloc(1, sizeof(sif_doc_t)); 210 if (doc == NULL) 211 return ENOMEM; 212 213 doc->fname = str_dup(fname); 214 if (doc->fname == NULL) { 261 215 rc = ENOMEM; 262 216 goto error; … … 278 232 } 279 233 280 sess->root = root; 281 282 sess->f = f; 283 sess->root = root; 284 *rsess = sess; 234 doc->root = root; 235 *rdoc = doc; 285 236 return EOK; 286 237 error: 287 238 sif_node_delete(root); 288 if (sess->fname != NULL) 289 free(sess->fname); 290 free(sess); 239 free(doc); 291 240 return rc; 292 241 } 293 242 294 /** Close SIF session.295 * 296 * @param sess SIF session243 /** Delete SIF document. 244 * 245 * @param doc SIF document 297 246 * @return EOK on success or error code 298 247 */ 299 errno_t sif_close(sif_sess_t *sess) 300 { 301 sif_node_delete(sess->root); 302 303 if (fclose(sess->f) < 0) { 304 free(sess); 305 return EIO; 306 } 307 308 if (sess->fname != NULL) 309 free(sess->fname); 310 free(sess); 311 return EOK; 248 void sif_delete(sif_doc_t *doc) 249 { 250 sif_node_delete(doc->root); 251 free(doc); 312 252 } 313 253 314 254 /** Return root node. 315 255 * 316 * @param sess SIF session317 */ 318 sif_node_t *sif_get_root(sif_ sess_t *sess)319 { 320 return sess->root;256 * @param doc SIF document 257 */ 258 sif_node_t *sif_get_root(sif_doc_t *doc) 259 { 260 return doc->root; 321 261 } 322 262 … … 383 323 } 384 324 385 /** Begin SIF transaction. 386 * 387 * @param trans Transaction 325 /** Save SIF document to file. 326 * * 327 * @param doc SIF document 328 * @param fname File name 388 329 * @return EOK on success or error code 389 330 */ 390 errno_t sif_trans_begin(sif_sess_t *sess, sif_trans_t **rtrans) 391 { 392 sif_trans_t *trans; 393 394 trans = calloc(1, sizeof(sif_trans_t)); 395 if (trans == NULL) 396 return ENOMEM; 397 398 trans->sess = sess; 399 *rtrans = trans; 400 return EOK; 401 } 402 403 /** Commit SIF transaction. 404 * 405 * Commit and free the transaction. If an error is returned, that means 406 * the transaction has not been freed (and sif_trans_abort() must be used). 407 * 408 * @param trans Transaction 409 * @return EOK on success or error code 410 */ 411 errno_t sif_trans_end(sif_trans_t *trans) 412 { 331 errno_t sif_save(sif_doc_t *doc, const char *fname) 332 { 333 FILE *f = NULL; 413 334 errno_t rc; 414 335 415 (void) fclose(trans->sess->f);416 417 trans->sess->f = fopen(trans->sess->fname, "w");418 if (trans->sess->f == NULL)419 return EIO;420 421 rc = sif_export_node( trans->sess->root, trans->sess->f);336 f = fopen(fname, "w"); 337 if (f == NULL) { 338 rc = EIO; 339 goto error; 340 } 341 342 rc = sif_export_node(doc->root, f); 422 343 if (rc != EOK) 423 return rc; 424 425 if (fputc('\n', trans->sess->f) == EOF) 426 return EIO; 427 428 if (fflush(trans->sess->f) == EOF) 429 return EIO; 430 431 free(trans); 432 return EOK; 433 } 434 435 /** Abort SIF transaction. 436 * 437 * @param trans Transaction 438 */ 439 void sif_trans_abort(sif_trans_t *trans) 440 { 441 free(trans); 344 goto error; 345 346 if (fputc('\n', f) == EOF) { 347 rc = EIO; 348 goto error; 349 } 350 351 if (fflush(f) == EOF) { 352 rc = EIO; 353 goto error; 354 } 355 356 return EOK; 357 error: 358 if (f != NULL) 359 fclose(f); 360 return rc; 442 361 } 443 362 … … 447 366 * @a parent. 448 367 * 449 * @param trans Transaction450 368 * @param parent Parent node 451 369 * @param ctype Child type … … 454 372 * @return EOK on success or ENOMEM if out of memory 455 373 */ 456 errno_t sif_node_prepend_child(sif_ trans_t *trans, sif_node_t *parent,457 const char *ctype,sif_node_t **rchild)374 errno_t sif_node_prepend_child(sif_node_t *parent, const char *ctype, 375 sif_node_t **rchild) 458 376 { 459 377 sif_node_t *child; … … 479 397 * Create a new child and append it at the end of children list of @a parent. 480 398 * 481 * @param trans Transaction482 399 * @param parent Parent node 483 400 * @param ctype Child type … … 486 403 * @return EOK on success or ENOMEM if out of memory 487 404 */ 488 errno_t sif_node_append_child(sif_ trans_t *trans, sif_node_t *parent,489 const char *ctype,sif_node_t **rchild)405 errno_t sif_node_append_child(sif_node_t *parent, const char *ctype, 406 sif_node_t **rchild) 490 407 { 491 408 sif_node_t *child; … … 511 428 * Create a new child and insert it before an existing child. 512 429 * 513 * @param trans Transaction514 430 * @param sibling Sibling before which to insert 515 431 * @param ctype Child type … … 518 434 * @return EOK on success or ENOMEM if out of memory 519 435 */ 520 errno_t sif_node_insert_before(sif_ trans_t *trans, sif_node_t *sibling,521 const char *ctype,sif_node_t **rchild)436 errno_t sif_node_insert_before(sif_node_t *sibling, const char *ctype, 437 sif_node_t **rchild) 522 438 { 523 439 sif_node_t *child; … … 543 459 * Create a new child and insert it after an existing child. 544 460 * 545 * @param trans Transaction546 461 * @param sibling Sibling after which to insert 547 462 * @param ctype Child type … … 550 465 * @return EOK on success or ENOMEM if out of memory 551 466 */ 552 errno_t sif_node_insert_after(sif_ trans_t *trans, sif_node_t *sibling,553 const char *ctype,sif_node_t **rchild)467 errno_t sif_node_insert_after(sif_node_t *sibling, const char *ctype, 468 sif_node_t **rchild) 554 469 { 555 470 sif_node_t *child; … … 573 488 /** Destroy SIF node. 574 489 * 575 * This function does not return an error, but the transaction may still576 * fail to complete.577 *578 * @param trans Transaction579 490 * @param node Node to destroy 580 491 */ 581 void sif_node_destroy(sif_ trans_t *trans, sif_node_t *node)492 void sif_node_destroy(sif_node_t *node) 582 493 { 583 494 list_remove(&node->lparent); … … 587 498 /** Set node attribute. 588 499 * 589 * @param trans Transaction590 500 * @param node SIF node 591 501 * @param aname Attribute name … … 594 504 * @return EOK on success, ENOMEM if out of memory 595 505 */ 596 errno_t sif_node_set_attr(sif_ trans_t *trans, sif_node_t *node,597 const char *a name, const char *avalue)506 errno_t sif_node_set_attr(sif_node_t *node, const char *aname, 507 const char *avalue) 598 508 { 599 509 odlink_t *link; … … 636 546 /** Unset node attribute. 637 547 * 638 * This function does not return an error, but the transaction may still639 * fail to complete.640 *641 * @param trans Transaction642 548 * @param node Node 643 549 * @param aname Attribute name 644 550 */ 645 void sif_node_unset_attr(sif_trans_t *trans, sif_node_t *node, 646 const char *aname) 551 void sif_node_unset_attr(sif_node_t *node, const char *aname) 647 552 { 648 553 odlink_t *link;
Note:
See TracChangeset
for help on using the changeset viewer.