Pagina Principale   Moduli   Lista dei namespaces   Gerarchia delle classi   Lista in ordine alfabetico   Lista dei composti   Lista dei files   Membri dei namespaces   Membri dei composti   Membri dei files   Esempi  

/home/fbassi/devel/projects/reti/ObjectManager/ObjectManager_i.cc

Vai alla documentazione di questo file.
00001 /*
00002  *    FBFS Distributed Object Repository
00003  *    Copyright (C) 2001 Francesco V. Bassi
00004  *
00005  *    This program is free software; you can redistribute it and/or modify
00006  *    it under the terms of the GNU General Public License as published by
00007  *    the Free Software Foundation; either version 2 of the License, or
00008  *    (at your option) any later version.
00009  *
00010  *    This program is distributed in the hope that it will be useful,
00011  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *    GNU General Public License for more details.
00014  *
00015  *    You should have received a copy of the GNU General Public License
00016  *    along with this program; if not, write to the Free Software
00017  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00025 #include "ObjectManager_i.h"
00026 #include "../utils/URI.h"
00027 #include "../utils/NameServer.h"
00028 #include "../utils/TimeStamp.h"
00029 #include "../utils/Rand.h"
00030 #include "../idl/Storage.hh"
00031 #include "../Object/Properties.h"
00032 
00033 #include <iostream.h>
00034 
00035 using namespace fbfs;
00036 using namespace utils;
00037 
00038 fbfs::ObjectManager_i::ObjectManager_i(const utils::Prefs &p, const CORBA::ORB_ptr &o)
00039         : prefs(p), orb(o) {
00040         
00041         // Scandisco il file con l'elenco degli hosts e riempio la struttura servers.
00042         ifstream file;
00043         file.open(prefs.get("hostfile", "objectmanager-server.hosts").c_str());
00044         while(!file.eof()) {
00045             string s;
00046             file >> s;
00047             URI uri(s);
00048             if(uri.isValid())
00049                 servers.push_front(s);
00050         };
00051 
00052         // Eseguo la funzione di convalida degli Storage e di preparazione della
00053         // struttura Repository.
00054         validate();
00055 
00056         // Ora rep contiene il repository aggiornato e consistente.
00057         // Posso attivare il servizio.
00058 };
00059 
00060 char *fbfs::ObjectManager_i::lookup(const Security &cert, const Obj_id &id)
00061         throw(NotFound, SecurityException, InternalError) {
00062     string name(id.name);
00063     lock.lock(name);
00064     
00065     if( rep.count(name) == 0 ) {
00066         lock.unlock(name);
00067         throw NotFound();
00068     };
00069     
00070     Servers &s = rep[name];
00071 
00072     if( s.size() < 1 ) {
00073         lock.unlock(name);
00074         throw InternalError();
00075     };
00076 
00077     // Sceglie tra i server quello più opportuno. Potrebbe essere effettuato
00078     // secondo politiche di vicinanza, per esempio analizzando il certificato
00079     // di identità del richiedente.
00080     // Qui: scelta casuale tra i server disponibili.
00081     int n = utils::rand(s.size());
00082     Servers::iterator i = s.begin();
00083     while(n-->0)
00084         i++;
00085     lock.unlock(name);
00086     return strdup((*i).c_str());
00087 };
00088 
00089 void fbfs::ObjectManager_i::remove(const Security &cert, const Obj_id &id)
00090         throw(PartialExecution, NotFound, SecurityException, InternalError) {
00091     string name(id.name);
00092     lock.lock(name, true);
00093     
00094     if( rep.count(name) == 0 ) {
00095         lock.unlock(name);
00096         throw NotFound();
00097     };
00098     
00099     Servers &s = rep[name];
00100 
00101     if( s.size() < 1) {
00102         lock.unlock(name);
00103         throw InternalError();
00104     };
00105 
00106     // Devo contattare ogni server, cancellare l'oggetto da ogniuno di essi
00107     // ed alla fine rimuovere l'entry da rep.
00108 
00109     // Politica in caso di guasti: cerco di cancellare l'oggetto da ogni
00110     // Storage collegato. Se qualcuno dà errore, proseguo fino alla fine
00111     // con gli altri Storage e ritorno InternalError().
00112     bool failed = false;
00113     
00114     for(Servers::iterator i = s.begin(); i != s.end(); i++) {
00115         URI uri(*i);
00116         try {
00117             CORBA::Object_var obj = utils::NameServer::get_object(orb, uri);
00118             fbfs::Storage_var server = fbfs::Storage::_narrow(obj);
00119             if(CORBA::is_nil(server))
00120                 throw InternalError();
00121 
00122             server->remove(cert, id);
00123         } catch (...) {
00124             // Attenzione: in questo caso maledetto il repository può essere in
00125             // uno stato inconsistente.
00126             failed = true;
00127         }
00128     }
00129     rep.erase(name);
00130     lock.unlock(name);
00131     
00132     if(failed)
00133         throw PartialExecution();
00134 };
00135 
00136 void fbfs::ObjectManager_i::put(const Security &cert, const Obj_id &id, const Obj &o, const Obj_prop &p)
00137         throw(PartialExecution, AlreadyPresent, SecurityException, InternalError) {
00138 
00139     string name(id.name);
00140     lock.lock(name, true);
00141     
00142     // Verifico che l'oggetto non sia già nel repository
00143     if(rep.count(name) != 0) {
00144         lock.unlock(name);
00145         throw AlreadyPresent();
00146     };
00147         
00148     // Genero una struttura Obj_ts per l'oggetto.
00149     Obj_ts ts;
00150     ts.time = utils::TimeStamp::current();
00151     
00152     // Stabilisco da Obj_prop la politica di replicazione e la metto in atto.
00153     switch(p.type) {
00154         case Properties::DONT_SAVE :
00155             break;
00156         case Properties::REPLICATE_ON_CREAT :
00157         case Properties::REPLICATE_ALWAYS :
00158         case Properties::REPLICATE_MIN_MAX :
00159         {
00160             int ns = servers.size();
00161             int n = p.value_a;
00162             if(n>ns)
00163                 n=ns;
00164             // itemserver sarà l'elenco dei server che contengolo l'oggetto desiderato.
00165             Servers itemservers;
00166             
00167             // Metto gli oggetti nei server, scandendo in modo ciclico la lista.
00168             // Se arrivo in fondo, riparto dall'inizio.
00169             Servers::iterator i = servers.begin();
00170             for(int skip = utils::rand(servers.size()); skip-- > 0; i++);
00171             bool failed = false;
00172             while(n--) {
00173                 const string &s = (*i);
00174                 URI uri(s);
00175             
00176                 // Contatto il server "s" e cerco di mettergli dento l'oggetto
00177                 // desiderato.
00178                 try{
00179                     CORBA::Object_var obj = utils::NameServer::get_object(orb, uri);
00180                     fbfs::Storage_var server = fbfs::Storage::_narrow(obj);
00181                     if(CORBA::is_nil(server))
00182                         throw NotFound();
00183                     server->put(cert, o, id, p, ts);
00184                     itemservers.push_front(s);
00185                 } catch (...) {
00186                     // Potrei ritentare su altri server, ma la cosa indurre
00187                     // deadlock difficilmente gestibili.
00188                     // Meglio rinunciare. 
00189                     failed = true;
00190                 };
00191                 // Incrementa l'iterator, ricominciando da capo se la lista è finita.
00192                 i++;
00193                 if(i == servers.end() )
00194                     i = servers.begin();
00195             };
00196             
00197             // Nessun oggetto messo nel repository
00198             if(itemservers.size()==0) {
00199                 lock.unlock(name);
00200                 throw InternalError();
00201             }
00202                 
00203             // In questo caso la creazione non rispecchia le necessità imposte.
00204             // Cancello l'oggetto dagli Storage che ce l'hanno e ritorno InternalError.
00205             if(p.type == Properties::REPLICATE_MIN_MAX && itemservers.size() < p.value_b) {
00206                 Servers::iterator i = itemservers.begin();
00207                 while(i != itemservers.end()) {
00208                     URI uri(*i);
00209                     try {
00210                         CORBA::Object_var obj = utils::NameServer::get_object(orb, uri);
00211                         fbfs::Storage_var server = fbfs::Storage::_narrow(obj);
00212                         if(CORBA::is_nil(server))
00213                             throw InternalError();
00214                         server->remove(cert, id);
00215                     } catch (...) {};
00216                 };
00217                 lock.unlock(name);
00218                 throw InternalError();
00219             };
00220 
00221             // Metto la coppia [oggetto . lista dei server] nel repository.
00222             rep[name] = itemservers;
00223             
00224             if(failed) {
00225                 lock.unlock(name);
00226                 throw PartialExecution();
00227             };
00228             break;
00229         };
00230         default:
00231             lock.unlock(name);
00232             throw InternalError();
00233     };
00234     lock.unlock(name);
00235 };
00236 
00237 void fbfs::ObjectManager_i::reparse(const Security &cert) throw(SecurityException) {
00238 };

Generato il Thu Feb 15 13:24:56 2001 per A Simple Distributed Object Repository with CORBA & C++. da doxygen1.2.3 scritto da Dimitri van Heesch, © 1997-2000