1.ProudNet Database Cache System version 2

Warning : DBCache 2 only works on Windows.

Characteristic of game database is “small amount of transaction but a lot of accessing attempt” and almost all data are doing save and load repeatedly.

ProudNet Database Cache System version 2 reduce database access with get cached those steps. It means, it reduces overload of database.

First you need to understand 1.1 Understanding DB cache as theoretically.

ProudNet Database Cache System version 2 is divided into 1.2 Game database schema for DB cache and 1.3 DB cache client and server. First, install 1.2 Game database schema for DB cache then manage your database using 1.3 DB cache client and server.

The basic steps are explained in 1.4 DB cache ver.2 Basic Usage. And in 1.5 Using DB Cache, you can find all the details of 1. ProudNet Database Cache System version 2.

1.1Understanding DB cache as theoretically

Data structure that can get DB cached

Usually data has tree structure that saved in game database. ProudNet Database Cache System version 2 is designed for that. ProudNet Database Cache System version 2 handle data with “tree”

그림 1-1Example of saving user account data in DB

This tree is divided into nodes. Of course each nodes has parents/child relation and each nodes has name-parameter pair (Property field) This tree corresponds to database as followed.

From loaded Tree

From database

”1” Node

”1” Record

Type of Node

Name of Table

Property that Node owned

Fields in the record

Parent/Child relation of Node

Required filed in the record

그림 1-2“Table structure for saving user account information to DB”

Table name in root node and table name in child node must be different on top node of data tree that ProudNet Database Cache System version 2 loaded.

Pattern of accessing DB Cached data

Exclusive data loading is a basic usage in DB cache. Please refer to Exclusive Load for more detail.

ProudNet Database Cache System version 2 provide accessing pattern as followed.

Access Pattern

Example

Get cached

Immediately return

Require exclusive loading

Internal process form

Change a data unilaterally

Change player character information frequently during game play

YES

YES

YES

Get Cached in memory then write in DB

Change request responding type data

Create new player character with unique name

NO

NO

YES

When write in DB is succeed then get cached in memory

Accessing non-exclusive data

Buy charge item from web server

NO

NO

NO

When write in DB is succeed then get cached in memory

Exclusive Load

At DB cache system, only 1 DB cache client is allowed to proceed with same data loading. This method is called exclusive load.

The purpose of exclusive load is to avoid 5.4 Race Condition.

DB Cache System transfers the right of exclusive use when a DB Cache Client requests the exclusive use while another DB Cache Client is exclusively using.

The way is as in the following.

DB Cache System version 2

The main subject for exclusive load is DB Cache Client.

In case a DB Cache Client does exclusive load while another DB Cache Client is doing exclusive load, old DB Cache Client will be required to transfer the exclusive right and can select either permission or refusal.

At this time, if old DB Cache Client unloads data, new DB Cache Client will have the exclusive right.

그림 1-3The state of Gamer X loaded by Server 2 when it was already loaded by Server 1

Change a data unilaterally

When you do Change a data unilaterally, a data will apply to memory in DB cache immediately.

And applied data will be written in database with in short period time. Therefore it gets cached.

Internal process form when it does Change a data unilaterally.

Processing Change a data unilaterally is return immediately. So when you use Change a data unilaterally, it does not occur waiting time in changing a data routine. Therefore you do not need to wait until it completes changing a data. For example you do not need to “unlock then lock” process as followed.

UpdateSomeData()
{
    lock(X);
    ...
    unlock(X);
    UnilateralUpdateSomeData(X);
    lock(X);
    ...
    unlock(X);
}

However you need to keep in your mind few things. Change a data unilaterally apply in memory of DB cache without any condition. However record that set DB Constraints will not apply changed information on database.

Change request responding type data

Changes will be applied to memory in DB cache then write to database later in Change a data unilaterally. However Change request responding type data works opposite way. It records to database then apply to memory in DB cache.

Request responding type is handling data with Change request responding type data. DB cache client request Change request responding type data to DB cache server and DB cache server do actual writing. And result can check through DB cache client.

Internal process form when you do Change request responding type data

Change request responding type data is not actual cache. However Change request responding type data has immunity when it fails to record a data because of DB Constraints. Because it does not apply changes to DB cache until it succeed to actual writing to database.

Normally Change request responding type data is required such as creating player character with unique name.

Accessing non-exclusive data

Change a data unilaterally and Change request responding type data is only able to change with exclusive loaded data. However sometimes you may need to read or write exclusive loaded data that loaded other DB cache client. For example, you may need to open player character’s information on web server or need to add or change item in inventory of player character on cash item payment server.

In operation tool, you may need to open or change player’s character information that already logged on. Accessing non-exclusive data is a function that for above situation.

All non-exclusive data access works as Change request responding type data type. So it will not respond immediately but it has immunity from DB Constraints.

Internal process form when you do Accessing non-exclusive data

DB cache client with exclusive loaded data will receive information of changing a data once a data has changed non-exclusively.

DB directly has access to data that DB cache deals with.

Data (data in data tree that is loaded by DB cache) in DB cache is latest comparing to data in DB. It is because data is recorded in DB caches first and then it is recorded in DB.

Therefore, if you directly record data in DB irrespective of data tree that DB cache manages, there might be an unexpected error because the status of data in DB is old for a moment. This is similar with data race condition issue.

그림 1-4Data race condition by DB cache vs. DB access

But you might need to directly manage data tree (that DB cache manages) in DB. In this case, ProudNet provides data isolation function in order to avoid data race condition.

Data isolation is the function that deactivates the right of using data tree (that you want) at DB cache so that data race condition cannot be occurred in spite of direct DB access.

그림 1-5Data isolation

The way of use is as below.

그림 1-6Data isolation usage

DB Constraints

It called all blocking thing when specification does not match with requirement.

For example,

Primary Key Unique Index etc ( >, <, =, != )

Constraints realize with Unique Index, Trigger, etc.

1.2Game database schema for DB cache

User can compose database schema for DB cache themselves. But you need to observe rules as followed.

그림 1-7Example of data schema for saving gamer data in MMORPG

< An example Script for adding three essential fields >

ALTER TABLE dbo.Gamer ADD CONSTRAINT

PK_Gamer PRIMARY KEY CLUSTERED

(

UUID

) WITH( IGNORE_DUP_KEY = OFF) ON [PRIMARY]


CREATE INDEX IX_Gamer_OwnerUUID ON dbo.Gamer

(

OwnerUUID

) WITH( IGNORE_DUP_KEY = OFF) ON [PRIMARY]


CREATE INDEX IX_Gamer_RootUUID ON dbo.Gamer

(

RootUUID

) WITH( IGNORE_DUP_KEY = OFF) ON [PRIMARY]

Creating a sample database

Creating a sample MS SQL Server database

First, you need to create an instance for sample game database. For this, one of MS SQL Server 2000, 2005 and 2008 must be installed. Available on MS SQL Server 2005 and 2008 Express Edition. You can download these programs from Microsoft official website.

Once MS SQL Server is installed, you need to create the database instance whose name is same as the sample that is going to be used. The table below is about database name per each sample & the location of the relevant DB schema.

Sample

Database

DB Schema Path

Casual Game 2

ProudDB2-TEST

<installed folder>//ProudNet/Samples/DbmsSchema/ProudDB2

Log-Test

<installed folder>//ProudNet/Samples/DbmsSchema/Logon&DBLog

DbLogViewer

Log-Test

<installed folder>//ProudNet/Samples/DbmsSchema/Logon&DBLog

RealtimeSocialVille

ProudDB-Sng

<installed folder>//ProudNet/Sample/RealtimeSocialVille/SngDb

SimpleAdo

ADO_Test2

<installed folder>//ProudNet/Samples/DbmsSchema/SimpleAdo

SimpleAdoImage

Ado_ImageTest

<installed folder>//ProudNet/Samples/DbmsSchema/SimpleAdoImage

SimpleAdoMysql

prouddb-test

<installed folder>//ProudNet/Samples/DbmsSchema/SimpleAdoMysql

SimpleAdoXmlField

test

<installed folder>//ProudNet/Samples/DbmsSchema/SimpleAdoXmlField

SimpleDB2

ProudDB2-Test

<installed folder>//ProudNet/Samples/DbmsSchema/ProudDB2

SQL Network setting of Server 2005, Setting SQL Server 2008 Network should be done in case of SQL Server 2005 version or a version over SQL Server 2005.

And then, you need to install DB Schema.

• Create the database instance that sample uses first and if not familiar with SQL Server, please ask Part XIV. Nettention Technical Support.

• As referring to the table above, create DB schema by executing each .sql file.

When you complete creating a database as guided in above, you may be able to see the following format.

그림 1-8Example of sample database installation completion (SQL Server 2008)

SQL Network setting of Server 2005

These settings are only applicable when using SQL Server 2005. SQL Server 2005 or higher version is set not to receive any connection by default. Without overriding such setting, you may not be able to access SQL Server 2005.

First, run the program shown in below at Startup menu.

그림 1-9Configuring SQL Server Exposure Area

Select “OK” for “Accept local or remote connection”.

그림 1-10Accepting SQL Server Connection

When needed, you need to set the firewall setting as well.

그림 1-11Setting Windows firewall

Setting SQL Server 2008 Network

These setting are applicable to only SQL Server 2008. SQL Server 2008 or higher version doesn't allow any connection unless the guided settings are applied.

First, run the program shown in below from Startup menu.

그림 1-12Running SQL Server Configuration Manager

Select “Ok” for “Accept local or remote connection.”.

그림 1-13Setting TCP/IP, Named Pipes as Enabled

When needed, you need to set for firewall setting as well.

그림 1-14Setting Windows firewall

Creating a sample MySQL database

First, you need to generate an instance for sample game database. In order to do this, you need to have MySQL installed in your system. The current version is based on MySQL 5.1. You need to download or purchase MySQL from http://www.mysql.com. (Alert! MySQL is a premium software that you need to purchase if you are using it for any commercial purposes. Please contact MySQL if you have any licensing related questions.)

If you want to use MySQL more easily in GUI environment, we recommend you to use it together with tools like SqlYog and etc. You can either download or purchase SqlYog from http://www.webyog.com.

Install MySQL

그림 1-15Language Setting in MySQL

Now you need to install DB Schema

You may see the following format when you complete in creating a database.

그림 1-16Example of Sample Database Installation Completion.

The generated tables should have fields named as FieldA, FieldB and etc. These fields are only being used in the sample sources so please feel free to remove them if you want.

1.3DB cache client and server

DB cache system of ProudNet Database Cache System version 2 is a sub system that read and writes game database. And since the information in database gets cached in server memory, it can significantly reduce overload of DBMS.

DB cache system is structured in client and server. DB cache server is the only process that can directly access DBMS. Servers like game server and authentication server must have DB cache client. DB cache client connects to DB cache server and indirectly access game DBMS through stored procedure.

그림 1-17Structure of ProudDB Cache Server and Client

DB Cache Server

DB cache server is the only process that can directly access DBMS. The main reason only DB cache server can access DBMS is possibly new information of DB cache has not applied to DBMS yet. So if you want to change information of DBMS that accessing by DB cache, we recommend using Accessing non-exclusive data.

DB Cache Client

DB cache client loads game DBMS’s information of objects. And such information can be read without giving any load to DBMS.

If any edit is made on the information loaded by DB cache client, the edited information gets passed to DB cache server. DB cache system doesn't immediately reflect corrections even though it receives the correction request from DB cache client. Instead, it refreshes values in memory of DB cache server. And finally when it reaches a specific or important time (defined by user), it starts writing in DBMS.

1.4DB cache ver.2 Basic Usage

This section guides how to use ProudNet Database Cache System version 2. The sample programs of this system are available in 4. SimpleDB2 Sample Sample. It is recommended that you refer to 4. SimpleDB2 Sample as going through the guided usage here.

Making database instance for DB cache

To use ProudNet Database Cache System version 2, you need to create game database as schema (or instance). Please refer to Game database schema for DB cache.

If you have any question regarding the procedure, please contact us via Nettention Technical Support for immediate assistance.

Preparing DB Cache 2 Server

Once you generate Game database schema for DB cache, you need to generate ProudDB Cache Server instance. ProudDB Cache Server instance is Proud.CDbCacheServer2 type. It is sufficient enough to have just one ProudDB Cache Server instance between each gamer server. The method that generates ProudDB Cache Server instance is Proud.CDbCacheServer2.New.

When ProudDB Cache Server instance is generated, run Proud.CDbCacheServer2.Start. Parameters that get input at the start up are connection string of accessing DB instance.

Preparing DB Cache2 Client

Each game server(authentication server, game zone sever, lobby server and etc.) must generate DB cache client instance. Run Proud.CDbCacheClient2.New and generate client instance. Type of DB cache client is Proud.CDbCacheClient2.

When instance is generated, try to connect to DB cache server through Proud.CDbCacheClient2.Connect. Connecting attempt should be made asynchronously and connection success or fail result should callback Proud.IDbCacheClientDelegate2.OnJoinDbCacheServerComplete.

DB cache client use CLanClient internally. It is thread pooling type so there are no FrameMove.

If you want to disconnect from DB cache server, all you need to do is destroy CDbCacheClient2 object or call Proud.CDbCacheClient2.Disconnect. At this stage, Proud.IDbCacheClientDelegate2.OnLeaveDbCacheServer gets callback in DB cache client.

How to load exclusive data and add new data

Method for Exclusive Load is Proud.CDbCacheClient2.RequestExclusiveLoadData You need to put condition to fieldname and cmpValue to search a data. Here is an example.

Proud::Guid outSessetionGuid;
Proud::CDbCacheClient2* c = ...;
c->RequestExclusiveLoadData(L"Gamer",L"GamerID",gamername,outSessetionGuid);

Also Proud.CDbCacheClient2.RequestExclusiveLoadNewData method is function that do Exclusive Load. You can use it when you added a data to RootTable. Here is an example.

CPropNodePtr newNode = CPropNodePtr(new CPropNode(L"Gamer"));

newNode->Fields[L"GamerID"] = "Ulelio";

Proud::Guid outSessetionGuid;
Proud::CDbCacheClient2* c = ...;
c->RequestExclusiveLoadNewData(L"Gamer", newNode, outSessetionGuid);

How to change data unilaterally

Method that are doing Change a data unilaterally as followed.

This method apply changes to memory in DB cache then write on DBMS as asynchronously. So this method will return immediately when it called. Also it does not have response method callback.

How to use request response method and blocked method that apply to DBMS first

How to use request response method and blocked method that apply to DBMS first is methodes for Change request responding type data.

This method return immediately when it called. Changes will apply to memory in DB cahce once it finished to write on DBMS,

If it succeed or failed write changes to DBMS, following methods are calling back.

If you want blocked call instead of request response as above, please use methods as followed.

요청 응답형 SessionGuid

이 Session Guid는 한개의 독점 Client들의 식별값입니다.

독점 Client 들이 각각 한개의 Session을 가지게 되고, DB Cache Client는 각각의 Session들을 구분하기 위하여 Guid값을 사용합니다.

요청 시 Output Parameter로 SessionGuid값을 발급받게 되고, 응답 Event의 CCallbackArgs::m_sessionGuid 로 발급받았던 값을 받게 됩니다.

outSessionGuid를 저장하였다가 비교하여 요청한 session을 확인할 수 있습니다.

요청

CDbCacheClient2::RequestExclusiveLoadNewData(String rootTableName, CPropNodePtr addData, Guid &outSessionGuid);

응답

IDbCacheClientDelegate2::OnExclusiveLoadDataFailed(CCallbackArgs args)

요청의 outSessionGuid는 응답의 args.m_sessionGuid와 같습니다.

How to access a data as non-exclusively

To permit nonexclusive access, Proud.CDbCacheServer2StartParameter.m_allowNonExclusiveAccess must be set.

When you call following methods for Accessing non-exclusive data

It will try apply to DBMS then calling back result through following methods

Once it succeed changing a data non-exclusively, changes will notice to DB cache client who loaded a data exclusively first. For notice, follwoing methods are calling back

Let me match each request with the proper response to display nicely.

Proud.CDbCacheClient2.RequestNonExclusiveSnapshotData : Getting a snapshot

// response:
IDbCacheClientDelegate2::OnNonExclusiveSnapshotDataSuccess (CCallbackArgs args)
IDbCacheClientDelegate2::OnNonExclusiveSnapshotDataFailed (CCallbackArgs args)

Proud.CDbCacheClient2.RequestNonExclusiveAddData : Adding a data

// response:
IDbCacheClientDelegate2::OnNonExclusiveAddDataAck (CCallbackArgs args)
// Monopolized DB Cache Client's Callback Event:
IDbCacheClientDelegate2::OnSomeoneAddData(CCallbackArgs& args)

Proud.CDbCacheClient2.RequestNonExclusiveRemoveData : Eliminating a data

// response:
IDbCacheClientDelegate2::OnNonExclusiveRemoveDataAck (CCallbackArgs args)
// Monopolized DB Cache Client's Callback Event:
IDbCacheClientDelegate2::OnSomeoneRemoveData (CCallbackArgs& args)

Proud.CDbCacheClient2.RequestNonExclusiveModifyValue : Let some instruction to a data (+, -, *, /)

// response :
IDbCacheClientDelegate2::OnNonExclusiveModifyValueSuccess (CCallbackArgs args)
IDbCacheClientDelegate2::OnNonExclusiveModifyValueFailed (CCallbackArgs args)
// Monopolized DB Cache Client's Callback Event:
IDbCacheClientDelegate2::OnSomeoneModifyValue (CCallbackArgs& args)

Proud.CDbCacheClient2.RequestNonExclusiveSetValueIf : Compare the two values and request to store the values.

// response :
IDbCacheClientDelegate2::OnNonExclusiveSetValueIfSuccess (CCallbackArgs args)
IDbCacheClientDelegate2::OnNonExclusiveSetValueIfFailed (CCallbackArgs args)

// Monopolized DB Cache Client's Callback Event:
IDbCacheClientDelegate2::OnSomeoneSetValue (CCallbackArgs& args)

Things you need to attention when you use DB cache

This is attention thing when you use mixture of How to change data unilaterally, How to use request response method and blocked method that apply to DBMS first and How to access a data as non-exclusively.

If someone uses How to change data unilaterally, Proud.IDbCacheClientDelegate2.OnAccessError is possibly calling back during How to use request response method and blocked method that apply to DBMS first or How to access a data as non-exclusively is running.

Mixing ProudDB cache system and ADO

You can mix 1. ProudNet Database Cache System version 2 and 2. ADO Wrapper API together as long as they follow the rules.

Need special attention to the followings when a user directly deals with a table that is exclusively accessing at 1.3 DB cache client and server.

Please refer to DB directly has access to data that DB cache deals with.. as an alternative plan

1.5Using DB Cache

Controlling DB Cache behavior

Parameter setting of DB Cache is like a double-bladed sword. If the period of writing cached DB data on DBMS is short then it would reduce the performance rate of DBMS but in return, it also reduces the chance of risking data-loss when DB cache server inappropriately shuts down (sudden power outage or else). The related method to this is Proud.CDbCacheServer2.SetDbmsWriteIntervalMs.

When gamer data is unloaded from DB cache client after its use, the associated gamer data remains in memory of DB cache server. And when a certain time passes, it ceases to exist from DB cache server memory. Shorter you set the time of this process would give more usable memory in DB cache server. And it also reduces the number of calling gamer data that helps lessening load of DBMS. The related method to this is Proud.CDbCacheServer2.SetUnloadedDataHibernateDurationMs.

Partly load DB Cache

When you use DB, you may need to load partly. For example, you may need ‘Load gamer’s character then when you choose one character, load information only for that character.

ProudNet Database Cache System version 2 make that possible.

ProudNet Database Cache System version 2 use tree structure. It has data under one RooNode as like a tree. At this stage, user will define Schema of DBMS like this.

When you define like above, you can load Gamer and load ChracterInfo depends on what they choose using How to load exclusive data and add new data.

Here is sample code

Proud::Guid outSessionGuid;

Proud::CDbCacheClient2* c = ...;
c->RequestExclusiveLoadData(L"Gamer",L"GamerID",gamername,outSessionGuid);// This request will receive loadedGamerData

...// User select character. Find that character from loadedGamerData

c->RequestExclusiveLoadData(L"CharacterInfo",L"HeroIndex",findCharacter->heroIndex,outSessionGuid); // Loading information tree as user selection character.

1.6Transfer DB cache from Ver 1

You need to understand difference between DB Cache Ver.1 and Ver.2 before you transfer it.

List of difference

Ver 1

Ver 2

Manage it

Issue Credential

YES

NO

Need to realize issuing Credential

Callback authorize gamer with DB cache

YES

NO

Need to call directly rather than gamer authorize callback

In DB Cache Ver1, it handles Gamer, Hero, and World Object Table. If you want to use it continuously, you need to specify OwnerUUID, RootUUID, ParentUUDI.

In DB Cache Ver1, it handles CLoadedHeroData, CLoadedItemData, CLoadedGamerData. You need to handle CLoadedData instead of those one.

1.7DB Cache Tutorial

DB Cache 를 사용하는 기본적인 방법을 익힙니다.

DB Cache2 Sample 을 참고하시면 됩니다.

서버 시작하기

가장 먼저 ".\include\ProudDB.h" 파일을 include 하셔야 합니다.

IDBCacheServerDelegate2를 상속받은 객체와 CDBCacheServer2객체가 필요합니다.

IDBCacheServerDelegate2는 DB Cache Server 의 이벤트를 상속받기 위한 Interface Class 입니다.

namespace Proud;
Class CDBServer : public IDBCacheServerDelegate2
{
    ~CDBServer()
    {
        if(m_dbServer != NULL)
        {
            m_dbServer->Stop();
            delete m_dbServer;
        }
    }

    // DB cache server 인스턴스는 각 게임 서버들 사이에서 단 1개만 있으면 충분합니다.
    CDBCacheServer2 *m_dbServer;
    void Start();

    // virtual 함수들은 생략
}

DB Cache Server를 시작하는 예제 로직입니다.

CDbCacheServer2StartParameter p;
p.m_delegate = this;
p.m_tcpPort = 44442; // Port

// DB cache server에서 DB Cache Client를 인증하기 위한 Key 입니다.
p.m_authenticationKey = L”Sample Key should be something”;

// DB 인스턴스에 접속하는 connection string 은 ADO connection string 형식이며, 샘플에서 참고하실 수 있습니다.
p.m_DBmsConnectionString = L” Data Source=localhost;Database=TestDB;Trusted_Connection=yes”

CCachedTableName userTable;
userTable.m_rootTableName = L"Gamer";
userTable.m_childTableNames.Add(L"Hero");
userTable.m_childTableNames.Add(L"Item");

param.m_tableNames.Add(m_userTable);

// DB cache server 인스턴스를 생성하는 메서드는 Proud.CDbCacheServer2::New() 입니다.
CDbCacheServer2 *dbServer = CDbCacheServer2::New();

dbServer->Start(p);

클라이언트 시작하기

IDBCacheClientDelegate2를 상속받은 객체와 CDBCacheServer2객체가 필요합니다.

IDBCacheClientDelegate2는 DB Cache Server 의 이벤트를 상속받기 위한 Interface Class 입니다.

namespace Proud;
Class CDBClient : public IDBCacheClientDelegate2
{
    ~CDBClient ()
    {
        if(m_dbClient != NULL)
        {
            m_dbClient->Stop();
            delete m_dbClient;
        }
    }
    CDBCacheServer2 *m_dbClient;
    void Start();
    // virtual 함수들은 생략
}

DB Cache Client를 시작하는 예제 입니다.

CDBCacheClient2ConnectParameter p;
p.m_delegate = this;
p.m_serverAddr = L”192.168.xx.xx”;
p.m_serverPort = 33355;



// DB cache server에서 DB Cache Client를 인증하기 위한 Key 입니다.
p.m_authenticationKey = L”Sample Key should be something”;



// Proud.CDbCacheClient2.New 를 실행해서 client 인스턴스를 생성합니다.
CDBCacheClient2 *dbClient = CDBCacheClient2::New();
m_dbClient->Connect(p);

응답 Parameter - CCallbackArgs

요청 응답형의 경우 DB Cache Client는 Callback Event의 parameter 인 CCallbackArgs 를 통하여 상태 정보를 알 수 있습니다.

CCallbackArgs 에는 요청에 대한 결과가 저장되어 있으며, 요청 성공 시 DB 의 Snapshot(복사본) 정보를 확인 하실 수 있습니다.

CCallbackArgs 로 부터 받은 data 는 복사본이기 때문에 CCallbackArgs 내의 정보를 바꾸셔도 엔진 내부의 Data 영향이 없습니다.

CCallbackArgs 의 Snapshot 지원기능은 다음과 같습니다.

CCallbackArgs.m_loadedData

CCallbackArgs.m_data

Snapshot의 활용 예

CPropNode* child = Args.m_loadedData->GetRootNode()->GetChild();

While(child)
{
    // Table의 이름을 얻어 이름을 비교할 수 있습니다.
    Proud::String txt = Child.TypeName;
    if(txt.Compare(L”CHARACTER”) == 0)
    {
        return child;
    }
    // 다음 Table Node를 얻습니다.
    Child = child->sibling;
}
CPropNode* root = Args.m_loadedData->GetRootNode();

// 해당 레코드의 값을 얻습니다.
Proud::String id = Root->Field[L”UserID”];
Proud::String id = Root->Field[L”Passworld”];
Int index = Root->Field[L”Index”];

독점 로딩의 예

먼저 두개의 객체를 있다고 가정해 보겠습니다.

// ./include/ProudDB.h를 추가 해주셔야 합니다.
using namespace Proud;

class CRemote
{
    Guid m_sessionGuid;
    CLoadedData2Ptr m_loadedData;
}

class CSample : public IDbCacheClientDelegate2
{
    CFastArray<*CRemote> m_remotes;
    CRemote* FindByGuid(Guid&);

    DBCacheClient2 *m_dbClient;

    // virtual 함수들 생략
}

데이터를 추가하면서 독점로딩 하는 예제 입니다.

요청:

CRemote *remote = new CRemote;

// 추가시킬 Table의 이름을 넣어 줍니다.
CPropNodePtr newNode = CPropNodePtr(new CPropNode(L"Gamer"));
Guid guid = Guid::RandomGuid();

// 추가할 Data를 Setting합니다.
newNode->Fields[L"UUID"] = guid;
newNode->Fields[L"OwnerUUID"] = guid;
newNode->Fields[L"RootUUID"] = guid;
newNode->Fields[L"GamerID"] = gamerID;
newNode->Fields[L"Password"] = password;

Guid outSessionGuid;
if(m_dbClient->RequestExclusiveLoadNewData(L"Gamer", newNode, outSessionGuid) 
    == true)
{
    remote->m_sessionGuid = outSessionGuid;
    m_remotes.Add(remote);
}

RequestExclusiveLoadNewData의 인자는 다음과 같습니다. 첫번째: 추가할 Table Name 두번쨰: 추가할 노드정보 세번쨰: 발급받을 sessionGuid out Parameter 값입니다. 이 값은 한개의 독점 Client에 대한 식별값이 됩니다.

IDbCacheClientDelegate2 으로 상속받은 함수가 Callback됩니다.

응답:

CSample::OnExclusiveLoadDataFailed(CCallbackArgs args)

CSample::OnExclusiveLoadDataSuccess(CCallbackArgs args)
{
    // CRemote라는 객체가 있다고 가정합니다.
    CRemote *remote = FindByGuid(args.m_sessionGuid);

    // m_loadedData를 복사하여 사용할 수 있습니다.
    remote,m_loadedData = args.m_loadedData;
}

위 예와 같이 sessionGuid를 통하여 요청 시점이나, 객체 등을 확인할 수 있습니다.

data를 독점 로딩한 후에는 응답 요청 형을 사용하실 수 있습니다.

독점적 데이터 - 요청 응답 형

요청 응답 형 사용 예제 입니다.

먼저 예제 코드를 진행하기 위하여 아래의 class가 있다고 가정하겠습니다.

Class CRemote
{
    CLoadedData2Ptr m_loadedData;
    Guid m_heroGuid;
}

class CSample : public IDbCacheClientDelegate2
{
    CFastMap2<HostID, *CRemote> m_remotes;
    CRemote *FindByHostID(HostID);

    DBCacheClient2 *m_dbClient;

    // virtual 함수들 생략
}

Proud.CDbCacheClient2.RequestAddData

Data를 추가합니다.

앞서 로드된 Data가 있다고 가정합니다.

요청:

CRemote *remote = FindByHostID(hostID);



CPropNodePtr newNode = CPropNodePtr(new CPropNode(L"Hero"));
newNode->Fields[L"Name"] = m_heroName;
newNode->Fields[L"Removed"] = 0;
newNode->Fields[L"HeroType"] = 1;



if(m_dbClient->RequestAddData(remote->m_loadedData->RootUUID, remote->m_loadedData->RootUUID, newNode, hostID) == true)
{
}

RequestAddData의 각 인자는 아래와 같습니다.

IDbCacheClientDelegate2 으로 상속받은 함수가 Callback됩니다.

응답:

CSample::OnAddDataSuccess(CCallbackArgs args)
{
    CRemote *remote = FindByHostID((HostID)args.m_tag);
    // load된 data를 새로 갱신해 줍니다.
    remote.m_loadedData = args.m_loadedData;
}
CSample::OnAddDataFailed(CCallbackArgs args)
{
    // Add 실패 입니다.
}

Proud.CDbCacheClient2.RequestUpdateData

DB의 Data를 수정합니다.

기존에 로드된 Data가 있다고 가정 하겠습니다. 요청:

CRemote *remote = FindByHostID((HostID)args.m_tag);

CPropNodePtr heroNode = remote->m_loadedData->GetNode(hostID);

// 히어로의 정보를 바꾼다.
heroNode->Fields[L"HeroType"] = 2;

// 히어로의 정보를 업데이트한다.
if(m_dbClient->RequestUpdateData(heroNode, hostID) == true)
{
}

RequestUpdateData의 각 인자는 아래와 같습니다.

IDbCacheClientDelegate2 으로 상속받은 함수가 Callback됩니다.

응답:

CSample::OnUpdateDataSuccess(CCallbackArgs args)
{
    CRemote *remote = FindByHostID((HostID)args.m_tag);
    // load된 data를 새로 갱신해 줍니다.
    remote.m_loadedData = args.m_loadedData;
}

CSample::OnUpdateDataFailed(CCallbackArgs args)
{
    // update 실패
}

Proud.CDbCacheClient2.RequestRemoveData

DB의 Data를 제거 합니다.

기존에 로드된 Data가 있다고 가정하겠습니다.

요청:

CRemote *remote = FindByHostID(hostID);

if(m_dbClient->RequestRemoveData(remote->m_loadedData->RootUUID, remote->m_heroGuid, hostID) == true)
{
}

RequestRemoveData의 인자는 다음과 같습니다.

IDbCacheClientDelegate2 으로 상속받은 함수가 Callback됩니다.

응답:

CSample::OnRemoveDataSuccess(CCallbackArgs args)
{
    CRemote *remote = FindByHostID((HostID)args.m_tag);
    // load된 data를 새로 갱신해 줍니다.
    remote.m_loadedData = args.m_loadedData;
}
CSample::OnRemoveDataFailed(CCallbackArgs args)
{
    // remove 실패
}

독점적 데이터 - 일방 형

일방 형 함수를 사용하기 위한 예 입니다.

먼저 예제 코드를 진행하기 위하여 아래의 class가 있다고 가정하겠습니다.

Class CRemote
{
    CLoadedData2Ptr m_loadedData;
    Guid m_heroGuid;
}

class CSample
{
    CFastMap2<HostID, *CRemote> m_remotes;
    CRemote *FindByHostID(HostID);

    DBCacheClient2 *m_dbClient;
}

Node를 제거하는 예제 입니다. 일방 형 응답을 받지 않기 때문에 load된 data를 요청 후 직접 수정하시면 됩니다.

CRemote *remote = FindByHostID(hostId);

if(m_dbClient->UnilateralRemoveData(remote->m_loadedData->RootUUID, remote->m_heroGuid, true) == true)
{
    CPropNodePtr heroNode = remote->m_loadedData->GetNode(m_heroGuid);

    // 바로 수정합니다.
    remote->m_loadedData->RemoveNode(heroNode);
}

UnilateralRemoveData 의 인자는 다음과 같습니다.

비독점 로딩 예

비 독점적으로 Data 얻어오기 예제 입니다.

비 독점적으로 Data의 최신 상태를 얻어옵니다.

먼저 예제 코드를 진행하기 위하여 아래의 class가 있다고 가정하겠습니다.

Class CRemote
{
    CLoadedData2Ptr m_loadedData;
    Guid m_heroGuid;
}

class CSample : public IDbCacheClientDelegate2
{
    CFastMap2<HostID, *CRemote> m_remotes;
    CRemote *FindByHostID(HostID);

    DBCacheClient2 *m_dbClient;

    // virtual 함수 생략
}

요청:

Proud::String strSearch;
strSearch.Format(L"GamerID='%s'",m_GamerName);

m_dbClient->RequestNonExclusiveSnapshotData(L"Gamer",strSearch, (intptr_t)hostID);

DBCacheClient2::RequestNonExclusiveSnapshotData 의 인자는 다음과 같습니다.

IDbCacheClientDelegate2 으로 상속받은 함수가 Callback됩니다.

응답:

CSample::OnNonExclusiveSnapshotDataSuccess (CCallbackArgs args)
{
    CRemote* remote = FindByHostID((HostID)args.m_tag);
    remote.m_loadedData = args.m_loadedData;
}
CSample::OnNonExclusiveSnapshotDataFailed (CCallbackArgs args)
{
    // 실패 입니다. 로그를 남기세요
}

비독점 형 데이터 사용 예

먼저 예제 코드를 진행하기 위하여 아래의 class가 있다고 가정하겠습니다. 기존에 이미 로드된 Data가 있다고 가정합니다.

Class CRemote
{
    CLoadedData2Ptr m_loadedData;
    Guid m_heroGuid;
}

class CSample : public IDbCacheClientDelegate2
{
    CFastMap2<HostID, *CRemote> m_remotes;
    CRemote *FindByHostID(HostID);

    DBCacheClient2 *m_dbClient;

    // virtual 함수 생략
}

DBCacheClient2::RequestNonExclusiveAddData 비 독점적으로 Data추가 하기 입니다.

요청:

CPropNodePtr newData = CPropNodePtr(new CPropNode(L"Hero"));
newData->SetField(L"Name",m_heroName);
newData->SetField(L"Removed",0);
newData->SetField(L"HeroType",1);

// DB에 Hero 정보를 추가 합니다.
m_dbClient->RequestNonExclusiveAddData(RootTableName, RootUUID, RootUUID, newData, m_diffCustomArg, Proud::ByteArray());

IDbCacheClientDelegate2 를 상속받은 함수가 Callback됩니다.

응답:

// 비 독점 형 사용에서는 처음의 Data 로딩 외에는 m_loadedData를 접근하실 수 없습니다. CCallbackArgs::m_data를 사용하십시오.
CSample::OnNonExclusiveAddDataAck (CCallbackArgs args)
{
    // args.m_data;
}

// 아래는 원래의 독점을 하고 있었던 DB Cache Client가 받게 되는 Callback입니다.
CSample::OnSomeoneAddData( CCallbackArgs& args )
{
    // 기존 loadedData를 저장하고 있다면, 바뀐 Data로 다시 저장해 주셔야 합니다.
    m_client->m_loadedData = args.m_loadedData;
}