What’s new at MAINFRAMES 360
(Updates May '11)...
- We are a cosmopolitan community of 400 members, from around the globe.
- Working on writing and publishing articles on CICS.
- Special article on "How do I learn Mainframe Programming"

Sunday, July 25, 2010

CA-7 Commands


Q. What is CA-7 Scheduler? Where did CA-7 come from?
Think of jobs as, Flights taking off from an Airport. On a busy airport, when the clock strikes 09:00 AM, all jobs that were scheduled to depart at 09:00 AM take-off. CA-7 Scheduler manages and oversees all of this.

In the Production Environment(where things are running live), you don’t type SUB on a Production Job and give it to the Mainframe Computer for Processing. Production Jobs are generally scheduled – they auto-start at a given time. The CA-7 Scheduler on Mainframes maintains a periodic Time-table, a database or chart of which jobs run when?

A company had made CA-7 in the United States for their own internal use, under the name SASS. You would still see programs like SASSBSTR and SASS Messages today. Universal Computing Company(UCC) bought the product SASS and renamed it UCC-7. In 1987, Computer Associates(CA) bought UCC, and it was their policy to name all their products with CA Prefix, so UCC-7 became CA-7.
Q. What is the CA-7 Queueing System?
CA-7 has different staging areas called Queues, where jobs could be. The CA-7 Queues are the (1) Request Queue (2) Ready Queue and (3) Active Queue. These queues are like traffic signals on a road. First the job has got to wait in the Request Queue(Red Signal). Next, the job has to wait in the Ready Queue(Orange Signal) – this means the job is almost ready to run. When the job is currently running, we say its in the Active Queue(Green Signal).

Image219[1] 
(1) The Database holds the Timetable of when the jobs run. CA-7 periodically scans the database(timetable) for which jobs are likely to run in the next few minutes.

(2) When the clock strikes 09:00 HRS, the Job A enters into the Request Queue. The JCL of the Job is picked up from the JCL Library and added to the Trailer of the CA-7 Request. Each Job in the Request Queue, waits for certain requirements to met.

(3) When all conditions and requirements are met, the job progresses ahead to the WLB(Workload Balancing).

(4) When there are enough initiators to pick up the Job from the Queue, the job is sent to the JES2. While a job is on WLB or JES2, its shown on the
Ready Queue.

(5) An SMF Type 20 or 30 record(job initialization) is received by CA-7, and the job is moved to the Active Queue, and will start execution in an address space.

(6) The job will remain on the Active Queue, until an SMF Type 5 or 30(job completion) is received by CA-7. On receipt of the job completion, if the job is successful, the Prior Run Queue(PRRN) Queue will be updated with the details of the execution. This serves as a last run-time record for the job. However, if the job fails, it will be returned to the Request Queue(REQ).
Q. How a job enters into the Request(REQ) Queue?
There are 3 ways, a job can enter into the Request Queue[REQ]. A job can be Scheduled, triggered or demanded out.

(1) Scheduled(SSCN) – Jobs can be scheduled to run at a fixed time – for example, Reporting job runs every month-end at 08:00 PM, Load jobs run every-day at 05:00 AM and so on.

(2) Triggered(AUTO) – A parent job X, when it runs to successful completion, can TRIGGER another child job Y. A TRIGGER automatically brings Job Y into the REQ Queue.

(3) Demanded(DEMD) – A Job X can programmatically Demand out another Job Y. For example,
Job X has the following code :

If Input File contains DATA
   Demand Job Y
Else
   Continue
End-if

Here, Job Y is brought into the Request Queue[REQ], only if the Input-file has data records. If the Input file is empty; if there’s no data to process, the job is not demanded out. So, in this fashion, you can exercise more control, over how the job kicks off.
Q. How to know Job’s information in CA-7?
You type the command LJOB,JOB=jobname,LIST=ALL to find all the information about a job. Look at how I’ve found all the information about my job GEMPAIAS on CA-7.

image

This shows all the information about my job CPARSDLY – which jobs does it trigger, which are the successor jobs, what are the steps in this job etc.

image

To know, if a job is Scheduled, or Triggered or Demanded out, the CA-7 Commands are
ScheduledLSCHD,JOB=jobname,LIST=CALS
TriggeredLJOB,JOB=jobname,LIST=TRIG
Demanded – Unfortunately, there’s no direct way no this, as Demand Information is not stored in CA-7, but in JCL. However, if the Job is demanded out into the REQ Queue, it shows up as DEMD in the Entry Mode column. Sometimes, you can use LJOB,JOB=jobname,LIST=PROS option of the LJOB Command to find out information about the Demanding job.
Q. How to know, if a job is scheduled?
The quick way to know if a Job is Scheduled, is to use the List Schedule[LSCHD] Command, with LIST=CALS(Calendar) option. This opens up a Calendar view, and tells us, what time and on what calendar days of the year, your job is going to run.

In the clipping below, my job GMSBDRQ1 runs on all week-days, Monday-to-Friday at 23:00 hrs.

alt
Q. How to know, if a job is triggered?
A job X can be brought in the REQ(Request) Queue, when it is triggered by
Job Y. How do you know, the Triggering Job or Parent Job. You can code LIST=TRIG(Triggers) option on the LJOB Command, to find out the
triggering job. In the below clipping, my job XRPDGLPS is triggered by the parent job GMSBDRQ1. When GMSBDRQ1 completes, my job XRPDGLPS would be brought into the REQ(Request) Queue.

alt
Q. How to know if a Job is Demanded out?
A job can be programmatically demanded out by another job, based on given condition. If the condition is true, the job is demanded out into the REQ(Request) Queue. If the condition is false, the job is not demanded out. Generally, information about the Demanding job is not stored in CA-7. Sometimes, the LIST=PROSE option of the LJOB command, may give details about the Demanding job. In the below clipping, my job GEMIATAL job is demanded out by GMLIASXA.

alt
Q. How long does a job wait in REQ Queue, before it enters RDY Queue?
A job has to wait in the CA-7 REQ(Request) Queue, until all of the requirements it has are satisfied. Requirements are like additional promises, which must be fulfilled, before a job is allowed to run. Requirements could be anything like, Completion of another job, Arrival(creation) of a file(Dataset), Submit Time, User Hold or a Negative Dependency. Its only when all the Requirements, of a job are fulfilled or posted, the job is brought to the Ready Queue(RDY).

Check out this example. A Job X triggers Job Y. Job X completes everyday at 08:00 AM. Job Y has 2 requirements – R1 and R2. Job R1 completes at 07:00 AM and Job R2 completes at 09:00 AM. The question is, when does Job Y kick-off? I would say, when Job X completes at 08:00 AM, it triggers Job Y, so it brought to the Request Queue at 08:00 AM. The requirement R1 of Job Y is satisfied, but it will wait in Request Queue[REQ], till R2 is satisfied. When R2 completes at 09:00 AM, both the requirements are satisfied, and Job Y will be brought to the Ready Queue[RDY].
Q. What are predecessors and successors of a Job?
Think of a relay-race with three participants – Arnold, Danny and Carol. The three participants are scheduled to start running, but spaced apart in intervals of 15 minutes each. Arnold is scheduled to start running when the timer is 00:00 hrs. Danny is scheduled to start running when the time is 00:15 Hrs. Carol is scheduled to start running, when the time is 00:30 Hrs.

Requirement of Danny – Danny is allowed to start running, only after Arnold completes the race, and passes on the baton to him.

Dependent Carol – Danny owes a favour to Carol, he has a commitment towards her. He must complete the race and pass on the baton to her, before she can start off.

Arnold –> Danny –> Carol

Danny’s predecessor is Arnold. Danny’s successor(dependent) is Carol.

You can use the LIST=RQMT option on LJOB Command, to find out the requirements or predecessors of a job. You use the LIST=DEPJ option on the LJOB Command, to find the successors of a job.

alt

In the above video clipping, my job GEMTOPR3 has the requirement
(pred job) AXMYTOPV. When GEMTOPR3 enters into CA-7 REQ(Request) Queue, its gonna wait for the Requirement AXMYTOPV to be satisfied. Only, when the requirements are met, my job GEMTOPR3 can enter into RDY(Ready) Queue. Moreover, the jobs GEMCNSTL, GMCNTODL and QRPDR3PA are the successors of GEMTOPR3. This implies that the jobs GEMCNSTL, GEMCNTODL and QRPDR3PA have my job GEMTOPR3 as a requirement.

Predecessor job-names may be preceded by a slash(/) to indicate 
Negative dependency. A conditional Dependency is indicated by prefixing the predecessor job-name with a question-mark(?). If a job A is conditionally dependent on Job B, then Job A will have dependency(requirement) on Job B, only if Job B is in the REQ(Request) Queue, RDY(Ready) Queue or ACT(Active) Queue. The dependency is conditionally applied, provided the pred-job is in
CA-7 Queue.
Q. What is Lead Time? What are Look-back issues?
Lead Time is the period(in hours)[time-window], that a job looks back in time, to check if all its requirements(promises) are fulfilled. See the below example. Here, my job GEMPAIAS has a requirement on PZCPDWKY, with a Lead Time of 5 hours.

JOB=GEMPAIAS LIST=RQMT

NAME ID MEMBER -NAME- -ID -ID- DSNBR DSNBR STP DDS RUNS DATE/TIME

JOB=PZCPDWKY  SCHID=000 VRSN=10176/1131 LEADTM=05
JOB=/GEMPAIMG SCHID=000 VRSN=98258/0010 LEADTM=99
JOB=/GEMCNS6L SCHID=000 VRSN=95334/0012 LEADTM=99

Suppose, my job GEMPAIAS is a scheduled job, it is scanned out everyday, and enters the REQ(Request) Queue at 07:00 AM in the mornings. Now, the GEM* Job is going to check for its requirement of Pee-zee(PZ*) job. Has the Pee-Zee(PZ*) Job completed in the last 5 hours? Thus, the GEM* Job searches for its requirement Pee-Zee(PZ*) job’s completion in the time-window of 02:00 AM to 07:00 AM. If the Pee-Zee(PZ*) Job would have completed in the time-frame[02:00-07:00 AM], the requirement is satisfied.

However, if the Pee-Zee(PZ*) Job completes, say at 00:00 Hrs, this doesn’t fall in the time-window 02:00-07:00 AM, so the requirement shall not be satisfied. The GEM* Job merely keeps waiting in REQ(Request) Queue(even though the PZ* Job ran, but ran at 00:00 Hrs). This is a classic example of a Look-back Issue.

Very often, there is too large a time-gap that elapses between a predecessor job A's completion, and its dependent B's starting out. When B is brought into the REQ(Request) Queue, if A's completion doesn’t fall in the Look-back(Lead-time) window, B keeps waiting in the REQ Queue. These are called Look-back Issues. CA-7 Look-back issues generally happen in the Production Environment, generally due to delays in Batch Cycle, holidays etc.

Lead-Time could take several values.

00 – No special consideration for the amount of time elapsed, between the pred-job and dependent job's runs.
99 – The requirement is never to be considered as already satisfied, when the job enters the Queue.
nn – Since, the last run of the job, each predecessor job must have run within the last nn hours. Values for nn may be from 1 to 98.

Q. What is a Negative Dependency?

Sometimes, you wish - I hope these two jobs don't collide, don't run at the same time. If a Job P has a Negative Dependency N, Job P and Job N can't run together(mutually exclusive). So there are 2 possibilities -

1. Job P can run, if Job N has not started.
2. Job P can run, if Job N has completed.

In the snapshot below, my job GEMTOPR3 has a negative-dependency on XRPDR3PA.

GEMTOPR3 000 GEMTOPR3 GEMIDB   005 SY2  007743 *NONE* 002 000 1326 10194/2315 
       --------------------------- SUCCESSOR JOBS ----------------------------  
        JOB=GEMCNSTL SCHID=000                                                
        JOB=GMCNTODL SCHID=000                                                
        JOB=QRPDR3PA SCHID=000                                                
        JOB=/XRPDR3PA SCHID=000    (Negative dependency)        
             

Generally, Negative Dependencies are used in the Production Environment, to prevent contention problems. Say, for example, if two jobs access the same
DB2 Table, it’s a good idea, to have a negative dependency created amongst them.

Q. What are the advanced CA-7 Commands?

You can type CA-7 advanced Forecast commands, to find out the hierarchy of jobs in the forward order, or reverse-order. FSTRUC Command gives the complete list of triggered jobs, at all levels, top-to-bottom. FRJOB gives the complete list of triggered jobs, at all levels in the reverse order, bottom-up fashion. Look, how I’ve found the complete hierarchy of jobs triggered by my job GEMCAL00.

alt

This is how it works. GEMCAL00 triggers GEMCAPHDR(Header job). GEMCAPHDR on the other hand triggers GEMCARAL and GEMCAR1L. The AL triggers a complete stream or wave of my jobs – GEMCARBL, which triggers the *CL, triggering *EL and so on.

Q. What is Job Monitoring? How to check if a job has completed?

When a Mainframe Job completes successfully, it goes to the Log-Area[LRLOG]. The log-area stores tracking-information – the log of the completed job of the past 5 days. The CA-7 LRLOG Command is used to retrieve from the logs, information about the previous runs of a job. I have scribbled below, how you can code several different options on the LRLOG Paragraph.

LRLOG,JOB=job-name,DATE=*
Log of the job, for the past 5 days.

LRLOG,JOB=job-name,DATE=10200
Log of the job, for the run on 2010-07-19(Julian Date 197 day of the year 2010).

When a job abends at a particular step, you may re-start the job from the next successive step, you may force-complete the job, or you may cancel the job. Force completing a job, force-fully marks the job as complete(even if the job has not run entirely successfully). All triggered down-stream jobs are brought into the CA-7 Queue.

Cancelling the job off, is like stopping the job altogether. With this the entire job-cycle downstream will be held up/hung.

LRLOG,ST=RSTR,SPAN=24
This command tells, which jobs abended and were restarted in last 24 hours.

LRLOG,ST=FORCE,SPAN=24
This command tells, which jobs abended and were force-completed in last 24 hours.

LRLOG,ST=CANCEL,SPAN=24
This command tells, which jobs abended and were cancelled off in last 24 hours.

LPRRN,JOB=job-name
This command is used find out information about the Last job-run.

alt

Sunday, July 11, 2010

COBOL-DB2 Program - Introduction

Q. What are DB2 Storage Areas?
When you write COBOL Programs, that read data records from Files, and store Output results to a File, you must declare Input and Output Storage Areas for the files in the COBOL Program.
Image204[1] 

COBOL has a strict rule – first Declare, then use. Look at the picture above. Firstly whenever, you access data from Files in COBOL, you need to declare(announce) the file-names in COBOL. Moreover, you also declare COBOL Storage Areas for sending data to and receiving data from files. The Input Storage Area is the place in the COBOL Program, where the data arrives and get stored, from a File, out here for the INPUT-FILE it is EMPLOYEE-INPUT-RECORD. When you do a READ INPUT-FILE, the input record QUASAR 1000 20-10-06 is read from the file, and received and stored in EMPLOYEE-INPUT-RECORD Storage Area. Similarly, the Output Storage Area is the place in the COBOL Program, from where the data departs and is output to the File, here for the OUTPUT-FILE it is EMPLOYEE-OUTPUT-RECORD. So, when you do a WRITE EMPLOYEE-OUTPUT-RECORD, whatever’s stored in EMPLOYEE-OUTPUT-RECORD is written to the file.

In the same fashion, when you access data from DB2 Tables in a COBOL Program, you need to first DECLARE(announce) the TABLE in the COBOL Program. Suppose there’s an EMPLOYEE DB2 Table, that you want to access in the COBOL Program. The EMPLOYEE DB2 Table looks like this -

Image206[1]

Before using EMPLOYEE Table, you must DECLARE the SQL EMPLOYEE TABLE at the top of the COBOL Program in the DATA DIVISION. You can DECLARE EMPLOYEE TABLE as shown in the picture below -

Image205[1]

The DECLARE EMPLOYEE TABLE in the COBOL Program makes a statement – hey pal, this COBOL Program uses the EMPLOYEE table, which is broken into EMPID, ENAME, SALARY and JDATE SQL-Fields(columns). Since, this is SQL, and not COBOL Statements, you embed them – put them inside a EXEC SQL and END-EXEC Block.

When you fetch data from these SQL Fields(columns) into the COBOL, there is should also be corresponding COBOL Variables to receive and hold the fetched data. For every SQL-Field, you must declare a corresponding COBOL Variable(Storage Area).  

Image212[1]   

EMPLOYEE-ID is the receiving COBOL Variable which will hold the values fetched from the SQL Field EMPID. The SQL Type INTEGER(4 Bytes) translates to
S9(09) COMP(4 Bytes) in COBOL. EMPLOYEE-NAME is the receiving COBOL Variable, that shall hold the values fetched from the SQL Field ENAME. The SQL Type CHAR(n) translates in COBOL as PIC X(n), where n is the size. EMPLOYEE-NAME is the receiving COBOL variable that shall, store the data fetched from SQL Field SALARY. For the SQL Type DECIMAL(7,2), 7 is the total width, 2 is the digits after the decimal point. Therefore, digits before the decimal point would be
7-2=5. Thus, in COBOL it translates to PIC 9(05)V99 COMP-3. EMPLOYEE-JDATE is the receiving COBOL Variable, for the values retrieved from JDATE SQL Field. Generally, DATE in SQL becomes a PIC X(10) in COBOL, TIME is a PIC X(08), and TIMESTAMP is a PIC X(26).

Specifying the table-name, SQL Fields and the corresponding COBOL Variables at the top of the COBOL Program is called Declaration. You can write DB2 Declaration manually, the way I’ve written, or you can auto-generate it. The tool that auto-generates Declarations, so that you can avoid the manual labour of writing it at the top of the COBOL Program, is called Declaration Generator Tool(DCLGEN Tool).
Q. How do you use DCLGEN tool, to auto-generate Declarations?
The Declarations Generator(DCLGEN) tool can be found inside the DB2I(DB2 Interactive) Menu 2.

Image208[3] 

I have typed the Table-name EMPLOYEE. I have also keyed in the output file(should be a member of a pds/library), in which the auto-generated DB2 Declarations are stored by the DCLGEN Tool. After hitting ENTER, you should get a message, EXECUTION COMPLETE.

Image209[1] 
This is how the DB2 Declarations auto-generated in the AGY0157.DEMO.DCLGEN(EMPLOYEE) file look like -

Image210[1] 
Q. How to use Cursors to retrieve data from DB2 Tables in COBOL?
When you fetch Data from DB2 Tables in COBOL, you cannot directly fetch all the rows from the table in one shot, in one go. Once you execute the query, the results of the Query are fetched from the DB2 Table, and are brought into another temporary, rough-work area – called Cursor Area. The Cursor Area is like a rough scratch-pad area. A marker(pointer) is set to point to the beginning/1st row in Cursor area. Now, when you fetch the data from the cursor, it reads the data-row, to which the marker(pointer) is currently set. After each FETCH, the marker(pointer) is incremented(set) to the next row. This way you FETCH data from the cursor area, row-by-row, until you’ve read all the rows, and reached the end of the Cursor Area.

In this fashion in COBOL-DB2 Programs, whenever the result of a SQL Query is multiple-rows, you must use cursors to fetch the data results row-by-row one at a time.

There are 4 steps to use a Cursor. First, you must DECLARE the Cursor Query. DECLARE C1 CURSOR merely tells, what query to run. Second, you OPEN the cursor. When you OPEN the cursor, the cursor Query is executed, and rows are fetched from the DB2 Table into the Cursor Area. Third, you FETCH data from the Cursor area into the COBOL Program row-by-row, until you reach the End of the Cursor. Fourth and last, you CLOSE the Cursor.

Whenever you perform any SQL Operation, like an OPEN cursor, FETCH data from the cursor, or a CLOSE cursor, the DB2 System returns back a 3-digit status-code to indicate the Success or Failure of the SQL operation. This 3-digit status-code is stored in a Communication Area shared between DB2 and your COBOL Program. This Shared communication-area is called SQLCA. The SQLCA is a 01-level variable(storage-area) in COBOL, that is broken down into two parts – SQLCODE and SQLSTATE.
Q. Could you show me a COBOL Program to read data-rows from a DB2 Table?
First, you need to declare the Cursor Query. DECLARE C1 CURSOR FOR is the statement used to declare a cursor. I am going to declare a cursor, which can retrieve Employee-id, name, salary and joining-date from the Employee-table.

Image213[1]

You also need to supply the SQLCA COBOL Variable, that shall hold the results of the OPEN, FETCH and CLOSE Cursor operations. You want to be sure, that OPEN, FETCH and CLOSE Cursor operations go clean, without any errors, so you need SQLCA to check on that. You generally type an INCLUDE SQLCA entry.

Now, you begin type executable COBOL Instructions in the PROCEDURE DIVISION. Essentially, the task of fetching data-rows from the DB2 Table can be divided into 3-paragraphs 1. OPENing the Cursor 2. FETCHing data from the Cursor row-by-row and 3. CLOSEing Cursor. I have typed the MAIN Paragraph in the PROCEDURE DIVISION like this -

Image214[1] 

Line 37 performs the Open paragraph, to open the cursor.

When you do a FETCH in SQL, it returns(retrieves) back the row, the cursor is currently pointing to. Every-time you FETCH, the current-row is returned, and the cursor is incremented(set to the next row). A SQLCODE=+0 signals a successful FETCH. This sequential row-after-row process of FETCH’ing, continues on and on. But, how do you know, how many rows you want to fetch – 5, 10, 15, how many to be precise. You don’t!

The situation where the cursor points to the Last row, and there is no more data to get, is detected using the special SQLCODE=+100. A SQLCODE=+100 is the special, exceptional condition, where the cursor points to the last row, and there are no more data-rows to FETCH. You should do as many FETCH’s until, you hit SQLCODE=+100. 

Line 38 in the PROCEDURE DIVISION, performs FETCH paragraph to get one row at a time, repeatedly until SQLCODE is set to +100.

Line 39 performs the Close, to close the cursor.

To Open a Cursor(and execute the Cursor query), in SQL you type OPEN cursor-name. I have coded 100-OPEN Paragraph below, which executes the SQL instruction, OPEN EMP_CSR on Line 44. When you OPEN EMP_CSR, it means

SELECT EMPID,ENAME,SALARY,JDATE
FROM EMPLOYEE

query will run. The results will be stored in a SQL Area – EMP_CSR. The contents pf the Cursor Area EMP_CSR are

--> 1    RAM    1000    2010-06-09
    2    RAJ    2000    2005-01-03
    3    RAKESH 3000    2005-02-27

A marker or a pointer is set to the first row in the Cursor-Area. This pointer position, tells what’s the next row to be read?

Image215[1]

To fetch(receive) data-rows from the SQL Cursor-area into the COBOL Program, in SQL you type

FETCH cursor-area-name
INTO  COBOL-variables

The 200-FETCH Paragraph from Lines 48-56 fetches 1 single row from the Cursor Area EMP_CSR. So, this reads the row [1   RAM    1000    2010-06-09]. But, when this data arrives in the COBOL Program, where is it stored? So you also supply a list of COBOL Variables corresponding to each SQL Data-value received. In the picture below, EMPLOYEE-ID COBOL Variable will receive the value 1, EMPLOYEE-NAME COBOL Variable will receive the value RAM,  EMPLOYEE-SALARY COBOL Variable will receive the value 1000, and EMPLOYEE-JDATE COBOL Variable will receive the value 2010-06-09. FETCH cursor-area-name is a SQL Instruction. When you want to use COBOL Variables(non-SQL Variables) like EMPLOYEE-ID, EMPLOYEE-NAME etc. in a SQL Instruction, you prefix them with a :(Colon). I have DISPLAYed the recently fetched EMPLOYEE-INPUT-RECORD. After the FETCH Operation is completed successfully, the SQLCODE is set to +0. The pointer is incremented and set to the next row in the cursor area.

    1    RAM    1000    2010-06-09
--> 2    RAJ    2000    2005-01-03
    3    RAKESH 3000    2005-02-27


The 200-FETCH Paragraph is performed over and over again, till you’ve read the last row, until SQLCODE=+100. The 2nd FETCH will store 2 in EMPLOYEE-ID, RAJ in EMPLOYEE-NAME, 2000 in EMPLOYEE-SALARY and 2005-01-03 in EMPLOYEE-JDATE.


Image216[1]

After you’re done with retrieving/working with all the data rows in the cursor-area, you must CLOSE the Cursor-area. To close the SQL Cursor-area, in SQL you type -

CLOSE cursor-area-name

The 300-CLOSE Paragraph on Lines 59-63 executes the CLOSE EMP_CSR SQL Instruction to close the cursor.

Image217[1]
Related Posts Plugin for WordPress, Blogger...

Note :

Protected by Copyscape Online Copyright Protection
© Copyright – Quasar Chunawalla, 2010.
Note : The copyrights of all the material, text and pictures posted in this website belong to the author. Any instance of lifting the material from this website, shall be considered as an act of plagiarism. For any clarifications, please drop me a line at
 
back to top