Toggle Theme Editor
Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Charcoal

O O D B Design And Implementation - Part 3 -

Discussion in 'Java Update' started by Joe, 11/1/20.

  1. Joe

    Joe Thành viên VIP

    Hi

    (cont. of Part 2)

    ODB Infrastructure on the Client site
    The most optimal Database design is the Client/Server (C/S) design. Herein the clients are physically "segregated" from the direct accessing to the DBs which are under control of a DB server. This architectural feature guarantees the independency of DB from any direct manipulation carried by the clients -intended or unintended. And the Clients are immune against any kind of problems on the server site. Both sites are happy and stay independent from each other's problems.

    Nevertheless the Clients must be somehow qualified for some certain activities such as Delete/Update/Create/etc. Authentication with Password and UserID is the most popular and the most reliable technique in a C/S environment. We don't try to complicate the matter (Kalashnikov Principle), but work with this "tested" technology: Password-UserID. So, the first infrastructure on the Client site is the User-Creditability which is in form of:
    • Read. The basic right (0). The lowest privilege. Users with this privilege can only view (READ) the objects.
    • Write (or update). The next higher level (1). Users with 1-privilege can not only view, but also modify (UPDATE) the objects.
    • Delete (and Create). The highest level (2) or the highest privilege for a user. With this privilege (s)he has all the rights: view, modify and remove (DELETE) objects. DELETE means also CREATE. If a user with this privilege opens an ODB (file) which is nonexistent ODManager will create an empty ODB on his/her local ODB Server.
    The 3 basic rights are the principle activities for an ODB-API for the clients. And we have to provide this ODB infrastructure on the client site. Beside the 3 types of privilege for the users UserList must provide a Superuser privilege for the maintenance tasks on the ODB Server site. In case of problems (e.g. loss/oblivion of Superuser Password or ID) UserList must be able to recreate a new UserList with the default Superuser with the Password system and the ID admin (both are case sensitive) and the facility to recover the rest of the users of the "old" UserList. However, this default Superuser cannot access the ODB. How? I'll explain the implementation in the next section.
    1. An authentication process that works on both sites (Client-Server) and provides the clients these basic rights (0, 1 and 2).
    2. An API that allows the Client-App to plug-in and to work with the desired ODB on the server site.
    In the previous sections we've learned that OO Data and Object are inseparable. That requires an existence of all working objects on the Client site. And they are the JAVA classes. The OO Data are on the Server site, their "shuck" (or class) is on the Client site. Due to following reasons why JAVA classes shouldn't be included in ODB:
    • they could include some inner classes,
    • they are parts of an external or internal package,
    • they must be known during the compiling phase. Casting during the runtime requires also their explicite existence,
    • reflection could lead to security leaks (access to private fields or methods).
    And developers who created the apps usually possess the compiled classes before the apps were packaged and distributed to the users (clients).

    The following UserList API that works on both sites should provide the following basic methods (YOU should try to implement this UserList):
    PHP:
    Package joodb
    Class UserList
     
        Object joodb
    .UserList
     
        
    public class UserList extends Object
     
        Constructors Constructor     Description
     
        UserList
    (String file)        Contructor.
     
        
    Modifier/Type      Method                                         Description
     
        boolean            addUser
    (String pwString uidint right)      add new User
        boolean            deleteUser
    (String uid)                         delete User
        ArrayList
    <String>  getUserList(String pwString uid)             getUserList a list of all Users.
        
    int                getUserPrivilege(String pwString uid)        getUserPrivilege()
        
    boolean            isSuperuser(String pwString uid)             isSuperuser
        boolean            isUser
    (String pwString uid)                  isUser
        void               recover
    (String path)                           recover Userlistrecover a Userlist with the default Superuser PW:systemID:admin
        void               save
    ()                                         Save userlist in the give path (see Constructor)
        
    boolean            updateUser(String uidString pwOLDString pwNEWupdate User Password
                                                                          
    (used by users to change their PW)
        
    boolean            upgradeUserPrivileg(String suPWString suID,  upgrade User Privilege (used by Superuser)
                                               
    String uidint newPriv)   
    The UserList API is naturally maintained and kept on the Server site. I show the UserList here because of the user or client's right on the Client site.

    Note: for the ease of use (Kalashnikov) the UserList must be "pegged" on a fixed name without suffix. In my implementation it's the name "userlist". The storing of user data must be encrypted, too. Encryption/Decryption is only "foolproof" if the encrypting/decrypting technique is known only by YOU yourself. Otherwise it's the question of time that your technique will be broken. In the Source-bundle you won't find the source EnDecrypt.java. But a dummy EnDecrypt.java and you have to develop the two declared methods on your own.
    PHP:
    public class EnDecrypt {
      
    /**
        decrypt an encrypted String
        @param inp String to be encrypted
        @param ext boolean, true for Extended encrypting (used for Networking), false for local UserList
        @return decrypted String (null if invalid inp)
      */
      
    public static String decrypt(String inpboolean ext) {
        return 
    inp;
      }
      
    /**
        decrypt() a String
        @param inp String to be decrypted
        @param ext boolean, true for Extended encrypting (used for Networking), false for local UserList
        @return encrypted String (null if invalid inp)
      */
      
    public static String encrypt(String inpboolean ext) {
        return 
    inp;
      }
    }
    The most important part for a functional infrastructure on the Client-Site is the "Plug-In API". Like SQL for RDB Client Applications can only access the ODB via this "Plug-in API". The 3-basic access rights (read/update/delete) are the bases for the implementation. Because we are dealing with the C/S architecture the Plug-In API is here also the (network) communication API.

    Network communication is complex and variable. In the past Networking-Communication is the bottleneck. Even in the 90s a "leased line" with 64 K-bps is an expensive wonder. Today we deal with GB-bps over a public fiber optical line and none of us is aware about it. But some of us become fat (or obese) with demands (more video streaming, more hifi music, more colorful images, etc.) and run into troubles with the "response time". And the networking technology runs pantingly after our demands. Some of us, old codgers, still work with "Socket" while SocketChannel is available since years. What is the difference between Socket and SocketChannel, anyway?

    As I've already mentioned about the "expensive wonder of 64 Kbps" Socket is the replacement of TTY which stands for "teletypewriter". A Technology of Alexamder Bell's [​IMG] epoch. A bit-wise communication. And this technique still mints the communication of today: bit-wise. Socket works bit-wise, too.
    [​IMG]
    [​IMG]
    (source: Oracle)

    Further, modern networking still bases on the "age-old US military designed TCP/IP" as memory was as precious as gold: the max buffering was (and still is) 32768 bytes. Meager, isn't it? SUN, swallowed by Oracle, implemented the so-called "New IO (nio)" technology in order to overcome the sluggish bitwise communication. There are FileChannel and SocketChannel. Both work block-wise as the computer today does: in block of 4KB (Windows or Linux). It's obvious that blockwise is faster than bitwise (or bytewise). You want some evidences? Well, let check the source of InputStream and OutputStream (the IO of Socket):
    PHP:
    // InputStream
        
    public int read(byte b[], int offint lenthrows IOException {
            if (
    == null) {
                throw new 
    NullPointerException();
            } else if (
    off || len || len b.length off) {
                throw new 
    IndexOutOfBoundsException();
            } else if (
    len == 0) {
                return 
    0;
            }
     
            
    int c read();
            if (
    == -1) {
                return -
    1;
            }
            
    b[off] = (byte)c;
     
            
    int i 1;
            try {
                for (; 
    len i++) {
                    
    read();
                    if (
    == -1) {
                        break;
                    }
                    
    b[off i] = (byte)c;
                }
            } catch (
    IOException ee) {
            }
            return 
    i;
        }
    //--------------------------------------------------------------------------
    // OutputStream
        
    public void write(byte b[], int offint lenthrows IOException {
            if (
    == null) {
                throw new 
    NullPointerException();
            } else if ((
    off 0) || (off b.length) || (len 0) ||
                       ((
    off len) > b.length) || ((off len) < 0)) {
                throw new 
    IndexOutOfBoundsException();
            } else if (
    len == 0) {
                return;
            }
            for (
    int i len i++) {
                
    write(b[off i]);
            }
        }
    Both Read and Write work bitwise. Let verify the SocketChannel
    PHP:
        public abstract int read(ByteBuffer dstthrows IOException;
     
        public abstract 
    long write(ByteBuffer srcthrows IOException;
    Both Read and Write are abstract and must be implemented depending on the underlying hardware. And ByteBuffer? It's the new basic Buffering block of NIO.

    Our next implementation for the Client infrastructure is the Networking API that bases on SocketChannel. Try to implement this API. The requirements are:
    PHP:
    Package joodb
    Class ODBConnect
     
        Object
            joodb
    .ODBConnect
     
        
    public class ODBConnect extends Object
     
        Object Data Connect
     
            Constructor Summary
            Constructors Constructor                                                  Description
            ODBConnect
    ()                                                              Empty contructor
            ODBConnect
    (String dbHostint portString pwString uID)                contructor
     
            Method Summary
            Modifier 
    and Type      Method                                             Description
            void                   add
    (String dbNameString keybyte[] obj)         add object
            void                   add
    (String dbNameString keyObject obj)         add object
            void                   close
    (String dbName)                               close.
            
    boolean                commit(String dbName)                              commit
            boolean                commit
    (String dbNameString key)                  commit
            void                   connect
    (String dbName)                             connect to ODB Server
            void                   delete
    (String dbNameString key)                  delete object
            void                   disconnect
    ()                                       disconnect the connection to OODB Server and closes all opened DBs
            byte
    []                 getByteArray(String dbNameString key)            getBytes byte array (of object)
            
    ArrayList<String>      getClusterKeys(String dbNameString node)         getClusterKeys returns cluster keys of dbName
            String                 getID
    ()                                            getID of this connection
            ArrayList
    <String>      getKeys(String dbName)                             getKeys returns all keys of dbName
            ArrayList
    <String>      getLocalKeys(String dbName)                        getLocalKeys returns local keys of dbName
     
            
    protected joodb.ODBResult getResult(String dbNameByteArrayOutputStream bao)
            
    boolean                isExisted(String dbNameString key)              isExisted
            boolean                isLocked
    (String dbNameString key)               isLocked
            boolean                lock
    (String dbNameString key)                   lock key.
            protected 
    void         panicShutdown()
            
    Object                 read(String dbNameString key)                   read object
            boolean                rollback
    (String dbName)                           rollback ALL modified objects
            boolean                rollback
    (String dbNameString key)               rollback
            void                   save
    (String dbName)                               save.
            protected 
    joodb.ODBResult send(String dbNameString cmdString key)
            protected 
    joodb.ODBResult send(String dbNameString cmdString keyObject obj)
            
    boolean                transAction(String dbNameString actionString keyObject object)  transAction starts a Transaction and completes a commit if nothing happened in-between
            boolean                unlock
    (String dbName)                            unlock all locked keys of this dbName
            boolean                unlock
    (String dbNameString key)                unlock key
            void                   update
    (String dbNameString keybyte[] obj)    update object
            void                   update
    (String dbNameString keyObject obj)    update object
    The Constructor ODBConnect(String dbHost, int port, String pw, String uID) contains ONE sensitive field: the Password. Therefore the mentioned EnDecrypt.java is involved with the boolean variable ext which is set to the value true.

    OO data can be "big". Very big. To relieve the traffic on the net we should use the proven technology which works splendidly with the HTTP/HTTPS. It's the GZIP technology. OO Data are "gzipped" before they can be put on the net.

    The basic ODBConnect API will serve as the base for further extensions. We are dealing with a very precarious approach: the load-balancing between Client and Server. The question is "where should the load be carried?" On the Server site or on the Client site? I decided to put the post-processing part on the Client site. Two reasons:
    • ODB Server has to serve numerous clients. So, it shouldn't be forced to do some post-processing works for its clients. And that could severely degrade the performance of ODB Server.
    • Client computer is nowaday quite powerful, and the (web)net is fast enough to transfer (all) the needed OO Data for the post-processing such as Data Mining. And that reduces considerably the load on the Server site.
    I provide an API ODBMining for the Client site as an example so that YOU (or the licencees) could take it as a pattern to develop your own API for data mining purposes.
    PHP:
    Package joodb
    Class ODBMining
     
      Object
        joodb.ODBConnect
          joodb.ODBMining
     
     
      public class ODBMining extends joodb.ODBConnect
     
        Constructor                                                    Description
        ODBMining(String dbHost, int port, String pw, String uID)      Contructor, open a connection to ODB-Server
     
        Modifier and Type   Method                                     Description
        ArrayList<Object>   allObjects(String dbName)                  allObjects of the specified ODB.
        ArrayList<Object>   allObjects(String dbName, String clsName)  allObjects.
        String              getClassName(String dbName, String key)    getClassName.
        ArrayList<String>   getFieldNames(String dbName, Class<?clsgetFieldNames.
        
    ArrayList<String>   getFieldNames(String dbNameObject obj)   getFieldNames.
        
    ArrayList<String>   getFieldNames(String dbNameString key)   getFieldNames.
        
    ArrayList<Object>   selectAll(String dbNameString pat)       SelectAll.
        
    ArrayList<Object>   selectAll(String dbNameString compdouble cValselect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"EQ"123.456);
        
    ArrayList<Object>   selectAll(String dbNameString compfloat cValselect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"EQ"123.456f);
        
    ArrayList<Object>    selectAll(String dbNameString compint cValselect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"LE"123);
        
    ArrayList<Object>    selectAll(String dbNameString complong cValselect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"GT"123456);
        
    ArrayList<Object>    selectAll(String dbNameString compshort cValselect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"EQ"123);
        
    ArrayList<Object>    selectAll(String dbNameString vNameString patselect all objects with a vName that matches the pattern.
        
    ArrayList<Object>    selectAll(String dbNameString vNameString compdouble cValSelect all objects that match the criterion of value
                                                                       Example
    selectAll(dbNamesalary"EQ"123.456);
        
    ArrayList<Object>    selectAll(String dbNameString vNameString compfloat cVal)  Select all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"Salary""EQ"123.456);
        
    ArrayList<Object>    selectAll(String dbNameString vNameString compint cValSelect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"age""LT"50);
        
    ArrayList<Object>    selectAll(String dbNameString vNameString complong cValSelect all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"Salary""GE"123456);
        
    ArrayList<Object>    selectAll(String dbNameString vNameString compshort cVal)  Select all objects that match the criterion of value
                                                                       Example
    selectAll(dbName"age""EQ"50);
     
    (Next:OODB Infrastructure on the Server site)
     
    Last edited: 12/1/20

Chia sẻ trang này

Loading...