You are on page 1of 85

Shared Memory

Programming with ABAP

Andreas Blumenthal, SAP AG

Learning Objectives

As a result of this workshop, you will


be able to:
 Understand the memory architecture of the SAP Web AS
 Know about the plethora of transparent shared memory







usages in the SAP Web AS


Know about the different possibilities for accessing shared
memory explicitly from within ABAP
Know about the strengths and weaknesses of the different
ways of utilizing shared memory
Determine which technique is best suited in which situation
Know about the performance and memory consumption
characteristics of the different techniques
Know how to customize the shared memory parameters of
your system
Know about the exciting new 'Shared Objects' features which
will be available with the next major technology release

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 2

Agenda

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 3

Overall Memory Architecture

Buffered Database Tables

EXPORT/IMPORT to/from Different


Media

Classes CL_ABAP_EXPIMP_* for


Administrating EXP/IMP Media

Shared Objects: Sneak Preview

Summary

Overall Memory Architecture

Overall Memory
Architecture

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 4

Straight Forward Memory Architecture

Task 1

Task i

Task n

Process 1

Process i

Process n

Local
memory

Local
memory

Local
memory

Shared memory

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 5

Task Dispatching

Task i
Task 1
Task 1
Task 1
Task 1
Task 1
Task 1 Context i
Task i Context 1
Context 1
Context 1
Context 1
Context 1
Context 1
Context i

Process i
Process i
Process i
Process i
Process i
Process i
Process i
Process i
Process i
Process j

Shared memory

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 6

Memory Structure of Task Contexts ('Roll Areas')

Roll
(1st try)
Extended
memory
Context i
Roll
(2nd helping)
Local
memory
(heap)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 7

Shared
memory
(task
contexts)

Transparent Shared Memory Buffers


Roll
(1st try)
Extended
memory
Context i
Roll
(2nd helping)

Local
memory
(heap)

Table
Dictionary
buffers
buffers

Dev. obj.
Dev. obj.
buffers
buffers

Calendar
buffer

Shared memory
(transparent buffers)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 8

OTR
buffer

Shared
memory
(task
contexts)

Apparent Shared Memory Buffers


EXP/IMP
Memory
(paging)
EXP/IMP
Shared
Buffer
Shared
memory
(apparent
buffers)

Roll
(1st try)
Extended
memory

Shared
memory

Context i
Roll
(2nd helping)

EXP/IMP
Shared
Memory

Local
memory
(heap)

Shared
Objects
Memory
Table
buffers

Table
Dictionary
buffers
buffers

Dev. obj.
Program
buffers
buffer
(prog. etc.)

Calendar
buffer

Shared memory
(transparent buffers)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 9

OTR
buffer

Show Buffer Characteristics

ST02

Dictionary
buffers
Dev. obj.
buffers
Calendar &
OTR buffer
Table
buffers
EXP/IMP
buffers
Memory
settings

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 10

Detail Analysis Menu

Dictionary
buffers

Table
buffers

Dev.
Table
obj.
buffers

Calendar
buffer

Memory
settings

OTR
buffer

EXP/IMP
Buffers
buffers

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 11

Detail Analysis Program Buffer

Efficiency

Size

Directory
entries

Swaps

Resets

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 12

Current Parameters Program Buffer

abap/
buffersize

abap/
pxa

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 13

Profile Parameter Display Properties


abap/buffersize
Minimum

Maximum

Dynamically
switchable?
Same on all
servers?

Default value

Profile value

Current value

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 14

Buffered Objects Program Buffer

Type pools
%_C*

Generated
basis programs
/1BC*/*

Some other
programs

Global classes
CL_*

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 15

Buffered Objects Program Buffer Entry Details

Version
20:52:35

Text Pool

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 16

Version
20:55:57

Version
20:56:39

Detail Analysis Shared Buffer EXP/IMP

Efficiency

Size

Directory
entries

Swaps

Resets

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 17

Current Parameters Shared Buffer EXP/IMP

rsdb/obj/
buffersize

rsdb/obj/
max_objects

rsdb/obj/
large_obj_size

rsdb/obj/
mutex_n

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 18

Profile Param. Display Properties


rsdb/obj/buffersize
Minimum

Maximum

Dynamically
switchable?
Same on all
servers?

Default value

Profile value

Current value

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 19

Profile Parameter Documentation


rsdb/obj/buffersize

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 20

Buffered Objects Shared Buffer EXP/IMP

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 21

Exercises Chapter 1
1. What are the system's current memory settings ?
2. How are the EXPORT/IMPORT buffers configured ?
3. What is the advantage of using shared memory instead of
process local memory for task/transaction contexts ?
4. What is the advantage of still using paging for EXPORT TO
MEMORY ?

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 22

Buffered Database Tables

Buffered Database Tables

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 23

Buffered Database Tables


 Buffering
 Buffering not allowed
 Buffering allowed but switched off
 Buffering switched on

 Buffering type (if buffering is switched on)


 Single records buffered
 Generic areas buffered specify number of key fields
 Fully buffered

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 24

Buffering not allowed - INDX

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 25

Single records buffered T100

Single records buffered 


Single messages are buffered

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 26

Generic areas buffered TRMSG

Generic areas buffered, no. of key


fields = 2 
All messages for a given keyword
in a given language are buffered

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 27

Fully buffered T005

Fully buffered 
All country information is
buffered

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 28

Buffered Tables - Caveats




A buffered table is a database table, even if you want to use it just as a


buffer
 writing to the buffer implies writing to the database
 data are shared across all application servers
 frequent updates impose a heavy synchronisation burden on the server
 nested tables are not suported

When using more advanced SELECT variants, the buffer will be silently
bypassed in many cases
 DISTINCT
 aggregate functions COUNT, SUM, AVG, MIN, MAX
 GROUP BY, HAVING
 joins, subqueries
 IS NULL
 ORDER BY (<> PRIMARY KEY)
 BYPASSING BUFFER

No option for data compression (in the buffer)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 29

Buffered Tables - Merits


 A buffered table is a database table, so table buffers are
 transactional
 synchronized across application servers
 transparently reloaded on demand after invalidation or
displacement

 High performance data access


 Well understood, flexible query language (though somewhat
restricted)
 Simple programming model for buffer updates

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 30

Exercises Chapter 2
1. Is client table t000 buffered ? If yes, how ?
2. When should you specify "Buffering not allowed" for a database
table ?

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 31

EXPORT/IMPORT TO/FROM Different Media

EXPORT/IMPORT
TO/FROM
Different Media

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 32

EXPORT/IMPORT Different Media


Transient, context-local memory:
 DATA BUFFER
 INTERNAL TABLE

Semi-persistent, shared memory:


 MEMORY
 SHARED MEMORY
 SHARED BUFFER

Persistent memory:
 DATABASE
 DATASET (obsolete)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 33

EXPORT/IMPORT Transient Media


EXPORT TO / IMPORT FROM DATA BUFFER:
 Scope: context of a single task/transaction
 Internal medium: context local main memory ('roll area')
 Displacement: no
 Key structure: none
 Output/input data: maintained by application
(via field of type xstring)

EXPORT TO / IMPORT FROM INTERNAL TABLE:


 Scope: context of a single task/transaction
 Internal medium: context local main memory ('roll area')
 Displacement: no
 Key structure: none
 Output/input data: maintained by application
(via internal table with line type <int2, x(n)>)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 34

EXPORT/IMPORT Semi-Persistent Media (1)


EXPORT TO / IMPORT FROM MEMORY:






Scope: Top-level task/transaction within a user session, i.e. "up to /n"


Internal medium: paging (process buffer shared memory buffer file)
Displacement: no
Key structure: <id>
Output/input data: maintained by ABAP runtime

EXPORT TO / IMPORT FROM SHARED MEMORY:








Scope: Application server


Internal medium: shared memory
Displacement: no
Key structure: <tabname, [client,] area, id>
Output/input data: maintained by application server

EXPORT TO / IMPORT FROM SHARED BUFFER:








Scope: Application server


Internal medium: shared memory
Displacement: yes (LRU based), but no transparent reload
Key structure: <tabname, [client,] area, id>
Output/input data: maintained by application server

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 35

EXPORT/IMPORT Semi-Persistent Media (2)


For MEMORY, SHARED BUFFER, and SHARED MEMORY holds:
 Transactional: no
 Synchronized: no
 Data have to be copied from shared memory into local context ('roll
area') before they are accessible (no locate mode, only move mode)

Although SHARED MEMORY and SHARED BUFFER are accessible in


parallel, normally no locking on application level is necessary:
 EXPORT and IMPORT are atomic operations (from an application logic
point of view)
 But: when
 items stored under different keys are logically related or
 the whole process of importing, processing, and exporting must not be
uninterrupted by concurrent exports,

application level locks become necessary

 When using enqueue/dequeue for shared memory synchronization,


keep in mind that enqueue/dequeue uses remote resources

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 36

EXPORT/IMPORT Persistent Media


EXPORT TO / IMPORT FROM DATABASE:
 Scope: SAP system(s)
 Internal medium: database
 Displacement: no
 Key structure: <tabname, [client,] area, id>
 Output/input data: maintained by application server and database

EXPORT TO / IMPORT FROM DATASET:


 Obsolete !!!!!
 Scope: SAP systems
 Internal medium: file system
 Displacement: no
 Key structure: none (<dataset name, area, id> just does not work)
 Output/input data: maintained by application server and file system

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 37

Non-Standard Usages of Different Media

Using transient media for persistent purposes

Using transient & persistent media for semi-persistent purposes

Storing arbitrary (data) object graphs in whatever media by using


CALL TRANSFORMATION id

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 38

Using Transient Media for Persistent Purposes


1. EXPORT TO DATA BUFFER dbuf / INTERNAL TABLE itab
[COMPRESSION ON].
2. Write dbuf/itab with whatever wrapping to whatever data store
(database, file, )
3. years pass by
4. Read dbuf/itab from whatever data store
5. IMPORT FROM DATA BUFFER dbuf / INTERNAL TABLE itab.


What you get is a customizable, self-controlled EXPORT/IMPORT,


i.e. a nice replacement for the unofficial & now obsolete addition
USING form

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 39

Using Transient & Persistent Media for SemiPersistent Purposes


1. EXPORT TO DATA BUFFER dbuf / INTERNAL TABLE itab
[COMPRESSION ON].
2. Write dbuf/itab with whatever wrapping to buffered database table
3. Read dbuf/itab from buffered database table
4. IMPORT FROM DATA BUFFER dbuf / INTERNAL TABLE itab.
5. What you get is a transactional, synchronized, optionally
compressed cluster buffer with transparent reload.
6. Caveat: don't buffer cluster tables like INDX directly (danger of
inconsistent read because of consecutive record mismatch:
isolation level is implicitly increased by IMPORT, but not when
reading into the table buffer)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 40

Storing Arbitrary (Data) Object Graphs in Whatever


Media by Using CALL TRANSFORMATION id
1. CALL TRANSFORMATION id SOURCE item = obj1
RESULT XML xmlstr.
2. Write xmlstr with whatever wrapping to whatever (semi-)persistent
data store (shared memory, database, file, )
3. seconds or hours or years pass by
4. Read xmlstr from whatever data store
5. CALL TRANSFORMATION id SOURCE XML xmlstr
RESULT item = obj2

What you get is a customizable, self-controlled (de-)serialization of


arbitrary (data) object graphs

Beware! For a class to be serializable, it has to implement tag


interface IF_SERIALIZABLE_OBJECT.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 41

Exercises Chapter 3
1. Export some data structure containing object and/or data
references to shared buffer. Use the following framework:
* ...
CALL TRANSFORMATION id SOURCE item = src RESULT XML xmlstr.
EXPORT ser FROM xmlstr TO SHARED BUFFER ...
* ...
IMPORT ser TO xmlstr FROM SHARED BUFFER ...
CALL TRANSFORMATION id SOURCE XML xmlstr RESULT item = dest.
* ...
IF equal( op1 = src op2 = dest ) <> abap_true.
* ...
ENDIF.

Don't forget: Classes need to implement


IF_SERIALIZABLE_OBJECT to be serializable.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 42

Exporting Data Structures with References (1)


*---------------------------------------------------------------------*
*
REPORT zshmserializesimple
*---------------------------------------------------------------------*
* Example program showing how to
* - (de-)serialize arbitrary data possibly containing data and/or object
*
references
* via the
* - canonical XML representation of ABAP data structures
* by using
* - CALL TRANSFORMATION id
* together with
* - EXPORT/IMPORT
*---------------------------------------------------------------------*
REPORT zshmserializesimple.
TYPE-POOLS: abap.
CLASS node DEFINITION DEFERRED.
* Data structure ITEMS (definition below) to be serialized:
*
internal table of
*
references to
*
structures containing - besides other data *
a reference to
*
some object (i.e. instance of some class)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 43

Exporting Data Structures with References (2)


TYPES: BEGIN OF item,
val TYPE i,
node TYPE REF TO node,
END OF item,
items TYPE TABLE OF REF TO item WITH NON-UNIQUE KEY table_line.
*---------------------------------------------------------------------*
*
CLASS node DEFINITION
*---------------------------------------------------------------------*
* Dummy class instances of which can be serialized
*---------------------------------------------------------------------*
CLASS node DEFINITION.
PUBLIC SECTION.
*

Tag interface indicating that instances of this class can be serialized


INTERFACES: if_serializable_object.

Some dummy instance attribute


DATA: val TYPE i.

ENDCLASS.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 44

"node DEFINITION

Exporting Data Structures with References (3)


*---------------------------------------------------------------------*
*
CLASS test DEFINITION
*---------------------------------------------------------------------*
CLASS test DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: main.
PRIVATE SECTION.
CLASS-METHODS: fill_items
CHANGING items TYPE
display_items IMPORTING items TYPE
equal_items
IMPORTING it1
it2
RETURNING value(equal)
ENDCLASS.

items,
items,
TYPE items
TYPE items
TYPE abap_bool.

"test DEFINITION

*---------------------------------------------------------------------*
*
CLASS test IMPLEMENTATION
*---------------------------------------------------------------------*
CLASS test IMPLEMENTATION.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 45

Exporting Data Structures with References (4)


*---------------------------------------------------------------------*
*
METHOD fill_items
*---------------------------------------------------------------------*
METHOD fill_items.
DATA: itemref TYPE REF TO item.
DO 10 TIMES.
CREATE DATA itemref.
itemref->val = sy-index.
CREATE OBJECT itemref->node.
itemref->node->val = 100 + sy-index.
INSERT itemref INTO TABLE items.
ENDDO.
ENDMETHOD.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 46

"fill_items

Exporting Data Structures with References (5)


*---------------------------------------------------------------------*
*
METHOD display_items
*---------------------------------------------------------------------*
METHOD display_items.
DATA: itemref TYPE REF TO item.
NEW-LINE.
LOOP AT items INTO itemref.
WRITE: (3) itemref->val, (3) itemref->node->val.
ENDLOOP.
ENDMETHOD.

"display_items

*---------------------------------------------------------------------*
*
METHOD equal_items
*---------------------------------------------------------------------*
METHOD equal_items.
DATA: lines1
lines2
ref1
ref2

TYPE
TYPE
TYPE
TYPE

i,
i,
REF TO item,
REF TO item.

equal = abap_false.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 47

Exporting Data Structures with References (6)


lines1 = lines( it1 ).
lines2 = lines( it2 ).
IF lines1 <> lines2. RETURN. ENDIF.
DO lines1 TIMES.
READ TABLE: it1 INDEX sy-index INTO ref1,
it2 INDEX sy-index INTO ref2.
IF ref1->val <> ref2->val OR ref1->node->val <> ref2->node->val.
RETURN.
ENDIF.
ENDDO.
equal = abap_true.
ENDMETHOD.

"equal_items

*---------------------------------------------------------------------*
*
METHOD main
*---------------------------------------------------------------------*
METHOD main.
DATA: items1
items2
xmlstr
id

TYPE
TYPE
TYPE
TYPE

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 48

items,
items,
string,
indx-srtfd VALUE 'items_id'.

Exporting Data Structures with References (7)

(1) Create data containing data and object references


fill_items( CHANGING items = items1 ).

(2) Display data


display_items( items1 ).

*
*

(3) Serialize data containing data and object references into its canonical
XML representation
CALL TRANSFORMATION id SOURCE items = items1 RESULT XML xmlstr.

(4) Export XML representation to semi-persistent medium


EXPORT items FROM xmlstr TO SHARED BUFFER indx(xk) ID id.

(5) Import XML representation from semi-persistent medium


IMPORT items TO xmlstr FROM SHARED BUFFER indx(xk) ID id.

*
*

(6) Deserialize data containing data and object references from its
canonical XML representation
CALL TRANSFORMATION id SOURCE XML xmlstr RESULT items = items2.

(7) Check equality


IF equal_items( it1 = items1 it2 = items2 ) <> abap_true.
BREAK-POINT.
ENDIF.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 49

Exporting Data Structures with References (8)


*

(8) Display re-imported data again


display_items( items2 ).
ENDMETHOD.

ENDCLASS.

"main
"test IMPLEMENTATION

*---------------------------------------------------------------------*
*
START-OF-SELECTION
*---------------------------------------------------------------------*
START-OF-SELECTION.
test=>main( ).

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 50

Classes CL_ABAP_EXPIMP_* for Administrating


EXP/IMP Media

Classes
CL_ABAP_EXPIMP_* for
Administrating EXP/IMP
Media

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 51

CL_ABAP_EXPIMP_* - Class Hierarchie (1)


cl_abap_expimp

cl_abap_expimp_mem
+get_next_level(id generic_key)
->level_tab
+get_keys(id generic_key)->keytab
+get_directory(id)->directory
+delete(id generic_key)
+delete_all()

cl_abap_expimp_shmem

cl_abap_expimp_shbuf

cl_abap_expimp_db

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 52

CL_ABAP_EXPIMP_* - Class Hierarchie (2)


cl_abap_expimp

cl_abap_expimp_shmem
cl_abap_expimp_shbuf

cl_abap_expimp_db

+get_next_level(tabname client area id


generic_key client_specified)
->level_tab
+get_keys(tabname client area id
generic_key client_specified)
->keytab
+get_directory(tabname client area id)
->directory
+delete(tabname client area id
generic_key client_specified)
+delete_all()

+get_next_level(tabname client area id


generic_key client_specified)
->level_tab
+get_keys(tabname client area id
generic_key client_specified)
->keytab
+get_directory(tabname client area id)
->directory
+delete(tabname client area id
generic_key client_specified)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 53

CL_ABAP_EXPIMP_* - Functionality
Administration is especially important for SHARED MEMORY, because
there is no automatic displacement of items that are buffered in
SHARED MEMORY !

get_next_level(): return next key level (tables, clients, areas, or ids) for
a given partial sequential key

get_keys(): return key list for a given partial sequential key

get_directory(): return directory for a given fully qualified key;


analogous to IMPORT DIRECTORY

delete(): delete for a given partial sequential key;


for a fully qualified, equivalent to DELETE FROM

delete_all(): delete everything

generic_key: flag, indicating that trailing blanks in the last key field
supplied are to be replaced by pattern '*'

client_specified: flag, as in Open SQL, indicating explicit client


handling

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 54

Example 1: Display List of Shared Buffer Keys (1)


*
Keys with client dependent key structures
TYPES: BEGIN OF expimp_key_c,
tabname TYPE tabname2,
client TYPE mandt,
area
TYPE indx-relid,
id
TYPE c LENGTH 59, "55,
END OF expimp_key_c,
*

Keys with client independent key structures


BEGIN OF expimp_key_nc,
tabname TYPE tabname2,
area
TYPE indx-relid,
id
TYPE c LENGTH 62, "58,
END OF expimp_key_nc.

CLASS main DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: display_keys.
PRIVATE SECTION.
CLASS-METHODS: client_dependent
IMPORTING tabname
TYPE csequence
RETURNING value(client_dependent) TYPE flag.
ENDCLASS.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 55

"main DEFINITION

Example 1: Display List of Shared Buffer Keys (2)


CLASS main IMPLEMENTATION.
METHOD client_dependent.
DATA: abs_tabname TYPE string,
struc
TYPE REF TO cl_abap_structdescr,
comp
TYPE abap_compdescr.
CONCATENATE '\TYPE=' tabname INTO abs_tabname.
struc ?= cl_abap_typedescr=>describe_by_name( abs_tabname ).
READ TABLE struc->components INDEX 1 INTO comp.
IF comp-name = 'MANDT'.
client_dependent = abap_true.
ELSE.
client_dependent = abap_false.
ENDIF.
ENDMETHOD.

"client_dependent

METHOD display_keys.
DATA: shbuf
TYPE REF TO cl_abap_expimp_shbuf,
keytab_c TYPE TABLE OF expimp_key_c,
entries TYPE i.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 56

Example 1: Display List of Shared Buffer Keys (3)


FIELD-SYMBOLS: <key_c> TYPE expimp_key_c,
<key_nc> TYPE expimp_key_nc.
CREATE OBJECT shbuf.
shbuf->get_keys( IMPORTING keytab = keytab_c ).
SORT keytab_c.
entries = lines( keytab_c ).
WRITE: / 'Total number of keys in SHARED BUFFER:', entries.
SKIP.
LOOP AT keytab_c ASSIGNING <key_c>.
IF client_dependent( <key_c>-tabname ) = abap_true.
WRITE: <key_c>-tabname NO-GAP, '[' NO-GAP, <key_c>-client NO-GAP,
'](' NO-GAP, <key_c>-area NO-GAP, ')', <key_c>-id.
ELSE.
ASSIGN <key_c> TO <key_nc> CASTING.
WRITE: <key_nc>-tabname NO-GAP, '
(' NO-GAP, <key_nc>-area NO-GAP,
')', <key_c>-id.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 57

"display_keys
"main IMPLEMENTATION

Example 2: Handling Shared Memory Overflow (1)


TYPES: items TYPE STANDARD TABLE OF i WITH DEFAULT KEY,
id
TYPE indx-srtfd.
CLASS cl_items_wrapper DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: get_items_ref IMPORTING id
TYPE id
RETURNING value(ref) TYPE REF TO items.
PRIVATE SECTION.
TYPES: BEGIN OF items_admin,
id TYPE id,
ref TYPE REF TO items,
END OF items_admin.
CLASS-DATA:
items_admin_tab TYPE HASHED TABLE OF items_admin
WITH UNIQUE KEY id.
CLASS-METHODS: fill_items IMPORTING id
TYPE id
CHANGING items TYPE items.
ENDCLASS.

"cl_items_wrapper DEFINITION

CLASS cl_items_wrapper IMPLEMENTATION.


METHOD fill_items.
*
... Fill items depending on id
ENDMETHOD.
"fill_items

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 58

Example 2: Handling Shared Memory Overflow (2)


METHOD get_items_ref.
DATA: admin TYPE items_admin,
cx
TYPE REF TO cx_sy_export_no_shared_memory,
shmem TYPE REF TO cl_abap_expimp_shmem.
*
Items(id) already loaded into context ?
READ TABLE items_admin_tab WITH TABLE KEY id = id INTO admin.
IF sy-subrc <> 0.
*
Items(id) not yet loaded into context
*
Create empty items object
CREATE DATA admin-ref.
*
Items(id) buffered in shared memory ?
IMPORT items TO admin-ref->* FROM SHARED MEMORY indx(xk) ID id.
IF sy-subrc <> 0.
*
Items(id) not yet or not any more buffered in shared memory
*
Fill items(id)
fill_items( EXPORTING id = id CHANGING items = admin-ref->* ).
*
Store items(id) in shared memory
TRY.
EXPORT items FROM admin-ref->* TO SHARED MEMORY indx(xk) ID id.
CATCH cx_sy_export_no_shared_memory INTO cx.
*
... Some error handling if shared memory is full
CREATE OBJECT shmem.
shmem->delete( tabname = 'INDX' area = 'XK' id = 'abc'
generic_key = abap_true ).
EXPORT items FROM admin-ref->* TO SHARED MEMORY indx(xk) ID id.
ENDTRY.
ENDIF.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 59

Example 2: Handling Shared Memory Overflow (3)


*

Save items(id) in context-local items administration


admin-id = id.
INSERT admin INTO TABLE items_admin_tab.
ENDIF.
*
Return reference to items(id)
ref = admin-ref.
ENDMETHOD.
"get_items_ref
ENDCLASS.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 60

"cl_items_wrapper IMPLEMENTATION

Performance and Memory Consumption 100 KB


Data
Shared Memory Programming in ABAP Examples
Times in Microseconds

Without compression
EXPORT
IMPORT

With compression
EXPORT
IMPORT

Pure itab
Buffered DB-Tab
Data Buffer
Internal Table
Memory
Shared Memory
Shared Buffer
Database

----464
553
501
855
868
95,631

----13,498
13,520
13,660
13,594
13,521
32,913

135
470
508
503
557
817
827
18,335

Input size:

102,400

Output uncompressed (bytes):


Output compressed
(bytes):

103,088
18,858

----2,486
2,461
2,430
2,461
2,453
7,386

Bytes = 51,200 Characters

(Measured on 800 MHz Pentium with optimized UC kernel, times in microseconds)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 61

Performance and Memory Consumption 1 MB Data


Shared Memory Programming in ABAP Examples
Times in Microseconds

Pure itab
Buffered DB-Tab
Data Buffer
Internal Table
Memory
Shared Memory
Shared Buffer
Database

Without compression
EXPORT
IMPORT
----7,260
7,878
7,353
13,191
13,148
2,528,886

5,190
5,974
7,895
7,919
7,845
13,832
13,991
173,071

With compression
EXPORT
IMPORT
----139,524
138,015
140,245
138,402
138,257
357,992

----25,019
25,008
24,909
25,621
25,432
57,046

Input size:

1,024,000 Bytes = 512,000 Characters

Output uncompressed (bytes):


Output compressed
(bytes):

1,030,088
186,553

(Measured on 800 MHz Pentium with optimized UC kernel, times in microseconds)

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 62

Example: Storing Items in the Shared Buffer

Scenario: buffer some data (here: some tables of integers - called


items - identified by some id) in the shared buffer (here: in
shared buffer indx(xk)).

Provide an encapsulated access to these data 


class items_wrapper with access method get_items_ref( id )

For each id, load data only once from shared memory into the
context of a task/transaction (i.e. load only once per id into the 'roll
area') 
buffer accessed items in a private static attribute
items_admin_tab

(Re-)buffer data in the shared buffer




when they are requested for the first time or

when they have been displaced from the shared buffer.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 63

Exercises Chapter 4
1. Write a class that encapsulates a shared-buffer-based ressource
identified by some id. Provide methods for
 getting items out of the buffer,
 reading the keys (= ids) of the items currently stored in the buffer,
 deleting items in the buffer.

The following code fragments might be useful:


DATA: shbuf TYPE REF TO cl_abap_expimp_shbuf.
* ...
EXPORT ... TO SHARED BUFFER ...
* ...
IMPORT ... FROM SHARED BUFFER ...
* ...
shbuf->get_keys( ... )
* ...
shbuf->delete( ... )
* ...

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 64

Example: Storing Items in the Shared Buffer (1)


*---------------------------------------------------------------------*
*
REPORT zshmitemsbuffer
*---------------------------------------------------------------------*
* Example program showing how to use
* - EXPORT/IMPORT with semi-persistent media SHARED BUFFER
*
(could be SHARED MEMORY as well)
* in combination with an
* - encapsulating class (here: items_wrapper)
* for providing buffered access to some items
*---------------------------------------------------------------------*
REPORT zshmitemsbuffer.
TYPES: item

TYPE STANDARD TABLE OF i WITH DEFAULT KEY, " Type of items to be


managed
item_key TYPE indx-srtfd,
" Type of item keys

*
*

Line type of internal table exported by cl_abap_expimp_shbuf->get_keys( )


when called for a client dependent table
BEGIN OF expimp_c_key,
tabname TYPE tabname2,
client TYPE mandt,
area
TYPE indx-relid,
id
TYPE c LENGTH 59, " actually the id is restricted to 55 char's
END OF expimp_c_key.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 65

Example: Storing Items in the Shared Buffer (2)


SELECTION-SCREEN BEGIN OF BLOCK oper WITH FRAME TITLE text-ope.
PARAMETERS: p_show
TYPE flag RADIOBUTTON GROUP oper,
p_acc
TYPE flag RADIOBUTTON GROUP oper,
p_ovfl
TYPE flag RADIOBUTTON GROUP oper,
p_del
TYPE flag RADIOBUTTON GROUP oper.
SELECTION-SCREEN END OF BLOCK oper.
PARAMETERS: p_ovflnr TYPE i DEFAULT 1000000.

*---------------------------------------------------------------------*
*
CLASS items_wrapper DEFINITION
*---------------------------------------------------------------------*
* Encapsulated buffered access to some items via get_item_ref( )
*---------------------------------------------------------------------*
CLASS items_wrapper DEFINITION.
PUBLIC SECTION.
*

Method providing buffered access to some items identified by some key


CLASS-METHODS: get_item_ref IMPORTING key
TYPE item_key
RETURNING value(ref) TYPE REF TO item.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 66

Example: Storing Items in the Shared Buffer (3)


PRIVATE SECTION.
*
*

Line type of internal table used for managing context-local (i.e. roll area
specific) versions of buffered items
TYPES: BEGIN OF item_admin,
key TYPE item_key,
ref TYPE REF TO item,
END OF item_admin.

Internal table for managing context-local versions of buffered items


CLASS-DATA:
item_admin_tab TYPE HASHED TABLE OF item_admin
WITH UNIQUE KEY key.

Dummy method creating items for some keys


CLASS-METHODS: fill_item IMPORTING key TYPE item_key
CHANGING item TYPE item.

ENDCLASS.

"items_wrapper DEFINITION

*---------------------------------------------------------------------*
*
CLASS items_wrapper IMPLEMENTATION
*---------------------------------------------------------------------*
CLASS items_wrapper IMPLEMENTATION.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 67

Example: Storing Items in the Shared Buffer (4)


*---------------------------------------------------------------------*
*
METHOD fill_item
*---------------------------------------------------------------------*
* Private dummy method creating items for some keys
*---------------------------------------------------------------------*
METHOD fill_item.
IMPORT item TO item FROM DATABASE indx(xk) ID key.
IF item IS INITIAL.
CASE key.
WHEN 'key1'.
APPEND: 1 TO item, 2 TO item, 3 TO item.
WHEN 'key2'.
APPEND: 4711 TO item, -987 TO item, 12345 TO item, 55555 TO item.
WHEN 'key3'.
APPEND: 2002 TO item, 3003 TO item.
WHEN 'key_ovfl'.
DO p_ovflnr TIMES.
APPEND sy-index TO item.
ENDDO.
WHEN OTHERS.
APPEND: -1 TO item, -2 TO item.
ENDCASE.
ENDIF.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 68

Example: Storing Items in the Shared Buffer (5)


EXPORT item FROM item TO DATABASE indx(xk) ID key.

ENDMETHOD.

"fill_item

*---------------------------------------------------------------------*
*
METHOD get_item_ref
*---------------------------------------------------------------------*
* Public method providing buffered access to some items identified by
* some key
*---------------------------------------------------------------------*
METHOD get_item_ref.
DATA: admin TYPE item_admin,
cx
TYPE REF TO cx_sy_export_buffer_no_memory.
*

(1) Item(key) alread loaded into local context ?


READ TABLE item_admin_tab WITH TABLE KEY key = key INTO admin.
IF sy-subrc = 0.
Item(key) already loaded into local context
WRITE: /(8) key, 'from local context:'.
ELSE.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 69

Example: Storing Items in the Shared Buffer (6)


*
*

Item(key) not yet loaded into local context,


prepare for managing local version of item(key):
CREATE DATA admin-ref.

(2) Item(key) available from shared buffer ?


IMPORT item TO admin-ref->* FROM SHARED BUFFER indx(xk) ID key.
IF sy-subrc = 0.

*
*

Item(key) available from shared buffer,


local version of item(key) filled by IMPORT
WRITE: /(8) key, 'from shared buffer:'.
ELSE.

*
*

(3) Item(key) not available from shared buffer,


item(key) needs to be filled 'from scratch':
WRITE: /(8) key, 'from scratch:
' .
fill_item( EXPORTING key = key CHANGING item = admin-ref->* ).

Store item(key) in shared buffer:


TRY.
EXPORT item FROM admin-ref->* TO SHARED BUFFER indx(xk) ID key.
CATCH cx_sy_export_buffer_no_memory INTO cx.
... Some error handling if item(key) is too large given the
current shared buffer configuration

*
*

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 70

Example: Storing Items in the Shared Buffer (7)


WRITE: /(8) key, 'too large, item truncated'.
DELETE admin-ref->* FROM 6.
EXPORT item FROM admin-ref->* TO SHARED BUFFER indx(xk) ID key.
ENDTRY.
ENDIF.
*

Register item(key) in local administration:


admin-key = key.
INSERT admin INTO TABLE item_admin_tab.
ENDIF.

Return reference to item(key)


ref = admin-ref.
ENDMETHOD.

ENDCLASS.

"get_item_ref

"items_wrapper IMPLEMENTATION

*---------------------------------------------------------------------*
*
CLASS test DEFINITION
*---------------------------------------------------------------------*
CLASS test DEFINITION.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 71

Example: Storing Items in the Shared Buffer (8)


PUBLIC SECTION.
CLASS-METHODS: main.
PRIVATE SECTION.
CLASS-METHODS: access_item IMPORTING key TYPE item_key,
access_items,
delete_items,
show_items.
ENDCLASS.

"test DEFINITION

*---------------------------------------------------------------------*
*
CLASS test IMPLEMENTATION
*---------------------------------------------------------------------*
CLASS test IMPLEMENTATION.

*---------------------------------------------------------------------*
*
METHOD show_items
*---------------------------------------------------------------------*
METHOD show_items.
DATA: shbuf TYPE REF TO cl_abap_expimp_shbuf,
keys TYPE TABLE OF expimp_c_key,
dir
TYPE TABLE OF cdir.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 72

Example: Storing Items in the Shared Buffer (9)


FIELD-SYMBOLS: <key>
TYPE expimp_c_key,
<entry> TYPE cdir.
CREATE OBJECT shbuf.
*

Get keys of all buffered items


shbuf->get_keys( EXPORTING tabname = 'INDX' area = 'XK'
IMPORTING keytab
= keys ).
SORT keys.
WRITE: / 'Keys in shared buffer INDX(XK):'.
LOOP AT keys ASSIGNING <key>.
Get directory info for one single item
shbuf->get_directory( EXPORTING tabname
=
area
=
id
=
IMPORTING directory =
WRITE: /(8) <key>-id.
LOOP AT dir ASSIGNING <entry>.
WRITE: '#item_lines:', (3) <entry>-tfill.
ENDLOOP.
ENDLOOP.
ENDMETHOD.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 73

"show_items

'INDX'
'XK'
<key>-id
dir ).

Example: Storing Items in the Shared Buffer (10)


*---------------------------------------------------------------------*
*
METHOD access_item
*---------------------------------------------------------------------*
METHOD access_item.
DATA: item_ref
item_line
t1
t2
pos

TYPE
TYPE
TYPE
TYPE
TYPE

REF TO item,
LINE OF item,
i,
i,
i VALUE 80.

GET RUN TIME FIELD t1.


item_ref = items_wrapper=>get_item_ref( key ).
GET RUN TIME FIELD t2.
t2 = t2 - t1.
LOOP AT item_ref->* INTO item_line.
WRITE: item_line.
ENDLOOP.
IF sy-colno > pos. pos = sy-colno + 2. ENDIF.
WRITE: AT pos t2, 's'.
NEW-LINE.
ENDMETHOD.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 74

"access_item

Example: Storing Items in the Shared Buffer (11)


*---------------------------------------------------------------------*
*
METHOD access_item
*---------------------------------------------------------------------*
METHOD access_items.
DO 2 TIMES.
CALL METHOD access_item EXPORTING key =: 'key1', 'key2', 'key1',
'key2', 'key3', 'key1'.
SKIP.
ENDDO.
ENDMETHOD.

"access_items

*---------------------------------------------------------------------*
*
METHOD delete_items
*---------------------------------------------------------------------*
METHOD delete_items.
DATA: shbuf TYPE REF TO cl_abap_expimp_shbuf.
show_items( ).
CREATE OBJECT shbuf.
shbuf->delete( tabname = 'INDX' area = 'XK' ).
ENDMETHOD.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 75

"delete_items

Example: Storing Items in the Shared Buffer (12)


*---------------------------------------------------------------------*
*
METHOD main
*---------------------------------------------------------------------*
METHOD main.
CASE 'X'.
WHEN p_show.
show_items( ).
WHEN p_acc.
access_items( ).
WHEN p_ovfl.
access_item( 'key_ovfl' ).
WHEN p_del.
delete_items( ).
ENDCASE.
ENDMETHOD.
ENDCLASS.

"main
"test IMPLEMENTATION

*---------------------------------------------------------------------*
*
START-OF-SELECTION
*---------------------------------------------------------------------*
START-OF-SELECTION.
test=>main( ).

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 76

Shared Objects: Sneak Preview

Shared Objects:
Sneak Preview

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 77

Shared Objects Basic Principles (1)




At design time, create Shared Objects Memory Areas with certain


properties.

At run time, instantiate these areas.

Shared Objects Memory Areas are represented by generated classes


derived from CL_AREA. At run time, instances of these classes allow
attaching and detaching of Shared Objects Memory Area Instances

Have type-safe access to the content of a Shared Objects Memory Area


Instance.

Operate directly on Shared Objects Memory Area Instances:


 locate mode,
 not move mode !

Place arbitrary (data) objects directly in Shared Objects Memory Area


Instances,
 including all kinds of references and dynamically created (data) objects and
 without any need for (de-)serialization.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 78

Shared Objects Basic Principles (2)




With Shared Objects, you can create


 shared buffers (one writer - many readers) as well as
 exclusive buffers (one single writer / reader).

Realize buffers that are optionally


 transactional and
 synchronized.

Use versioning of Shared Objects Memory Area Instances for


uninterrupted buffer availability even when reconstructing the buffer.

Realize buffers with partially transparent (re-)load:


 Provide area constructors
 Define





build kind (read request, invalidation, start-up),


start-up-lists for area,
refresh time and/or
invalidation time

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 79

Shared Objects Basic Principles (3)




Choose the appropriate 'life context' for the instances of your


Shared Objects Memory Areas:


bound to application server lifetime,

bound to user session, i.e. a user's set of E-modes


(analogous to SPA/GPA memory)

bound to single E-mode,

bound to top level task/transaction within a user session, i.e. "up to /n"
(analogous to EXPORT TO MEMORY)

Specify memory limits for




single instances of Shared Objects Memory Area as well as for

Shared Objects Memory Areas in total.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 80

Summary

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 81

There's a lot of transparent shared


memory support built into the system

Use buffered database tables or


SHARED BUFFER|MEMORY for
application specific shared memory
buffers

Be patient if you need to operate


directly without copy - on shared
memory: Shared Objects will be the
answer

Questions?

Q&A

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 82

Feedback

Please complete your session


evaluation and drop it in the box on
your way out.
Be courteous deposit your trash,
and do not take the handouts for the
following session.

The SAP TechEd 02 New Orleans Team

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 83

Copyright 2002 SAP AG. All Rights Reserved


 No part of this publication may be reproduced or transmitted in any form or for any purpose without the express
permission of SAP AG. The information contained herein may be changed without prior notice.

 Some software products marketed by SAP AG and its distributors contain proprietary software components of other
software vendors.

 Microsoft, WINDOWS, NT, EXCEL, Word, PowerPoint and SQL Server are registered trademarks of
Microsoft Corporation.

 IBM, DB2, DB2 Universal Database, OS/2, Parallel Sysplex, MVS/ESA, AIX, S/390, AS/400, OS/390,
OS/400, iSeries, pSeries, xSeries, zSeries, z/OS, AFP, Intelligent Miner, WebSphere, Netfinity, Tivoli,
Informix and Informix Dynamic ServerTM are trademarks of IBM Corporation in USA and/or other countries.

 ORACLE is a registered trademark of ORACLE Corporation.


 UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.
 Citrix, the Citrix logo, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, MultiWin and
other Citrix product names referenced herein are trademarks of Citrix Systems, Inc.

 HTML, DHTML, XML, XHTML are trademarks or registered trademarks of W3C, World Wide Web Consortium,
Massachusetts Institute of Technology.

 JAVA is a registered trademark of Sun Microsystems, Inc.


 JAVASCRIPT is a registered trademark of Sun Microsystems, Inc., used under license for technology invented
and implemented by Netscape.

 MarketSet and Enterprise Buyer are jointly owned trademarks of SAP AG and Commerce One.
 SAP, SAP Logo, R/2, R/3, mySAP, mySAP.com and other SAP products and services mentioned herein as well as
their respective logos are trademarks or registered trademarks of SAP AG in Germany and in several other
countries all over the world. All other product and service names mentioned are trademarks of their respective
companies.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 84

Copyright 2002 SAP AG. Alle Rechte vorbehalten


 Weitergabe und Vervielfltigung dieser Publikation oder von Teilen daraus sind, zu welchem Zweck und in welcher
Form auch immer, ohne die ausdrckliche schriftliche Genehmigung durch SAP AG nicht gestattet. In dieser
Publikation enthaltene Informationen knnen ohne vorherige Ankndigung gendert werden.

 Die von SAP AG oder deren Vertriebsfirmen angebotenen Softwareprodukte knnen Softwarekomponenten auch
anderer Softwarehersteller enthalten.

 Microsoft, WINDOWS, NT, EXCEL, Word, PowerPoint und SQL Server sind eingetragene Marken der
Microsoft Corporation.

 IBM, DB2, DB2 Universal Database, OS/2, Parallel Sysplex, MVS/ESA, AIX, S/390, AS/400, OS/390,
OS/400, iSeries, pSeries, xSeries, zSeries, z/OS, AFP, Intelligent Miner, WebSphere, Netfinity, Tivoli, Informix
und Informix Dynamic ServerTM sind Marken der IBM Corporation in den USA und/oder anderen Lndern.

 ORACLE ist eine eingetragene Marke der ORACLE Corporation.


 UNIX, X/Open, OSF/1 und Motif sind eingetragene Marken der Open Group.
 Citrix, das Citrix-Logo, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, MultiWin und
andere hier erwhnte Namen von Citrix-Produkten sind Marken von Citrix Systems, Inc.

 HTML, DHTML, XML, XHTML sind Marken oder eingetragene Marken des W3C, World Wide Web Consortium,
Massachusetts Institute of Technology.

 JAVA ist eine eingetragene Marke der Sun Microsystems, Inc.


 JAVASCRIPT ist eine eingetragene Marke der Sun Microsystems, Inc., verwendet unter der Lizenz der von
Netscape entwickelten und implementierten Technologie.

 MarketSet und Enterprise Buyer sind gemeinsame Marken von SAP AG und Commerce One.
 SAP, SAP Logo, R/2, R/3, mySAP, mySAP.com und weitere im Text erwhnte SAP-Produkte und -Dienst-leistungen
sowie die entsprechenden Logos sind Marken oder eingetragene Marken der SAP AG in Deutschland und anderen
Lndern weltweit. Alle anderen Namen von Produkten und Dienstleistungen sind Marken der jeweiligen Firmen.

2002 SAP Labs, LLC, ABAP213, Andreas Blumenthal 85

You might also like