Persistence State Service ------------------------- The Persistent State Service (PSS) provides a standard way to persistently save the state of objects in a datastore. A datastore is an entity that manages data like a database or a set of files. For TAO's implementation of PSS, the datastore is a normal file, for now. The PSS defines two ways to define the datastore schema and the interfaces to the storage object instances in the datastore. One way is to use the Persistent State Definition Language (PSDL). PSDL language is a superset to the IDL language and introduces four new constructs: storagehome, storagetype, abstract storagehome and abstract storagetype. A PSDL file (which is similar to an IDL file) contain the definitions which describe the interface to the datastore. This psdl interface and the datastore is visible only to the server which saves the state of objects. The clients to this server do not idea about how the server saves the state of the objects and hence have no idea about the psdl interface or the datastore. The PSS implementation provides a compiler tool to process the psdl file and generates stubs (I will use the name 'stub' just for the lack of any other name.. though this stub is not the same as the normal stub that is generated by the IDL compiler). PSDL Compiler ============= TAO's implementation of the PSS provides psdl_tao as the compiler to Design ====== The Input file (of format pidl) is first parsed with the yacc-lex parser. The TAO_PSDL_Interpreter has a method (build_tree) which helps construct an expression tree representing nodes from the tokens returned by the Yacc generated parser. In addition, based on the grammar set in PSDL.yy, any syntax errors are checked by the yacc parser. Using the '-b' (build-tree) option, you can print out the generated parse-tree for debugging purposes. All the classes in PSDL_Node help build the parse tree. (@@ To-do: I should be adding an option to the executable so that the parse tree can be printed out when the option is set.) Along with the basic parsing, we build the symbol table. The TAO_PSDL_Scope class is the base class which helps add each type (like interface, exceptions etc) to the symbol table. The symbol table is constructed using the ACE hash maps. We use two kinds of hash-maps...one maps the identifier to a structure (Node_Info) which has information about the identifier (identifier_type, module_name & interface_name (module and interfaces to which this identifier belongs). This is used in cases where in the identifier doesnt have some members in itself.. constant declarations, typedefs, exceptions with no members etc. Unlike a simple declaration or a typedef, types like interfaces have member declarations which come with their scope. For example, an interface has its own set of declarations, methods, interfaces etc. For such types, we will have a class derived from base TAO_PDSL_Scope. [In the case of interfaces, it is TAO_PSDL_Interface_Scope.] The second hash map is to map the identifier and the instance of the identifier's type... i.e. say the identifier is of type interface, this hash-map has a mapping between the identifier and the pointer to the instance of TAO_PSDL_Interface_Scope. [All the TAO_PSDL_*_Scope classes fall in this category.] In this phase, along with building the symbol table, we also do the semantic checking. Semantic checking includes checking if an identifier that is declared before is now being redeclared. Identifiers are case-sensitive and case-insensitive too... ie. for ex: You cannot have CosNaming and cosnaming. After the symbol tables are built, the next step is to generate code in to the stubs. The classes TAO_PSDL_*_Visitor generates this code. TAO_PSDL_Node_Visitor is the base class and the derived classes override the necessary methods. So, if you want to generate for some other type in future, we need to have another of TAO_PSDL_*_Visitor class and override the necessary virtual method. Implementation files of the stubs (idlC.cpp) ================================= The generation of the header and implementation files for the stubs can be done in a single pass. The implementation files mainly involves the '<<' and '>>' operator support. These operators support will be mainly useful while marshalling and demarshalling the data types. Status in a summary. ======= 1. Can parse any psdl file. 2. Does syntax checking. 3. Can build parse tree for most but not all of the types. 4. Builds ASTs for the basic types which includes typedefs, interfaces, structs, modules, exceptions, constant declarations. 5. Generate the code that goes into the header file for the same types listed above. Files and Description ===================== PSDL.yy Yacc file which has the PSDL grammar. PSDL_y.cpp PSDL_y.h Yacc generated files. PSDL_l.cpp Lex generated file. PSDL_Node.h PSDL_Node.cpp Each node in the parse tree is derived from the base type TAO_PSDL_Node. The classes in this file provide the interface for the different types. Each class will have accessor methods to access the private members and an accept method to invoke the corresponding visitor method. (We are applying the visitor pattern here.) PSDL_Scope.h PSDL_Scope.cpp PSDL_*_Scope.* The classes in these files are useful for building the AST. TAO_PSDL_Scope is the base class and there are classes for each type (which has members in it, ex: interface) which needs to be added to the AST which derive from TAO_PSDL_Scope. PSDL_Node_Visitor.h PSDL_Node_Visitor.cpp PSDL_*_Visitor.* TAO_PSDL_Node_Visitor acts as a base class useful for generating code into stubs. TAO_PDSL_Node_Visitor derives from TAO_PSDL_Scope_Visitor. The sub-classes (for the different types) which need to override the basic functionality of the visitor methods in TAO_PSDL_Node_Visitor derive from it and override accordingly. The derived classes methods are invoked from the base class as needed making use of the factory pattern (TAO_PSDL_Visitor_Factory). To-Do ==== 1. The visitor classes should generate the code into a file and not to stdout as I am doing now. 2. Support for comments , pragmas etc. Right now, if you have comments or pragmas, its going to fail. Test ==== % ./psdl_tao < trial_idl.idl Things to do ============ 1. Have a test to include all the existing types. Should check the generated code and check if it is the right thing. - 2 days 2. Work on the stubs. . Redirect the output to a file rather than to stdout. . Work on the implementation files (*C.cpp). This will be based on ACE Reliable Multicast framework. ps: Bala told last friday that ACE Reliable Multicast Framework has several bugs. So, this might end up taking longer. FYI, - 2 weeks. 3. Have a test/example for the total framework. 1 week- 10 days - Have an application which is going to use the PSS framework.. have a server etc. 4. Additional Documentation as needed including . Steps for modifying the existing services to use PSS. 1 week. 5. Include support for all the types in PSDL language in all the stages which includes mainly . Building the parse tree . While building ASTs . Generating the stubs. 6. Extend the tests to include all the new types. IMR === 1. Test 2. Documentation abt the differences between old and new IMR. 3. How to update/migrate to the new IMR. 4. Code review. 2 days 5. modift 2 days. MInor things ============ 1. Print out the Caps of the names #if !defined (_TRIAL_INTERFACE___PTR_CH_) instead of #if !defined (__trial_interface___PTR_CH_) 2. Check out TAO_NAMESPACE_STORAGE_CLASS and static nad extern storage classes before _tc_* Notes on how to proceed ======================= 1. Serialize the data using TAO_OutputCDR. The implementation files should have the '<<' and '>>' methods. 2. There needs to be another executable or library which would be actually saving the state of objects to the database. Since RMCast is not working right now, we can save the data to a file and retrieve from it. Example ======= 1. Have a mini naming idl which just has the bind and find functions support. There can be just a server.cpp which will bind information. 2. Have a psdl interface which has a sequence of struct (name, stringified_ior). When a bind is done, it has to be going through the helper classes and inserted into a hash_map and saved to the file. And when find is invoked, it has to be read from the file and demarshalled.