![]() ![]() | ![]() |
Passage de la branche 4.1 en branche stable.
1: /* 2: ================================================================================ 3: RPL/2 (R) version 4.1.0 4: Copyright (C) 1989-2011 Dr. BERTRAND Joël 5: 6: This file is part of RPL/2. 7: 8: RPL/2 is free software; you can redistribute it and/or modify it 9: under the terms of the CeCILL V2 License as published by the french 10: CEA, CNRS and INRIA. 11: 12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT 13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License 15: for more details. 16: 17: You should have received a copy of the CeCILL License 18: along with RPL/2. If not, write to info@cecill.info. 19: ================================================================================ 20: */ 21: 22: 23: #include "rpl-conv.h" 24: 25: 26: /* 27: ================================================================================ 28: Routines de gestion des fichiers 29: ================================================================================ 30: Entrées : nom du fichier 31: -------------------------------------------------------------------------------- 32: Sorties : 0, le fichier n'existe pas, -1, il existe. 33: -------------------------------------------------------------------------------- 34: Effets de bord : néant 35: ================================================================================ 36: */ 37: 38: /* 39: * Génère un nom de fichier 40: */ 41: 42: unsigned char * 43: creation_nom_fichier(struct_processus *s_etat_processus, 44: unsigned char *chemin) 45: { 46: /* 47: * Le nom du fichier est créé à l'aide du pid du processus et 48: * d'un numéro d'ordre pour ce processus. 49: */ 50: 51: logical1 erreur; 52: 53: logical1 existence; 54: logical1 ouverture; 55: 56: pthread_mutex_t exclusion = PTHREAD_MUTEX_INITIALIZER; 57: 58: unsigned char *nom; 59: unsigned char tampon[256 + 1]; 60: 61: unsigned long ordre_initial; 62: unsigned long unite; 63: 64: static unsigned long ordre = 0; 65: 66: if (pthread_mutex_lock(&exclusion) != 0) 67: { 68: return(NULL); 69: } 70: 71: ordre_initial = ordre; 72: 73: if (pthread_mutex_unlock(&exclusion) != 0) 74: { 75: return(NULL); 76: } 77: 78: do 79: { 80: sprintf(tampon, "RPL-%lu-%lu-%lu", (unsigned long) getpid(), 81: (unsigned long) pthread_self(), ordre); 82: 83: if (chemin == NULL) 84: { 85: if ((nom = malloc((strlen(tampon) + 1) * 86: sizeof(unsigned char))) == NULL) 87: { 88: return(NULL); 89: } 90: 91: strcpy(nom, tampon); 92: } 93: else 94: { 95: if ((nom = malloc((strlen(chemin) + strlen(tampon) + 2) * 96: sizeof(unsigned char))) == NULL) 97: { 98: return(NULL); 99: } 100: 101: sprintf(nom, "%s/%s", chemin, tampon); 102: } 103: 104: if (pthread_mutex_lock(&exclusion) != 0) 105: { 106: return(NULL); 107: } 108: 109: ordre++; 110: 111: if (pthread_mutex_unlock(&exclusion) != 0) 112: { 113: return(NULL); 114: } 115: 116: if (ordre == ordre_initial) 117: { 118: // Il n'existe plus aucun nom de fichier disponible... 119: 120: free(nom); 121: return(NULL); 122: } 123: 124: erreur = caracteristiques_fichier(s_etat_processus, 125: nom, &existence, &ouverture, &unite); 126: 127: if (erreur != 0) 128: { 129: free(nom); 130: return(NULL); 131: } 132: 133: if (existence == d_vrai) 134: { 135: free(nom); 136: } 137: } while(existence == d_vrai); 138: 139: return(nom); 140: } 141: 142: /* 143: * Efface un fichier 144: */ 145: 146: logical1 147: destruction_fichier(unsigned char *nom_fichier) 148: { 149: return((unlink(nom_fichier) == 0) ? d_absence_erreur : d_erreur); 150: } 151: 152: /* 153: * Renvoie le descripteur en fonction de la structure de contrôle du fichier 154: */ 155: 156: struct_descripteur_fichier * 157: descripteur_fichier(struct_processus *s_etat_processus, 158: struct_fichier *s_fichier) 159: { 160: logical1 concordance_descripteurs; 161: 162: struct_liste_chainee *l_element_courant; 163: 164: l_element_courant = (*s_etat_processus).s_fichiers; 165: concordance_descripteurs = d_faux; 166: 167: while(l_element_courant != NULL) 168: { 169: if ((*((struct_descripteur_fichier *) (*l_element_courant).donnee)) 170: .identifiant == (*s_fichier).descripteur) 171: { 172: if (((*((struct_descripteur_fichier *) (*l_element_courant).donnee)) 173: .pid == (*s_fichier).pid) && (pthread_equal( 174: (*((struct_descripteur_fichier *) (*l_element_courant) 175: .donnee)).tid, pthread_self()) != 0)) 176: { 177: return((struct_descripteur_fichier *) 178: (*l_element_courant).donnee); 179: } 180: else 181: { 182: concordance_descripteurs = d_vrai; 183: } 184: } 185: 186: l_element_courant = (*l_element_courant).suivant; 187: } 188: 189: if (concordance_descripteurs == d_vrai) 190: { 191: (*s_etat_processus).erreur_execution = d_ex_fichier_hors_contexte; 192: } 193: else 194: { 195: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 196: } 197: 198: return(NULL); 199: } 200: 201: /* 202: * Recherche un chemin pour les fichiers temporaires 203: */ 204: 205: unsigned char * 206: recherche_chemin_fichiers_temporaires(struct_processus *s_etat_processus) 207: { 208: file *fichier; 209: 210: unsigned char *candidat; 211: unsigned char *chemin; 212: unsigned char *chemins[] = { "$RPL_TMP_PATH", 213: "/tmp", "/var/tmp", NULL }; 214: unsigned char *nom_candidat; 215: 216: unsigned long int i; 217: 218: i = 0; 219: chemin = NULL; 220: 221: while(chemin == NULL) 222: { 223: if (chemins[i][0] == '$') 224: { 225: candidat = getenv("RPL_TMP_PATH"); 226: 227: if (candidat != NULL) 228: { 229: if ((nom_candidat = creation_nom_fichier(s_etat_processus, 230: candidat)) == NULL) 231: { 232: return(NULL); 233: } 234: 235: if ((fichier = fopen(nom_candidat, "w+")) != NULL) 236: { 237: fclose(fichier); 238: unlink(nom_candidat); 239: free(nom_candidat); 240: 241: if ((chemin = malloc((strlen(candidat) + 1) 242: * sizeof(unsigned char))) != NULL) 243: { 244: strcpy(chemin, candidat); 245: } 246: else 247: { 248: return(NULL); 249: } 250: } 251: else 252: { 253: free(nom_candidat); 254: } 255: } 256: } 257: else 258: { 259: if ((nom_candidat = creation_nom_fichier(s_etat_processus, 260: chemins[i])) == NULL) 261: { 262: return(NULL); 263: } 264: 265: if ((fichier = fopen(nom_candidat, "w+")) != NULL) 266: { 267: fclose(fichier); 268: unlink(nom_candidat); 269: free(nom_candidat); 270: 271: if ((chemin = malloc((strlen(chemins[i]) + 1) 272: * sizeof(unsigned char))) != NULL) 273: { 274: strcpy(chemin, chemins[i]); 275: } 276: else 277: { 278: return(NULL); 279: } 280: } 281: else 282: { 283: free(nom_candidat); 284: } 285: } 286: 287: i++; 288: } 289: 290: return chemin; 291: } 292: 293: 294: /* 295: * Fonction d'interrogation du fichier 296: */ 297: 298: logical1 299: caracteristiques_fichier(struct_processus *s_etat_processus, 300: unsigned char *nom, logical1 *existence, logical1 *ouverture, 301: unsigned long *unite) 302: { 303: int descripteur; 304: 305: logical1 erreur; 306: 307: struct_liste_chainee *l_element_courant; 308: 309: (*unite) = 0; 310: (*ouverture) = d_faux; 311: (*existence) = d_faux; 312: 313: if ((descripteur = open(nom, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) == -1) 314: { 315: if (errno == EEXIST) 316: { 317: // Le fichier préexiste. 318: 319: erreur = d_absence_erreur; 320: (*existence) = d_vrai; 321: 322: // On chercher à savoir si le fichier est ouvert. S'il est ouvert, 323: // on renvoie son unité de rattachement. 324: 325: l_element_courant = (*s_etat_processus).s_fichiers; 326: 327: while(l_element_courant != NULL) 328: { 329: if (strcmp((*((struct_descripteur_fichier *) 330: (*l_element_courant).donnee)).nom, nom) == 0) 331: { 332: if (((*((struct_descripteur_fichier *) (*l_element_courant) 333: .donnee)).pid == getpid()) && 334: (pthread_equal((*((struct_descripteur_fichier *) 335: (*l_element_courant).donnee)).tid, pthread_self()) 336: != 0)) 337: { 338: (*ouverture) = d_vrai; 339: 340: (*unite) = (unsigned long) 341: fileno((*((struct_descripteur_fichier *) 342: (*l_element_courant).donnee)) 343: .descripteur_c); 344: break; 345: } 346: } 347: 348: l_element_courant = (*l_element_courant).suivant; 349: } 350: } 351: else 352: { 353: erreur = d_erreur; 354: } 355: } 356: else 357: { 358: close(descripteur); 359: unlink(nom); 360: erreur = d_absence_erreur; 361: } 362: 363: return(erreur); 364: } 365: 366: 367: /* 368: ================================================================================ 369: Routines d'initialisation des fichiers à accès direct et indexé 370: ================================================================================ 371: Entrées : pointeur sur le fichier SQLITE 372: -------------------------------------------------------------------------------- 373: Sorties : drapeau d'erreur 374: -------------------------------------------------------------------------------- 375: Effets de bord : néant 376: ================================================================================ 377: */ 378: 379: /* 380: * Un fichier à accès direct se compose d'une seule table : 381: * 1: identifiant (entier sur 64 bits) -> enregistrement 382: * 383: * Un fichier à accès indexé comporte trois tables : 384: * 1 : contrôle 385: * 2 : clef (unique) -> identifiant (entier sur 64 bits) 386: * 3 : identifiant -> collection d'enregistrements 387: * 388: * La table de contrôle contient 389: * 1/ la position de la clef pour les fichiers à accès indexés 390: */ 391: 392: static logical1 393: initialisation_controle(struct_processus *s_etat_processus, sqlite3 *sqlite, 394: integer8 position_clef, logical1 fichier_indexe) 395: { 396: const char commande1[] = 397: "create table control(id integer primary key asc, key integer)"; 398: const char commande2[] = 399: "insert into control (id, key) values (1, %lld)"; 400: const char *queue; 401: 402: sqlite3_stmt *ppStmt; 403: 404: unsigned char *commande; 405: 406: if (sqlite3_prepare_v2(sqlite, commande1, strlen(commande1), &ppStmt, 407: &queue) != SQLITE_OK) 408: { 409: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 410: return(d_erreur); 411: } 412: 413: if (sqlite3_step(ppStmt) != SQLITE_DONE) 414: { 415: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 416: return(d_erreur); 417: } 418: 419: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 420: { 421: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 422: return(d_erreur); 423: } 424: 425: if (fichier_indexe == d_vrai) 426: { 427: if (alsprintf(&commande, commande2, position_clef) < 0) 428: { 429: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; 430: return(d_erreur); 431: } 432: 433: if (sqlite3_prepare_v2(sqlite, commande, strlen(commande), &ppStmt, 434: &queue) != SQLITE_OK) 435: { 436: free(commande); 437: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 438: return(d_erreur); 439: } 440: 441: if (sqlite3_step(ppStmt) != SQLITE_DONE) 442: { 443: free(commande); 444: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 445: return(d_erreur); 446: } 447: 448: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 449: { 450: free(commande); 451: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 452: return(d_erreur); 453: } 454: 455: free(commande); 456: } 457: 458: return(d_absence_erreur); 459: } 460: 461: logical1 462: initialisation_fichier_acces_indexe(struct_processus *s_etat_processus, 463: sqlite3 *sqlite, integer8 position_clef, logical1 binaire) 464: { 465: const char commande1[] = 466: "create table data(id integer primary key asc, key_id integer, " 467: "data text, sequence integer)"; 468: const char commande10[] = 469: "create table key(id integer primary key asc, key text)"; 470: const char commande2[] = 471: "create table data(id integer primary key asc, key_id integer, " 472: "data blob, sequence integer)"; 473: const char commande20[] = 474: "create table key(id integer primary key asc, key blob)"; 475: const char commande3[] = 476: "create index data_idx on data(key_id)"; 477: const char commande4[] = 478: "create index key_idx on key(key)"; 479: const char *queue; 480: 481: sqlite3_stmt *ppStmt; 482: 483: if (initialisation_controle(s_etat_processus, sqlite, position_clef, d_vrai) 484: != d_absence_erreur) 485: { 486: return(d_erreur); 487: } 488: 489: if (binaire == d_faux) 490: { 491: if (sqlite3_prepare_v2(sqlite, commande1, strlen(commande1), &ppStmt, 492: &queue) != SQLITE_OK) 493: { 494: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 495: return(d_erreur); 496: } 497: 498: if (sqlite3_step(ppStmt) != SQLITE_DONE) 499: { 500: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 501: return(d_erreur); 502: } 503: 504: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 505: { 506: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 507: return(d_erreur); 508: } 509: 510: if (sqlite3_prepare_v2(sqlite, commande10, strlen(commande10), &ppStmt, 511: &queue) != SQLITE_OK) 512: { 513: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 514: return(d_erreur); 515: } 516: 517: if (sqlite3_step(ppStmt) != SQLITE_DONE) 518: { 519: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 520: return(d_erreur); 521: } 522: 523: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 524: { 525: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 526: return(d_erreur); 527: } 528: } 529: else 530: { 531: if (sqlite3_prepare_v2(sqlite, commande2, strlen(commande2), &ppStmt, 532: &queue) != SQLITE_OK) 533: { 534: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 535: return(d_erreur); 536: } 537: 538: if (sqlite3_step(ppStmt) != SQLITE_DONE) 539: { 540: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 541: return(d_erreur); 542: } 543: 544: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 545: { 546: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 547: return(d_erreur); 548: } 549: 550: if (sqlite3_prepare_v2(sqlite, commande20, strlen(commande20), &ppStmt, 551: &queue) != SQLITE_OK) 552: { 553: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 554: return(d_erreur); 555: } 556: 557: if (sqlite3_step(ppStmt) != SQLITE_DONE) 558: { 559: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 560: return(d_erreur); 561: } 562: 563: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 564: { 565: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 566: return(d_erreur); 567: } 568: } 569: 570: if (sqlite3_prepare_v2(sqlite, commande3, strlen(commande3), &ppStmt, 571: &queue) != SQLITE_OK) 572: { 573: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 574: return(d_erreur); 575: } 576: 577: if (sqlite3_step(ppStmt) != SQLITE_DONE) 578: { 579: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 580: return(d_erreur); 581: } 582: 583: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 584: { 585: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 586: return(d_erreur); 587: } 588: 589: if (sqlite3_prepare_v2(sqlite, commande4, strlen(commande4), &ppStmt, 590: &queue) != SQLITE_OK) 591: { 592: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 593: return(d_erreur); 594: } 595: 596: if (sqlite3_step(ppStmt) != SQLITE_DONE) 597: { 598: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 599: return(d_erreur); 600: } 601: 602: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 603: { 604: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 605: return(d_erreur); 606: } 607: 608: return(d_absence_erreur); 609: } 610: 611: logical1 612: initialisation_fichier_acces_direct(struct_processus *s_etat_processus, 613: sqlite3 *sqlite, logical1 binaire) 614: { 615: const char commande1[] = 616: "create table data(id integer primary key asc, data text)"; 617: const char commande2[] = 618: "create table data(id integer primary key asc, data blob)"; 619: const char commande3[] = 620: "create index data_idx on data(id)"; 621: const char *queue; 622: 623: sqlite3_stmt *ppStmt; 624: 625: if (initialisation_controle(s_etat_processus, sqlite, (integer8) 0, d_faux) 626: != d_absence_erreur) 627: { 628: return(d_erreur); 629: } 630: 631: if (binaire == d_faux) 632: { 633: if (sqlite3_prepare_v2(sqlite, commande1, strlen(commande1), &ppStmt, 634: &queue) != SQLITE_OK) 635: { 636: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 637: return(d_erreur); 638: } 639: 640: if (sqlite3_step(ppStmt) != SQLITE_DONE) 641: { 642: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 643: return(d_erreur); 644: } 645: 646: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 647: { 648: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 649: return(d_erreur); 650: } 651: } 652: else 653: { 654: if (sqlite3_prepare_v2(sqlite, commande2, strlen(commande2), &ppStmt, 655: &queue) != SQLITE_OK) 656: { 657: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 658: return(d_erreur); 659: } 660: 661: if (sqlite3_step(ppStmt) != SQLITE_DONE) 662: { 663: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 664: return(d_erreur); 665: } 666: 667: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 668: { 669: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 670: return(d_erreur); 671: } 672: } 673: 674: if (sqlite3_prepare_v2(sqlite, commande3, strlen(commande3), &ppStmt, 675: &queue) != SQLITE_OK) 676: { 677: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 678: return(d_erreur); 679: } 680: 681: if (sqlite3_step(ppStmt) != SQLITE_DONE) 682: { 683: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 684: return(d_erreur); 685: } 686: 687: if (sqlite3_finalize(ppStmt) != SQLITE_OK) 688: { 689: (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; 690: return(d_erreur); 691: } 692: 693: return(d_absence_erreur); 694: } 695: 696: // vim: ts=4